%other-pointer-widetag derive-type: derive for simple-array.
[sbcl.git] / src / runtime / gc-thread-pool.c
blob812bd24425545c44672c5848cf48d9c4f96c50c8
1 #define _GNU_SOURCE
2 #include <errno.h>
3 #include <pthread.h>
4 #include <stdlib.h>
5 #include <semaphore.h>
6 #include "interr.h"
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;
16 while (1) {
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?
22 action();
23 os_sem_post(&join_semaphore);
25 return NULL;
28 void thread_pool_init() {
29 char *str = getenv("GC_THREADS"), *tail;
30 if (str == NULL) {
31 gc_threads = 3;
32 } else {
33 unsigned long parse = strtoul(str, &tail, 10);
34 if (tail == str || parse >= 256) lose("%s isn't a number of GC threads", str);
35 gc_threads = parse;
38 #ifdef LISP_FEATURE_DARWIN
39 if (1) { // pre-existing semaphores aren't visible in a forked child
40 #else
41 if (!start_semaphores) {
42 #endif
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);
53 else {
54 #ifdef LISP_FEATURE_LINUX
55 pthread_setname_np(threads[i], "Parallel GC");
56 #endif
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)) {
69 action = act;
70 wake_gc_threads();
71 act();
72 join_gc_threads();
73 action = 0; // tidy up