Skip to content

Commit 4f766cd

Browse files
Refactor thread local storage
1 parent d8b1d8e commit 4f766cd

File tree

5 files changed

+48
-95
lines changed

5 files changed

+48
-95
lines changed

src/gc.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,22 @@ HL_PRIM gc_pheader *hl_gc_get_page( void *v ) {
308308

309309
HL_API int hl_thread_id();
310310

311+
HL_PRIM int hl_atomic_add32(int *a, int b);
312+
313+
static int tls_counter = 0;
314+
315+
int get_tls_slot() {
316+
return hl_atomic_add32(&tls_counter, 1);
317+
}
318+
319+
void free_tls_slot(int key) {
320+
// this should only run in the finalizer, which is called when all threads
321+
// are stopped
322+
for (int i = 0; i < gc_threads.count; i++) {
323+
hl_hiremove(gc_threads.threads[i]->tls_slots, key);
324+
}
325+
}
326+
311327
HL_API void hl_register_thread( void *stack_top ) {
312328
if( hl_get_thread() )
313329
hl_fatal("Thread already registered");
@@ -324,6 +340,8 @@ HL_API void hl_register_thread( void *stack_top ) {
324340
current_thread = t;
325341
hl_add_root(&t->exc_value);
326342
hl_add_root(&t->exc_handler);
343+
hl_add_root(&t->tls_slots);
344+
t->tls_slots = hl_hialloc();
327345

328346
gc_global_lock(true);
329347
hl_thread_info **all = (hl_thread_info**)malloc(sizeof(void*) * (gc_threads.count + 1));
@@ -340,6 +358,7 @@ HL_API void hl_unregister_thread() {
340358
hl_fatal("Thread not registered");
341359
hl_remove_root(&t->exc_value);
342360
hl_remove_root(&t->exc_handler);
361+
hl_remove_root(&t->tls_slots);
343362
gc_global_lock(true);
344363
for(i=0;i<gc_threads.count;i++)
345364
if( gc_threads.threads[i] == t ) {

src/hl.h

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -785,7 +785,6 @@ HL_API void hl_condition_free(hl_condition *cond);
785785
HL_API hl_tls *hl_tls_alloc( bool gc_value );
786786
HL_API void hl_tls_set( hl_tls *l, void *value );
787787
HL_API void *hl_tls_get( hl_tls *l );
788-
HL_API void hl_tls_free( hl_tls *l );
789788

790789
// ----------------------- ALLOC --------------------------------------------------
791790

@@ -843,6 +842,17 @@ HL_API uchar *hl_to_string( vdynamic *v );
843842
HL_API const uchar *hl_type_str( hl_type *t );
844843
HL_API void hl_throw_buffer( hl_buffer *b );
845844

845+
// Maps
846+
847+
struct hl_hi_map;
848+
typedef struct hl_hi_map hl_hi_map;
849+
850+
HL_API hl_hi_map *hl_hialloc();
851+
HL_API void hl_hiset(hl_hi_map *, int, vdynamic *);
852+
HL_API bool hl_hiexists(hl_hi_map *, int);
853+
HL_API vdynamic *hl_higet(hl_hi_map *, int);
854+
HL_API bool hl_hiremove(hl_hi_map *, int);
855+
846856
// ----------------------- FFI ------------------------------------------------------
847857

848858
// match GNU C++ mangling
@@ -984,6 +994,7 @@ typedef struct {
984994
thread_t mach_thread_id;
985995
pthread_t pthread_id;
986996
#endif
997+
hl_hi_map *tls_slots;
987998
} hl_thread_info;
988999

9891000
typedef struct {

src/std/maps.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,9 @@ typedef struct {
4545
} hl_free_list;
4646

4747
static void hl_freelist_resize( hl_free_list *f, int newsize ) {
48-
hl_free_bucket *buckets = (hl_free_bucket*)hl_gc_alloc_noptr(sizeof(hl_free_bucket)*newsize);
48+
hl_free_bucket *buckets = (hl_free_bucket*)malloc(sizeof(hl_free_bucket)*newsize);
4949
memcpy(buckets,f->buckets,f->head * sizeof(hl_free_bucket));
50+
free(f->buckets);
5051
f->buckets = buckets;
5152
f->nbuckets = newsize;
5253
}

src/std/maps.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
#define _MSTATIC static
1717
#endif
1818

19-
typedef struct {
19+
typedef struct t_map {
2020
void *cells;
2121
void *nexts;
2222
t_entry *entries;

src/std/thread.c

Lines changed: 14 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -64,13 +64,6 @@ struct _hl_condition {
6464
CRITICAL_SECTION cs;
6565
CONDITION_VARIABLE cond;
6666
};
67-
68-
struct _hl_tls {
69-
void (*free)( hl_tls * );
70-
DWORD tid;
71-
bool gc;
72-
};
73-
7467
#else
7568

7669
# include <pthread.h>
@@ -104,13 +97,6 @@ struct _hl_condition {
10497
pthread_mutex_t mutex;
10598
pthread_cond_t cond;
10699
};
107-
108-
struct _hl_tls {
109-
void (*free)( hl_tls * );
110-
pthread_key_t key;
111-
bool gc;
112-
};
113-
114100
#endif
115101

116102
// ----------------- ALLOC
@@ -463,95 +449,31 @@ DEFINE_PRIM(_VOID, condition_broadcast, _CONDITION)
463449

464450
// ----------------- THREAD LOCAL
465451

466-
#if defined(HL_THREADS)
467-
static void **_tls_get( hl_tls *t ) {
468-
# ifdef HL_WIN
469-
return (void**)TlsGetValue(t->tid);
470-
# else
471-
return (void**)pthread_getspecific(t->key);
472-
# endif
473-
}
474-
static void _tls_set( hl_tls *t, void *store ) {
475-
# ifdef HL_WIN
476-
TlsSetValue(t->tid, store);
477-
# else
478-
pthread_setspecific(t->key, store);
479-
# endif
480-
}
481-
#endif
452+
int get_tls_slot();
453+
void free_tls_slot(int id);
454+
455+
struct _hl_tls {
456+
void (*free)( hl_tls * );
457+
int key;
458+
bool gc;
459+
};
460+
461+
static void tls_free(hl_tls *l) { free_tls_slot(l->key); }
482462

483463
HL_PRIM hl_tls *hl_tls_alloc( bool gc_value ) {
484-
# if !defined(HL_THREADS)
485464
hl_tls *l = (hl_tls*)hl_gc_alloc_finalizer(sizeof(hl_tls));
486-
l->free = hl_tls_free;
487-
l->value = NULL;
488-
return l;
489-
# elif defined(HL_WIN)
490-
hl_tls *l = (hl_tls*)hl_gc_alloc_finalizer(sizeof(hl_tls));
491-
l->free = hl_tls_free;
492-
l->tid = TlsAlloc();
493-
l->gc = gc_value;
494-
TlsSetValue(l->tid,NULL);
495-
return l;
496-
# else
497-
hl_tls *l = (hl_tls*)hl_gc_alloc_finalizer(sizeof(hl_tls));
498-
l->free = hl_tls_free;
465+
l->free = tls_free;
499466
l->gc = gc_value;
500-
pthread_key_create(&l->key,NULL);
467+
l->key = get_tls_slot();
501468
return l;
502-
# endif
503-
}
504-
505-
HL_PRIM void hl_tls_free( hl_tls *l ) {
506-
# if !defined(HL_THREADS)
507-
free(l);
508-
# elif defined(HL_WIN)
509-
if( l->free ) {
510-
TlsFree(l->tid);
511-
l->free = NULL;
512-
}
513-
# else
514-
if( l->free ) {
515-
pthread_key_delete(l->key);
516-
l->free = NULL;
517-
}
518-
# endif
519469
}
520470

521471
HL_PRIM void hl_tls_set( hl_tls *l, void *v ) {
522-
# if !defined(HL_THREADS)
523-
l->value = v;
524-
# else
525-
if( l->gc ) {
526-
void **store = _tls_get(l);
527-
if( !store) {
528-
if( !v )
529-
return;
530-
store = (void**)malloc(sizeof(void*));
531-
hl_add_root(store);
532-
_tls_set(l, store);
533-
} else {
534-
if( !v ) {
535-
free(store);
536-
hl_remove_root(store);
537-
_tls_set(l, NULL);
538-
return;
539-
}
540-
}
541-
*store = v;
542-
} else
543-
_tls_set(l, v);
544-
# endif
472+
hl_hiset(hl_get_thread()->tls_slots, l->key, v);
545473
}
546474

547475
HL_PRIM void *hl_tls_get( hl_tls *l ) {
548-
# if !defined(HL_THREADS)
549-
return l->value;
550-
# else
551-
void **store = _tls_get(l);
552-
if( !l->gc ) return store;
553-
return store ? *store : NULL;
554-
# endif
476+
return hl_higet(hl_get_thread()->tls_slots, l->key);
555477
}
556478

557479
#define _TLS _ABSTRACT(hl_tls)

0 commit comments

Comments
 (0)