/
githubmirror
/
julia
Обзор
Документация
Войти
/
githubmirror
/
julia
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
src/gc-common.h
236 строк
8 KB
Sam Schweigel
Use preproc defines for finalizer pointer tags
27 июл 2026, 19:20
27 июл 2026, 19:20
3fe82f2
Код
Авторство
О чём код?
// This file is a part of Julia. License is MIT: https://julialang.org/license #ifndef JL_GC_COMMON_H #define JL_GC_COMMON_H #include "julia.h" #include "julia_internal.h" #ifndef _OS_WINDOWS_ #include <sys/mman.h> #ifndef MADV_HUGEPAGE #define MADV_HUGEPAGE 14 // Compatibility for kernels < 2.6.38 (as in numpy implementation) #endif #if defined(_OS_DARWIN_) && !defined(MAP_ANONYMOUS) #define MAP_ANONYMOUS MAP_ANON #endif #endif #include <stdlib.h> #if defined(_OS_DARWIN_) #include <malloc/malloc.h> #else #include <malloc.h> // for malloc_trim #endif #ifdef __cplusplus extern "C" { #endif // =========================================================================== // // GC Big objects // =========================================================================== // // layout for big (>2k) objects JL_EXTENSION typedef struct _bigval_t { struct _bigval_t *next; struct _bigval_t *prev; size_t sz; #ifdef _P64 // Add padding so that the value is 64-byte aligned // (8 pointers of 8 bytes each) - (4 other pointers in struct) void *_padding[8 - 4]; #else // (16 pointers of 4 bytes each) - (4 other pointers in struct) void *_padding[16 - 4]; #endif //struct jl_taggedvalue_t <>; union { uintptr_t header; struct { uintptr_t gc:2; } bits; }; // must be 64-byte aligned here, in 32 & 64 bit modes } bigval_t; // =========================================================================== // // GC Callbacks // =========================================================================== // typedef void (*jl_gc_cb_func_t)(void); typedef struct _jl_gc_callback_list_t { struct _jl_gc_callback_list_t *next; jl_gc_cb_func_t func; } jl_gc_callback_list_t; extern jl_gc_callback_list_t *gc_cblist_root_scanner; extern jl_gc_callback_list_t *gc_cblist_task_scanner; extern jl_gc_callback_list_t *gc_cblist_pre_gc; extern jl_gc_callback_list_t *gc_cblist_post_gc; extern jl_gc_callback_list_t *gc_cblist_notify_external_alloc; extern jl_gc_callback_list_t *gc_cblist_notify_external_free; extern jl_gc_callback_list_t *gc_cblist_notify_gc_pressure; #define gc_invoke_callbacks(ty, list, args) \ do { \ for (jl_gc_callback_list_t *cb = list; \ cb != NULL; \ cb = cb->next) \ { \ ((ty)(cb->func)) args; \ } \ } while (0) // =========================================================================== // // malloc wrappers, aligned allocation // =========================================================================== // #if defined(_OS_WINDOWS_) STATIC_INLINE void *jl_malloc_aligned(size_t sz, size_t align) { return _aligned_malloc(sz ? sz : 1, align); } STATIC_INLINE void *jl_realloc_aligned(void *p, size_t sz, size_t oldsz, size_t align) { (void)oldsz; return _aligned_realloc(p, sz ? sz : 1, align); } STATIC_INLINE void jl_free_aligned(void *p) JL_NOTSAFEPOINT { _aligned_free(p); } #else STATIC_INLINE void *jl_malloc_aligned(size_t sz, size_t align) { #if defined(_P64) || defined(__APPLE__) if (align <= 16) return malloc(sz); #endif void *ptr; if (posix_memalign(&ptr, align, sz)) return NULL; return ptr; } STATIC_INLINE void *jl_realloc_aligned(void *d, size_t sz, size_t oldsz, size_t align) { #if defined(_P64) || defined(__APPLE__) if (align <= 16) return realloc(d, sz); #endif void *b = jl_malloc_aligned(sz, align); if (b != NULL) { memcpy(b, d, oldsz > sz ? sz : oldsz); free(d); } return b; } STATIC_INLINE void jl_free_aligned(void *p) JL_NOTSAFEPOINT { free(p); } #endif #define malloc_cache_align(sz) jl_malloc_aligned(sz, JL_CACHE_BYTE_ALIGNMENT) #define realloc_cache_align(p, sz, oldsz) jl_realloc_aligned(p, sz, oldsz, JL_CACHE_BYTE_ALIGNMENT) #define malloc_page_align(sz) jl_malloc_aligned(sz, jl_getpagesize()) // =========================================================================== // // Pointer tagging // =========================================================================== // STATIC_INLINE int gc_marked(uintptr_t bits) JL_NOTSAFEPOINT { return (bits & GC_MARKED) != 0; } STATIC_INLINE int gc_old(uintptr_t bits) JL_NOTSAFEPOINT { return (bits & GC_OLD) != 0; } STATIC_INLINE uintptr_t gc_set_bits(uintptr_t tag, int bits) JL_NOTSAFEPOINT { return (tag & ~(uintptr_t)3) | bits; } STATIC_INLINE uintptr_t gc_ptr_tag(void *v, uintptr_t mask) JL_NOTSAFEPOINT { return ((uintptr_t)v) & mask; } STATIC_INLINE void *gc_ptr_clear_tag(void *v, uintptr_t mask) JL_NOTSAFEPOINT { return (void*)(((uintptr_t)v) & ~mask); } // =========================================================================== // // GC Metrics // =========================================================================== // extern jl_gc_num_t gc_num; // =========================================================================== // // Stop-the-world for GC // =========================================================================== // void jl_gc_wait_for_the_world(jl_ptls_t* gc_all_tls_states, int gc_n_threads); // =========================================================================== // // Finalization // =========================================================================== // // Protect all access to `finalizer_list_marked` and `to_finalize`. // For accessing `ptls->finalizers`, the lock is needed if a thread // is going to realloc the buffer (of its own list) or accessing the // list of another thread extern jl_mutex_t finalizers_lock; // `ptls->finalizers` and `finalizer_list_marked` might have tagged pointers. // If an object pointer has `GC_FIN_CFUNC_TAG` set, the next pointer is an unboxed c function pointer. // If an object pointer has `GC_FIN_COBJ_TAG` set, the current pointer is a c object pointer. // It must be aligned at least 4, and it finalized immediately (at "quiescence"). // `to_finalize` should not have tagged pointers. #define GC_FIN_CFUNC_TAG 1 #define GC_FIN_COBJ_TAG 2 #define GC_FIN_TAG_MASK 3 extern arraylist_t finalizer_list_marked; extern arraylist_t to_finalize; void schedule_finalization(void *o, void *f) JL_NOTSAFEPOINT; void run_finalizer(jl_task_t *ct, void *o, void *ff) JL_CANSAFEPOINT; void run_finalizers(jl_task_t *ct, int finalizers_thread) JL_CANSAFEPOINT; JL_DLLEXPORT void jl_gc_add_finalizer_th(jl_ptls_t ptls, jl_value_t *v, jl_value_t *f) JL_NOTSAFEPOINT; JL_DLLEXPORT void jl_finalize_th(jl_task_t *ct, jl_value_t *o) JL_CANSAFEPOINT; // =========================================================================== // // Threading // =========================================================================== // extern int gc_n_threads; extern jl_ptls_t* gc_all_tls_states; // =========================================================================== // // Logging // =========================================================================== // extern int gc_logging_enabled; // =========================================================================== // // MISC // =========================================================================== // // number of stacks to always keep available per pool #define MIN_STACK_MAPPINGS_PER_POOL 5 void _jl_free_stack(jl_ptls_t ptls, void *stkbuf, size_t bufsz) JL_NOTSAFEPOINT; void sweep_mtarraylist_buffers(void) JL_NOTSAFEPOINT; int gc_slot_to_fieldidx(void *_obj, void *slot, jl_datatype_t *vt) JL_NOTSAFEPOINT; int gc_slot_to_arrayidx(void *_obj, void *begin) JL_NOTSAFEPOINT; #ifdef __cplusplus } #endif #endif // JL_GC_COMMON_H