-
Notifications
You must be signed in to change notification settings - Fork 471
introduce usage of thread local storage structure #44
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -913,6 +913,60 @@ _dispatch_root_queues_init(void *context DISPATCH_UNUSED) | |
|
||
#define countof(x) (sizeof(x) / sizeof(x[0])) | ||
|
||
#if DISPATCH_USE_THREAD_LOCAL_STORAGE | ||
#include <unistd.h> | ||
#include <sys/syscall.h> | ||
|
||
#ifdef SYS_gettid | ||
DISPATCH_ALWAYS_INLINE | ||
static inline pid_t | ||
gettid(void) | ||
{ | ||
return (pid_t) syscall(SYS_gettid); | ||
} | ||
#else | ||
#error "SYS_gettid unavailable on this system" | ||
#endif | ||
|
||
#define _tsd_call_cleanup(k, f) do { \ | ||
if (f && tsd->k) ((void(*)(void*))(f))(tsd->k); \ | ||
} while (0) | ||
|
||
static void | ||
_libdispatch_tsd_cleanup(void *ctx) | ||
{ | ||
struct dispatch_tsd *tsd = (struct dispatch_tsd*) ctx; | ||
|
||
_tsd_call_cleanup(dispatch_queue_key, _dispatch_queue_cleanup); | ||
_tsd_call_cleanup(dispatch_voucher_key, _voucher_thread_cleanup); | ||
_tsd_call_cleanup(dispatch_cache_key, _dispatch_cache_cleanup); | ||
_tsd_call_cleanup(dispatch_io_key, NULL); | ||
_tsd_call_cleanup(dispatch_apply_key, NULL); | ||
_tsd_call_cleanup(dispatch_defaultpriority_key, NULL); | ||
_tsd_call_cleanup(dispatch_pthread_root_queue_observer_hooks_key, | ||
NULL); | ||
#if DISPATCH_PERF_MON && !DISPATCH_INTROSPECTION | ||
_tsd_call_cleanup(dispatch_bcounter_key, NULL); | ||
#endif | ||
#if !DISPATCH_USE_OS_SEMAPHORE_CACHE | ||
_tsd_call_cleanup(dispatch_sema4_key, | ||
(void (*)(void *))_dispatch_thread_semaphore_dispose); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why the cast? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. code take from other case to maintain code symmetry: |
||
#endif | ||
tsd->tid = -1; | ||
tsd->initialized = false; | ||
} | ||
|
||
DISPATCH_EXPORT DISPATCH_NOINLINE | ||
void | ||
libdispatch_tsd_init(void) | ||
{ | ||
__dispatch_tsd.tid = gettid(); | ||
pthread_setspecific(__dispatch_tsd_key, &__dispatch_tsd); | ||
__dispatch_tsd.initialized = true; | ||
} | ||
|
||
#endif | ||
|
||
DISPATCH_EXPORT DISPATCH_NOTHROW | ||
void | ||
libdispatch_init(void) | ||
|
@@ -951,6 +1005,9 @@ libdispatch_init(void) | |
dispatch_assert(sizeof(struct dispatch_root_queue_context_s) % | ||
DISPATCH_CACHELINE_SIZE == 0); | ||
|
||
#if DISPATCH_USE_THREAD_LOCAL_STORAGE | ||
_dispatch_thread_key_create(&__dispatch_tsd_key, _libdispatch_tsd_cleanup); | ||
#else | ||
_dispatch_thread_key_create(&dispatch_queue_key, _dispatch_queue_cleanup); | ||
_dispatch_thread_key_create(&dispatch_voucher_key, _voucher_thread_cleanup); | ||
_dispatch_thread_key_create(&dispatch_cache_key, _dispatch_cache_cleanup); | ||
|
@@ -966,6 +1023,7 @@ libdispatch_init(void) | |
_dispatch_thread_key_create(&dispatch_sema4_key, | ||
(void (*)(void *))_dispatch_thread_semaphore_dispose); | ||
#endif | ||
#endif | ||
|
||
#if DISPATCH_USE_RESOLVERS // rdar://problem/8541707 | ||
_dispatch_main_q.do_targetq = &_dispatch_root_queues[ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -53,8 +53,9 @@ char* mach_error_string(mach_msg_return_t x) { | |
void mach_vm_deallocate() { LINUX_PORT_ERROR(); } | ||
|
||
mach_port_t pthread_mach_thread_np(void) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. and you can probably get rid of that guy |
||
return (pid_t)syscall(SYS_gettid); | ||
return (mach_port_t)pthread_self(); | ||
} | ||
|
||
mach_port_t mach_task_self(void) { | ||
return (mach_port_t)pthread_self(); | ||
} | ||
|
@@ -72,3 +73,8 @@ unsigned short dispatch_timer__fire_semaphore; | |
unsigned short dispatch_timer__configure_semaphore; | ||
void (*_dispatch_block_special_invoke)(void*); | ||
struct dispatch_queue_attr_s _dispatch_queue_attr_concurrent; | ||
|
||
#if DISPATCH_USE_THREAD_LOCAL_STORAGE | ||
__thread struct dispatch_tsd __dispatch_tsd; | ||
pthread_key_t __dispatch_tsd_key; | ||
#endif |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -73,6 +73,56 @@ _dispatch_thread_key_create(const unsigned long *k, void (*d)(void *)) | |
if (!*k || !d) return; | ||
dispatch_assert_zero(pthread_key_init_np((int)*k, d)); | ||
} | ||
#elif DISPATCH_USE_THREAD_LOCAL_STORAGE | ||
|
||
DISPATCH_TSD_INLINE | ||
static inline void | ||
_dispatch_thread_key_create(pthread_key_t *k, void (*d)(void *)) | ||
{ | ||
dispatch_assert_zero(pthread_key_create(k, d)); | ||
} | ||
|
||
struct dispatch_tsd { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. style nits for this struct:
|
||
bool initialized; | ||
pid_t tid; | ||
void *dispatch_queue_key; | ||
void *dispatch_voucher_key; | ||
#if DISPATCH_USE_OS_SEMAPHORE_CACHE | ||
#error "Invalid DISPATCH_USE_OS_SEMAPHORE_CACHE configuration" | ||
#else | ||
void *dispatch_sema4_key; | ||
#endif | ||
void *dispatch_cache_key; | ||
void *dispatch_io_key; | ||
void *dispatch_apply_key; | ||
void *dispatch_defaultpriority_key; | ||
#if DISPATCH_INTROSPECTION | ||
void *dispatch_introspection_key; | ||
#elif DISPATCH_PERF_MON | ||
void *dispatch_bcounter_key; | ||
#endif | ||
void *dispatch_pthread_root_queue_observer_hooks_key; | ||
}; | ||
|
||
extern __thread struct dispatch_tsd __dispatch_tsd; | ||
extern pthread_key_t __dispatch_tsd_key; | ||
extern void libdispatch_tsd_init(void); | ||
|
||
DISPATCH_ALWAYS_INLINE | ||
static inline struct dispatch_tsd * | ||
_dispatch_get_tsd_base(void) | ||
{ | ||
if (slowpath(!__dispatch_tsd.initialized)) { | ||
libdispatch_tsd_init(); | ||
} | ||
return &__dispatch_tsd; | ||
} | ||
|
||
#define _dispatch_thread_getspecific(key) \ | ||
(_dispatch_get_tsd_base()->key) | ||
#define _dispatch_thread_setspecific(key, value) \ | ||
(void)(_dispatch_get_tsd_base()->key = (value)) | ||
|
||
#else | ||
extern pthread_key_t dispatch_queue_key; | ||
extern pthread_key_t dispatch_voucher_key; | ||
|
@@ -100,7 +150,7 @@ _dispatch_thread_key_create(pthread_key_t *k, void (*d)(void *)) | |
} | ||
#endif | ||
|
||
#if DISPATCH_USE_TSD_BASE && !DISPATCH_DEBUG | ||
#if (DISPATCH_USE_TSD_BASE && !DISPATCH_DEBUG) || DISPATCH_USE_THREAD_LOCAL_STORAGE | ||
#else // DISPATCH_USE_TSD_BASE | ||
DISPATCH_TSD_INLINE | ||
static inline void | ||
|
@@ -134,6 +184,8 @@ _dispatch_thread_getspecific(pthread_key_t k) | |
#if DISPATCH_USE_DIRECT_TSD | ||
#define _dispatch_thread_self() ((uintptr_t)_dispatch_thread_getspecific( \ | ||
_PTHREAD_TSD_SLOT_PTHREAD_SELF)) | ||
#elif DISPATCH_USE_THREAD_LOCAL_STORAGE | ||
#define _dispatch_thread_self() ((uintptr_t)pthread_self()) | ||
#else | ||
#define _dispatch_thread_self() ((uintptr_t)pthread_self()) | ||
#endif | ||
|
@@ -145,6 +197,8 @@ _dispatch_thread_getspecific(pthread_key_t k) | |
#if DISPATCH_USE_DIRECT_TSD | ||
#define _dispatch_thread_port() ((mach_port_t)_dispatch_thread_getspecific(\ | ||
_PTHREAD_TSD_SLOT_MACH_THREAD_SELF)) | ||
#elif DISPATCH_USE_THREAD_LOCAL_STORAGE | ||
#define _dispatch_thread_port() ((mach_port_t)(_dispatch_get_tsd_base()->tid)) | ||
#else | ||
#define _dispatch_thread_port() (pthread_mach_thread_np(_dispatch_thread_self())) | ||
#endif | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Style would rather be:
why the cast? it looks gross
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
to handle calls like this:
_tsd_call_cleanup(dispatch_io_key, NULL);
in the _libdispatch_thread_cleanup.
One can argue I don't need that anyway, since it will be optimized out (see macro), but
I wanted it there to get some symmetry in the code for TSD and non-TSD code.
If you prefer I don't call the NULL instances of these I can simplify the macro.
Also look at the "dispatch_sema4_key K,V" .. same ugliness there in the code by default"