a semaphore problem

dear all:   I have a problem about the semaphore. When A task be locked by a semaphore, and B task is running with the same semaphore. But if B task is yielded by vTaskdelay(), then A task will fail immediately without blocking to get the semaphore.

a semaphore problem

Hi, Can you clarify your question – I don’t quite follow what you are asking. >I have a problem about the semaphore. When A >task be locked by a semaphore, Does this mean that task A is blocked waiting for a semaphore to become available? >and B task is >running with the same semaphore. Does this mean that task B has control of the semaphore that task A is blocked on? >But if B task >is yielded by vTaskdelay(), then A task will fail >immediately without blocking to get the >semaphore.  So task B calls vTaskDelay() while it has control of the semaphore? What do you mean by "fail"? If you can clarify these points I will be pleased assist.  Maybe you could provide a snippet of source code to demonstrate your question?  For example: // Assume two tasks of the same priority.  The // semaphore has already been created. // First vTest1 executes and ‘takes’ the semaphore. // vTest1 then blocks by calling vTaskDelay. // As vTest1 has blocked, vTest2 executes.  It // tries to ‘take’ the semphore but cannot (vTask1 // has it).  It therefore blocks to wait for the // semaphore. // Now both tasks are blocked so the idle task // executes until the 500 delay in vTask1 expires. void vTest1( void *pvParameters ) {   for( ;; )   {     // Take the semaphore.     cSemaphoreTake( xSem, 100000 );     vTaskDelay( 500 );   } } void vTest1( void *pvParameters ) {   for( ;; )   {     // Take the semaphore.     cSemaphoreTake( xSem, 100000 );     vTaskDelay( 500 );   } }

a semaphore problem

please refer to the following code. void taskA {   for(;;) {     vIOfunc();      …….   } } void taskB {   for(;;) {     vIOfunc();      …….   } } bool vIOfunc() {   if(cSemaphoreTake(xSemaphore, _1_Sec) != pdFAIL) {     while(!IO_Ready) vTaskDelay(_50_mSec);      ……..     while(IO_Command_Busy) vTaskDelay(_50_mSec);      ……..      do_IO_job;      cSemaphoreGive(xSemaphore);      return SUCCESS;   }   return FAIL; }   I need you help, thanks.

a semaphore problem

comment: if taskA has control of xsemaphore, then taskB will receive pdFAIL less then 1 sec. Because taskA is yielded by vTaskDelay, and make taskB get pdFAIL immediately. I am sure 1 second is enough to do the IO job.

a semaphore problem

This behavior could be correct depending on the priority of your tasks. Below is a simple test program that demonstrates the behavior. 1) Main creates the semaphore, then creates the two tasks. 2) Task B starts executing first, and obtains the semaphore. 3) Task B delays – causing Task A to execute. 4) Task A attempts to obtain the semaphore, but Task B has it so Task A blocks. 5) Eventually Task B is able to continue and does its ‘job’. 6) Task B gives up the semaphore.  As Task A is blocked on the semaphore it is unblocked when the semaphore is given up. If Task A had a higher priority than Task B it would now preempt Task B, obtain the semaphore, and do its ‘job’. However, as in this demo Task A has the same priority as Task B, Task A does not preempt Task B and Task B continues to execute. 7) Task B immediately obtains the semaphore again. 8) Task B then blocks waiting to be able to do it’s task.  Now Task B is blocked Task A can execute. 9) Task A attempts to obtain the semaphore, but it is unavailable (Task B has it again), so the call to cSemaphoreTake() fails! Solutions (in order of preference): a) Rearrange lIOFunc so that there is no delay while the semaphore is locked.  This could be done if the semaphore is only released when the IO ‘job’ becomes available. b) Add a call to portYIELD immediately after the call to lIOFunc().  This would force a context switch meaning that Task A and Task B would then alternate in obtaining the semaphore. c) Lower the priority of the task once it has the semaphore (could mean the semaphore is locked for longer depending on other task priorities), then raise it again once it is released. ///// TEST PROGRAM ///// xSemaphoreHandle xSemaphore; portLONG lIOfunc( void ) { portLONG l;     if( cSemaphoreTake( xSemaphore, 1000UL ) != pdFAIL )     {         // Simulate a delay;         for( l = 0; l < 0x2; l++ )         {             vTaskDelay( 2 );         }         // Do job         cSemaphoreGive( xSemaphore );         return pdPASS;     }     return pdFAIL; } void vTaskA( void *pvParameters ) {     for( ;; )     {         lIOfunc();     } } void vTaskB( void *pvParameters ) {     for( ;; )     {         lIOfunc();     } } int main( void ) {     prvSetupHardware();     vSemaphoreCreateBinary( xSemaphore );     sTaskCreate( vTaskA, "A", 128, NULL, 1, NULL );     sTaskCreate( vTaskB, "B", 128, NULL, 1, NULL );     vTaskStartScheduler( portUSE_PREEMPTION );     /* Should never reach here! */     return 0; }

a semaphore problem

> Solutions (in order of perference) Alternatively; if you want the unblocked task to preempt the unblocking task even when the priorities are the same then change the line if( pxUnblockedTCB->ucPriority > pxCurrentTCB->ucPriority ) to if( pxUnblockedTCB->ucPriority >= pxCurrentTCB->ucPriority ) in cTaskRemoveFromEventList() in tasks.c.