|
1 /* Basic platform-independent macro definitions for mutexes, |
|
2 thread-specific data and parameters for malloc. |
|
3 Posix threads (pthreads) version. |
|
4 Copyright (C) 2004 Wolfram Gloger <wg@malloc.de>. |
|
5 |
|
6 Permission to use, copy, modify, distribute, and sell this software |
|
7 and its documentation for any purpose is hereby granted without fee, |
|
8 provided that (i) the above copyright notices and this permission |
|
9 notice appear in all copies of the software and related documentation, |
|
10 and (ii) the name of Wolfram Gloger may not be used in any advertising |
|
11 or publicity relating to the software. |
|
12 |
|
13 THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, |
|
14 EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY |
|
15 WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. |
|
16 |
|
17 IN NO EVENT SHALL WOLFRAM GLOGER BE LIABLE FOR ANY SPECIAL, |
|
18 INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY |
|
19 DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, |
|
20 WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY |
|
21 OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR |
|
22 PERFORMANCE OF THIS SOFTWARE. |
|
23 */ |
|
24 |
|
25 #ifndef _PTHREAD_MALLOC_MACHINE_H |
|
26 #define _PTHREAD_MALLOC_MACHINE_H |
|
27 |
|
28 #include <pthread.h> |
|
29 |
|
30 #undef thread_atfork_static |
|
31 |
|
32 /* Use fast inline spinlocks with gcc. */ |
|
33 #if (defined __i386__ || defined __x86_64__) && defined __GNUC__ && \ |
|
34 !defined USE_NO_SPINLOCKS |
|
35 |
|
36 #include <time.h> |
|
37 #include <sched.h> |
|
38 |
|
39 typedef struct { |
|
40 volatile unsigned int lock; |
|
41 int pad0_; |
|
42 } mutex_t; |
|
43 |
|
44 #define MUTEX_INITIALIZER { 0 } |
|
45 #define mutex_init(m) ((m)->lock = 0) |
|
46 static inline int mutex_lock(mutex_t *m) { |
|
47 int cnt = 0, r; |
|
48 struct timespec tm; |
|
49 |
|
50 for(;;) { |
|
51 __asm__ __volatile__ |
|
52 ("xchgl %0, %1" |
|
53 : "=r"(r), "=m"(m->lock) |
|
54 : "0"(1), "m"(m->lock) |
|
55 : "memory"); |
|
56 if(!r) |
|
57 return 0; |
|
58 if(cnt < 50) { |
|
59 sched_yield(); |
|
60 cnt++; |
|
61 } else { |
|
62 tm.tv_sec = 0; |
|
63 tm.tv_nsec = 2000001; |
|
64 nanosleep(&tm, NULL); |
|
65 cnt = 0; |
|
66 } |
|
67 } |
|
68 } |
|
69 static inline int mutex_trylock(mutex_t *m) { |
|
70 int r; |
|
71 |
|
72 __asm__ __volatile__ |
|
73 ("xchgl %0, %1" |
|
74 : "=r"(r), "=m"(m->lock) |
|
75 : "0"(1), "m"(m->lock) |
|
76 : "memory"); |
|
77 return r; |
|
78 } |
|
79 static inline int mutex_unlock(mutex_t *m) { |
|
80 __asm__ __volatile__ ("movl %1, %0" : "=m" (m->lock) : "g"(0) : "memory"); |
|
81 return 0; |
|
82 } |
|
83 |
|
84 #else |
|
85 |
|
86 /* Normal pthread mutex. */ |
|
87 typedef pthread_mutex_t mutex_t; |
|
88 |
|
89 #define MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER |
|
90 #define mutex_init(m) pthread_mutex_init(m, NULL) |
|
91 #define mutex_lock(m) pthread_mutex_lock(m) |
|
92 #define mutex_trylock(m) pthread_mutex_trylock(m) |
|
93 #define mutex_unlock(m) pthread_mutex_unlock(m) |
|
94 |
|
95 #endif /* (__i386__ || __x86_64__) && __GNUC__ && !USE_NO_SPINLOCKS */ |
|
96 |
|
97 /* thread specific data */ |
|
98 #if defined(__sgi) || defined(USE_TSD_DATA_HACK) |
|
99 |
|
100 /* Hack for thread-specific data, e.g. on Irix 6.x. We can't use |
|
101 pthread_setspecific because that function calls malloc() itself. |
|
102 The hack only works when pthread_t can be converted to an integral |
|
103 type. */ |
|
104 |
|
105 typedef void *tsd_key_t[256]; |
|
106 #define tsd_key_create(key, destr) do { \ |
|
107 int i; \ |
|
108 for(i=0; i<256; i++) (*key)[i] = 0; \ |
|
109 } while(0) |
|
110 #define tsd_setspecific(key, data) \ |
|
111 (key[(unsigned)pthread_self() % 256] = (data)) |
|
112 #define tsd_getspecific(key, vptr) \ |
|
113 (vptr = key[(unsigned)pthread_self() % 256]) |
|
114 |
|
115 #else |
|
116 |
|
117 typedef pthread_key_t tsd_key_t; |
|
118 |
|
119 #define tsd_key_create(key, destr) pthread_key_create(key, destr) |
|
120 #define tsd_setspecific(key, data) pthread_setspecific(key, data) |
|
121 #define tsd_getspecific(key, vptr) (vptr = pthread_getspecific(key)) |
|
122 |
|
123 #endif |
|
124 |
|
125 /* at fork */ |
|
126 #define thread_atfork(prepare, parent, child) \ |
|
127 pthread_atfork(prepare, parent, child) |
|
128 |
|
129 #include <sysdeps/generic/malloc-machine.h> |
|
130 |
|
131 #endif /* !defined(_MALLOC_MACHINE_H) */ |