-
-
Notifications
You must be signed in to change notification settings - Fork 5.6k
/
Copy pathgc-common.h
190 lines (159 loc) · 5.87 KB
/
gc-common.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
// 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>
#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 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)
#ifdef __cplusplus
}
#endif
// =========================================================================== //
// 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)
// =========================================================================== //
// 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 the lowest bit set, the next pointer is an unboxed c function pointer.
// If an object pointer has the second lowest bit 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.
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);
void run_finalizers(jl_task_t *ct, int finalizers_thread);
JL_DLLEXPORT void jl_gc_add_finalizer_th(jl_ptls_t ptls, jl_value_t *v, jl_function_t *f) JL_NOTSAFEPOINT;
JL_DLLEXPORT void jl_finalize_th(jl_task_t *ct, jl_value_t *o);
// =========================================================================== //
// Threading
// =========================================================================== //
extern int gc_n_threads;
extern jl_ptls_t* gc_all_tls_states;
// =========================================================================== //
// Logging
// =========================================================================== //
extern int gc_logging_enabled;
#endif // JL_GC_COMMON_H