Created
June 25, 2013 06:12
-
-
Save thoughtpolice/5856323 to your computer and use it in GitHub Desktop.
Über fast thread-local storage on OS X
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include <unistd.h> | |
#include <pthread.h> | |
/** Snipped from pthread_machdep.h */ | |
#define __PTK_FRAMEWORK_JAVASCRIPTCORE_KEY4 94 | |
extern __inline__ void * | |
_pthread_getspecific_direct(unsigned long slot) { | |
void* ret; | |
#if defined(__i386__) || defined(__x86_64__) | |
__asm__("mov %%gs:%1, %0" : "=r" (ret) : "m" (*(void **)(slot * sizeof(void *)))); | |
#else | |
#error "No definition of pthread_getspecific_direct!" | |
#endif | |
return ret; | |
} | |
/* To be used with static constant keys only */ | |
extern __inline__ int | |
_pthread_setspecific_direct(unsigned long slot, void * val) | |
{ | |
#if defined(__x86_64__) | |
/* PIC is free and cannot be disabled, even with: gcc -mdynamic-no-pic ... */ | |
__asm__("movq %1,%%gs:%0" : "=m" (*(void **)(slot * sizeof(void *))) : "rn" (val)); | |
#else | |
#error "No definition of pthread_setspecific_direct!" | |
#endif | |
return 0; | |
} | |
/** End snippets */ | |
static const pthread_key_t fooKey = | |
__PTK_FRAMEWORK_JAVASCRIPTCORE_KEY4; | |
#define GET_FOO() ((void*)(_pthread_getspecific_direct(fooKey))) | |
#define SET_FOO(to) (_pthread_setspecific_direct(fooKey, to)) | |
void* f1(void* x) { | |
int* tmp; | |
SET_FOO(x); | |
sleep(10); | |
tmp = GET_FOO(); | |
printf("thread #1: foo = %p/%d\n", tmp, *tmp); | |
/* el fin */ | |
free(x); | |
pthread_exit(0); | |
} | |
void* f2(void* x) { | |
int* tmp; | |
sleep(5); | |
SET_FOO(x); | |
tmp = GET_FOO(); | |
printf("thread #2: foo = %p/%d\n", tmp, *tmp); | |
/* el fin */ | |
free(x); | |
pthread_exit(0); | |
} | |
int main(int ac, char* av[]) { | |
int foobar = 0; | |
if (ac < 2) foobar = 10; | |
else foobar = atoi(av[1]); | |
printf("[MAIN] default value = %d\n", foobar); | |
/* initialize thread-local data structures */ | |
int* i1 = malloc(sizeof(*i1)); | |
int* i2 = malloc(sizeof(*i2)); | |
*i1 = foobar+1; | |
*i2 = foobar+2; | |
printf("[MAIN] mallocs: thr1 = %p; thr2 = %p\n", i1, i2); | |
/* initialize threads */ | |
pthread_t thr1, thr2; | |
pthread_create(&thr1, NULL, &f1, i1); | |
pthread_create(&thr2, NULL, &f2, i2); | |
pthread_join(thr1, NULL); | |
pthread_join(thr2, NULL); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment