Pumpkin, Inc.

Pumpkin User Forums

OS_WaitSem()

If you can't make Salvo do what you want it to do, post it here.

OS_WaitSem()

Postby jeffc » Fri Feb 24, 2006 12:29 pm

What should I expect Salvo to do when I wait on a semaphore with a non-zero value.

Specifically, should it return to the scheduler or decrement the semaphore and continue in the current task without returning to the scheduler?

The manual, page 274, says that the task decrements the semaphore and continues. But that's not what I see with the following code.

code:
void TestCase( void )
{
DPRINTF(( "Create two tasks
" ));

OS_VERIFY_VOID( OSCreateTask( Task_A
,OSTEST_TASK_A_TCB_P
,PRIORITY_OSTEST_TASK_HIGH
)
,__LINE__
);

OS_VERIFY_VOID( OSCreateTask( Task_B
,OSTEST_TASK_B_TCB_P
,PRIORITY_OSTEST_TASK_HIGH
)
,__LINE__
);

OS_VERIFY_VOID( OSCreateBinSem( OSTEST_BINSEM_A_ECB_P, 0 )
,__LINE__
);

OS_VERIFY_VOID( OSCreateSem( OSTEST_SEM_A_ECB_P, 2 )
,__LINE__
);

OS_WAIT_ALL_EVENTS_SET( OSTEST_RESULT_ECB_P
,OSTEST_COMPLETED_2_TASKS
,TEST_CASE_1
);

DisplayResults( OSReadEFlag( OSTEST_RESULT_ECB_P ) );

/*---------------------------------------------------------------------- */

OSSAFESignalBinSem( OSTEST_CASE_ECB_P );

/* Terminate the task */
OS_Destroy( TEST_CASE_STOP );
}

void Task_A( void )
{
DPRINTF(( "task a
" ));

OS_Yield( TASK_A_1 );

DPRINTF(( " a1
" ));

OSSAFESignalBinSem( OSTEST_BINSEM_A_ECB_P );

OSSAFESignalSem( OSTEST_SEM_A_ECB_P );

OS_Yield( TASK_A_2 );

DPRINTF(( " a2
" ));

OSSAFESetEFlag( OSTEST_RESULT_ECB_P, OSTEST_COMPLETE_A );

DPRINTF(( " a exit
" ));

/* Terminate the task */
OS_Destroy( TASK_A_STOP );
}

void Task_B( void )
{
OStypeState state;
OStypeBinSem binary_sem_state;
OStypeSem current_sem_value;
static OStypeSem original_sem_value;
static int8 done;
static int16 count = 0;

DPRINTF(( "task b
" ));

state = OSGetStateTask( OSTEST_TASK_A_TCB_P );
if( OSTCB_TASK_ELIGIBLE == state )
{
done = 0;
while( !done )
{
original_sem_value = OSReadSem( OSTEST_SEM_A_ECB_P );
if( original_sem_value != 0 )
{
DPRINTF(( " b%d
", count ));

OS_WaitSem( OSTEST_SEM_A_ECB_P, OSNO_TIMEOUT, TASK_B_1 );

DPRINTF(( " b%d
", count ));

binary_sem_state = OSReadBinSem( OSTEST_BINSEM_A_ECB_P );
if( binary_sem_state != 0 )
{
DPRINTF(( " binary sem a signaled
" ));
OSSAFESetEFlag( OSTEST_RESULT_ECB_P, OSTEST_FAILED );
}

current_sem_value = OSReadSem( OSTEST_SEM_A_ECB_P );
if( (current_sem_value + 1) != original_sem_value )
{
DPRINTF(( " unexpected sem a value
" ));
OSSAFESetEFlag( OSTEST_RESULT_ECB_P, OSTEST_FAILED );
}
}
else
{
DPRINTF(( " b final
" ));

OS_WaitSem( OSTEST_SEM_A_ECB_P, OSNO_TIMEOUT, TASK_B_2 );

binary_sem_state = OSReadBinSem( OSTEST_BINSEM_A_ECB_P );
if( binary_sem_state != 1 )
{
DPRINTF(( " binary sem a not signaled
" ));
OSSAFESetEFlag( OSTEST_RESULT_ECB_P, OSTEST_FAILED );
}

current_sem_value = OSReadSem( OSTEST_SEM_A_ECB_P );
if( current_sem_value != 0 )
{
DPRINTF(( " sem a signaled
" ));
OSSAFESetEFlag( OSTEST_RESULT_ECB_P, OSTEST_FAILED );
}

done = 1;
}

count++;
if( count > 256 )
{
DPRINTF(( " too many loops
" ));
OSSAFESetEFlag( OSTEST_RESULT_ECB_P, OSTEST_FAILED );
done = 1;
}
}
}
else
{
DPRINTF(( " task a not eligible
" ));
OSSAFESetEFlag( OSTEST_RESULT_ECB_P, OSTEST_FAILED );
}

OSSAFESetEFlag( OSTEST_RESULT_ECB_P, OSTEST_COMPLETE_B );

DPRINTF(( " b exit
" ));

/* Terminate the task */
OS_Destroy( TASK_B_STOP );
}


The output from the code looks like:

code:
Create two tasks
task a
task b
b0
a1
b0
binary sem a signaled
unexpected sem a value
b1
a2
a exit
b1
binary sem a signaled
b2
b2
binary sem a signaled
b final

Even thought the semaphore was created with a value, when task B waited on the semaphore, taks A was allowed to run.

Is that the expected result?

thanks,
Jeff
jeffc@logicpd.com

jeffc
 
Posts: 8
Joined: Thu Oct 27, 2005 11:00 pm

Re: OS_WaitSem()

Postby aek » Fri Feb 24, 2006 12:41 pm

Hi Jeff.

Every Salvo OS_WaitXyz() call is an unconditional context switch, followed by a re-evaluation of the event's value. This is what enables Salvo to be maximally responsive, and to avoid problems like those explained in SB-12. If it didn't do the context switch first, then an entire application could die if a waiting task's event was being signaled faster than the task could process it. That would clearly be a bad thing, and is one of the reasons why Salvo v3 fixed this problem from Salvo v2.

So, if the sem is non-zero, the task will continue execution after returning to the scheduler if and only if it is the highest-priority task when the semaphore is evaluated as part of the call to OS_WaitSem() (see the macro definition for OS_WaitSem() in salvo.h).

If another task is of equal or higher priority is currently eligible, our task in question will not run until the higher-priority task(s) are no longer eligible, regardless of the value of the semaphore.

Since both tasks were created at the same priority, they are round-robining at that same priority, and execution transfers from one to the other whenever the other is eligible to run.

------------------

[This message has been edited by aek (edited February 24, 2006).]

-------
aek
aek
 
Posts: 1888
Joined: Sat Aug 26, 2000 11:00 pm

Re: OS_WaitSem()

Postby aek » Fri Feb 24, 2006 12:44 pm

quote:
If another task is of equal or higher priority is currently eligible, our task in question will not run until the higher-priority task(s) are no longer eligible, regardless of the value of the semaphore.
If the tasks are at the same priority, they're round-robining, e.g. a,b,a,b,a,b is the execution sequence if task A is created first and task B is created second, and they both yield.

Perhaps the fact that the tasks have the same priority may be confusing you?

------------------

-------
aek
aek
 
Posts: 1888
Joined: Sat Aug 26, 2000 11:00 pm

Re: OS_WaitSem()

Postby jeffc » Fri Feb 24, 2006 12:57 pm

I think that what was confusing me is this quote from the description of OS_WaitSem():

'Wait the current task on a semaphore, with
a timeout. If the semaphore is 0, return to
the scheduler and continue waiting. If the
semaphore is non-zero, decrement the
semaphore and continue.'

It only specifically mentions returning to the scheduler if the semaphore is 0. It sounds like if it's non-zero, it decrements but didn't return to the scheduler.

Now that I understand what's going on, I'm good to go.

thanks,
Jeff
jeffc@logicpd.com

quote:
Originally posted by aek:
[QUOTE]If another task is of equal or higher priority is currently eligible, our task in question will not run until the higher-priority task(s) are no longer eligible, regardless of the value of the semaphore.
If the tasks are at the same priority, they're round-robining, e.g. a,b,a,b,a,b is the execution sequence if task A is created first and task B is created second, and they both yield.

Perhaps the fact that the tasks have the same priority may be confusing you?

[/QUOTE]

jeffc
 
Posts: 8
Joined: Thu Oct 27, 2005 11:00 pm

Re: OS_WaitSem()

Postby aek » Fri Feb 24, 2006 12:58 pm

Hi Jeff.

I have a hard time following your OS macros (sorry, it's just your style vs. my style, I suppose), but after walking through the code,

quote:
Is that the expected result?
Yes, because they're at the same priority.

In order to do your kind of testing without being affected by the round-robining of tasks that run at the same priority, I suggest changing the OS_Yield() calls to OS_Delay(1). That will guarantee that e.g. TaskB() is the only eligible task while waiting the semaphore (TaskA() is delayed), and you'll see the behavior you expect.

Also, one other useful way to test is to call OSSched() in a linear sequence of calls instead of in a main loop. You can then probe / dprintf() / whatever afetr each call to the scheduler to see what's going on. We use that a lot in-house to test stuff. Not suited for when OS_Delay() is involved, though :-(

------------------

[This message has been edited by aek (edited February 24, 2006).]

-------
aek
aek
 
Posts: 1888
Joined: Sat Aug 26, 2000 11:00 pm

Re: OS_WaitSem()

Postby aek » Fri Feb 24, 2006 12:59 pm

quote:
It only specifically mentions returning to the scheduler if the semaphore is 0. It sounds like if it's non-zero, it decrements but didn't return to the scheduler.
I think the references to the unconditional nature of context switches appear in a different part of the manual, probably for historical reasons. I'll see if that can be made more clear.

------------------

-------
aek
aek
 
Posts: 1888
Joined: Sat Aug 26, 2000 11:00 pm


Return to Coding

Who is online

Users browsing this forum: No registered users and 1 guest

cron