Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. #include <stdlib.h>
  2. #include <sys/errno.h>
  3. #include <kos32sys.h>
  4.  
  5. void __mutex_lock(volatile int *val);
  6.  
  7. static inline int tls_get(int key)
  8. {
  9.     int val;
  10.     __asm__ __volatile__(
  11.     "movl %%fs:(%1), %0"
  12.     :"=r"(val)
  13.     :"r"(key));
  14.  
  15.   return val;
  16. };
  17.  
  18. typedef struct {
  19.   int done;
  20.   long started;
  21. } __gthread_once_t;
  22.  
  23. typedef struct {
  24.   int counter;
  25.   void *sema;
  26. } __gthread_mutex_t;
  27.  
  28. typedef struct {
  29.   int counter;
  30.   int depth;
  31.   unsigned long owner;
  32.   int sema;
  33. } __gthread_recursive_mutex_t;
  34.  
  35.  
  36. int
  37. __gthr_win32_once (__gthread_once_t *once, void (*func) (void))
  38. {
  39.     if (once == NULL || func == NULL)
  40.         return EINVAL;
  41.  
  42.     if (! once->done)
  43.     {
  44.         if (__sync_add_and_fetch (&(once->started), 1) == 0)
  45.         {
  46.             (*func) ();
  47.             once->done = 1;
  48.         }
  49.         else
  50.         {
  51.           /* Another thread is currently executing the code, so wait for it
  52.              to finish; yield the CPU in the meantime.  If performance
  53.              does become an issue, the solution is to use an Event that
  54.              we wait on here (and set above), but that implies a place to
  55.              create the event before this routine is called.  */
  56.             while (! once->done)
  57.                 delay(1);
  58.         }
  59.     }
  60.     return 0;
  61. }
  62.  
  63. void __gthr_win32_mutex_init_function (__gthread_mutex_t *mutex)
  64. {
  65.   mutex->counter = 0;
  66.   mutex->sema = 0;
  67. }
  68.  
  69. int __gthr_win32_mutex_lock (__gthread_mutex_t *mutex)
  70. {
  71.     __mutex_lock(&mutex->counter);
  72.     return 0;
  73. }
  74.  
  75. int
  76. __gthr_win32_mutex_unlock (__gthread_mutex_t *mutex)
  77. {
  78.   mutex->counter = 0;
  79.   return 0;
  80. }
  81.  
  82. void
  83. __gthr_win32_recursive_mutex_init_function (__gthread_recursive_mutex_t *mutex)
  84. {
  85.   mutex->counter = -1;
  86.   mutex->depth = 0;
  87.   mutex->owner = 0;
  88.   mutex->sema = 0;
  89. }
  90.  
  91. void
  92. __gthr_win32_mutex_destroy (__gthread_mutex_t *mutex)
  93. { }
  94.  
  95. int
  96. __gthr_win32_recursive_mutex_lock (__gthread_recursive_mutex_t *mutex)
  97. {
  98.     int me = tls_get(0);
  99.     if ( __sync_add_and_fetch(&mutex->counter, 1) == 0)
  100.     {
  101.         mutex->depth = 1;
  102.         mutex->owner = me;
  103.         mutex->sema  = 1;
  104.     }
  105.     else if (mutex->owner == me)
  106.     {
  107.         __sync_sub_and_fetch(&mutex->counter, 1);
  108.         ++(mutex->depth);
  109.     }
  110.     else
  111.     {
  112.         __mutex_lock(&mutex->sema);
  113.         mutex->depth = 1;
  114.         mutex->owner = me;
  115.     }
  116.     return 0;
  117. }
  118.  
  119. int
  120. __gthr_win32_recursive_mutex_trylock (__gthread_recursive_mutex_t *mutex)
  121. {
  122.     int me = tls_get(0);
  123.     if (__sync_val_compare_and_swap (&mutex->counter, -1, 0) < 0)
  124.     {
  125.         mutex->depth = 1;
  126.         mutex->owner = me;
  127.         mutex->sema  = 1;
  128.     }
  129.     else if (mutex->owner == me)
  130.         ++(mutex->depth);
  131.     else
  132.         return 1;
  133.  
  134.   return 0;
  135. }
  136.  
  137. int
  138. __gthr_win32_recursive_mutex_unlock (__gthread_recursive_mutex_t *mutex)
  139. {
  140.     --(mutex->depth);
  141.     if (mutex->depth == 0)
  142.     {
  143.         mutex->owner = 0;
  144.  
  145.         if (__sync_sub_and_fetch (&mutex->counter, 1) >= 0)
  146.             mutex->sema = 0;
  147.     }
  148.  
  149.     return 0;
  150. }
  151.