I’m developing a middle layer between a peripheral an upper layers, and this middle layer has a binary semaphore.
The upper layers (threads) call the “Request” function of the middle layer, this takes the binary semaphore (xSemaphoreTake) to allow only one access to the peripheral at a time. Once the use of the peripheral is finished, the upper layer executes the “Release” function of the middle layer that releases the semaphore.
Now suppose the case that the semaphore is taken, and other upper layer (thread) executes the Request function. This will lead the thread to be waiting for the semaphore. If this thread is externally deleted, will the semaphore keep correct values? Is it safe to do?
When a task is being killed, the OS won’t know which semaphores were taken by the task.
I my opinion, it is more transparent to let a task kill itself. So if you want to kill a task, send it a message or set some flag to which it will respond. The task will know perfectly which resources it has claimed and what to do to terminate properly.
Yes, it would be easier if the task terminates itself and releases all the resources but I’m not sure if it is compatible with the low power. The xSemaphoreTake it was supposed to be blocked “forever” until the resource became available.
From your reply, I guess you are saying to avoid the “forever” semaphore and check from time to time a flag (or something else) to know if it has to terminate itself. Is that right?
Are you asking what happens if the middle layer task gets deleted while
it has the semaphore, or what happens if a higher level task that is
blocked waiting for the semaphore gets deleted? If you are just talking
about the latter case, where a task attempts to take a semaphore,
blocks, then gets deleted before it unblocks, then nothing happens -
everything will be fine. The task will get deleted and removed from the
list of tasks waiting for the semaphore. This holds for binary
semaphores but not necessarily other types of semaphore.
I generally find that I don’t need to delete/recreate tasks, and that people doing this tend to be thinking much more of a unix type model with full processes, and not a micro-kernal with tasks (which are much more like threads on bigger machines). The key thing is that if you are going to delete a task, you are almost certainly going to also be recreating the task later, and without a lot of careful analysis, you need to be prepared for the create task to fail. The major way to be sure that the create will succeed (other than not deleting in the first place so you don’t need to recreate) is to have a lot of memory, but then there isn’t much need to delete the task in the first place.
Because tasks are NOT full blown processes of the unix ilk, you need to take a lot of care to be sure the task is in a proper state before deleting it (so you don’t lose resources), which tends to make it simplest that if you do delete tasks, it is them self-deleting, otherwise it is very hard to avoid race conditions.
A task that is block indefinately on a semaphore or queue will not prevent the system from entering low power mode (the key is indefinately or at least for a long time), This generally SHOULD be the normal state for any task that doesn’t have something immediately to do anyway.