TNeoKernel
v1.03
|
A semaphore: an object to provide signaling mechanism.
There is a lot of confusion about differences between semaphores and mutexes, so, it's quite recommended to read small article by Michael Barr: Mutexes and Semaphores Demystified.
Very short:
While mutex is seemingly similar to a semaphore with maximum count of 1
(the so-called binary semaphore), their usage is very different: the purpose of mutex is to protect shared resource. A locked mutex is "owned" by the task that locked it, and only the same task may unlock it. This ownership allows to implement algorithms to prevent priority inversion. So, mutex is a locking mechanism.
Semaphore, on the other hand, is signaling mechanism. It's quite legal and encouraged for semaphore to be waited for in the task A, and then signaled from task B or even from ISR. It may be used in situations like "producer and consumer", etc.
In addition to the article mentioned above, you may want to look at the related question on stackoverflow.com.
Definition in file tn_sem.h.
Go to the source code of this file.
Data Structures | |
struct | TN_Sem |
Semaphore. More... | |
Functions | |
enum TN_RCode | tn_sem_create (struct TN_Sem *sem, int start_count, int max_count) |
Construct the semaphore. More... | |
enum TN_RCode | tn_sem_delete (struct TN_Sem *sem) |
Destruct the semaphore. More... | |
enum TN_RCode | tn_sem_signal (struct TN_Sem *sem) |
Signal the semaphore. More... | |
enum TN_RCode | tn_sem_isignal (struct TN_Sem *sem) |
The same as tn_sem_signal() but for using in the ISR. More... | |
enum TN_RCode | tn_sem_wait (struct TN_Sem *sem, TN_Timeout timeout) |
Wait for the semaphore. More... | |
enum TN_RCode | tn_sem_wait_polling (struct TN_Sem *sem) |
The same as tn_sem_wait() with zero timeout. More... | |
enum TN_RCode | tn_sem_iwait_polling (struct TN_Sem *sem) |
The same as tn_sem_wait() with zero timeout, but for using in the ISR. More... | |
Construct the semaphore.
id_sem
field should not contain TN_ID_SEMAPHORE
, otherwise, TN_RC_WPARAM
is returned.
sem | Pointer to already allocated struct TN_Sem |
start_count | Initial counter value, typically it is equal to max_count |
max_count | Maximum counter value. |
TN_RC_OK
if semaphore was successfully created;TN_CHECK_PARAM
is non-zero, additional return code is available: TN_RC_WPARAM
. Destruct the semaphore.
All tasks that wait for the semaphore become runnable with TN_RC_DELETED
code returned.
sem | semaphore to destruct |
TN_RC_OK
if semaphore was successfully deleted;TN_RC_WCONTEXT
if called from wrong context;TN_CHECK_PARAM
is non-zero, additional return codes are available: TN_RC_WPARAM
and TN_RC_INVALID_OBJ
. Signal the semaphore.
If current semaphore counter (count
) is less than max_count
, counter is incremented by one, and first task (if any) that waits for the semaphore becomes runnable with TN_RC_OK
returned from tn_sem_wait()
.
if semaphore counter is already has its max value, no action performed and TN_RC_OVERFLOW
is returned
sem | semaphore to signal |
TN_RC_OK
if successfulTN_RC_WCONTEXT
if called from wrong context;TN_RC_OVERFLOW
if count
is already at maximum value (max_count
)TN_CHECK_PARAM
is non-zero, additional return codes are available: TN_RC_WPARAM
and TN_RC_INVALID_OBJ
. enum TN_RCode tn_sem_wait | ( | struct TN_Sem * | sem, |
TN_Timeout | timeout | ||
) |
Wait for the semaphore.
If the current semaphore counter (count
) is non-zero, it is decremented and TN_RC_OK
is returned. Otherwise, behavior depends on timeout
value: task might switch to WAIT
state until someone signaled the semaphore or until the timeout
expired. refer to TN_Timeout
.
sem | semaphore to wait for |
timeout | refer to TN_Timeout |
TN_RC_OK
if waiting was successfulltimeout
value, refer to TN_Timeout
TN_CHECK_PARAM
is non-zero, additional return codes are available: TN_RC_WPARAM
and TN_RC_INVALID_OBJ
. The same as tn_sem_wait()
with zero timeout, but for using in the ISR.