Either I don’t understand how semaphores are intended to work, or this seems to be a bug in RobotC. I’ve encountered an issue with multiple tasks using semaphores to wait on each other and the incorrect task owning the semaphore when it should be unlocked. The following code produces the output provided below.
task a(); // Task 1
task b(); // Task 2
TSemaphore s;
bool startB;
task main() // Task 0
{
clearDebugStream();
semaphoreInitialize(s);
startB = true;
startTask(a);
sleep(5000);
startB = true;
startTask(a);
sleep(10000);
}
task a()
{
writeDebugStreamLine("%d]\tA Start %d", nPgmTime, s.nOwningTask);
while (!bDoesTaskOwnSemaphore(s)) semaphoreLock(s);
writeDebugStreamLine("%d]\tA Lock %d", nPgmTime, s.nOwningTask);
sleep(1000);
if (startB == true)
{
startB = false;
startTask(b);
}
semaphoreUnlock(s);
writeDebugStreamLine("%d]\tA End %d", nPgmTime, s.nOwningTask);
}
task b()
{
sleep(1500);
writeDebugStreamLine("%d]\tB Start %d", nPgmTime, s.nOwningTask);
startTask(a);
sleep(500);
writeDebugStreamLine("%d]\tB Before Lock %d", nPgmTime, s.nOwningTask);
while (!bDoesTaskOwnSemaphore(s)) semaphoreLock(s);
writeDebugStreamLine("%d]\tB Lock %d", nPgmTime, s.nOwningTask);
semaphoreUnlock(s);
writeDebugStreamLine("%d]\tB End %d", nPgmTime, s.nOwningTask);
}
[0] A Start 255
[0] A Lock 1
[1000] A End 255
[2500] B Start 255
[2500] A Start 255
[2500] A Lock 1
[3000] B Before Lock 1
[3500] A End 2
[3500] B Lock 2
[3500] B End 255
[5000] A Start 255
[5000] A Lock 1
[6000] A End 2
[6000] B Start 2
[6000] A Start 2
[6500] B Before Lock 2
[6500] B Lock 2
[6500] B End 1
[6500] A Lock 1
[7500] A End 255
As shown by the output, the first time through, everything works as intended, task A starts and no one owns the semaphore, locks it, starts B and then ends. By the time B does anything, the semaphore is unlocked again and it starts A, which locks it right away. B then tries to lock it and succeeds when A unlocks the semaphore and returns. B then unlocks the semaphore and returns so it is owned by nobody. The second time through (5000 ms), A starts with the semaphore still owned by nobody and locks it, starts B and then unlocks it and returns. Here’s when strange things start happening, B now owns the semaphore without ever locking it and I now realize while writing this that it seems to wake up from its sleep when A unlocks the semaphore as if it wasn’t sleeping but waiting to lock a semaphore. It would seem that whatever brings the tasks back to life after something like a sleep or a semaphore unlock that it’s waiting on isn’t being cleared correctly and is causing issues. The data set posted above is from the RobotC emulator but the same problem (I didn’t notice the time issue) occurred on an actual Cortex. Thank you very much for the assistance.
Edit: The created thread is here: https://vexforum.com/t/obscure-semaphore-issue/38477/1