Subversion Repositories Kolibri OS

Rev

Rev 6520 | Go to most recent revision | 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 <kos32sys.h>
  24. #include "gthr-kos32.h"
  25.  
  26. #define FUTEX_INIT      0
  27. #define FUTEX_DESTROY   1
  28. #define FUTEX_WAIT      2
  29. #define FUTEX_WAKE      3
  30.  
  31. #define exchange_acquire(ptr, new) \
  32.   __atomic_exchange_4((ptr), (new), __ATOMIC_ACQUIRE)
  33.  
  34. #define exchange_release(ptr, new) \
  35.   __atomic_exchange_4((ptr), (new), __ATOMIC_RELEASE)
  36.  
  37. int __gthr_kos32_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.             while (! once->done)
  52.                 yield();
  53.         }
  54.     }
  55.     return 0;
  56. };
  57.  
  58. int __gthr_kos32_key_create (__gthread_key_t *key,
  59.                          void (*dtor) (void *) __attribute__((unused)))
  60. {
  61.     int status = 0;
  62.     unsigned int tls_index = tls_alloc();
  63.     if (tls_index != 0xFFFFFFFF)
  64.     {
  65.         *key = tls_index;
  66. #ifdef MINGW32_SUPPORTS_MT_EH
  67.       /* Mingw runtime will run the dtors in reverse order for each thread
  68.          when the thread exits.  */
  69.         status = __mingwthr_key_dtor (*key, dtor);
  70. #endif
  71.     }
  72.     else
  73.         status = -1;
  74.     return status;
  75. }
  76.  
  77. int __gthr_kos32_key_delete (__gthread_key_t key)
  78. {
  79.     return tls_free(key);
  80. }
  81.  
  82. void* __gthr_kos32_getspecific (__gthread_key_t key)
  83. {
  84.     return tls_get(key);
  85. }
  86.  
  87. int __gthr_kos32_setspecific (__gthread_key_t key, const void *ptr)
  88. {
  89.     return tls_set(key, CONST_CAST2(void *, const void *, ptr));
  90. }
  91.  
  92. void __gthr_kos32_mutex_init_function (__gthread_mutex_t *mutex)
  93. {
  94.     int handle;
  95.  
  96.     mutex->lock = 0;
  97.  
  98.     __asm__ volatile(
  99.     "int $0x40\t"
  100.     :"=a"(handle)
  101.     :"a"(77),"b"(FUTEX_INIT),"c"(mutex));
  102.     mutex->handle = handle;
  103. }
  104.  
  105. void __gthr_kos32_mutex_destroy (__gthread_mutex_t *mutex)
  106. {
  107.     int retval;
  108.  
  109.     __asm__ volatile(
  110.     "int $0x40\t"
  111.     :"=a"(retval)
  112.     :"a"(77),"b"(FUTEX_DESTROY),"c"(mutex->handle));
  113. }
  114.  
  115. int __gthr_kos32_mutex_lock (__gthread_mutex_t *mutex)
  116. {
  117.     int tmp;
  118.  
  119.     if( __sync_fetch_and_add(&mutex->lock, 1) == 0)
  120.         return 0;
  121.  
  122.     while (exchange_acquire (&mutex->lock, 2) != 0)
  123.     {
  124.         __asm__ volatile(
  125.         "int $0x40\t\n"
  126.         :"=a"(tmp)
  127.         :"a"(77),"b"(FUTEX_WAIT),
  128.         "c"(mutex->handle),"d"(2),"S"(0));
  129.    }
  130.    return 0;
  131. }
  132.  
  133. int __gthr_kos32_mutex_trylock (__gthread_mutex_t *mutex)
  134. {
  135.     int zero = 0;
  136.  
  137.     return !__atomic_compare_exchange_4(&mutex->lock, &zero, 1,0,__ATOMIC_ACQUIRE,__ATOMIC_RELAXED);
  138. }
  139.  
  140. int __gthr_kos32_mutex_unlock (__gthread_mutex_t *mutex)
  141. {
  142.     int prev;
  143.  
  144.     prev = exchange_release (&mutex->lock, 0);
  145.  
  146.     if (prev != 1)
  147.     {
  148.         __asm__ volatile(
  149.         "int $0x40\t"
  150.         :"=a"(prev)
  151.         :"a"(77),"b"(FUTEX_WAKE),
  152.         "c"(mutex->handle),"d"(1));
  153.     };
  154.     return 0;
  155. }
  156.  
  157. void __gthr_kos32_recursive_mutex_init_function (__gthread_recursive_mutex_t *mutex)
  158. {
  159.     int handle;
  160.  
  161.     mutex->lock = 0;
  162.  
  163.     __asm__ volatile(
  164.     "int $0x40\t"
  165.     :"=a"(handle)
  166.     :"a"(77),"b"(FUTEX_INIT),"c"(mutex));
  167.     mutex->handle = handle;
  168.  
  169.     mutex->depth = 0;
  170.     mutex->owner = 0;
  171. }
  172.  
  173. int __gthr_kos32_recursive_mutex_lock (__gthread_recursive_mutex_t *mutex)
  174. {
  175.     int tmp;
  176.  
  177.     unsigned long me = (unsigned long)tls_get(TLS_KEY_LOW_STACK);
  178.  
  179.     if( __sync_fetch_and_add(&mutex->lock, 1) == 0)
  180.     {
  181.         mutex->depth = 1;
  182.         mutex->owner = me;
  183.         return 0;
  184.     }
  185.     else if (mutex->owner == me)
  186.     {
  187.         __sync_fetch_and_sub(&mutex->lock, 1);
  188.         ++(mutex->depth);
  189.     }
  190.     else while (exchange_acquire (&mutex->lock, 2) != 0)
  191.     {
  192.         __asm__ volatile(
  193.         "int $0x40\t\n"
  194.         :"=a"(tmp)
  195.         :"a"(77),"b"(FUTEX_WAIT),
  196.         "c"(mutex->handle),"d"(2),"S"(0));
  197.         mutex->depth = 1;
  198.         mutex->owner = me;
  199.     };
  200.  
  201.     return 0;
  202. }
  203.  
  204. int __gthr_kos32_recursive_mutex_trylock (__gthread_recursive_mutex_t *mutex)
  205. {
  206.     unsigned long me = (unsigned long)tls_get(TLS_KEY_LOW_STACK);
  207.     int zero = 0;
  208.  
  209.     if(__atomic_compare_exchange_4(&mutex->lock, &zero, 1,0,__ATOMIC_ACQUIRE,__ATOMIC_RELAXED))
  210.     {
  211.         mutex->depth = 1;
  212.         mutex->owner = me;
  213.     }
  214.     else if (mutex->owner == me)
  215.         ++(mutex->depth);
  216.     else
  217.         return 1;
  218.  
  219.     return 0;
  220. }
  221.  
  222. int __gthr_kos32_recursive_mutex_unlock (__gthread_recursive_mutex_t *mutex)
  223. {
  224.     --(mutex->depth);
  225.  
  226.     if (mutex->depth == 0)
  227.     {
  228.         int prev;
  229.  
  230.         prev = exchange_release (&mutex->lock, 0);
  231.  
  232.         if (prev != 1)
  233.         {
  234.             __asm__ volatile(
  235.             "int $0x40\t"
  236.             :"=a"(prev)
  237.             :"a"(77),"b"(FUTEX_WAKE),
  238.             "c"(mutex->handle),"d"(1));
  239.         };
  240.         mutex->owner = 0;
  241.     };
  242.  
  243.     return 0;
  244. }
  245.  
  246. int __gthr_kos32_recursive_mutex_destroy (__gthread_recursive_mutex_t *mutex)
  247. {
  248.     int retval;
  249.  
  250.     __asm__ volatile(
  251.     "int $0x40\t"
  252.     :"=a"(retval)
  253.     :"a"(77),"b"(FUTEX_DESTROY),"c"(mutex->handle));
  254.  
  255.     return 0;
  256. }
  257.  
  258.