8 static unsigned int gc_threads
;
9 static pthread_t
*threads
;
10 static os_sem_t
*start_semaphores
;
11 static os_sem_t join_semaphore
;
12 static void (*action
)(void);
14 static void *worker(void *index
) {
15 uword_t i
= (uword_t
)index
;
17 os_sem_wait(start_semaphores
+ i
);
18 // We don't need pthread_jit_write_protect_np(0) here because workers
19 // never alter Lisp objects- they'll only touch side tables.
20 // Though how does incremental compaction work? I guess _only_ the main thread
21 // transports objects after marking is done?
23 os_sem_post(&join_semaphore
);
28 void thread_pool_init() {
29 char *str
= getenv("GC_THREADS"), *tail
;
33 unsigned long parse
= strtoul(str
, &tail
, 10);
34 if (tail
== str
|| parse
>= 256) lose("%s isn't a number of GC threads", str
);
38 #ifdef LISP_FEATURE_DARWIN
39 if (1) { // pre-existing semaphores aren't visible in a forked child
41 if (!start_semaphores
) {
43 start_semaphores
= successful_malloc(sizeof(os_sem_t
) * gc_threads
);
44 for (unsigned int i
= 0; i
< gc_threads
; i
++)
45 os_sem_init(start_semaphores
+ i
, 0);
46 os_sem_init(&join_semaphore
, 0);
49 threads
= successful_malloc(sizeof(pthread_t
) * gc_threads
);
50 for (uword_t i
= 0; i
< gc_threads
; i
++)
51 if (pthread_create(threads
+ i
, NULL
, worker
, (void*)i
))
52 lose("Failed to create GC thread #%ld", i
);
54 #ifdef LISP_FEATURE_LINUX
55 pthread_setname_np(threads
[i
], "Parallel GC");
60 static void wake_gc_threads() {
61 for (unsigned int i
= 0; i
< gc_threads
; i
++) os_sem_post(start_semaphores
+ i
);
64 static void join_gc_threads() {
65 for (unsigned int i
= 0; i
< gc_threads
; i
++) os_sem_wait(&join_semaphore
);
68 void run_on_thread_pool(void (*act
)(void)) {
73 action
= 0; // tidy up