123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302 |
- #include "private/gc_priv.h"
- #if defined(THREAD_LOCAL_ALLOC)
- #ifndef THREADS
- # error "invalid config - THREAD_LOCAL_ALLOC requires GC_THREADS"
- #endif
- #include "private/thread_local_alloc.h"
- #include <stdlib.h>
- #if defined(USE_COMPILER_TLS)
- __thread GC_ATTR_TLS_FAST
- #elif defined(USE_WIN32_COMPILER_TLS)
- __declspec(thread) GC_ATTR_TLS_FAST
- #endif
- GC_key_t GC_thread_key;
- static GC_bool keys_initialized;
- static void return_single_freelist(void *fl, void **gfl)
- {
- if (*gfl == 0) {
- *gfl = fl;
- } else {
- void *q, **qptr;
- GC_ASSERT(GC_size(fl) == GC_size(*gfl));
-
- qptr = &(obj_link(fl));
- while ((word)(q = *qptr) >= HBLKSIZE)
- qptr = &(obj_link(q));
- GC_ASSERT(0 == q);
- *qptr = *gfl;
- *gfl = fl;
- }
- }
- static void return_freelists(void **fl, void **gfl)
- {
- int i;
- for (i = 1; i < TINY_FREELISTS; ++i) {
- if ((word)(fl[i]) >= HBLKSIZE) {
- return_single_freelist(fl[i], &gfl[i]);
- }
-
-
- fl[i] = (ptr_t)HBLKSIZE;
- }
-
- # ifdef GC_GCJ_SUPPORT
- if (fl[0] == ERROR_FL) return;
- # endif
- if ((word)(fl[0]) >= HBLKSIZE) {
- return_single_freelist(fl[0], &gfl[1]);
- }
- }
- #ifdef USE_PTHREAD_SPECIFIC
-
-
-
-
-
- static void reset_thread_key(void* v) {
- pthread_setspecific(GC_thread_key, v);
- }
- #else
- # define reset_thread_key 0
- #endif
- GC_INNER void GC_init_thread_local(GC_tlfs p)
- {
- int i, j, res;
- GC_ASSERT(I_HOLD_LOCK());
- if (!EXPECT(keys_initialized, TRUE)) {
- GC_ASSERT((word)&GC_thread_key % sizeof(word) == 0);
- res = GC_key_create(&GC_thread_key, reset_thread_key);
- if (COVERT_DATAFLOW(res) != 0) {
- ABORT("Failed to create key for local allocator");
- }
- keys_initialized = TRUE;
- }
- res = GC_setspecific(GC_thread_key, p);
- if (COVERT_DATAFLOW(res) != 0) {
- ABORT("Failed to set thread specific allocation pointers");
- }
- for (j = 0; j < TINY_FREELISTS; ++j) {
- for (i = 0; i < THREAD_FREELISTS_KINDS; ++i) {
- p -> _freelists[i][j] = (void *)(word)1;
- }
- # ifdef GC_GCJ_SUPPORT
- p -> gcj_freelists[j] = (void *)(word)1;
- # endif
- }
-
-
-
- # ifdef GC_GCJ_SUPPORT
- p -> gcj_freelists[0] = ERROR_FL;
- # endif
- }
- GC_INNER void GC_destroy_thread_local(GC_tlfs p)
- {
- int k;
-
- GC_STATIC_ASSERT(THREAD_FREELISTS_KINDS <= MAXOBJKINDS);
- for (k = 0; k < THREAD_FREELISTS_KINDS; ++k) {
- if (k == (int)GC_n_kinds)
- break;
- return_freelists(p -> _freelists[k], GC_obj_kinds[k].ok_freelist);
- }
- # ifdef GC_GCJ_SUPPORT
- return_freelists(p -> gcj_freelists, (void **)GC_gcjobjfreelist);
- # endif
- }
- GC_API GC_ATTR_MALLOC void * GC_CALL GC_malloc_kind(size_t bytes, int kind)
- {
- size_t granules;
- void *tsd;
- void *result;
- # if MAXOBJKINDS > THREAD_FREELISTS_KINDS
- if (EXPECT(kind >= THREAD_FREELISTS_KINDS, FALSE)) {
- return GC_malloc_kind_global(bytes, kind);
- }
- # endif
- # if !defined(USE_PTHREAD_SPECIFIC) && !defined(USE_WIN32_SPECIFIC)
- {
- GC_key_t k = GC_thread_key;
- if (EXPECT(0 == k, FALSE)) {
-
-
- return GC_malloc_kind_global(bytes, kind);
- }
- tsd = GC_getspecific(k);
- }
- # else
- if (!EXPECT(keys_initialized, TRUE))
- return GC_malloc_kind_global(bytes, kind);
- tsd = GC_getspecific(GC_thread_key);
- # endif
- # if !defined(USE_COMPILER_TLS) && !defined(USE_WIN32_COMPILER_TLS)
- if (EXPECT(0 == tsd, FALSE)) {
- return GC_malloc_kind_global(bytes, kind);
- }
- # endif
- GC_ASSERT(GC_is_initialized);
- GC_ASSERT(GC_is_thread_tsd_valid(tsd));
- granules = ROUNDED_UP_GRANULES(bytes);
- GC_FAST_MALLOC_GRANS(result, granules,
- ((GC_tlfs)tsd) -> _freelists[kind], DIRECT_GRANULES,
- kind, GC_malloc_kind_global(bytes, kind),
- (void)(kind == PTRFREE ? NULL
- : (obj_link(result) = 0)));
- # ifdef LOG_ALLOCS
- GC_log_printf("GC_malloc_kind(%lu, %d) returned %p, recent GC #%lu\n",
- (unsigned long)bytes, kind, result,
- (unsigned long)GC_gc_no);
- # endif
- return result;
- }
- #ifdef GC_GCJ_SUPPORT
- # include "gc_gcj.h"
- GC_API GC_ATTR_MALLOC void * GC_CALL GC_gcj_malloc(size_t bytes,
- void * ptr_to_struct_containing_descr)
- {
- if (EXPECT(GC_incremental, FALSE)) {
- return GC_core_gcj_malloc(bytes, ptr_to_struct_containing_descr);
- } else {
- size_t granules = ROUNDED_UP_GRANULES(bytes);
- void *result;
- void **tiny_fl;
- GC_ASSERT(GC_gcj_malloc_initialized);
- tiny_fl = ((GC_tlfs)GC_getspecific(GC_thread_key))->gcj_freelists;
- GC_FAST_MALLOC_GRANS(result, granules, tiny_fl, DIRECT_GRANULES,
- GC_gcj_kind,
- GC_core_gcj_malloc(bytes,
- ptr_to_struct_containing_descr),
- {AO_compiler_barrier();
- *(void **)result = ptr_to_struct_containing_descr;});
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- return result;
- }
- }
- #endif
- GC_INNER void GC_mark_thread_local_fls_for(GC_tlfs p)
- {
- ptr_t q;
- int i, j;
- for (j = 0; j < TINY_FREELISTS; ++j) {
- for (i = 0; i < THREAD_FREELISTS_KINDS; ++i) {
-
-
- q = (ptr_t)AO_load((volatile AO_t *)&p->_freelists[i][j]);
- if ((word)q > HBLKSIZE)
- GC_set_fl_marks(q);
- }
- # ifdef GC_GCJ_SUPPORT
- if (EXPECT(j > 0, TRUE)) {
- q = (ptr_t)AO_load((volatile AO_t *)&p->gcj_freelists[j]);
- if ((word)q > HBLKSIZE)
- GC_set_fl_marks(q);
- }
- # endif
- }
- }
- #if defined(GC_ASSERTIONS)
-
- void GC_check_tls_for(GC_tlfs p)
- {
- int i, j;
- for (j = 1; j < TINY_FREELISTS; ++j) {
- for (i = 0; i < THREAD_FREELISTS_KINDS; ++i) {
- GC_check_fl_marks(&p->_freelists[i][j]);
- }
- # ifdef GC_GCJ_SUPPORT
- GC_check_fl_marks(&p->gcj_freelists[j]);
- # endif
- }
- }
- #endif
- #endif
|