xref: /trueos/lib/libdispatch/src/shims/tsd.h (revision 4f5f2a926b26b32a0f94957c91acff6a94f18b06)
1 /*
2  * Copyright (c) 2008-2013 Apple Inc. All rights reserved.
3  *
4  * @APPLE_APACHE_LICENSE_HEADER_START@
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  * @APPLE_APACHE_LICENSE_HEADER_END@
19  */
20 
21 /*
22  * IMPORTANT: This header file describes INTERNAL interfaces to libdispatch
23  * which are subject to change in future releases of Mac OS X. Any applications
24  * relying on these interfaces WILL break.
25  */
26 
27 #ifndef __DISPATCH_SHIMS_TSD__
28 #define __DISPATCH_SHIMS_TSD__
29 
30 #if HAVE_PTHREAD_MACHDEP_H
31 #include <pthread_machdep.h>
32 #endif
33 
34 #define DISPATCH_TSD_INLINE DISPATCH_ALWAYS_INLINE_NDEBUG
35 
36 #if USE_APPLE_TSD_OPTIMIZATIONS && HAVE_PTHREAD_KEY_INIT_NP && \
37 	!defined(DISPATCH_USE_DIRECT_TSD)
38 #define DISPATCH_USE_DIRECT_TSD 1
39 #if __has_include(<os/tsd.h>)
40 #include <os/tsd.h>
41 #endif
42 #endif
43 
44 #if DISPATCH_USE_DIRECT_TSD
45 static const unsigned long dispatch_queue_key		= __PTK_LIBDISPATCH_KEY0;
46 static const unsigned long dispatch_voucher_key		= __PTK_LIBDISPATCH_KEY1;
47 static const unsigned long dispatch_cache_key		= __PTK_LIBDISPATCH_KEY2;
48 static const unsigned long dispatch_io_key			= __PTK_LIBDISPATCH_KEY3;
49 static const unsigned long dispatch_apply_key		= __PTK_LIBDISPATCH_KEY4;
50 static const unsigned long dispatch_defaultpriority_key =__PTK_LIBDISPATCH_KEY5;
51 #if DISPATCH_INTROSPECTION
52 static const unsigned long dispatch_introspection_key =__PTK_LIBDISPATCH_KEY5+1;
53 #elif DISPATCH_PERF_MON
54 static const unsigned long dispatch_bcounter_key	= __PTK_LIBDISPATCH_KEY5+1;
55 #endif
56 #if DISPATCH_USE_OS_SEMAPHORE_CACHE
57 static const unsigned long dispatch_sema4_key		= __TSD_SEMAPHORE_CACHE;
58 #else
59 static const unsigned long dispatch_sema4_key		= __PTK_LIBDISPATCH_KEY5+2;
60 #endif
61 
62 #ifndef __TSD_THREAD_QOS_CLASS
63 #define __TSD_THREAD_QOS_CLASS 4
64 #endif
65 static const unsigned long dispatch_priority_key	= __TSD_THREAD_QOS_CLASS;
66 
67 DISPATCH_TSD_INLINE
68 static inline void
_dispatch_thread_key_create(const unsigned long * k,void (* d)(void *))69 _dispatch_thread_key_create(const unsigned long *k, void (*d)(void *))
70 {
71 	if (!*k || !d) return;
72 	dispatch_assert_zero(pthread_key_init_np((int)*k, d));
73 }
74 #else
75 extern pthread_key_t dispatch_queue_key;
76 extern pthread_key_t dispatch_voucher_key;
77 #if DISPATCH_USE_OS_SEMAPHORE_CACHE
78 #error "Invalid DISPATCH_USE_OS_SEMAPHORE_CACHE configuration"
79 #else
80 extern pthread_key_t dispatch_sema4_key;
81 #endif
82 extern pthread_key_t dispatch_cache_key;
83 extern pthread_key_t dispatch_io_key;
84 extern pthread_key_t dispatch_apply_key;
85 extern pthread_key_t dispatch_defaultpriority_key;
86 #if DISPATCH_INTROSPECTION
87 extern pthread_key_t dispatch_introspection_key;
88 #elif DISPATCH_PERF_MON
89 extern pthread_key_t dispatch_bcounter_key;
90 #endif
91 
92 
93 DISPATCH_TSD_INLINE
94 static inline void
_dispatch_thread_key_create(pthread_key_t * k,void (* d)(void *))95 _dispatch_thread_key_create(pthread_key_t *k, void (*d)(void *))
96 {
97 	dispatch_assert_zero(pthread_key_create(k, d));
98 }
99 #endif
100 
101 #if DISPATCH_USE_TSD_BASE && !DISPATCH_DEBUG
102 #else // DISPATCH_USE_TSD_BASE
103 DISPATCH_TSD_INLINE
104 static inline void
_dispatch_thread_setspecific(pthread_key_t k,void * v)105 _dispatch_thread_setspecific(pthread_key_t k, void *v)
106 {
107 #if DISPATCH_USE_DIRECT_TSD
108 	if (_pthread_has_direct_tsd()) {
109 		(void)_pthread_setspecific_direct(k, v);
110 		return;
111 	}
112 #endif
113 	dispatch_assert_zero(pthread_setspecific(k, v));
114 }
115 
116 DISPATCH_TSD_INLINE
117 static inline void *
_dispatch_thread_getspecific(pthread_key_t k)118 _dispatch_thread_getspecific(pthread_key_t k)
119 {
120 #if DISPATCH_USE_DIRECT_TSD
121 	if (_pthread_has_direct_tsd()) {
122 		return _pthread_getspecific_direct(k);
123 	}
124 #endif
125 	return pthread_getspecific(k);
126 }
127 #endif // DISPATCH_USE_TSD_BASE
128 
129 #if TARGET_OS_WIN32
130 #define _dispatch_thread_self() ((uintptr_t)GetCurrentThreadId())
131 #else
132 #if DISPATCH_USE_DIRECT_TSD
133 #define _dispatch_thread_self() ((uintptr_t)_dispatch_thread_getspecific( \
134 		_PTHREAD_TSD_SLOT_PTHREAD_SELF))
135 #else
136 #define _dispatch_thread_self() ((uintptr_t)pthread_self())
137 #endif
138 #endif
139 
140 #if TARGET_OS_WIN32
141 #define _dispatch_thread_port() ((mach_port_t)0)
142 #else
143 #if DISPATCH_USE_DIRECT_TSD
144 #define _dispatch_thread_port() ((mach_port_t)_dispatch_thread_getspecific(\
145 		_PTHREAD_TSD_SLOT_MACH_THREAD_SELF))
146 #else
147 #define _dispatch_thread_port() (pthread_mach_thread_np(_dispatch_thread_self()))
148 #endif
149 #endif
150 
151 DISPATCH_TSD_INLINE DISPATCH_CONST
152 static inline unsigned int
_dispatch_cpu_number(void)153 _dispatch_cpu_number(void)
154 {
155 #ifdef __FreeBSD__
156 	return 0; // XXX: I don't know any easy way to get current CPU number
157 #endif
158 #if TARGET_IPHONE_SIMULATOR && IPHONE_SIMULATOR_HOST_MIN_VERSION_REQUIRED < 1090
159 	return 0;
160 #elif __has_include(<os/tsd.h>)
161 	return _os_cpu_number();
162 #elif defined(__x86_64__) || defined(__i386__)
163 	struct { uintptr_t p1, p2; } p;
164 	__asm__("sidt %[p]" : [p] "=&m" (p));
165 	return (unsigned int)(p.p1 & 0xfff);
166 #else
167 	// Not yet implemented.
168 	return 0;
169 #endif
170 }
171 
172 #undef DISPATCH_TSD_INLINE
173 
174 #endif
175