GC_API void * GC_generic_malloc_kind(size_t bytes, int kind) { size_t granules = ROUNDED_UP_GRANULES(bytes); void *tsd; void *result; void **tiny_fl; # if !defined(USE_PTHREAD_SPECIFIC) && !defined(USE_WIN32_SPECIFIC) GC_key_t k = GC_thread_key; if (EXPECT(0 == k, FALSE)) { /* We haven't yet run GC_init_parallel. That means */ /* we also aren't locking, so this is fairly cheap. */ return GC_generic_malloc_kind_global(bytes, kind); } tsd = GC_getspecific(k); # else tsd = GC_getspecific(GC_thread_key); # endif # if !defined(USE_COMPILER_TLS) && !defined(USE_WIN32_COMPILER_TLS) if (EXPECT(0 == tsd, FALSE)) { return GC_generic_malloc_kind_global(bytes, kind); } # endif GC_ASSERT(GC_is_initialized); GC_ASSERT(GC_is_thread_tsd_valid(tsd)); tiny_fl = ((GC_tlfs)tsd)->freelists[kind]; GC_FAST_MALLOC_GRANS(result, granules, tiny_fl, DIRECT_GRANULES, kind, GC_generic_malloc_kind_global(bytes, kind), obj_link(result) = 0); return result; }
GC_API GC_ATTR_MALLOC void * GC_CALL GC_malloc_kind(size_t bytes, int knd) { size_t granules; void *tsd; void *result; # if MAXOBJKINDS > THREAD_FREELISTS_KINDS if (EXPECT(knd >= THREAD_FREELISTS_KINDS, FALSE)) { return GC_malloc_kind_global(bytes, knd); } # endif # if !defined(USE_PTHREAD_SPECIFIC) && !defined(USE_WIN32_SPECIFIC) { GC_key_t k = GC_thread_key; if (EXPECT(0 == k, FALSE)) { /* We haven't yet run GC_init_parallel. That means */ /* we also aren't locking, so this is fairly cheap. */ return GC_malloc_kind_global(bytes, knd); } tsd = GC_getspecific(k); } # else 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, knd); } # 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[knd], DIRECT_GRANULES, knd, GC_malloc_kind_global(bytes, knd), (void)(knd == 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, knd, result, (unsigned long)GC_gc_no); # endif return result; }
GC_API GC_ATTR_MALLOC void * GC_CALL GC_malloc(size_t bytes) { size_t granules = ROUNDED_UP_GRANULES(bytes); void *tsd; void *result; void **tiny_fl; # if !defined(USE_PTHREAD_SPECIFIC) && !defined(USE_WIN32_SPECIFIC) GC_key_t k = GC_thread_key; if (EXPECT(0 == k, FALSE)) { /* We haven't yet run GC_init_parallel. That means */ /* we also aren't locking, so this is fairly cheap. */ return GC_core_malloc(bytes); } tsd = GC_getspecific(k); # else tsd = GC_getspecific(GC_thread_key); # endif # if !defined(USE_COMPILER_TLS) && !defined(USE_WIN32_COMPILER_TLS) if (EXPECT(0 == tsd, FALSE)) { return GC_core_malloc(bytes); } # endif GC_ASSERT(GC_is_initialized); GC_ASSERT(GC_is_thread_tsd_valid(tsd)); tiny_fl = ((GC_tlfs)tsd) -> normal_freelists; GC_FAST_MALLOC_GRANS(result, granules, tiny_fl, DIRECT_GRANULES, NORMAL, GC_core_malloc(bytes), obj_link(result)=0); # ifdef LOG_ALLOCS GC_log_printf("GC_malloc(%lu) returned %p, recent GC #%lu\n", (unsigned long)bytes, result, (unsigned long)GC_gc_no); # endif return result; }