ReactOS 0.4.15-dev-7907-g95bf896
_threads.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 1997-1999
3 * Silicon Graphics Computer Systems, Inc.
4 *
5 * Copyright (c) 1999
6 * Boris Fomitchev
7 *
8 * This material is provided "as is", with absolutely no warranty expressed
9 * or implied. Any use is at your own risk.
10 *
11 * Permission to use or copy this software for any purpose is hereby granted
12 * without fee, provided the above notices are retained on all copies.
13 * Permission to modify the code and to distribute modified code is granted,
14 * provided the above notices are retained, and a notice that the code was
15 * modified is included with the above copyright notice.
16 *
17 */
18
19// WARNING: This is an internal header file, included by other C++
20// standard library headers. You should not attempt to use this header
21// file directly.
22
23
24#ifndef _STLP_INTERNAL_THREADS_H
25#define _STLP_INTERNAL_THREADS_H
26
27// Supported threading models are native SGI, pthreads, uithreads
28// (similar to pthreads, but based on an earlier draft of the Posix
29// threads standard), and Win32 threads. Uithread support by Jochen
30// Schlick, 1999, and Solaris threads generalized to them.
31
32#ifndef _STLP_INTERNAL_CSTDDEF
33# include <stl/_cstddef.h>
34#endif
35
36#ifndef _STLP_INTERNAL_CSTDLIB
37# include <stl/_cstdlib.h>
38#endif
39
40// On SUN and Mac OS X gcc, zero-initialization works just fine...
41#if defined (__sun) || (defined (__GNUC__) && defined(__APPLE__))
42# define _STLP_MUTEX_INITIALIZER
43#endif
44
45/* This header defines the following atomic operation that platform should
46 * try to support as much as possible. Atomic operation are exposed as macro
47 * in order to easily test for their existance. They are:
48 * __stl_atomic_t _STLP_ATOMIC_INCREMENT(volatile __stl_atomic_t* __ptr) :
49 * increment *__ptr by 1 and returns the new value
50 * __stl_atomic_t _STLP_ATOMIC_DECREMENT(volatile __stl_atomic_t* __ptr) :
51 * decrement *__ptr by 1 and returns the new value
52 * __stl_atomic_t _STLP_ATOMIC_EXCHANGE(volatile __stl_atomic_t* __target, __stl_atomic_t __val) :
53 * assign __val to *__target and returns former *__target value
54 * void* _STLP_ATOMIC_EXCHANGE_PTR(void* volatile* __target, void* __ptr) :
55 * assign __ptr to *__target and returns former *__target value
56 */
57
58#if defined (_STLP_THREADS)
59
60# if defined (_STLP_SGI_THREADS)
61
62# include <mutex.h>
63// Hack for SGI o32 compilers.
64# if !defined(__add_and_fetch) && \
65 (__mips < 3 || !(defined (_ABIN32) || defined(_ABI64)))
66# define __add_and_fetch(__l,__v) add_then_test((unsigned long*)__l,__v)
67# define __test_and_set(__l,__v) test_and_set(__l,__v)
68# endif /* o32 */
69
70# if __mips < 3 || !(defined (_ABIN32) || defined(_ABI64))
71# define _STLP_ATOMIC_EXCHANGE(__p, __q) test_and_set(__p, __q)
72# else
73# define _STLP_ATOMIC_EXCHANGE(__p, __q) __test_and_set((unsigned long*)__p, (unsigned long)__q)
74# endif
75
76# define _STLP_ATOMIC_INCREMENT(__x) __add_and_fetch(__x, 1)
77# define _STLP_ATOMIC_DECREMENT(__x) __add_and_fetch(__x, (size_t) -1)
78typedef long __stl_atomic_t;
79
80# elif defined (_STLP_PTHREADS)
81
82# include <pthread.h>
83# if !defined (_STLP_USE_PTHREAD_SPINLOCK)
84# if defined (PTHREAD_MUTEX_INITIALIZER) && !defined (_STLP_MUTEX_INITIALIZER) && defined (_REENTRANT)
85# define _STLP_MUTEX_INITIALIZER = { PTHREAD_MUTEX_INITIALIZER }
86# endif
87//HPUX variants have (on some platforms optional) non-standard "DCE" pthreads impl
88# if defined (_DECTHREADS_) && (defined (_PTHREAD_USE_D4) || defined (__hpux)) && !defined (_CMA_SUPPRESS_EXTERNALS_)
89# define _STLP_PTHREAD_ATTR_DEFAULT pthread_mutexattr_default
90# else
91# define _STLP_PTHREAD_ATTR_DEFAULT 0
92# endif
93# else
94# if defined (__OpenBSD__)
95# include <spinlock.h>
96# endif
97# endif
98
99# if defined (__GNUC__) && defined (__i386__)
100# if !defined (_STLP_ATOMIC_INCREMENT)
101inline long _STLP_atomic_increment_gcc_x86(long volatile* p) {
102 long result;
103 __asm__ __volatile__
104 ("lock; xaddl %1, %0;"
105 :"=m" (*p), "=r" (result)
106 :"m" (*p), "1" (1)
107 :"cc");
108 return result + 1;
109}
110# define _STLP_ATOMIC_INCREMENT(__x) (_STLP_atomic_increment_gcc_x86((long volatile*)__x))
111# endif
112
113# if !defined (_STLP_ATOMIC_DECREMENT)
114inline long _STLP_atomic_decrement_gcc_x86(long volatile* p) {
115 long result;
116 __asm__ __volatile__
117 ("lock; xaddl %1, %0;"
118 :"=m" (*p), "=r" (result)
119 :"m" (*p), "1" (-1)
120 :"cc");
121 return result - 1;
122}
123# define _STLP_ATOMIC_DECREMENT(__x) (_STLP_atomic_decrement_gcc_x86((long volatile*)__x))
124# endif
125typedef long __stl_atomic_t;
126# else
127typedef size_t __stl_atomic_t;
128# endif /* if defined(__GNUC__) && defined(__i386__) */
129
130# elif defined (_STLP_WIN32THREADS)
131
132# if !defined (_STLP_ATOMIC_INCREMENT)
133# if !defined (_STLP_NEW_PLATFORM_SDK)
134# define _STLP_ATOMIC_INCREMENT(__x) InterlockedIncrement(__CONST_CAST(long*, __x))
135# define _STLP_ATOMIC_DECREMENT(__x) InterlockedDecrement(__CONST_CAST(long*, __x))
136# define _STLP_ATOMIC_EXCHANGE(__x, __y) InterlockedExchange(__CONST_CAST(long*, __x), __y)
137# else
138# define _STLP_ATOMIC_INCREMENT(__x) InterlockedIncrement(__x)
139# define _STLP_ATOMIC_DECREMENT(__x) InterlockedDecrement(__x)
140# define _STLP_ATOMIC_EXCHANGE(__x, __y) InterlockedExchange(__x, __y)
141# endif
142# define _STLP_ATOMIC_EXCHANGE_PTR(__x, __y) STLPInterlockedExchangePointer(__x, __y)
143# endif
144typedef long __stl_atomic_t;
145
146# elif defined (__DECC) || defined (__DECCXX)
147
148# include <machine/builtins.h>
149# define _STLP_ATOMIC_EXCHANGE __ATOMIC_EXCH_LONG
150# define _STLP_ATOMIC_INCREMENT(__x) __ATOMIC_ADD_LONG(__x, 1)
151# define _STLP_ATOMIC_DECREMENT(__x) __ATOMIC_ADD_LONG(__x, -1)
152typedef long __stl_atomic_t;
153
154# elif defined (_STLP_SPARC_SOLARIS_THREADS)
155
156typedef long __stl_atomic_t;
157# include <stl/_sparc_atomic.h>
158
159# elif defined (_STLP_UITHREADS)
160
161// this inclusion is potential hazard to bring up all sorts
162// of old-style headers. Let's assume vendor already know how
163// to deal with that.
164# ifndef _STLP_INTERNAL_CTIME
165# include <stl/_ctime.h>
166# endif
167# if defined (_STLP_USE_NAMESPACES) && ! defined (_STLP_VENDOR_GLOBAL_CSTD)
168using _STLP_VENDOR_CSTD::time_t;
169# endif
170# include <synch.h>
171# ifndef _STLP_INTERNAL_CSTDIO
172# include <stl/_cstdio.h>
173# endif
174# ifndef _STLP_INTERNAL_CWCHAR
175# include <stl/_cwchar.h>
176# endif
177typedef size_t __stl_atomic_t;
178
179# elif defined (_STLP_BETHREADS)
180
181# include <OS.h>
182# include <cassert>
183# include <stdio.h>
184# define _STLP_MUTEX_INITIALIZER = { 0 }
185typedef size_t __stl_atomic_t;
186
187# elif defined (_STLP_NWTHREADS)
188
189# include <nwthread.h>
190# include <nwsemaph.h>
191typedef size_t __stl_atomic_t;
192
193# elif defined(_STLP_OS2THREADS)
194
195# if defined (__GNUC__)
196# define INCL_DOSSEMAPHORES
197# include <os2.h>
198# else
199// This section serves to replace os2.h for VisualAge C++
200 typedef unsigned long ULONG;
201# if !defined (__HEV__) /* INCL_SEMAPHORE may also define HEV */
202# define __HEV__
203 typedef ULONG HEV;
204 typedef HEV* PHEV;
205# endif
206 typedef ULONG APIRET;
207 typedef ULONG HMTX;
208 typedef HMTX* PHMTX;
209 typedef const char* PCSZ;
210 typedef ULONG BOOL32;
211 APIRET _System DosCreateMutexSem(PCSZ pszName, PHEV phev, ULONG flAttr, BOOL32 fState);
212 APIRET _System DosRequestMutexSem(HMTX hmtx, ULONG ulTimeout);
213 APIRET _System DosReleaseMutexSem(HMTX hmtx);
214 APIRET _System DosCloseMutexSem(HMTX hmtx);
215# define _STLP_MUTEX_INITIALIZER = { 0 }
216# endif /* GNUC */
217typedef size_t __stl_atomic_t;
218
219# else
220
221typedef size_t __stl_atomic_t;
222
223# endif
224
225#else
226/* no threads */
227# define _STLP_ATOMIC_INCREMENT(__x) ++(*__x)
228# define _STLP_ATOMIC_DECREMENT(__x) --(*__x)
229/* We do not grant other atomic operations as they are useless if STLport do not have
230 * to be thread safe
231 */
232typedef size_t __stl_atomic_t;
233#endif
234
235#if !defined (_STLP_MUTEX_INITIALIZER)
236# if defined(_STLP_ATOMIC_EXCHANGE)
237# define _STLP_MUTEX_INITIALIZER = { 0 }
238# elif defined(_STLP_UITHREADS)
239# define _STLP_MUTEX_INITIALIZER = { DEFAULTMUTEX }
240# else
241# define _STLP_MUTEX_INITIALIZER
242# endif
243#endif
244
246
247#if defined (_STLP_THREADS) && !defined (_STLP_USE_PTHREAD_SPINLOCK)
248// Helper struct. This is a workaround for various compilers that don't
249// handle static variables in inline functions properly.
250template <int __inst>
251struct _STLP_mutex_spin {
252 enum { __low_max = 30, __high_max = 1000 };
253 // Low if we suspect uniprocessor, high for multiprocessor.
254 static unsigned __max;
255 static unsigned __last;
256 static void _STLP_CALL _M_do_lock(volatile __stl_atomic_t* __lock);
257 static void _STLP_CALL _S_nsec_sleep(int __log_nsec, unsigned int& __iteration);
258};
259#endif // !_STLP_USE_PTHREAD_SPINLOCK
260
261// Locking class. Note that this class *does not have a constructor*.
262// It must be initialized either statically, with _STLP_MUTEX_INITIALIZER,
263// or dynamically, by explicitly calling the _M_initialize member function.
264// (This is similar to the ways that a pthreads mutex can be initialized.)
265// There are explicit member functions for acquiring and releasing the lock.
266
267// There is no constructor because static initialization is essential for
268// some uses, and only a class aggregate (see section 8.5.1 of the C++
269// standard) can be initialized that way. That means we must have no
270// constructors, no base classes, no virtual functions, and no private or
271// protected members.
272
273// For non-static cases, clients should use _STLP_mutex.
274
276#if defined (_STLP_ATOMIC_EXCHANGE) || defined (_STLP_SGI_THREADS)
277 // It should be relatively easy to get this to work on any modern Unix.
278 volatile __stl_atomic_t _M_lock;
279#endif
280
281#if defined (_STLP_THREADS)
282# if defined (_STLP_ATOMIC_EXCHANGE)
283 inline void _M_initialize() { _M_lock = 0; }
284 inline void _M_destroy() {}
285
286 void _M_acquire_lock() {
287 _STLP_mutex_spin<0>::_M_do_lock(&_M_lock);
288 }
289
290 inline void _M_release_lock() {
291 volatile __stl_atomic_t* __lock = &_M_lock;
292# if defined(_STLP_SGI_THREADS) && defined(__GNUC__) && __mips >= 3
293 asm("sync");
294 *__lock = 0;
295# elif defined(_STLP_SGI_THREADS) && __mips >= 3 && \
296 (defined (_ABIN32) || defined(_ABI64))
297 __lock_release(__lock);
298# elif defined (_STLP_SPARC_SOLARIS_THREADS)
299# if defined (__WORD64) || defined (__arch64__) || defined (__sparcv9) || defined (__sparcv8plus)
300 asm("membar #StoreStore ; membar #LoadStore");
301# else
302 asm(" stbar ");
303# endif
304 *__lock = 0;
305# else
306 *__lock = 0;
307 // This is not sufficient on many multiprocessors, since
308 // writes to protected variables and the lock may be reordered.
309# endif
310 }
311# elif defined (_STLP_PTHREADS)
312# if defined (_STLP_USE_PTHREAD_SPINLOCK)
313# if !defined (__OpenBSD__)
314 pthread_spinlock_t _M_lock;
315 inline void _M_initialize() { pthread_spin_init( &_M_lock, 0 ); }
316 inline void _M_destroy() { pthread_spin_destroy( &_M_lock ); }
317
318 // sorry, but no static initializer for pthread_spinlock_t;
319 // this will not work for compilers that has problems with call
320 // constructor of static object...
321
322 // _STLP_mutex_base()
323 // { pthread_spin_init( &_M_lock, 0 ); }
324
325 // ~_STLP_mutex_base()
326 // { pthread_spin_destroy( &_M_lock ); }
327
328 inline void _M_acquire_lock() { pthread_spin_lock( &_M_lock ); }
329 inline void _M_release_lock() { pthread_spin_unlock( &_M_lock ); }
330# else // __OpenBSD__
331 spinlock_t _M_lock;
332 inline void _M_initialize() { _SPINLOCK_INIT( &_M_lock ); }
333 inline void _M_destroy() { }
334 inline void _M_acquire_lock() { _SPINLOCK( &_M_lock ); }
335 inline void _M_release_lock() { _SPINUNLOCK( &_M_lock ); }
336# endif // __OpenBSD__
337# else // !_STLP_USE_PTHREAD_SPINLOCK
338 pthread_mutex_t _M_lock;
339 inline void _M_initialize()
340 { pthread_mutex_init(&_M_lock,_STLP_PTHREAD_ATTR_DEFAULT); }
341 inline void _M_destroy()
342 { pthread_mutex_destroy(&_M_lock); }
343 inline void _M_acquire_lock() {
344# if defined ( __hpux ) && ! defined (PTHREAD_MUTEX_INITIALIZER)
345 if (!_M_lock.field1) _M_initialize();
346# endif
347 pthread_mutex_lock(&_M_lock);
348 }
349 inline void _M_release_lock() { pthread_mutex_unlock(&_M_lock); }
350# endif // !_STLP_USE_PTHREAD_SPINLOCK
351
352# elif defined (_STLP_UITHREADS)
353 mutex_t _M_lock;
354 inline void _M_initialize()
355 { mutex_init(&_M_lock, 0, NULL); }
356 inline void _M_destroy()
357 { mutex_destroy(&_M_lock); }
358 inline void _M_acquire_lock() { mutex_lock(&_M_lock); }
359 inline void _M_release_lock() { mutex_unlock(&_M_lock); }
360
361# elif defined (_STLP_OS2THREADS)
362 HMTX _M_lock;
363 inline void _M_initialize() { DosCreateMutexSem(NULL, &_M_lock, 0, false); }
364 inline void _M_destroy() { DosCloseMutexSem(_M_lock); }
365 inline void _M_acquire_lock() {
366 if (!_M_lock) _M_initialize();
367 DosRequestMutexSem(_M_lock, SEM_INDEFINITE_WAIT);
368 }
369 inline void _M_release_lock() { DosReleaseMutexSem(_M_lock); }
370# elif defined (_STLP_BETHREADS)
371 sem_id sem;
372 inline void _M_initialize() {
373 sem = create_sem(1, "STLPort");
374 assert(sem > 0);
375 }
376 inline void _M_destroy() {
377 int t = delete_sem(sem);
378 assert(t == B_NO_ERROR);
379 }
380 inline void _M_acquire_lock();
381 inline void _M_release_lock() {
382 status_t t = release_sem(sem);
383 assert(t == B_NO_ERROR);
384 }
385# elif defined (_STLP_NWTHREADS)
386 LONG _M_lock;
387 inline void _M_initialize()
388 { _M_lock = OpenLocalSemaphore(1); }
389 inline void _M_destroy()
390 { CloseLocalSemaphore(_M_lock); }
391 inline void _M_acquire_lock()
392 { WaitOnLocalSemaphore(_M_lock); }
393 inline void _M_release_lock() { SignalLocalSemaphore(_M_lock); }
394# else //*ty 11/24/2001 - added configuration check
395# error "Unknown thread facility configuration"
396# endif
397#else /* No threads */
398 inline void _M_initialize() {}
399 inline void _M_destroy() {}
400 inline void _M_acquire_lock() {}
401 inline void _M_release_lock() {}
402#endif // _STLP_PTHREADS
403};
404
405// Locking class. The constructor initializes the lock, the destructor destroys it.
406// Well - behaving class, does not need static initializer
407
409 public:
410 inline _STLP_mutex () { _M_initialize(); }
411 inline ~_STLP_mutex () { _M_destroy(); }
412 private:
414 void operator=(const _STLP_mutex&);
415};
416
417// A locking class that uses _STLP_STATIC_MUTEX. The constructor takes
418// a reference to an _STLP_STATIC_MUTEX, and acquires a lock. The destructor
419// releases the lock.
420// It's not clear that this is exactly the right functionality.
421// It will probably change in the future.
422
424 _STLP_auto_lock(_STLP_STATIC_MUTEX& __lock) : _M_lock(__lock)
425 { _M_lock._M_acquire_lock(); }
427 { _M_lock._M_release_lock(); }
428
429private:
433};
434
435/*
436 * Class _Refcount_Base provides a type, __stl_atomic_t, a data member,
437 * _M_ref_count, and member functions _M_incr and _M_decr, which perform
438 * atomic preincrement/predecrement. The constructor initializes
439 * _M_ref_count.
440 */
442 // The data member _M_ref_count
443#if defined (__DMC__)
444public:
445#endif
447
448#if defined (_STLP_THREADS) && \
449 (!defined (_STLP_ATOMIC_INCREMENT) || !defined (_STLP_ATOMIC_DECREMENT) || \
450 defined (_STLP_WIN95_LIKE))
451# define _STLP_USE_MUTEX
452 _STLP_mutex _M_mutex;
453#endif
454
455 public:
456 // Constructor
458#if defined (__BORLANDC__)
459 ~_Refcount_Base(){};
460#endif
461
462 // _M_incr and _M_decr
463#if defined (_STLP_THREADS)
464# if !defined (_STLP_USE_MUTEX)
465 __stl_atomic_t _M_incr() { return _STLP_ATOMIC_INCREMENT(&_M_ref_count); }
466 __stl_atomic_t _M_decr() { return _STLP_ATOMIC_DECREMENT(&_M_ref_count); }
467# else
468# undef _STLP_USE_MUTEX
469 __stl_atomic_t _M_incr() {
470 _STLP_auto_lock l(_M_mutex);
471 return ++_M_ref_count;
472 }
473 __stl_atomic_t _M_decr() {
474 _STLP_auto_lock l(_M_mutex);
475 return --_M_ref_count;
476 }
477# endif
478#else /* No threads */
479 __stl_atomic_t _M_incr() { return ++_M_ref_count; }
480 __stl_atomic_t _M_decr() { return --_M_ref_count; }
481#endif
482};
483
484/* Atomic swap on __stl_atomic_t
485 * This is guaranteed to behave as though it were atomic only if all
486 * possibly concurrent updates use _Atomic_swap.
487 * In some cases the operation is emulated with a lock.
488 * Idem for _Atomic_swap_ptr
489 */
490/* Helper struct to handle following cases:
491 * - on platforms where sizeof(__stl_atomic_t) == sizeof(void*) atomic
492 * exchange can be done on pointers
493 * - on platform without atomic operation swap is done in a critical section,
494 * portable but inefficient.
495 */
496template <int __use_ptr_atomic_swap>
498public:
499#if defined (_STLP_THREADS) && \
500 !defined (_STLP_ATOMIC_EXCHANGE) && \
501 (defined (_STLP_PTHREADS) || defined (_STLP_UITHREADS) || defined (_STLP_OS2THREADS) || \
502 defined (_STLP_USE_PTHREAD_SPINLOCK) || defined (_STLP_NWTHREADS))
503# define _STLP_USE_ATOMIC_SWAP_MUTEX
504 static _STLP_STATIC_MUTEX _S_swap_lock;
505#endif
506
508#if defined (_STLP_THREADS)
509# if defined (_STLP_ATOMIC_EXCHANGE)
510 return _STLP_ATOMIC_EXCHANGE(__p, __q);
511# elif defined (_STLP_USE_ATOMIC_SWAP_MUTEX)
512 _S_swap_lock._M_acquire_lock();
513 __stl_atomic_t __result = *__p;
514 *__p = __q;
515 _S_swap_lock._M_release_lock();
516 return __result;
517# else
518# error Missing atomic swap implementation
519# endif
520#else
521 /* no threads */
522 __stl_atomic_t __result = *__p;
523 *__p = __q;
524 return __result;
525#endif // _STLP_THREADS
526 }
527
528 static void* _S_swap_ptr(void* _STLP_VOLATILE* __p, void* __q) {
529#if defined (_STLP_THREADS)
530# if defined (_STLP_ATOMIC_EXCHANGE_PTR)
531 return _STLP_ATOMIC_EXCHANGE_PTR(__p, __q);
532# elif defined (_STLP_ATOMIC_EXCHANGE)
533 _STLP_STATIC_ASSERT(sizeof(__stl_atomic_t) == sizeof(void*))
536 );
537# elif defined (_STLP_USE_ATOMIC_SWAP_MUTEX)
538 _S_swap_lock._M_acquire_lock();
539 void *__result = *__p;
540 *__p = __q;
541 _S_swap_lock._M_release_lock();
542 return __result;
543# else
544# error Missing pointer atomic swap implementation
545# endif
546#else
547 /* no thread */
548 void *__result = *__p;
549 *__p = __q;
550 return __result;
551#endif
552 }
553};
554
557public:
558#if defined (_STLP_THREADS) && \
559 (!defined (_STLP_ATOMIC_EXCHANGE) || !defined (_STLP_ATOMIC_EXCHANGE_PTR)) && \
560 (defined (_STLP_PTHREADS) || defined (_STLP_UITHREADS) || defined (_STLP_OS2THREADS) || \
561 defined (_STLP_USE_PTHREAD_SPINLOCK) || defined (_STLP_NWTHREADS))
562# define _STLP_USE_ATOMIC_SWAP_MUTEX
563 static _STLP_STATIC_MUTEX _S_swap_lock;
564#endif
565
567#if defined (_STLP_THREADS)
568# if defined (_STLP_ATOMIC_EXCHANGE)
569 return _STLP_ATOMIC_EXCHANGE(__p, __q);
570# elif defined (_STLP_USE_ATOMIC_SWAP_MUTEX)
571 /* This should be portable, but performance is expected
572 * to be quite awful. This really needs platform specific
573 * code.
574 */
575 _S_swap_lock._M_acquire_lock();
576 __stl_atomic_t __result = *__p;
577 *__p = __q;
578 _S_swap_lock._M_release_lock();
579 return __result;
580# else
581# error Missing atomic swap implementation
582# endif
583#else
584 /* no threads */
585 __stl_atomic_t __result = *__p;
586 *__p = __q;
587 return __result;
588#endif // _STLP_THREADS
589 }
590
591 static void* _S_swap_ptr(void* _STLP_VOLATILE* __p, void* __q) {
592#if defined (_STLP_THREADS)
593# if defined (_STLP_ATOMIC_EXCHANGE_PTR)
594 return _STLP_ATOMIC_EXCHANGE_PTR(__p, __q);
595# elif defined (_STLP_ATOMIC_EXCHANGE)
596 _STLP_STATIC_ASSERT(sizeof(__stl_atomic_t) == sizeof(void*))
599 );
600# elif defined (_STLP_USE_ATOMIC_SWAP_MUTEX)
601 _S_swap_lock._M_acquire_lock();
602 void *__result = *__p;
603 *__p = __q;
604 _S_swap_lock._M_release_lock();
605 return __result;
606# else
607# error Missing pointer atomic swap implementation
608# endif
609#else
610 /* no thread */
611 void *__result = *__p;
612 *__p = __q;
613 return __result;
614#endif
615 }
616};
617
618#if defined (_STLP_MSVC) && (_STLP_MSVC == 1300)
619# pragma warning (push)
620# pragma warning (disable : 4189) //__use_ptr_atomic_swap initialized but not used
621#endif
622
624 const int __use_ptr_atomic_swap = sizeof(__stl_atomic_t) == sizeof(void*);
626}
627
628inline void* _STLP_CALL _Atomic_swap_ptr(void* _STLP_VOLATILE* __p, void* __q) {
629 const int __use_ptr_atomic_swap = sizeof(__stl_atomic_t) == sizeof(void*);
631}
632
633#if defined (_STLP_MSVC) && (_STLP_MSVC == 1300)
634# pragma warning (pop)
635#endif
636
637#if defined (_STLP_BETHREADS)
638template <int __inst>
639struct _STLP_beos_static_lock_data {
640 static bool is_init;
641 struct mutex_t : public _STLP_mutex {
642 mutex_t()
643 { _STLP_beos_static_lock_data<0>::is_init = true; }
644 ~mutex_t()
645 { _STLP_beos_static_lock_data<0>::is_init = false; }
646 };
647 static mutex_t mut;
648};
649
650template <int __inst>
651bool _STLP_beos_static_lock_data<__inst>::is_init = false;
652template <int __inst>
653typename _STLP_beos_static_lock_data<__inst>::mutex_t _STLP_beos_static_lock_data<__inst>::mut;
654
656 if (sem == 0) {
657 // we need to initialise on demand here
658 // to prevent race conditions use our global
659 // mutex if it's available:
660 if (_STLP_beos_static_lock_data<0>::is_init) {
661 _STLP_auto_lock al(_STLP_beos_static_lock_data<0>::mut);
662 if (sem == 0) _M_initialize();
663 }
664 else {
665 // no lock available, we must still be
666 // in startup code, THERE MUST BE ONE THREAD
667 // ONLY active at this point.
669 }
670 }
671 status_t t;
672 t = acquire_sem(sem);
673 assert(t == B_NO_ERROR);
674}
675#endif
676
678
679#if !defined (_STLP_LINK_TIME_INSTANTIATION)
680# include <stl/_threads.c>
681#endif
682
683#endif /* _STLP_INTERNAL_THREADS_H */
684
685// Local Variables:
686// mode:C++
687// End:
_STLP_INLINE_LOOP _InputIter __last
Definition: _algo.h:68
return __n
Definition: _algo.h:75
#define _STLP_CALL
Definition: _bc.h:131
#define _STLP_ATOMIC_EXCHANGE(__x, __y)
Definition: _sparc_atomic.h:59
#define _STLP_ATOMIC_DECREMENT(__x)
Definition: _sparc_atomic.h:58
#define _STLP_ATOMIC_INCREMENT(__x)
Definition: _sparc_atomic.h:57
size_t __stl_atomic_t
Definition: _threads.h:232
void *_STLP_CALL _Atomic_swap_ptr(void *_STLP_VOLATILE *__p, void *__q)
Definition: _threads.h:628
__stl_atomic_t _STLP_CALL _Atomic_swap(_STLP_VOLATILE __stl_atomic_t *__p, __stl_atomic_t __q)
Definition: _threads.h:623
r l[0]
Definition: byte_order.h:168
static void * _S_swap_ptr(void *_STLP_VOLATILE *__p, void *__q)
Definition: _threads.h:591
static __stl_atomic_t _S_swap(_STLP_VOLATILE __stl_atomic_t *__p, __stl_atomic_t __q)
Definition: _threads.h:566
static __stl_atomic_t _S_swap(_STLP_VOLATILE __stl_atomic_t *__p, __stl_atomic_t __q)
Definition: _threads.h:507
static void * _S_swap_ptr(void *_STLP_VOLATILE *__p, void *__q)
Definition: _threads.h:528
__stl_atomic_t _M_incr()
Definition: _threads.h:479
__stl_atomic_t _M_decr()
Definition: _threads.h:480
_Refcount_Base(__stl_atomic_t __n)
Definition: _threads.h:457
_STLP_VOLATILE __stl_atomic_t _M_ref_count
Definition: _threads.h:446
~_STLP_mutex()
Definition: _threads.h:411
void operator=(const _STLP_mutex &)
_STLP_mutex(const _STLP_mutex &)
#define NULL
Definition: types.h:112
#define _SPINUNLOCK(_lck)
Definition: spinlock.h:56
#define _SPINLOCK(_lck)
Definition: spinlock.h:60
#define assert(x)
Definition: debug.h:53
#define _STLP_TEMPLATE_NULL
Definition: features.h:652
#define __REINTERPRET_CAST(__x, __y)
Definition: features.h:586
#define _STLP_STATIC_ASSERT(expr)
Definition: features.h:313
#define _STLP_VOLATILE
Definition: features.h:277
#define _STLP_STATIC_MUTEX
Definition: features.h:267
#define _STLP_CLASS_DECLSPEC
Definition: features.h:983
#define _STLP_BEGIN_NAMESPACE
Definition: features.h:501
#define _STLP_END_NAMESPACE
Definition: features.h:503
GLdouble GLdouble t
Definition: gl.h:2047
GLfloat GLfloat p
Definition: glext.h:8902
GLuint64EXT * result
Definition: glext.h:11304
#define __max(a, b)
Definition: stdlib.h:101
static HANDLE sem
Definition: sync.c:674
long LONG
Definition: pedump.c:60
__asm__(".p2align 4, 0x90\n" ".seh_proc __seh2_global_filter_func\n" "__seh2_global_filter_func:\n" "\tpush %rbp\n" "\t.seh_pushreg %rbp\n" "\tsub $32, %rsp\n" "\t.seh_stackalloc 32\n" "\t.seh_endprologue\n" "\tmov %rdx, %rbp\n" "\tjmp *%rax\n" "__seh2_global_filter_func_exit:\n" "\t.p2align 4\n" "\tadd $32, %rsp\n" "\tpop %rbp\n" "\tret\n" "\t.seh_endproc")
#define mutex_init(m, a)
Definition: reentrant.h:127
#define mutex_lock(m)
Definition: reentrant.h:128
#define mutex_unlock(m)
Definition: reentrant.h:129
#define mutex_t
Definition: reentrant.h:119
_STLP_auto_lock(_STLP_STATIC_MUTEX &__lock)
Definition: _threads.h:424
_STLP_STATIC_MUTEX & _M_lock
Definition: _threads.h:430
void operator=(const _STLP_auto_lock &)
_STLP_auto_lock(const _STLP_auto_lock &)
void _M_acquire_lock()
Definition: _threads.h:400
void _M_release_lock()
Definition: _threads.h:401
void _M_initialize()
Definition: _threads.h:398
void _M_destroy()
Definition: _threads.h:399
Definition: module.h:456
uint32_t ULONG
Definition: typedefs.h:59
CONST char * PCSZ
Definition: umtypes.h:125