Skip to content

Commit 4fa8d8d

Browse files
authored
Merge pull request #82 from frankeh/TLS
TLS: Thread Local Storage
2 parents 3339b81 + 638372c commit 4fa8d8d

File tree

6 files changed

+159
-9
lines changed

6 files changed

+159
-9
lines changed

configure.ac

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,27 @@ AC_ARG_WITH([swift-toolchain],
108108
AM_CONDITIONAL(HAVE_SWIFT, $have_swift)
109109
AC_SUBST([SWIFTC])
110110

111+
#
112+
# Enable __thread based TSD on platforms where it is efficient
113+
# Allow override based on command line argument to configure
114+
#
115+
AC_CANONICAL_TARGET
116+
AC_ARG_ENABLE([thread-local-storage],
117+
[AS_HELP_STRING([--enable-thread-local-storage],
118+
[Enable usage of thread local storage via __thread])],,
119+
[case $target_os in
120+
linux*)
121+
enable_thread_local_storage=yes
122+
;;
123+
*)
124+
enable_thread_local_storage=no
125+
esac]
126+
)
127+
AS_IF([test "x$enable_thread_local_storage" = "xyes"],
128+
[AC_DEFINE(DISPATCH_USE_THREAD_LOCAL_STORAGE, 1,
129+
[Enable usage of thread local storage via __thread])]
130+
)
131+
111132
AC_USE_SYSTEM_EXTENSIONS
112133
AM_INIT_AUTOMAKE([foreign no-dependencies subdir-objects])
113134
LT_INIT([disable-static])

src/init.c

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,10 @@ void *(*_dispatch_begin_NSAutoReleasePool)(void);
6767
void (*_dispatch_end_NSAutoReleasePool)(void *);
6868
#endif
6969

70-
#if !DISPATCH_USE_DIRECT_TSD
70+
#if DISPATCH_USE_THREAD_LOCAL_STORAGE
71+
__thread struct dispatch_tsd __dispatch_tsd;
72+
pthread_key_t __dispatch_tsd_key;
73+
#elif !DISPATCH_USE_DIRECT_TSD
7174
pthread_key_t dispatch_queue_key;
7275
pthread_key_t dispatch_frame_key;
7376
pthread_key_t dispatch_cache_key;
@@ -82,7 +85,7 @@ pthread_key_t dispatch_bcounter_key;
8285
pthread_key_t dispatch_sema4_key;
8386
pthread_key_t dispatch_voucher_key;
8487
pthread_key_t dispatch_deferred_items_key;
85-
#endif // !DISPATCH_USE_DIRECT_TSD
88+
#endif // !DISPATCH_USE_DIRECT_TSD && !DISPATCH_USE_THREAD_LOCAL_STORAGE
8689

8790
#if VOUCHER_USE_MACH_VOUCHER
8891
dispatch_once_t _voucher_task_mach_voucher_pred;
@@ -184,10 +187,6 @@ const struct dispatch_tsd_indexes_s dispatch_tsd_indexes = {
184187
.dti_voucher_index = dispatch_voucher_key,
185188
.dti_qos_class_index = dispatch_priority_key,
186189
};
187-
#else // DISPATCH_USE_DIRECT_TSD
188-
#ifndef __LINUX_PORT_HDD__
189-
#error Not implemented on this platform
190-
#endif
191190
#endif // DISPATCH_USE_DIRECT_TSD
192191

193192
// 6618342 Contact the team that owns the Instrument DTrace probe before

src/queue.c

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -894,6 +894,9 @@ libdispatch_init(void)
894894
#endif
895895
#endif
896896

897+
#if DISPATCH_USE_THREAD_LOCAL_STORAGE
898+
_dispatch_thread_key_create(&__dispatch_tsd_key, _libdispatch_tsd_cleanup);
899+
#else
897900
_dispatch_thread_key_create(&dispatch_queue_key, _dispatch_queue_cleanup);
898901
_dispatch_thread_key_create(&dispatch_deferred_items_key,
899902
_dispatch_deferred_items_cleanup);
@@ -913,6 +916,7 @@ libdispatch_init(void)
913916
_dispatch_thread_semaphore_dispose);
914917
}
915918
#endif
919+
#endif
916920

917921
#if DISPATCH_USE_RESOLVERS // rdar://problem/8541707
918922
_dispatch_main_q.do_targetq = &_dispatch_root_queues[
@@ -967,6 +971,59 @@ _dispatch_get_mach_host_port(void)
967971
}
968972
#endif
969973

974+
#if DISPATCH_USE_THREAD_LOCAL_STORAGE
975+
#include <unistd.h>
976+
#include <sys/syscall.h>
977+
978+
#ifdef SYS_gettid
979+
DISPATCH_ALWAYS_INLINE
980+
static inline pid_t
981+
gettid(void)
982+
{
983+
return (pid_t) syscall(SYS_gettid);
984+
}
985+
#else
986+
#error "SYS_gettid unavailable on this system"
987+
#endif
988+
989+
#define _tsd_call_cleanup(k, f) do { \
990+
if ((f) && tsd->k) ((void(*)(void*))(f))(tsd->k); \
991+
} while (0)
992+
993+
void
994+
_libdispatch_tsd_cleanup(void *ctx)
995+
{
996+
struct dispatch_tsd *tsd = (struct dispatch_tsd*) ctx;
997+
998+
_tsd_call_cleanup(dispatch_queue_key, _dispatch_queue_cleanup);
999+
_tsd_call_cleanup(dispatch_frame_key, _dispatch_frame_cleanup);
1000+
_tsd_call_cleanup(dispatch_cache_key, _dispatch_cache_cleanup);
1001+
_tsd_call_cleanup(dispatch_context_key, _dispatch_context_cleanup);
1002+
_tsd_call_cleanup(dispatch_pthread_root_queue_observer_hooks_key,
1003+
NULL);
1004+
_tsd_call_cleanup(dispatch_defaultpriority_key, NULL);
1005+
#if DISPATCH_PERF_MON && !DISPATCH_INTROSPECTION
1006+
_tsd_call_cleanup(dispatch_bcounter_key, NULL);
1007+
#endif
1008+
#if DISPATCH_LOCK_USE_SEMAPHORE_FALLBACK
1009+
_tsd_call_cleanup(dispatch_sema4_key, _dispatch_thread_semaphore_dispose);
1010+
#endif
1011+
_tsd_call_cleanup(dispatch_priority_key, NULL);
1012+
_tsd_call_cleanup(dispatch_voucher_key, _voucher_thread_cleanup);
1013+
_tsd_call_cleanup(dispatch_deferred_items_key,
1014+
_dispatch_deferred_items_cleanup);
1015+
tsd->tid = 0;
1016+
}
1017+
1018+
DISPATCH_NOINLINE
1019+
void
1020+
libdispatch_tsd_init(void)
1021+
{
1022+
pthread_setspecific(__dispatch_tsd_key, &__dispatch_tsd);
1023+
__dispatch_tsd.tid = gettid();
1024+
}
1025+
#endif
1026+
9701027
DISPATCH_EXPORT DISPATCH_NOTHROW
9711028
void
9721029
dispatch_atfork_child(void)

src/shims/linux_stubs.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,3 +57,4 @@ unsigned short dispatch_callout__return_semaphore;
5757
unsigned short dispatch_queue__push_semaphore;
5858
void (*_dispatch_block_special_invoke)(void*);
5959
struct dispatch_queue_attr_s _dispatch_queue_attr_concurrent;
60+

src/shims/lock.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,8 @@ typedef pid_t dispatch_lock_owner;
9898
#define DLOCK_OWNER_MASK ((dispatch_lock)FUTEX_TID_MASK)
9999
#define DLOCK_WAITERS_BIT ((dispatch_lock)FUTEX_WAITERS)
100100
#define DLOCK_FAILED_TRYLOCK_BIT ((dispatch_lock)FUTEX_OWNER_DIED)
101-
#define _dispatch_tid_self() syscall(SYS_gettid) /* FIXME: should be cached in TSD instead of doing syscall each time */
101+
#define _dispatch_tid_self() \
102+
((dispatch_lock_owner)(_dispatch_get_tsd_base()->tid))
102103

103104
DISPATCH_ALWAYS_INLINE
104105
static inline bool

src/shims/tsd.h

Lines changed: 73 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,10 +92,76 @@ _dispatch_thread_key_create(const unsigned long *k, void (*d)(void *))
9292
if (!*k || !d) return;
9393
dispatch_assert_zero(pthread_key_init_np((int)*k, d));
9494
}
95+
#elif DISPATCH_USE_THREAD_LOCAL_STORAGE
96+
97+
DISPATCH_TSD_INLINE
98+
static inline void
99+
_dispatch_thread_key_create(pthread_key_t *k, void (*d)(void *))
100+
{
101+
dispatch_assert_zero(pthread_key_create(k, d));
102+
}
103+
104+
struct dispatch_tsd {
105+
pid_t tid;
106+
void *dispatch_queue_key;
107+
void *dispatch_frame_key;
108+
void *dispatch_cache_key;
109+
void *dispatch_context_key;
110+
void *dispatch_pthread_root_queue_observer_hooks_key;
111+
void *dispatch_defaultpriority_key;
112+
#if DISPATCH_INTROSPECTION
113+
void *dispatch_introspection_key;
114+
#elif DISPATCH_PERF_MON
115+
void *dispatch_bcounter_key;
116+
#endif
117+
#if DISPATCH_LOCK_USE_SEMAPHORE_FALLBACK
118+
void *dispatch_sema4_key;
119+
#endif
120+
void *dispatch_priority_key;
121+
void *dispatch_voucher_key;
122+
void *dispatch_deferred_items_key;
123+
};
124+
125+
extern __thread struct dispatch_tsd __dispatch_tsd;
126+
extern pthread_key_t __dispatch_tsd_key;
127+
extern void libdispatch_tsd_init(void);
128+
extern void _libdispatch_tsd_cleanup(void *ctx);
129+
130+
DISPATCH_ALWAYS_INLINE
131+
static inline struct dispatch_tsd *
132+
_dispatch_get_tsd_base(void)
133+
{
134+
if (unlikely(__dispatch_tsd.tid == 0)) {
135+
libdispatch_tsd_init();
136+
}
137+
OS_COMPILER_CAN_ASSUME(__dispatch_tsd.tid != 0);
138+
return &__dispatch_tsd;
139+
}
140+
141+
#define _dispatch_thread_getspecific(key) \
142+
(_dispatch_get_tsd_base()->key)
143+
#define _dispatch_thread_setspecific(key, value) \
144+
(void)(_dispatch_get_tsd_base()->key = (value))
145+
146+
#define _dispatch_thread_getspecific_pair(k1, p1, k2, p2) \
147+
( *(p1) = _dispatch_thread_getspecific(k1), \
148+
*(p2) = _dispatch_thread_getspecific(k2) )
149+
150+
#define _dispatch_thread_getspecific_packed_pair(k1, k2, p) \
151+
( (p)[0] = _dispatch_thread_getspecific(k1), \
152+
(p)[1] = _dispatch_thread_getspecific(k2) )
153+
154+
#define _dispatch_thread_setspecific_pair(k1, p1, k2, p2) \
155+
( _dispatch_thread_setspecific(k1,p1), \
156+
_dispatch_thread_setspecific(k2,p2) )
157+
158+
#define _dispatch_thread_setspecific_packed_pair(k1, k2, p) \
159+
( _dispatch_thread_setspecific(k1,(p)[0]), \
160+
_dispatch_thread_setspecific(k2,(p)[1]) )
161+
95162
#else
96163
extern pthread_key_t dispatch_queue_key;
97164
extern pthread_key_t dispatch_frame_key;
98-
extern pthread_key_t dispatch_sema4_key;
99165
extern pthread_key_t dispatch_cache_key;
100166
extern pthread_key_t dispatch_context_key;
101167
extern pthread_key_t dispatch_pthread_root_queue_observer_hooks_key;
@@ -105,7 +171,8 @@ extern pthread_key_t dispatch_introspection_key;
105171
#elif DISPATCH_PERF_MON
106172
extern pthread_key_t dispatch_bcounter_key;
107173
#endif
108-
extern pthread_key_t dispatch_cache_key;
174+
extern pthread_key_t dispatch_sema4_key;
175+
extern pthread_key_t dispatch_priority_key;
109176
extern pthread_key_t dispatch_voucher_key;
110177
extern pthread_key_t dispatch_deferred_items_key;
111178

@@ -117,6 +184,7 @@ _dispatch_thread_key_create(pthread_key_t *k, void (*d)(void *))
117184
}
118185
#endif
119186

187+
#ifndef DISPATCH_USE_THREAD_LOCAL_STORAGE
120188
DISPATCH_TSD_INLINE
121189
static inline void
122190
_dispatch_thread_setspecific(pthread_key_t k, void *v)
@@ -210,6 +278,7 @@ _dispatch_thread_setspecific_packed_pair(pthread_key_t k1, pthread_key_t k2,
210278
_dispatch_thread_setspecific(k1, p[0]);
211279
_dispatch_thread_setspecific(k2, p[1]);
212280
}
281+
#endif
213282

214283
#if TARGET_OS_WIN32
215284
#define _dispatch_thread_self() ((uintptr_t)GetCurrentThreadId())
@@ -228,6 +297,8 @@ _dispatch_thread_setspecific_packed_pair(pthread_key_t k1, pthread_key_t k2,
228297
#if DISPATCH_USE_DIRECT_TSD
229298
#define _dispatch_thread_port() ((mach_port_t)(uintptr_t)\
230299
_dispatch_thread_getspecific(_PTHREAD_TSD_SLOT_MACH_THREAD_SELF))
300+
#elif DISPATCH_USE_THREAD_LOCAL_STORAGE
301+
#define _dispatch_thread_port() ((mach_port_t)(_dispatch_get_tsd_base()->tid))
231302
#else
232303
#define _dispatch_thread_port() pthread_mach_thread_np(_dispatch_thread_self())
233304
#endif

0 commit comments

Comments
 (0)