Skip to content

Commit 0e43146

Browse files
aykevldeadprogram
authored andcommitted
darwin: add threading support and use it by default
1 parent 93f4099 commit 0e43146

File tree

3 files changed

+44
-4
lines changed

3 files changed

+44
-4
lines changed

compileopts/target.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -385,7 +385,7 @@ func defaultTarget(options *Options) (*TargetSpec, error) {
385385
platformVersion = "11.0.0" // first macosx platform with arm64 support
386386
}
387387
llvmvendor = "apple"
388-
spec.Scheduler = "tasks"
388+
spec.Scheduler = "threads"
389389
spec.Linker = "ld.lld"
390390
spec.Libc = "darwin-libSystem"
391391
// Use macosx* instead of darwin, otherwise darwin/arm64 will refer to
@@ -399,6 +399,7 @@ func defaultTarget(options *Options) (*TargetSpec, error) {
399399
)
400400
spec.ExtraFiles = append(spec.ExtraFiles,
401401
"src/internal/futex/futex_darwin.c",
402+
"src/internal/task/task_threads.c",
402403
"src/runtime/os_darwin.c",
403404
"src/runtime/runtime_unix.c",
404405
"src/runtime/signal.c")

src/internal/task/darwin.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
//go:build darwin
2+
3+
package task
4+
5+
import "unsafe"
6+
7+
// MacOS uses a pointer so unsafe.Pointer should be fine:
8+
//
9+
// typedef struct _opaque_pthread_t *__darwin_pthread_t;
10+
// typedef __darwin_pthread_t pthread_t;
11+
type threadID unsafe.Pointer

src/internal/task/task_threads.c

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,28 @@
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

Comments
 (0)