Subversion Repositories Kolibri OS

Rev

Rev 6540 | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. /* Implementation of Kos32-specific threads compatibility routines for
  2.    libgcc2.
  3.  
  4. GCC is free software; you can redistribute it and/or modify it under
  5. the terms of the GNU General Public License as published by the Free
  6. Software Foundation; either version 3, or (at your option) any later
  7. version.
  8.  
  9. GCC is distributed in the hope that it will be useful, but WITHOUT ANY
  10. WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11. FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12. for more details.
  13.  
  14. Under Section 7 of GPL version 3, you are granted additional
  15. permissions described in the GCC Runtime Library Exception, version
  16. 3.1, as published by the Free Software Foundation.
  17.  
  18. You should have received a copy of the GNU General Public License and
  19. a copy of the GCC Runtime Library Exception along with this program;
  20. see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
  21. <http://www.gnu.org/licenses/>.  */
  22.  
  23. #include <errno.h>
  24. #include <stdint.h>
  25. #include <sys/ksys.h>
  26. #include "gthr-kos32.h"
  27.  
  28. #define FUTEX_INIT      0
  29. #define FUTEX_DESTROY   1
  30. #define FUTEX_WAIT      2
  31. #define FUTEX_WAKE      3
  32.  
  33. #define exchange_acquire(ptr, new) \
  34.   __atomic_exchange_4((ptr), (new), __ATOMIC_ACQUIRE)
  35.  
  36. #define exchange_release(ptr, new) \
  37.   __atomic_exchange_4((ptr), (new), __ATOMIC_RELEASE)
  38.  
  39. #define TLS_KEY_PID         0
  40. #define TLS_KEY_TID         4
  41. #define TLS_KEY_LOW_STACK   8
  42. #define TLS_KEY_HIGH_STACK 12
  43. #define TLS_KEY_LIBC       16
  44.  
  45. unsigned int tls_alloc(void);
  46. int tls_free(unsigned int key);
  47.  
  48. static inline int tls_set(unsigned int key, void *val)
  49. {
  50.     int ret = -1;
  51.     if(key < 4096)
  52.     {
  53.         __asm__ __volatile__(
  54.         "movl %0, %%fs:(%1)"
  55.         ::"r"(val),"r"(key));
  56.         ret = 0;
  57.     }
  58.     return ret;
  59. };
  60.  
  61. static inline void *tls_get(unsigned int key)
  62. {
  63.     void *val = (void*)-1;
  64.     if(key < 4096)
  65.     {
  66.         __asm__ __volatile__(
  67.         "movl %%fs:(%1), %0"
  68.         :"=r"(val)
  69.         :"r"(key));
  70.     };
  71.     return val;
  72. }
  73.  
  74.  
  75. int __gthr_kos32_once (__gthread_once_t *once, void (*func) (void))
  76. {
  77.     if (once == NULL || func == NULL)
  78.         return EINVAL;
  79.  
  80.     if (! once->done)
  81.     {
  82.         if (__sync_add_and_fetch(&(once->started), 1) == 0)
  83.         {
  84.             (*func) ();
  85.             once->done = 1;
  86.         }
  87.         else
  88.         {
  89.             while (! once->done)
  90.                 _ksys_thread_yield();
  91.         }
  92.     }
  93.     return 0;
  94. };
  95.  
  96. int __gthr_kos32_key_create (__gthread_key_t *key,
  97.                          void (*dtor) (void *) __attribute__((unused)))
  98. {
  99.     int status = 0;
  100.     unsigned int tls_index = tls_alloc();
  101.     if (tls_index != 0xFFFFFFFF)
  102.     {
  103.         *key = tls_index;
  104. #ifdef MINGW32_SUPPORTS_MT_EH
  105.       /* Mingw runtime will run the dtors in reverse order for each thread
  106.          when the thread exits.  */
  107.         status = __mingwthr_key_dtor (*key, dtor);
  108. #endif
  109.     }
  110.     else
  111.         status = -1;
  112.     return status;
  113. }
  114.  
  115. int __gthr_kos32_key_delete (__gthread_key_t key)
  116. {
  117.     return tls_free(key);
  118. }
  119.  
  120. void* __gthr_kos32_getspecific (__gthread_key_t key)
  121. {
  122.     return tls_get(key);
  123. }
  124.  
  125. int __gthr_kos32_setspecific (__gthread_key_t key, const void *ptr)
  126. {
  127.     return tls_set(key, CONST_CAST2(void *, const void *, ptr));
  128. }
  129.  
  130. void __gthr_kos32_mutex_init_function (__gthread_mutex_t *mutex)
  131. {
  132.     mutex->lock = 0;
  133.     mutex->handle  = _ksys_futex_create(mutex);
  134. }
  135.  
  136. void __gthr_kos32_mutex_destroy (__gthread_mutex_t *mutex)
  137. {
  138.     int retval;
  139.     _ksys_futex_destroy(mutex->handle);
  140. }
  141.  
  142. int __gthr_kos32_mutex_lock (__gthread_mutex_t *mutex)
  143. {
  144.     int tmp;
  145.  
  146.     if( __sync_fetch_and_add(&mutex->lock, 1) == 0)
  147.         return 0;
  148.  
  149.     while (exchange_acquire (&mutex->lock, 2) != 0)
  150.     {
  151.         _ksys_futex_wait(mutex->handle, 2 , 0);
  152.     }
  153.     return 0;
  154. }
  155.  
  156. int __gthr_kos32_mutex_trylock (__gthread_mutex_t *mutex)
  157. {
  158.     int zero = 0;
  159.  
  160.     return !__atomic_compare_exchange_4(&mutex->lock, &zero, 1,0,__ATOMIC_ACQUIRE,__ATOMIC_RELAXED);
  161. }
  162.  
  163. int __gthr_kos32_mutex_unlock (__gthread_mutex_t *mutex)
  164. {
  165.     int prev;
  166.  
  167.     prev = exchange_release (&mutex->lock, 0);
  168.  
  169.     if (prev != 1)
  170.     {
  171.         _ksys_futex_wake(mutex->handle, 1);
  172.     };
  173.     return 0;
  174. }
  175.  
  176. void __gthr_kos32_recursive_mutex_init_function (__gthread_recursive_mutex_t *mutex)
  177. {
  178.     int handle;
  179.     mutex->lock = 0;
  180.  
  181.     mutex->handle = _ksys_futex_create(mutex);
  182.  
  183.     mutex->depth = 0;
  184.     mutex->owner = 0;
  185. }
  186.  
  187. int __gthr_kos32_recursive_mutex_lock (__gthread_recursive_mutex_t *mutex)
  188. {
  189.     int tmp;
  190.  
  191.     unsigned long me = (unsigned long)tls_get(TLS_KEY_LOW_STACK);
  192.  
  193.     if( __sync_fetch_and_add(&mutex->lock, 1) == 0)
  194.     {
  195.         mutex->depth = 1;
  196.         mutex->owner = me;
  197.         return 0;
  198.     }
  199.     else if (mutex->owner == me)
  200.     {
  201.         __sync_fetch_and_sub(&mutex->lock, 1);
  202.         ++(mutex->depth);
  203.     }
  204.     else while (exchange_acquire (&mutex->lock, 2) != 0)
  205.     {
  206.         _ksys_futex_wait(mutex->handle, 2, 0);
  207.         mutex->depth = 1;
  208.         mutex->owner = me;
  209.     };
  210.  
  211.     return 0;
  212. }
  213.  
  214. int __gthr_kos32_recursive_mutex_trylock (__gthread_recursive_mutex_t *mutex)
  215. {
  216.     unsigned long me = (unsigned long)tls_get(TLS_KEY_LOW_STACK);
  217.     int zero = 0;
  218.  
  219.     if(__atomic_compare_exchange_4(&mutex->lock, &zero, 1,0,__ATOMIC_ACQUIRE,__ATOMIC_RELAXED))
  220.     {
  221.         mutex->depth = 1;
  222.         mutex->owner = me;
  223.     }
  224.     else if (mutex->owner == me)
  225.         ++(mutex->depth);
  226.     else
  227.         return 1;
  228.  
  229.     return 0;
  230. }
  231.  
  232. int __gthr_kos32_recursive_mutex_unlock (__gthread_recursive_mutex_t *mutex)
  233. {
  234.     --(mutex->depth);
  235.  
  236.     if (mutex->depth == 0)
  237.     {
  238.         int prev;
  239.  
  240.         prev = exchange_release (&mutex->lock, 0);
  241.  
  242.         if (prev != 1)
  243.         {
  244.             _ksys_futex_wake(mutex->handle, 1);
  245.         };
  246.         mutex->owner = 0;
  247.     };
  248.  
  249.     return 0;
  250. }
  251.  
  252. int __gthr_kos32_recursive_mutex_destroy (__gthread_recursive_mutex_t *mutex)
  253. {
  254.     int retval;
  255.     _ksys_futex_destroy(mutex->handle);
  256.     return 0;
  257. }
  258.  
  259.