rtel wrote on Friday, January 22, 2016:
Semaphore ownership doesn’t really have a meaning unless you are using a
semaphore type mutex, in which case the semaphore is intended to be used
to guard a resource. If you want to access the resource first you must
successfully ‘obtain’ the mutex, and as long as you have the mutex, no
other task can successfully obtain it - and as only the mutex owner can
legitimately access the resource, the resource is protected. Once you
have finished with the resource you give the mutex back - at which point
other tasks that want to access the same resource have an opportunity to
obtain the mutex.
In your case, you are not using the semaphore in this way, so I was
guessing the only reason you were using a recursive mutex was so you
could ‘take’ it multiple times, but from you latest post I’m wondering
if that is what is causing you the problem. With a recursive mutex you
must ‘give’ it back the same number of times as you have [recursively]
taken it before it becomes available again.
When you say “If the timer is running, just restart it. if the timer is
not running, take the recursive mutex”, it sounds you are going to take
the mutex the same number of times as the timer callback function is
going to give it - because you are only taking the mutex again if the
timer has actually expired. However, you may get into race conditions
here - for example, if the timer were to expire between your task
determining it had not expired and your task restarting the timer.
I don’t want to confuse things, as you seem to have gone down this route
quite some way, and I don’t fully understand your use case, but perhaps
an event group would be a more appropriate object to use than a mutex.
Lets say you have three timers, the timers are started at different
times, and at some point your task wants to wait until all three timers
have expired. That might not be the actual case, but perhaps close
enough to your actual case to use as an example.
You can assign different bits in the event group to three different timers:
#define TIMER_1 ( 0x01 << 0 )
#define TIMER_2 ( 0x01 << 1 )
#define TIMER_3 ( 0x01 << 2 )
Before you start any timers you ensure all the bits are clear.
The callback function for timer 1 then sets bit TIMER_1 in the event
group. The callback function for timer 2 sets bit TIMER_2 in the event
group. The callback function for timer 3 sets bit TIMER_3 in the event
group (the same timer callback function could be used for all the
timers, but lets keep it simple now, and assume these are three separate
callback functions for three separate timers).
Once your code has started all three timers, and gets to the point where
it needs to wait for all three to expire, it has to wait
for all three bits to get set in the event group:
xEventGroupWaitBits( xEventGroup, // Handle of the event group
( TIMER_1 | TIMER_2 | TIMER_3 ), // Bits to wait for
pdTRUE, // Clear the bits back to zero before returning
pdTRUE, // Wait for all three bits to be set
BlockTime ); // However long you want to wai
Is this close to what you want to achieve?