Вопрос

I have run a sample C++ program on vxWorks platform to test the timing difference between mutex and a binary semaphore. The below program is the prototype

SEM ID semMutex;
UINT ITER = 10000;
taskIdOne = TASKSPAWN("t1",TASK_PRIORITY_2,0,8192,0,(FUNCPTR)myMutexMethod,0,0);
taskIdTwo = TASKSPAWN("t2",TASK_PRIORITY_2,0,8192,0,(FUNCPTR)myMutexMethod,0,0);
void myMutexMethod(void)
    {
        int i;
        VKI_PRINTF("I'm  (%s)\n",TASKNAME(0) );
        myMutexTimer.start();
        for (i=0; i < ITER; i++)
        {
            MUTEX_LOCK(semMutex,WAIT_FOREVER); 
            ++global;                     
            MUTEX_UNLOCK(semMutex); 
        } 
        myMutexTimer.stop();
        myMutexTimer.show();
    }

In the above program there is a contention ( 2 tasks are trying to get the mutex). my timer printed 37.43 ms for the above program. With the same prototype, binary semaphore program took just 2.8 ms. This is understood because binary semaphore is lightweight and does not have many features like a mutex (priority inversion, ownership etc).

However, I removed one task and ran the above program ( without contention). Since there is no contention, the task t1 just gets the mutex , executes the critical section and then releases the mutex. Same with Binary semaphore.
For the timings, mutex I got 3.35 ms and binary semaphore 4 ms.

I'm surprised to see mutex is faster than binary semaphore when there is no contention.
Is this expected? or am I missing something?

Any help is appreciated. !

Это было полезно?

Решение

The mutex is probably faster in this case due to the fact that the same task is taking it over and over again with no other task getting involved. My guess is that mutex code is taking a shortcut to enable recursive mutex calls (i.e. the same task takes the same mutex twice). Even though your code is not technically a recursive mutex take, the code probably uses the same shortcut due to the fact that the semaphore owner was not overwritten by any other task taking the semaphore.

In other words you do:

1) semTake(semMutex)
2) ++global;
3) semGive(semMutex) // sem owner flag is not changed
4) sameTake(semMutex) // from same task as previous semTake
...

Then in step 4 the semTake sees that sem owner == current task id (because the sem owner was set in step 1 and never changed to anything else), so it just marks the semaphore as taken and quickly jumps out.

Of course this is a guess, a quick look at the source code and some vxworks shell breakpoints could confirm this, something I am unable to do because I no longer have access to vxworks.

Additionally look at the semMLib docs for some documentation on the recursive use of mutex.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top