vdr-xine: is this code thread safe?

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

while facing deadlocks in xine I've written an emulation of an recursive 
mutex, as xine cannot use non posix extensions to be portable.

The code below seems to work but are there any errors left?
What happens if the thread owning the lock is cancelled?

Feel free to send me your improvements. Thanks!

/*
  * xine_rmutex - xine's recursive mutex emulation
  */

struct xine_rmutex_s {
   pthread_mutex_t            access_rmutex;
   pthread_cond_t             unlock_cond;
   int                        lock_count;
   pthread_t                  lock_owner;
};

typedef struct xine_rmutex_s xine_rmutex_t;

int _x_rmutex_init(xine_rmutex_t *rmutex);
int _x_rmutex_lock(xine_rmutex_t *rmutex);
int _x_rmutex_timedlock(xine_rmutex_t *rmutex, int ms_to_time_out);
int _x_rmutex_unlock(xine_rmutex_t *rmutex);
int _x_rmutex_destroy(xine_rmutex_t *rmutex);

#include "assert.h"

int _x_rmutex_init(xine_rmutex_t *rmutex)
{
   pthread_mutex_init(&rmutex->access_rmutex, 0);
   pthread_cond_init(&rmutex->unlock_cond, 0);
   rmutex->lock_count = 0;

   return 0;
}

int _x_rmutex_lock(xine_rmutex_t *rmutex)
{
   return _x_rmutex_timedlock(rmutex, -1);
}

int _x_rmutex_timedlock(xine_rmutex_t *rmutex, int ms_to_time_out)
{
   int r = 0;

   struct timespec abstime;
   {
     struct timeval now;
     gettimeofday(&now, 0);

     abstime.tv_sec = now.tv_sec + ms_to_time_out / 1000;
     abstime.tv_nsec = now.tv_usec * 1000 + (ms_to_time_out % 1000) * 1e6;

     if (abstime.tv_nsec > 1e9)
     {
       abstime.tv_nsec -= 1e9;
       abstime.tv_sec++;
     }
   }

   pthread_mutex_lock(&rmutex->access_rmutex);

   assert(rmutex->lock_count >= 0);

   while (0 == r
          && rmutex->lock_count > 0
          && !pthread_equal(rmutex->lock_owner, pthread_self()))
   {
     if (ms_to_time_out < 0)
       pthread_cond_wait(&rmutex->unlock_cond, &rmutex->access_rmutex);
     else
       r = pthread_cond_timedwait(&rmutex->unlock_cond, 
&rmutex->access_rmutex, &abstime);
   }

   if (0 == r)
   {
     rmutex->lock_owner = pthread_self();
     rmutex->lock_count++;
   }

   pthread_mutex_unlock(&rmutex->access_rmutex);

   return r;
}

int _x_rmutex_unlock(xine_rmutex_t *rmutex)
{
   int r = 0;

   pthread_mutex_lock(&rmutex->access_rmutex);

   assert(rmutex->lock_count > 0);
   assert(pthread_equal(rmutex->lock_owner, pthread_self()));

   rmutex->lock_count--;

   if (rmutex->lock_count == 0)
     pthread_cond_broadcast(&rmutex->unlock_cond);

   pthread_mutex_unlock(&rmutex->access_rmutex);

   return r;
}

int _x_rmutex_destroy(xine_rmutex_t *rmutex)
{
   pthread_cond_destroy(&rmutex->unlock_cond);
   pthread_mutex_destroy(&rmutex->access_rmutex);

   return 0;
}

Bye.
-- 
Dipl.-Inform. (FH) Reinhard Nissl
mailto:rnissl@xxxxxx


[Index of Archives]     [Linux Media]     [Asterisk]     [DCCP]     [Netdev]     [Xorg]     [Util Linux NG]     [Xfree86]     [Big List of Linux Books]     [Fedora Users]     [Fedora Women]     [ALSA Devel]     [Linux USB]

  Powered by Linux