This is the mail archive of the ecos-discuss@sources.redhat.com mailing list for the eCos project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: pthread_mutex_unlock when mutex is not locked


Ok,
I understand you explain me. The standard also defines that a mutex
locked by a thread must be unlocked by the same thread. However,
many implementations of Pthreads allow use the mutex to signal events
carring out lock and unlock of the mutex from different threads.
But, ok, the DSR is not a thread :-).
An example is the next code, that works with the POSIX compat layer
of eCOS.
N threads are created and executed in differents priority
levels each one of them in SCHED_FIFO policy. The thread th(K)
takes the priority equal to K and locks the pre-locked mutex
m((K-1)%N).
The th(K) also unlocks the mutex m(K) where the th(K+1) is
waiting. So, because the Prio(th(K+1)) > Prio(th(K)) then the
th(K+1) is dispatched at the same time that the th(K) unlocks
the mutex m(K).

#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <sched.h>

#include <prof.h>


#define STACK_SIZE (PTHREAD_STACK_MIN*2) #define NTHREADS 24


static pthread_t thread_id [NTHREADS];
static pthread_mutex_t mutex_id [NTHREADS];
static unsigned long thread_stk[NTHREADS][STACK_SIZE/sizeof(unsigned long)];
static profDeltaT_t clk_data [NTHREADS];




void *thread_fn (void *pdata)
{
 long          pre_index;

pre_index = (((long)pdata-1) < 0)?(NTHREADS-1):((long)pdata -1);

 pthread_mutex_lock(&mutex_id[pre_index]);
 profGetHwClock(&(clk_data[pre_index].end));
 profGetHwClock(&(clk_data[(long)pdata].start));
 pthread_mutex_unlock(&mutex_id[(long)pdata]);

 pthread_exit(pdata);
}


int main (void) { long i; struct sched_param schedparam; pthread_attr_t pthattr; pthread_mutexattr_t mattr;

pthread_mutexattr_init( &mattr );


schedparam.sched_priority = NTHREADS+2; pthread_setschedparam(pthread_self(), SCHED_FIFO, &schedparam);


pthread_attr_init(&pthattr);
pthread_attr_setinheritsched(&pthattr, PTHREAD_EXPLICIT_SCHED);
pthread_attr_setschedpolicy(&pthattr, SCHED_FIFO);
pthread_attr_setdetachstate(&pthattr, PTHREAD_CREATE_JOINABLE);
pthread_attr_setstacksize(&pthattr, STACK_SIZE);
for (i = 0; i < NTHREADS; i++)


{
pthread_mutex_init(&mutex_id[i], &mattr);
pthread_mutex_lock(&mutex_id[i]);
}
profWait4Tick();
for (i = 0; i < NTHREADS; i++)
{
pthread_attr_setstackaddr(&pthattr,
&thread_stk[i][STACK_SIZE/sizeof(unsigned long)]);
schedparam.sched_priority = i+1;
pthread_attr_setschedparam(&pthattr, &schedparam);
pthread_create(&thread_id[i],
&pthattr,
thread_fn,
(void *)i);
}


 profGetHwClock(&(clk_data[NTHREADS-1].start));
 pthread_mutex_unlock(&mutex_id[NTHREADS-1]);


for (i = 0; i < NTHREADS; i++) { pthread_join(thread_id[i], NULL); }

 printf("\n"
        " POSIX LAYER TEST 1: switch thread context\n"
        " when control is transfered through mutexes\n"
        "\n"
       );

 profPrintData((profDeltaT_t*)clk_data, NTHREADS-1, printf);
 return 0;
}


Anothe cuestion. Can I use the next code to guaratee the mutual exclusion in access to critical data from a thread and a DSR?

DSR ()
{
if (pthread_mutex_trylock(&mutex) == 0)
{
// Access to data
// Calculate .....
// Unlock
pthread_mutex_unlock(&mutex);
}
}



Thnak you very much



Nick Garnett wrote:


RubÃn PÃrez de Aranda Alonso <rperez@sidsa.es> writes:



I think the mutex is appropiate for the explained scenario.

The standard says:
"If the mutex type is PTHREAD_MUTEX_RECURSIVE, then the mutex
maintains the concept of a lock count. When a thread successfully
acquires a mutex for the first time, the lock count is set to
one. Every time a thread relocks this mutex, the lock count is
incremented by one. Each time the thread unlocks the mutex, the lock
count is decremented by one. When the lock count reaches zero, the
mutex becomes available for other threads to acquire. If a thread
attempts to unlock a mutex that it has not locked or a mutex which is
unlocked, an error will be returned."

http://www.opengroup.org/onlinepubs/007908799/xsh/pthread_mutex_lock.html

So, I think the unlock method must return an error code. In eCOS, this
method returns void. If we check the mutex is locked at least we avoided the
crash of the system.



eCos doesn't currently support recursive mutexes -- partly because some of us consider them the work of the devil and partly because it would require some significant work on the kernel mutex code to make it work smoothly with the priority inversion protocols.

DSRs are not threads, and can be called in the context of any thread
in the system. Calling mutex unlock from a DSR would do it in the
context of the thread that happened to running when the interrupt
occured. If you are lucky, this will be the thread that locked the
mutex and it will work. If you are unlucky, it will be a different
thread and the mutex will not get unlocked.

Condition variables can be signalled from DSRs and you should really
use one of those to wake up any threads.






--
______________________________________________________________

RubÃn Israel PÃrez de Aranda Alonso
SIDSA - Semiconductores InvestigaciÃn y DiseÃo S.A.
Parque TecnolÃgico de Madrid           Phone : +34 91 803 5052
C/ Torres Quevedo, n 1                Fax:    +34 91 803 9557
28760 TRES CANTOS (Madrid) (SPAIN)
e-mail: rperez@sidsa.com               www.sidsa.com
______________________________________________________________


-- Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]