22
33#define _GNU_SOURCE
44#include <pthread.h>
5- #include <semaphore.h>
65#include <signal.h>
76#include <stdint.h>
87#include <stdio.h>
98#include <unistd.h>
109
11- // BDWGC also uses SIGRTMIN+6 on Linux, which seems like a reasonable choice.
1210#ifdef __linux__
11+ #include <semaphore.h>
12+
13+ // BDWGC also uses SIGRTMIN+6 on Linux, which seems like a reasonable choice.
1314#define taskPauseSignal (SIGRTMIN + 6)
14- #endif
15+
16+ #elif __APPLE__
17+ #include <dispatch/dispatch.h>
18+ // SIGIO is for interrupt-driven I/O.
19+ // I don't think anybody should be using this nowadays, so I think we can
20+ // repurpose it as a signal for GC.
21+ // BDWGC uses a special way to pause/resume other threads on MacOS, which may be
22+ // better but needs more work. Using signal keeps the code similar between Linux
23+ // and MacOS.
24+ #define taskPauseSignal SIGIO
25+
26+ #endif // __linux__, __APPLE__
1527
1628// Pointer to the current task.Task structure.
1729// Ideally the entire task.Task structure would be a thread-local variable but
@@ -23,7 +35,11 @@ struct state_pass {
2335 void * args ;
2436 void * task ;
2537 uintptr_t * stackTop ;
38+ #if __APPLE__
39+ dispatch_semaphore_t startlock ;
40+ #else
2641 sem_t startlock ;
42+ #endif
2743};
2844
2945// Handle the GC pause in Go.
@@ -68,7 +84,11 @@ static void* start_wrapper(void *arg) {
6884
6985 // Notify the caller that the thread has successfully started and
7086 // initialized.
87+ #if __APPLE__
88+ dispatch_semaphore_signal (state -> startlock );
89+ #else
7190 sem_post (& state -> startlock );
91+ #endif
7292
7393 // Run the goroutine function.
7494 start (args );
@@ -92,11 +112,19 @@ int tinygo_task_start(uintptr_t fn, void *args, void *task, pthread_t *thread, u
92112 .task = task ,
93113 .stackTop = stackTop ,
94114 };
115+ #if __APPLE__
116+ state .startlock = dispatch_semaphore_create (0 );
117+ #else
95118 sem_init (& state .startlock , 0 , 0 );
119+ #endif
96120 int result = pthread_create (thread , NULL , & start_wrapper , & state );
97121
98122 // Wait until the thread has been created and read all state_pass variables.
123+ #if __APPLE__
124+ dispatch_semaphore_wait (state .startlock , DISPATCH_TIME_FOREVER );
125+ #else
99126 sem_wait (& state .startlock );
127+ #endif
100128
101129 return result ;
102130}
0 commit comments