diff --git a/headers/private/libroot/libroot_private.h b/headers/private/libroot/libroot_private.h
index d0676a6..79ec524 100644
a
|
b
|
void __init_env(const struct user_space_program_args *args);
|
36 | 36 | void __init_env_post_heap(void); |
37 | 37 | status_t __init_heap(void); |
38 | 38 | void __heap_terminate_after(void); |
| 39 | void __heap_before_fork(void); |
| 40 | void __heap_after_fork_child(void); |
| 41 | void __heap_after_fork_parent(void); |
39 | 42 | |
40 | 43 | void __init_time(addr_t commPageTable); |
41 | 44 | void __arch_init_time(struct real_time_data *data, bool setDefaults); |
diff --git a/headers/private/libroot/user_thread.h b/headers/private/libroot/user_thread.h
index 5c234fe..3f1a210 100644
a
|
b
|
|
12 | 12 | #include <user_thread_defs.h> |
13 | 13 | |
14 | 14 | |
15 | | static inline user_thread* |
| 15 | static inline struct user_thread* |
16 | 16 | get_user_thread() |
17 | 17 | { |
18 | | return (user_thread*)tls_get(TLS_USER_THREAD_SLOT); |
| 18 | return (struct user_thread*)tls_get(TLS_USER_THREAD_SLOT); |
19 | 19 | } |
20 | 20 | |
21 | 21 | |
… |
… |
defer_signals()
|
29 | 29 | static void inline |
30 | 30 | undefer_signals() |
31 | 31 | { |
32 | | user_thread* thread = get_user_thread(); |
| 32 | struct user_thread* thread = get_user_thread(); |
33 | 33 | if (--thread->defer_signals == 0 && thread->pending_signals != 0) { |
34 | 34 | // signals shall no longer be deferred -- call a dummy syscall to handle |
35 | 35 | // the pending ones |
diff --git a/src/system/libroot/posix/malloc/arch-specific.cpp b/src/system/libroot/posix/malloc/arch-specific.cpp
index 4167f04..7ac64c2 100644
a
|
b
|
static size_t sFreeHeapSize, sHeapAreaSize;
|
67 | 67 | static free_chunk *sFreeChunks; |
68 | 68 | |
69 | 69 | |
70 | | static void |
71 | | init_after_fork(void) |
| 70 | void |
| 71 | __init_after_fork(void) |
72 | 72 | { |
73 | 73 | // find the heap area |
74 | 74 | sHeapArea = area_for((void*)sFreeHeapBase); |
… |
… |
__init_heap(void)
|
110 | 110 | |
111 | 111 | hoardLockInit(sHeapLock, "heap"); |
112 | 112 | |
113 | | atfork(&init_after_fork); |
114 | | // Note: Needs malloc(). Hence we need to be fully initialized. |
115 | | // TODO: We should actually also install a hook that is called before |
116 | | // fork() is being executed. In a multithreaded app it would need to |
117 | | // acquire *all* allocator locks, so that we don't fork() an |
118 | | // inconsistent state. |
119 | | |
120 | 113 | return B_OK; |
121 | 114 | } |
122 | 115 | |
diff --git a/src/system/libroot/posix/malloc/heap.cpp b/src/system/libroot/posix/malloc/heap.cpp
index 99aba54..e2cc553 100644
a
|
b
|
hoardHeap::hoardHeap(void)
|
132 | 132 | , _magic(HEAP_MAGIC) |
133 | 133 | #endif |
134 | 134 | { |
135 | | // Initialize the per-heap lock. |
136 | | hoardLockInit(_lock, "hoard heap"); |
| 135 | initLock(); |
137 | 136 | |
138 | 137 | for (int i = 0; i < SUPERBLOCK_FULLNESS_GROUP; i++) { |
139 | 138 | for (int j = 0; j < SIZE_CLASSES; j++) { |
diff --git a/src/system/libroot/posix/malloc/heap.h b/src/system/libroot/posix/malloc/heap.h
index f42962e..42e9eb4 100644
a
|
b
|
class hoardHeap {
|
115 | 115 | // Unlock this heap. |
116 | 116 | inline void unlock(void); |
117 | 117 | |
| 118 | // Init this heap lock. |
| 119 | inline void initLock(void); |
| 120 | |
118 | 121 | // Set our index number (which heap we are). |
119 | 122 | inline void setIndex(int i); |
120 | 123 | |
… |
… |
hoardHeap::unlock(void)
|
444 | 447 | } |
445 | 448 | |
446 | 449 | |
| 450 | void |
| 451 | hoardHeap::initLock(void) |
| 452 | { |
| 453 | // Initialize the per-heap lock. |
| 454 | hoardLockInit(_lock, "hoard heap"); |
| 455 | } |
| 456 | |
| 457 | |
447 | 458 | size_t |
448 | 459 | hoardHeap::align(const size_t sz) |
449 | 460 | { |
diff --git a/src/system/libroot/posix/malloc/processheap.h b/src/system/libroot/posix/malloc/processheap.h
index f222289..2c94af9 100644
a
|
b
|
class processHeap : public hoardHeap {
|
67 | 67 | // Get a thread heap index. |
68 | 68 | inline int getHeapIndex(void); |
69 | 69 | |
| 70 | // Get thread heap max. |
| 71 | inline int getMaxThreadHeaps(void); |
| 72 | |
70 | 73 | // Get the thread heap with index i. |
71 | 74 | inline HEAPTYPE & getHeap(int i); |
72 | 75 | |
… |
… |
processHeap::getHeapIndex(void)
|
199 | 202 | } |
200 | 203 | |
201 | 204 | |
| 205 | // Return the maximum number of heaps. |
| 206 | |
| 207 | int |
| 208 | processHeap::getMaxThreadHeaps(void) |
| 209 | { |
| 210 | return fMaxThreadHeaps; |
| 211 | } |
| 212 | |
| 213 | |
202 | 214 | superblock * |
203 | 215 | processHeap::acquire(const int sizeclass, hoardHeap * dest) |
204 | 216 | { |
diff --git a/src/system/libroot/posix/malloc/wrapper.cpp b/src/system/libroot/posix/malloc/wrapper.cpp
index c83336a..38c4125 100644
a
|
b
|
getAllocator(void)
|
256 | 256 | } |
257 | 257 | |
258 | 258 | |
| 259 | extern "C" void |
| 260 | __heap_before_fork(void) |
| 261 | { |
| 262 | static processHeap *pHeap = getAllocator(); |
| 263 | for (int i = 0; i < pHeap->getMaxThreadHeaps(); i++) |
| 264 | pHeap->getHeap(i).lock(); |
| 265 | } |
| 266 | |
| 267 | void __init_after_fork(void); |
| 268 | |
| 269 | extern "C" void |
| 270 | __heap_after_fork_child(void) |
| 271 | { |
| 272 | __init_after_fork(); |
| 273 | static processHeap *pHeap = getAllocator(); |
| 274 | for (int i = 0; i < pHeap->getMaxThreadHeaps(); i++) |
| 275 | pHeap->getHeap(i).initLock(); |
| 276 | } |
| 277 | |
| 278 | |
| 279 | extern "C" void |
| 280 | __heap_after_fork_parent(void) |
| 281 | { |
| 282 | static processHeap *pHeap = getAllocator(); |
| 283 | for (int i = 0; i < pHeap->getMaxThreadHeaps(); i++) |
| 284 | pHeap->getHeap(i).unlock(); |
| 285 | } |
| 286 | |
| 287 | |
259 | 288 | // #pragma mark - public functions |
260 | 289 | |
261 | 290 | |
diff --git a/src/system/libroot/posix/malloc_debug/malloc_debug_api.cpp b/src/system/libroot/posix/malloc_debug/malloc_debug_api.cpp
index 3d3b062..bf38d4c 100644
a
|
b
|
__heap_terminate_after()
|
202 | 202 | } |
203 | 203 | |
204 | 204 | |
| 205 | extern "C" void |
| 206 | __heap_before_fork(void) |
| 207 | { |
| 208 | } |
| 209 | |
| 210 | |
| 211 | extern "C" void |
| 212 | __heap_after_fork_child(void) |
| 213 | { |
| 214 | } |
| 215 | |
| 216 | |
| 217 | extern "C" void |
| 218 | __heap_after_fork_parent(void) |
| 219 | { |
| 220 | } |
| 221 | |
| 222 | |
205 | 223 | // #pragma mark - Public API |
206 | 224 | |
207 | 225 | |
diff --git a/src/system/libroot/posix/unistd/fork.c b/src/system/libroot/posix/unistd/fork.c
index 8d8a963..0316750 100644
a
|
b
|
|
16 | 16 | #include <pthread_private.h> |
17 | 17 | #include <runtime_loader.h> |
18 | 18 | #include <syscalls.h> |
| 19 | #include <user_thread.h> |
19 | 20 | |
20 | 21 | |
21 | 22 | typedef struct fork_hook { |
… |
… |
call_fork_hooks(fork_hook *hook)
|
105 | 106 | status_t |
106 | 107 | __register_atfork(void (*prepare)(void), void (*parent)(void), void (*child)(void)) |
107 | 108 | { |
| 109 | defer_signals(); |
| 110 | |
108 | 111 | status_t status = mutex_lock(&sForkLock); |
109 | | if (status != B_OK) |
| 112 | if (status != B_OK) { |
| 113 | undefer_signals(); |
110 | 114 | return status; |
| 115 | } |
111 | 116 | |
112 | 117 | if (prepare) |
113 | 118 | status = add_fork_hook(&sPrepareHooks, NULL, prepare); |
… |
… |
__register_atfork(void (*prepare)(void), void (*parent)(void), void (*child)(voi
|
119 | 124 | status = add_fork_hook(&sChildHooks, &sLastChildHook, child); |
120 | 125 | |
121 | 126 | mutex_unlock(&sForkLock); |
| 127 | |
| 128 | undefer_signals(); |
| 129 | |
122 | 130 | return status; |
123 | 131 | } |
124 | 132 | |
… |
… |
fork(void)
|
129 | 137 | thread_id thread; |
130 | 138 | status_t status; |
131 | 139 | |
| 140 | defer_signals(); |
| 141 | |
132 | 142 | status = mutex_lock(&sForkLock); |
133 | | if (status != B_OK) |
| 143 | if (status != B_OK) { |
| 144 | undefer_signals(); |
134 | 145 | return status; |
| 146 | } |
135 | 147 | |
136 | 148 | // call preparation hooks |
137 | 149 | call_fork_hooks(sPrepareHooks); |
| 150 | __heap_before_fork(); |
138 | 151 | |
139 | 152 | thread = _kern_fork(); |
140 | 153 | if (thread < 0) { |
141 | 154 | // something went wrong |
| 155 | undefer_signals(); |
142 | 156 | mutex_unlock(&sForkLock); |
143 | 157 | __set_errno(thread); |
144 | 158 | return -1; |
… |
… |
fork(void)
|
155 | 169 | // process we should make sure that it is in a consistent state when |
156 | 170 | // calling the kernel. |
157 | 171 | __gRuntimeLoader->reinit_after_fork(); |
| 172 | __heap_after_fork_child(); |
158 | 173 | __reinit_pwd_backend_after_fork(); |
159 | 174 | |
160 | 175 | call_fork_hooks(sChildHooks); |
161 | 176 | } else { |
162 | 177 | // we are the parent |
| 178 | __heap_after_fork_parent(); |
163 | 179 | call_fork_hooks(sParentHooks); |
164 | 180 | mutex_unlock(&sForkLock); |
165 | 181 | } |
166 | 182 | |
| 183 | undefer_signals(); |
| 184 | |
167 | 185 | return thread; |
168 | 186 | } |
169 | 187 | |