mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-15 08:23:41 +00:00
darwin: add threading support and use it by default
This commit is contained in:
committed by
Ron Evans
parent
93f40992c1
commit
0e43146d32
@@ -385,7 +385,7 @@ func defaultTarget(options *Options) (*TargetSpec, error) {
|
|||||||
platformVersion = "11.0.0" // first macosx platform with arm64 support
|
platformVersion = "11.0.0" // first macosx platform with arm64 support
|
||||||
}
|
}
|
||||||
llvmvendor = "apple"
|
llvmvendor = "apple"
|
||||||
spec.Scheduler = "tasks"
|
spec.Scheduler = "threads"
|
||||||
spec.Linker = "ld.lld"
|
spec.Linker = "ld.lld"
|
||||||
spec.Libc = "darwin-libSystem"
|
spec.Libc = "darwin-libSystem"
|
||||||
// Use macosx* instead of darwin, otherwise darwin/arm64 will refer to
|
// Use macosx* instead of darwin, otherwise darwin/arm64 will refer to
|
||||||
@@ -399,6 +399,7 @@ func defaultTarget(options *Options) (*TargetSpec, error) {
|
|||||||
)
|
)
|
||||||
spec.ExtraFiles = append(spec.ExtraFiles,
|
spec.ExtraFiles = append(spec.ExtraFiles,
|
||||||
"src/internal/futex/futex_darwin.c",
|
"src/internal/futex/futex_darwin.c",
|
||||||
|
"src/internal/task/task_threads.c",
|
||||||
"src/runtime/os_darwin.c",
|
"src/runtime/os_darwin.c",
|
||||||
"src/runtime/runtime_unix.c",
|
"src/runtime/runtime_unix.c",
|
||||||
"src/runtime/signal.c")
|
"src/runtime/signal.c")
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
//go:build darwin
|
||||||
|
|
||||||
|
package task
|
||||||
|
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
|
// MacOS uses a pointer so unsafe.Pointer should be fine:
|
||||||
|
//
|
||||||
|
// typedef struct _opaque_pthread_t *__darwin_pthread_t;
|
||||||
|
// typedef __darwin_pthread_t pthread_t;
|
||||||
|
type threadID unsafe.Pointer
|
||||||
@@ -2,16 +2,28 @@
|
|||||||
|
|
||||||
#define _GNU_SOURCE
|
#define _GNU_SOURCE
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <semaphore.h>
|
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
// BDWGC also uses SIGRTMIN+6 on Linux, which seems like a reasonable choice.
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
|
#include <semaphore.h>
|
||||||
|
|
||||||
|
// BDWGC also uses SIGRTMIN+6 on Linux, which seems like a reasonable choice.
|
||||||
#define taskPauseSignal (SIGRTMIN + 6)
|
#define taskPauseSignal (SIGRTMIN + 6)
|
||||||
#endif
|
|
||||||
|
#elif __APPLE__
|
||||||
|
#include <dispatch/dispatch.h>
|
||||||
|
// SIGIO is for interrupt-driven I/O.
|
||||||
|
// I don't think anybody should be using this nowadays, so I think we can
|
||||||
|
// repurpose it as a signal for GC.
|
||||||
|
// BDWGC uses a special way to pause/resume other threads on MacOS, which may be
|
||||||
|
// better but needs more work. Using signal keeps the code similar between Linux
|
||||||
|
// and MacOS.
|
||||||
|
#define taskPauseSignal SIGIO
|
||||||
|
|
||||||
|
#endif // __linux__, __APPLE__
|
||||||
|
|
||||||
// Pointer to the current task.Task structure.
|
// Pointer to the current task.Task structure.
|
||||||
// Ideally the entire task.Task structure would be a thread-local variable but
|
// Ideally the entire task.Task structure would be a thread-local variable but
|
||||||
@@ -23,7 +35,11 @@ struct state_pass {
|
|||||||
void *args;
|
void *args;
|
||||||
void *task;
|
void *task;
|
||||||
uintptr_t *stackTop;
|
uintptr_t *stackTop;
|
||||||
|
#if __APPLE__
|
||||||
|
dispatch_semaphore_t startlock;
|
||||||
|
#else
|
||||||
sem_t startlock;
|
sem_t startlock;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
// Handle the GC pause in Go.
|
// Handle the GC pause in Go.
|
||||||
@@ -68,7 +84,11 @@ static void* start_wrapper(void *arg) {
|
|||||||
|
|
||||||
// Notify the caller that the thread has successfully started and
|
// Notify the caller that the thread has successfully started and
|
||||||
// initialized.
|
// initialized.
|
||||||
|
#if __APPLE__
|
||||||
|
dispatch_semaphore_signal(state->startlock);
|
||||||
|
#else
|
||||||
sem_post(&state->startlock);
|
sem_post(&state->startlock);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Run the goroutine function.
|
// Run the goroutine function.
|
||||||
start(args);
|
start(args);
|
||||||
@@ -92,11 +112,19 @@ int tinygo_task_start(uintptr_t fn, void *args, void *task, pthread_t *thread, u
|
|||||||
.task = task,
|
.task = task,
|
||||||
.stackTop = stackTop,
|
.stackTop = stackTop,
|
||||||
};
|
};
|
||||||
|
#if __APPLE__
|
||||||
|
state.startlock = dispatch_semaphore_create(0);
|
||||||
|
#else
|
||||||
sem_init(&state.startlock, 0, 0);
|
sem_init(&state.startlock, 0, 0);
|
||||||
|
#endif
|
||||||
int result = pthread_create(thread, NULL, &start_wrapper, &state);
|
int result = pthread_create(thread, NULL, &start_wrapper, &state);
|
||||||
|
|
||||||
// Wait until the thread has been created and read all state_pass variables.
|
// Wait until the thread has been created and read all state_pass variables.
|
||||||
|
#if __APPLE__
|
||||||
|
dispatch_semaphore_wait(state.startlock, DISPATCH_TIME_FOREVER);
|
||||||
|
#else
|
||||||
sem_wait(&state.startlock);
|
sem_wait(&state.startlock);
|
||||||
|
#endif
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user