Advertisement
Guest User

Untitled

a guest
Nov 2nd, 2022
59
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 22.22 KB | Source Code | 0 0
  1. /* Threads compatibility routines for libgcc2 and libobjc.  */
  2. /* Compile this one with gcc.  */
  3.  
  4. /* Copyright (C) 1999-2022 Free Software Foundation, Inc.
  5.    Contributed by Mumit Khan <khan@xraylith.wisc.edu>.
  6.  
  7. This file is part of GCC.
  8.  
  9. GCC is free software; you can redistribute it and/or modify it under
  10. the terms of the GNU General Public License as published by the Free
  11. Software Foundation; either version 3, or (at your option) any later
  12. version.
  13.  
  14. GCC is distributed in the hope that it will be useful, but WITHOUT ANY
  15. WARRANTY; without even the implied warranty of MERCHANTABILITY or
  16. FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  17. for more details.
  18.  
  19. Under Section 7 of GPL version 3, you are granted additional
  20. permissions described in the GCC Runtime Library Exception, version
  21. 3.1, as published by the Free Software Foundation.
  22.  
  23. You should have received a copy of the GNU General Public License and
  24. a copy of the GCC Runtime Library Exception along with this program;
  25. see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
  26. <http://www.gnu.org/licenses/>.  */
  27.  
  28. #ifndef GCC_GTHR_WIN32_H
  29. #define GCC_GTHR_WIN32_H
  30.  
  31. /* So we can test Windows version numbers.  */
  32. #include <stdlib.h>
  33.  
  34. /* The Windows threading model does not map well into the POSIX inspired
  35.    GCC threading model, so there are caveats one needs to be aware of.
  36.  
  37.    1. The destructor supplied to __gthread_key_create is ignored for
  38.       generic Windows ports.  This will certainly cause memory leaks
  39.       due to unreclaimed EH contexts (sizeof (eh_context) is at least
  40.       24 bytes for x86 currently).
  41.  
  42.       This memory leak may be significant for long-running applications
  43.       that make heavy use of C++ EH.
  44.  
  45.       However, Mingw runtime (version 0.3 or newer) provides a mechanism
  46.       to emulate pthreads key dtors; the runtime provides a special DLL,
  47.       linked in if -mthreads option is specified, that runs the dtors in
  48.       the reverse order of registration when each thread exits. If
  49.       -mthreads option is not given, a stub is linked in instead of the
  50.       DLL, which results in memory leak.  Other Windows ports can use
  51.       the same technique of course to avoid the leak.
  52.  
  53.    2. The error codes returned are non-POSIX like, and cast into ints.
  54.       This may cause incorrect error return due to truncation values on
  55.       hw where sizeof (DWORD) > sizeof (int).
  56.  
  57.    3. POSIX-like condition variables are supported, but only on Vista and
  58.       Server 2008 or later versions.
  59.  
  60.    4. Timed lock primitives are not supported.  */
  61.  
  62. #define __GTHREADS 1
  63.  
  64. /* Condition variables are supported on Vista and Server 2008 or later.  */
  65. #if _WIN32_WINNT >= 0x0600
  66. #define __GTHREAD_HAS_COND 1
  67. #define __GTHREADS_CXX0X 1
  68. #endif
  69.  
  70. #if _GTHREAD_USE_MUTEX_TIMEDLOCK
  71. #error Timed lock primitives are not supported on Windows targets
  72. #endif
  73.  
  74. /* Make sure CONST_CAST2 (origin in system.h) is declared.  */
  75. #ifndef CONST_CAST2
  76. #ifdef __cplusplus
  77. #define CONST_CAST2(TOTYPE,FROMTYPE,X) (const_cast<TOTYPE> (X))
  78. #else
  79. #define CONST_CAST2(TOTYPE,FROMTYPE,X) ((__extension__(union {FROMTYPE _q; TOTYPE _nq;})(X))._nq)
  80. #endif
  81. #endif
  82.  
  83. #ifndef ATTRIBUTE__GLIBCXX_UNUSED
  84. #define ATTRIBUTE__GLIBCXX_UNUSED __attribute__ ((__unused__))
  85. #endif
  86.  
  87. #ifdef _LIBOBJC
  88.  
  89. /* This is necessary to prevent windef.h (included from windows.h) from
  90.    defining its own BOOL as a typedef.  */
  91. #ifndef __OBJC__
  92. #define __OBJC__
  93. #endif
  94. #define WIN32_LEAN_AND_MEAN
  95. #include <windows.h>
  96. /* Now undef the windows BOOL.  */
  97. #undef BOOL
  98.  
  99. /* Key structure for maintaining thread specific storage */
  100. static DWORD __gthread_objc_data_tls = TLS_OUT_OF_INDEXES;
  101.  
  102. /* Backend initialization functions */
  103.  
  104. /* Initialize the threads subsystem.  */
  105. int
  106. __gthread_objc_init_thread_system (void)
  107. {
  108.   /* Initialize the thread storage key.  */
  109.   if ((__gthread_objc_data_tls = TlsAlloc ()) != TLS_OUT_OF_INDEXES)
  110.     return 0;
  111.   else
  112.     return -1;
  113. }
  114.  
  115. /* Close the threads subsystem.  */
  116. int
  117. __gthread_objc_close_thread_system (void)
  118. {
  119.   if (__gthread_objc_data_tls != TLS_OUT_OF_INDEXES)
  120.     TlsFree (__gthread_objc_data_tls);
  121.   return 0;
  122. }
  123.  
  124. /* Backend thread functions */
  125.  
  126. /* Create a new thread of execution.  */
  127. objc_thread_t
  128. __gthread_objc_thread_detach (void (*func)(void *arg), void *arg)
  129. {
  130.   DWORD thread_id = 0;
  131.   HANDLE win32_handle;
  132.  
  133.   if (!(win32_handle = CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE) func,
  134.                      arg, 0, &thread_id)))
  135.     thread_id = 0;
  136.  
  137.   return (objc_thread_t) (INT_PTR) thread_id;
  138. }
  139.  
  140. /* Set the current thread's priority.  */
  141. int
  142. __gthread_objc_thread_set_priority (int priority)
  143. {
  144.   int sys_priority = 0;
  145.  
  146.   switch (priority)
  147.     {
  148.     case OBJC_THREAD_INTERACTIVE_PRIORITY:
  149.       sys_priority = THREAD_PRIORITY_NORMAL;
  150.       break;
  151.     default:
  152.     case OBJC_THREAD_BACKGROUND_PRIORITY:
  153.       sys_priority = THREAD_PRIORITY_BELOW_NORMAL;
  154.       break;
  155.     case OBJC_THREAD_LOW_PRIORITY:
  156.       sys_priority = THREAD_PRIORITY_LOWEST;
  157.       break;
  158.     }
  159.  
  160.   /* Change priority */
  161.   if (SetThreadPriority (GetCurrentThread (), sys_priority))
  162.     return 0;
  163.   else
  164.     return -1;
  165. }
  166.  
  167. /* Return the current thread's priority.  */
  168. int
  169. __gthread_objc_thread_get_priority (void)
  170. {
  171.   int sys_priority;
  172.  
  173.   sys_priority = GetThreadPriority (GetCurrentThread ());
  174.  
  175.   switch (sys_priority)
  176.     {
  177.     case THREAD_PRIORITY_HIGHEST:
  178.     case THREAD_PRIORITY_TIME_CRITICAL:
  179.     case THREAD_PRIORITY_ABOVE_NORMAL:
  180.     case THREAD_PRIORITY_NORMAL:
  181.       return OBJC_THREAD_INTERACTIVE_PRIORITY;
  182.  
  183.     default:
  184.     case THREAD_PRIORITY_BELOW_NORMAL:
  185.       return OBJC_THREAD_BACKGROUND_PRIORITY;
  186.  
  187.     case THREAD_PRIORITY_IDLE:
  188.     case THREAD_PRIORITY_LOWEST:
  189.       return OBJC_THREAD_LOW_PRIORITY;
  190.     }
  191.  
  192.   /* Couldn't get priority.  */
  193.   return -1;
  194. }
  195.  
  196. /* Yield our process time to another thread.  */
  197. void
  198. __gthread_objc_thread_yield (void)
  199. {
  200.   Sleep (0);
  201. }
  202.  
  203. /* Terminate the current thread.  */
  204. int
  205. __gthread_objc_thread_exit (void)
  206. {
  207.   /* exit the thread */
  208.   ExitThread (__objc_thread_exit_status);
  209.  
  210.   /* Failed if we reached here */
  211.   return -1;
  212. }
  213.  
  214. /* Returns an integer value which uniquely describes a thread.  */
  215. objc_thread_t
  216. __gthread_objc_thread_id (void)
  217. {
  218.   return (objc_thread_t) (INT_PTR) GetCurrentThreadId ();
  219. }
  220.  
  221. /* Sets the thread's local storage pointer.  */
  222. int
  223. __gthread_objc_thread_set_data (void *value)
  224. {
  225.   if (TlsSetValue (__gthread_objc_data_tls, value))
  226.     return 0;
  227.   else
  228.     return -1;
  229. }
  230.  
  231. /* Returns the thread's local storage pointer.  */
  232. void *
  233. __gthread_objc_thread_get_data (void)
  234. {
  235.   DWORD lasterror = GetLastError ();
  236.   void * ptr = TlsGetValue (__gthread_objc_data_tls);
  237.   SetLastError (lasterror);
  238.   return ptr;
  239. }
  240.  
  241. /* Backend mutex functions */
  242.  
  243. /* Allocate a mutex.  */
  244. int
  245. __gthread_objc_mutex_allocate (objc_mutex_t mutex)
  246. {
  247.   if ((mutex->backend = (void *) CreateMutex (NULL, 0, NULL)) == NULL)
  248.     return -1;
  249.   else
  250.     return 0;
  251. }
  252.  
  253. /* Deallocate a mutex.  */
  254. int
  255. __gthread_objc_mutex_deallocate (objc_mutex_t mutex)
  256. {
  257.   CloseHandle ((HANDLE) (mutex->backend));
  258.   return 0;
  259. }
  260.  
  261. /* Grab a lock on a mutex.  */
  262. int
  263. __gthread_objc_mutex_lock (objc_mutex_t mutex)
  264. {
  265.   int status;
  266.  
  267.   status = WaitForSingleObject ((HANDLE) (mutex->backend), INFINITE);
  268.   if (status != WAIT_OBJECT_0 && status != WAIT_ABANDONED)
  269.     return -1;
  270.   else
  271.     return 0;
  272. }
  273.  
  274. /* Try to grab a lock on a mutex.  */
  275. int
  276. __gthread_objc_mutex_trylock (objc_mutex_t mutex)
  277. {
  278.   int status;
  279.  
  280.   status = WaitForSingleObject ((HANDLE) (mutex->backend), 0);
  281.   if (status != WAIT_OBJECT_0 && status != WAIT_ABANDONED)
  282.     return -1;
  283.   else
  284.     return 0;
  285. }
  286.  
  287. /* Unlock the mutex */
  288. int
  289. __gthread_objc_mutex_unlock (objc_mutex_t mutex)
  290. {
  291.   if (ReleaseMutex ((HANDLE) (mutex->backend)) == 0)
  292.     return -1;
  293.   else
  294.     return 0;
  295. }
  296.  
  297. /* Backend condition mutex functions */
  298.  
  299. /* Allocate a condition.  */
  300. int
  301. __gthread_objc_condition_allocate (objc_condition_t condition ATTRIBUTE__GLIBCXX_UNUSED)
  302. {
  303.   /* Unimplemented.  */
  304.   return -1;
  305. }
  306.  
  307. /* Deallocate a condition.  */
  308. int
  309. __gthread_objc_condition_deallocate (objc_condition_t condition ATTRIBUTE__GLIBCXX_UNUSED)
  310. {
  311.   /* Unimplemented.  */
  312.   return -1;
  313. }
  314.  
  315. /* Wait on the condition */
  316. int
  317. __gthread_objc_condition_wait (objc_condition_t condition ATTRIBUTE__GLIBCXX_UNUSED,
  318.                    objc_mutex_t mutex ATTRIBUTE__GLIBCXX_UNUSED)
  319. {
  320.   /* Unimplemented.  */
  321.   return -1;
  322. }
  323.  
  324. /* Wake up all threads waiting on this condition.  */
  325. int
  326. __gthread_objc_condition_broadcast (objc_condition_t condition ATTRIBUTE__GLIBCXX_UNUSED)
  327. {
  328.   /* Unimplemented.  */
  329.   return -1;
  330. }
  331.  
  332. /* Wake up one thread waiting on this condition.  */
  333. int
  334. __gthread_objc_condition_signal (objc_condition_t condition ATTRIBUTE__GLIBCXX_UNUSED)
  335. {
  336.   /* Unimplemented.  */
  337.   return -1;
  338. }
  339.  
  340. #else /* _LIBOBJC */
  341.  
  342. /* For struct timespec.  Do not include <sys/time.h> here since Gnulib provides
  343.    its own version which drags the Win32 API definitions.  */
  344. #include <sys/timeb.h>
  345.  
  346. #ifdef __cplusplus
  347. extern "C" {
  348. #endif
  349.  
  350. typedef unsigned int __gthr_win32_DWORD;
  351. typedef void *__gthr_win32_HANDLE;
  352.  
  353. typedef struct {
  354.   void *DebugInfo;
  355.   int LockCount;
  356.   int RecursionCount;
  357.   __gthr_win32_HANDLE OwningThread;
  358.   __gthr_win32_HANDLE LockSemaphore;
  359.   void *SpinCount;
  360. } __gthr_win32_CRITICAL_SECTION;
  361.  
  362. typedef struct {
  363.   void *Ptr;
  364. } __gthr_win32_CONDITION_VARIABLE;
  365.  
  366. typedef __gthr_win32_HANDLE __gthread_t;
  367. typedef __gthr_win32_DWORD __gthread_key_t;
  368. typedef struct { int done; long started; } __gthread_once_t;
  369. typedef __gthr_win32_CRITICAL_SECTION __gthread_mutex_t;
  370. typedef __gthr_win32_CRITICAL_SECTION __gthread_recursive_mutex_t;
  371. #if __GTHREAD_HAS_COND
  372. typedef __gthr_win32_CONDITION_VARIABLE __gthread_cond_t;
  373. #endif
  374. typedef struct timespec __gthread_time_t;
  375.  
  376. #define __GTHREAD_ONCE_INIT {0, -1}
  377. #define __GTHREAD_MUTEX_INIT_FUNCTION __gthread_mutex_init_function
  378. #define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION \
  379.   __gthread_recursive_mutex_init_function
  380. #define __GTHREAD_COND_INIT_FUNCTION __gthread_cond_init_function
  381. #define __GTHREAD_TIME_INIT {0, 0}
  382.  
  383. #if defined (_WIN32) && !defined(__CYGWIN__)
  384. #define MINGW32_SUPPORTS_MT_EH 1
  385. /* Mingw runtime >= v0.3 provides a magic variable that is set to nonzero
  386.    if -mthreads option was specified, or 0 otherwise. This is to get around
  387.    the lack of weak symbols in PE-COFF.  */
  388. extern int _CRT_MT;
  389. extern int __mingwthr_key_dtor (unsigned long, void (*) (void *));
  390. #endif /* _WIN32 && !__CYGWIN__ */
  391.  
  392. /* __GTHR_W32_InterlockedCompareExchange is left over from win95,
  393.    which did not support InterlockedCompareExchange. */
  394. #define __GTHR_W32_InterlockedCompareExchange InterlockedCompareExchange
  395.  
  396. static inline int
  397. __gthread_active_p (void)
  398. {
  399. #ifdef MINGW32_SUPPORTS_MT_EH
  400.   return _CRT_MT;
  401. #else
  402.   return 1;
  403. #endif
  404. }
  405.  
  406. extern int __gthr_win32_create (__gthread_t *, void *(*) (void*), void *);
  407. extern int __gthr_win32_join (__gthread_t, void **);
  408. extern __gthread_t __gthr_win32_self (void);
  409. extern int __gthr_win32_once (__gthread_once_t *, void (*) (void));
  410. extern int __gthr_win32_detach (__gthread_t);
  411. extern int __gthr_win32_equal (__gthread_t, __gthread_t);
  412. extern int __gthr_win32_yield (void);
  413. extern int __gthr_win32_key_create (__gthread_key_t *, void (*) (void*));
  414. extern int __gthr_win32_key_delete (__gthread_key_t);
  415. extern void * __gthr_win32_getspecific (__gthread_key_t);
  416. extern int __gthr_win32_setspecific (__gthread_key_t, const void *);
  417. extern void __gthr_win32_mutex_init_function (__gthread_mutex_t *);
  418. extern void __gthr_win32_mutex_destroy (__gthread_mutex_t *);
  419. extern int __gthr_win32_mutex_lock (__gthread_mutex_t *);
  420. extern int __gthr_win32_mutex_trylock (__gthread_mutex_t *);
  421. extern int __gthr_win32_mutex_unlock (__gthread_mutex_t *);
  422. extern int __gthr_win32_recursive_mutex_trylock (__gthread_recursive_mutex_t *);
  423. #if __GTHREAD_HAS_COND
  424. extern void __gthr_win32_cond_init_function (__gthread_cond_t *);
  425. extern int __gthr_win32_cond_broadcast (__gthread_cond_t *);
  426. extern int __gthr_win32_cond_signal (__gthread_cond_t *);
  427. extern int __gthr_win32_cond_wait (__gthread_cond_t *, __gthread_mutex_t *);
  428. extern int __gthr_win32_cond_timedwait (__gthread_cond_t *, __gthread_mutex_t *,
  429.                     const __gthread_time_t *);
  430. #endif
  431.  
  432. static inline int
  433. __gthread_create (__gthread_t *__thr, void *(*__func) (void*),
  434.           void *__args)
  435. {
  436.   return __gthr_win32_create (__thr, __func, __args);
  437. }
  438.  
  439. static inline int
  440. __gthread_join (__gthread_t __thr, void **__value_ptr)
  441. {
  442.   return __gthr_win32_join (__thr, __value_ptr);
  443. }
  444.  
  445. static inline __gthread_t
  446. __gthread_self (void)
  447. {
  448.   return __gthr_win32_self ();
  449. }
  450.  
  451. #if __GTHREAD_HIDE_WIN32API
  452.  
  453. /* The implementations are in config/i386/gthr-win32.c in libgcc.a.
  454.    Only stubs are exposed to avoid polluting the C++ namespace with
  455.    Win32 API definitions.  */
  456.  
  457. static inline int
  458. __gthread_detach (__gthread_t __thr)
  459. {
  460.   return __gthr_win32_detach (__thr);
  461. }
  462.  
  463. static inline int
  464. __gthread_equal (__gthread_t __thr1, __gthread_t __thr2)
  465. {
  466.   return __gthr_win32_equal (__thr1, __thr2);
  467. }
  468.  
  469. static inline int
  470. __gthread_yield (void)
  471. {
  472.   return __gthr_win32_yield ();
  473. }
  474.  
  475. static inline int
  476. __gthread_once (__gthread_once_t *__once, void (*__func) (void))
  477. {
  478.   if (__gthread_active_p ())
  479.     return __gthr_win32_once (__once, __func);
  480.   else
  481.     return -1;
  482. }
  483.  
  484. static inline int
  485. __gthread_key_create (__gthread_key_t *__key, void (*__dtor) (void *))
  486. {
  487.   return __gthr_win32_key_create (__key, __dtor);
  488. }
  489.  
  490. static inline int
  491. __gthread_key_delete (__gthread_key_t __key)
  492. {
  493.   return __gthr_win32_key_delete (__key);
  494. }
  495.  
  496. static inline void *
  497. __gthread_getspecific (__gthread_key_t __key)
  498. {
  499.   return __gthr_win32_getspecific (__key);
  500. }
  501.  
  502. static inline int
  503. __gthread_setspecific (__gthread_key_t __key, const void *__ptr)
  504. {
  505.   return __gthr_win32_setspecific (__key, __ptr);
  506. }
  507.  
  508. static inline void
  509. __gthread_mutex_init_function (__gthread_mutex_t *__mutex)
  510. {
  511.   __gthr_win32_mutex_init_function (__mutex);
  512. }
  513.  
  514. static inline void
  515. __gthread_mutex_destroy (__gthread_mutex_t *__mutex)
  516. {
  517.   __gthr_win32_mutex_destroy (__mutex);
  518. }
  519.  
  520. static inline int
  521. __gthread_mutex_lock (__gthread_mutex_t *__mutex)
  522. {
  523.   if (__gthread_active_p ())
  524.     return __gthr_win32_mutex_lock (__mutex);
  525.   else
  526.     return 0;
  527. }
  528.  
  529. static inline int
  530. __gthread_mutex_trylock (__gthread_mutex_t *__mutex)
  531. {
  532.   if (__gthread_active_p ())
  533.     return __gthr_win32_mutex_trylock (__mutex);
  534.   else
  535.     return 0;
  536. }
  537.  
  538. static inline int
  539. __gthread_mutex_unlock (__gthread_mutex_t *__mutex)
  540. {
  541.   if (__gthread_active_p ())
  542.     return __gthr_win32_mutex_unlock (__mutex);
  543.   else
  544.     return 0;
  545. }
  546.  
  547. static inline int
  548. __gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *__mutex)
  549. {
  550.   if (__gthread_active_p ())
  551.     return __gthr_win32_recursive_mutex_trylock (__mutex);
  552.   else
  553.     return 0;
  554. }
  555.  
  556. #if __GTHREAD_HAS_COND
  557.  
  558. static inline void
  559. __gthread_cond_init_function (__gthread_cond_t *__cond)
  560. {
  561.   __gthr_win32_cond_init_function (__cond);
  562. }
  563.  
  564. static inline int
  565. __gthread_cond_broadcast (__gthread_cond_t *__cond)
  566. {
  567.   return __gthr_win32_cond_broadcast (__cond);
  568. }
  569.  
  570. static inline int
  571. __gthread_cond_signal (__gthread_cond_t *__cond)
  572. {
  573.   return __gthr_win32_cond_signal (__cond);
  574. }
  575.  
  576. static inline int
  577. __gthread_cond_wait (__gthread_cond_t *__cond, __gthread_mutex_t *__mutex)
  578. {
  579.   return __gthr_win32_cond_wait (__cond, __mutex);
  580. }
  581.  
  582. static inline int
  583. __gthread_cond_timedwait (__gthread_cond_t *__cond, __gthread_mutex_t *__mutex,
  584.               const __gthread_time_t *__abs_time)
  585. {
  586.   return __gthr_win32_cond_timedwait (__cond, __mutex, __abs_time);
  587. }
  588.  
  589. #endif /* __GTHREAD_HAS_COND */
  590.  
  591. #else /* ! __GTHREAD_HIDE_WIN32API */
  592.  
  593. #ifndef __GTHREAD_WIN32_INLINE
  594. #define __GTHREAD_WIN32_INLINE static inline
  595. #endif
  596.  
  597. #ifndef __GTHREAD_WIN32_COND_INLINE
  598. #define __GTHREAD_WIN32_COND_INLINE static inline
  599. #endif
  600.  
  601. #ifndef __GTHREAD_WIN32_ACTIVE_P
  602. #define __GTHREAD_WIN32_ACTIVE_P __gthread_active_p
  603. #endif
  604.  
  605. #define WIN32_LEAN_AND_MEAN
  606. #include <windows.h>
  607.  
  608. __GTHREAD_WIN32_INLINE int
  609. __gthread_detach (__gthread_t __thr)
  610. {
  611.   CloseHandle ((HANDLE) __thr);
  612.   return 0;
  613. }
  614.  
  615. __GTHREAD_WIN32_INLINE int
  616. __gthread_equal (__gthread_t __t1, __gthread_t __t2)
  617. {
  618.   return GetThreadId ((HANDLE) __t1) == GetThreadId ((HANDLE) __t2);
  619. }
  620.  
  621. __GTHREAD_WIN32_INLINE int
  622. __gthread_yield (void)
  623. {
  624.   Sleep (0);
  625.   return 0;
  626. }
  627.  
  628. __GTHREAD_WIN32_INLINE int
  629. __gthread_once (__gthread_once_t *__once, void (*__func) (void))
  630. {
  631.   if (!__GTHREAD_WIN32_ACTIVE_P ())
  632.     return -1;
  633.  
  634.   if (__builtin_expect (!__once->done, 0))
  635.     {
  636.       /* We rely on the memory model of the x86 architecture where every load
  637.      has acquire semantics and every store has release semantics.  */
  638.       if (__atomic_add_fetch (&__once->started, 1, __ATOMIC_ACQ_REL) == 0)
  639.     {
  640.       (*__func) ();
  641.       __once->done = 1;
  642.     }
  643.       else
  644.     {
  645.       /* Another thread is currently executing the code, so wait for it
  646.          to finish and yield the CPU in the meantime.  If performance
  647.          does become an issue, the solution is to use an Event that
  648.          we wait on here (and set above), but that implies a place to
  649.          create the event before this routine is called.  */
  650.       while (!__once->done)
  651.         __gthread_yield ();
  652.     }
  653.     }
  654.  
  655.   return 0;
  656. }
  657.  
  658. /* Windows thread local keys don't support destructors; this leads to
  659.    leaks, especially in threaded applications making extensive use of
  660.    C++ EH. Mingw uses a thread-support DLL to work-around this problem.  */
  661. __GTHREAD_WIN32_INLINE int
  662. __gthread_key_create (__gthread_key_t *__key,
  663.               void (*__dtor) (void *) ATTRIBUTE__GLIBCXX_UNUSED)
  664. {
  665.   DWORD __tls_index = TlsAlloc ();
  666.   if (__tls_index != TLS_OUT_OF_INDEXES)
  667.     {
  668.       *__key = __tls_index;
  669. #ifdef MINGW32_SUPPORTS_MT_EH
  670.       /* Mingw runtime will run the dtors in reverse order for each thread
  671.          when the thread exits.  */
  672.       return __mingwthr_key_dtor (*__key, __dtor);
  673. #else
  674.       return 0;
  675. #endif
  676.     }
  677.   else
  678.     return (int) GetLastError ();
  679. }
  680.  
  681. __GTHREAD_WIN32_INLINE int
  682. __gthread_key_delete (__gthread_key_t __key)
  683. {
  684.   if (TlsFree (__key))
  685.     return 0;
  686.   else
  687.     return (int) GetLastError ();
  688. }
  689.  
  690. __GTHREAD_WIN32_INLINE void *
  691. __gthread_getspecific (__gthread_key_t __key)
  692. {
  693.   DWORD __lasterror = GetLastError ();
  694.   void *__ptr = TlsGetValue (__key);
  695.   SetLastError (__lasterror);
  696.   return __ptr;
  697. }
  698.  
  699. __GTHREAD_WIN32_INLINE int
  700. __gthread_setspecific (__gthread_key_t __key, const void *__ptr)
  701. {
  702.   if (TlsSetValue (__key, CONST_CAST2(void *, const void *, __ptr)))
  703.     return 0;
  704.   else
  705.     return (int) GetLastError ();
  706. }
  707.  
  708. __GTHREAD_WIN32_INLINE void
  709. __gthread_mutex_init_function (__gthread_mutex_t *__mutex)
  710. {
  711.   InitializeCriticalSection ((LPCRITICAL_SECTION) __mutex);
  712. }
  713.  
  714. __GTHREAD_WIN32_INLINE void
  715. __gthread_mutex_destroy (__gthread_mutex_t *__mutex)
  716. {
  717.   DeleteCriticalSection ((LPCRITICAL_SECTION) __mutex);
  718. }
  719.  
  720. __GTHREAD_WIN32_INLINE int
  721. __gthread_mutex_lock (__gthread_mutex_t *__mutex)
  722. {
  723.   if (__GTHREAD_WIN32_ACTIVE_P ())
  724.     EnterCriticalSection ((LPCRITICAL_SECTION) __mutex);
  725.   return 0;
  726. }
  727.  
  728. __GTHREAD_WIN32_INLINE int
  729. __gthread_mutex_trylock (__gthread_mutex_t *__mutex)
  730. {
  731.   if (__GTHREAD_WIN32_ACTIVE_P ())
  732.     {
  733.       BOOL __ret = TryEnterCriticalSection ((LPCRITICAL_SECTION) __mutex);
  734.       if (__ret)
  735.     {
  736.       if (__mutex->RecursionCount > 1)
  737.         {
  738.           LeaveCriticalSection ((LPCRITICAL_SECTION) __mutex);
  739.           return 1;
  740.         }
  741.       else
  742.         return 0;
  743.     }
  744.       else
  745.     return 1;
  746.     }
  747.   else
  748.     return 0;
  749. }
  750.  
  751. __GTHREAD_WIN32_INLINE int
  752. __gthread_mutex_unlock (__gthread_mutex_t *__mutex)
  753. {
  754.   if (__GTHREAD_WIN32_ACTIVE_P ())
  755.     LeaveCriticalSection ((LPCRITICAL_SECTION) __mutex);
  756.   return 0;
  757. }
  758.  
  759. __GTHREAD_WIN32_INLINE int
  760. __gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *__mutex)
  761. {
  762.   if (__GTHREAD_WIN32_ACTIVE_P ())
  763.     return TryEnterCriticalSection ((LPCRITICAL_SECTION) __mutex) ? 0 : 1;
  764.   else
  765.     return 0;
  766. }
  767.  
  768. #if __GTHREAD_HAS_COND
  769.  
  770. __GTHREAD_WIN32_COND_INLINE void
  771. __gthread_cond_init_function (__gthread_cond_t *__cond)
  772. {
  773.   InitializeConditionVariable ((PCONDITION_VARIABLE) __cond);
  774. }
  775.  
  776. __GTHREAD_WIN32_COND_INLINE int
  777. __gthread_cond_broadcast (__gthread_cond_t *__cond)
  778. {
  779.   WakeAllConditionVariable ((PCONDITION_VARIABLE) __cond);
  780.   return 0;
  781. }
  782.  
  783. __GTHREAD_WIN32_COND_INLINE int
  784. __gthread_cond_signal (__gthread_cond_t *__cond)
  785. {
  786.   WakeConditionVariable ((PCONDITION_VARIABLE) __cond);
  787.   return 0;
  788. }
  789.  
  790. __GTHREAD_WIN32_COND_INLINE int
  791. __gthread_cond_wait (__gthread_cond_t *__cond, __gthread_mutex_t *__mutex)
  792. {
  793.   if (SleepConditionVariableCS ((PCONDITION_VARIABLE) __cond,
  794.                 (PCRITICAL_SECTION) __mutex,
  795.                 INFINITE))
  796.     return 0;
  797.   else
  798.     return (int) GetLastError ();
  799. }
  800.  
  801. extern DWORD __gthr_win32_abs_to_rel_time (const __gthread_time_t *);
  802.  
  803. __GTHREAD_WIN32_COND_INLINE int
  804. __gthread_cond_timedwait (__gthread_cond_t *__cond,
  805.               __gthread_mutex_t *__mutex,
  806.               const __gthread_time_t *__abs_time)
  807. {
  808.   DWORD __rel_time = __gthr_win32_abs_to_rel_time (__abs_time);
  809.   if (SleepConditionVariableCS ((PCONDITION_VARIABLE) __cond,
  810.                 (PCRITICAL_SECTION) __mutex,
  811.                 __rel_time))
  812.     return 0;
  813.   else
  814.     return (int) GetLastError ();
  815. }
  816.  
  817. #endif /* __GTHREAD_HAS_COND */
  818.  
  819. #endif /*  __GTHREAD_HIDE_WIN32API */
  820.  
  821. static inline void
  822. __gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *__mutex)
  823. {
  824.   __gthread_mutex_init_function (__mutex);
  825. }
  826.  
  827. static inline void
  828. __gthread_recursive_mutex_destroy (__gthread_recursive_mutex_t *__mutex)
  829. {
  830.   __gthread_mutex_destroy (__mutex);
  831. }
  832.  
  833. static inline int
  834. __gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *__mutex)
  835. {
  836.   return __gthread_mutex_lock (__mutex);
  837. }
  838.  
  839. static inline int
  840. __gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *__mutex)
  841. {
  842.   return __gthread_mutex_unlock (__mutex);
  843. }
  844.  
  845. #if __GTHREAD_HAS_COND
  846.  
  847. static inline int
  848. __gthread_cond_destroy (__gthread_cond_t *__cond ATTRIBUTE__GLIBCXX_UNUSED)
  849. {
  850.   return 0;
  851. }
  852.  
  853. static inline int
  854. __gthread_cond_wait_recursive (__gthread_cond_t *__cond,
  855.                    __gthread_recursive_mutex_t *__mutex)
  856. {
  857.   return __gthread_cond_wait (__cond, __mutex);
  858. }
  859.  
  860. #endif
  861.  
  862. #ifdef __cplusplus
  863. }
  864. #endif
  865.  
  866. #endif /* _LIBOBJC */
  867.  
  868. #endif /* ! GCC_GTHR_WIN32_H */
  869.  
Tags: C++
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement