diff --git a/builder/musl.go b/builder/musl.go index 3c79c7c43..54ec2c83e 100644 --- a/builder/musl.go +++ b/builder/musl.go @@ -113,6 +113,7 @@ var libMusl = Library{ librarySources: func(target string) ([]string, error) { arch := compileopts.MuslArchitecture(target) globs := []string{ + "conf/*.c", "env/*.c", "errno/*.c", "exit/*.c", diff --git a/src/internal/task/task_threads.c b/src/internal/task/task_threads.c index a14844f2e..6ada95fa8 100644 --- a/src/internal/task/task_threads.c +++ b/src/internal/task/task_threads.c @@ -6,6 +6,7 @@ #include #include #include +#include // BDWGC also uses SIGRTMIN+6 on Linux, which seems like a reasonable choice. #ifdef __linux__ @@ -29,7 +30,7 @@ struct state_pass { void tinygo_task_gc_pause(int sig); // Initialize the main thread. -void tinygo_task_init(void *mainTask, pthread_t *thread, void *context) { +void tinygo_task_init(void *mainTask, pthread_t *thread, int *numCPU, void *context) { // Make sure the current task pointer is set correctly for the main // goroutine as well. current_task = mainTask; @@ -43,6 +44,14 @@ void tinygo_task_init(void *mainTask, pthread_t *thread, void *context) { act.sa_flags = SA_SIGINFO; act.sa_handler = &tinygo_task_gc_pause; sigaction(taskPauseSignal, &act, NULL); + + // Obtain the number of CPUs available on program start (for NumCPU). + int num = sysconf(_SC_NPROCESSORS_ONLN); + if (num <= 0) { + // Fallback in case there is an error. + num = 1; + } + *numCPU = num; } void tinygo_task_exited(void*); diff --git a/src/internal/task/task_threads.go b/src/internal/task/task_threads.go index 93204fb9b..c3531ef9c 100644 --- a/src/internal/task/task_threads.go +++ b/src/internal/task/task_threads.go @@ -38,6 +38,8 @@ type state struct { // Goroutine counter, starting at 0 for the main goroutine. var goroutineID uintptr +var numCPU int32 + var mainTask Task // Queue of tasks (see QueueNext) that currently exist in the program. @@ -53,7 +55,7 @@ func OnSystemStack() bool { // startup, before starting any other goroutines. func Init(sp uintptr) { mainTask.state.stackTop = sp - tinygo_task_init(&mainTask, &mainTask.state.thread) + tinygo_task_init(&mainTask, &mainTask.state.thread, &numCPU) } // Return the task struct for the current thread. @@ -249,7 +251,7 @@ func runtimePanic(msg string) // that the 't' parameter won't escape (because it will). // //go:linkname tinygo_task_init tinygo_task_init -func tinygo_task_init(t *Task, thread *threadID) +func tinygo_task_init(t *Task, thread *threadID, numCPU *int32) // Here same as for tinygo_task_init. // @@ -263,3 +265,7 @@ func tinygo_task_send_gc_signal(threadID) //export tinygo_task_current func tinygo_task_current() unsafe.Pointer + +func NumCPU() int { + return int(numCPU) +} diff --git a/src/runtime/debug.go b/src/runtime/debug.go index 139e18bcd..230515908 100644 --- a/src/runtime/debug.go +++ b/src/runtime/debug.go @@ -1,14 +1,5 @@ package runtime -// NumCPU returns the number of logical CPUs usable by the current process. -// -// The set of available CPUs is checked by querying the operating system -// at process startup. Changes to operating system CPU allocation after -// process startup are not reflected. -func NumCPU() int { - return 1 -} - // Stub for NumCgoCall, does not return the real value func NumCgoCall() int { return 0 diff --git a/src/runtime/scheduler_cooperative.go b/src/runtime/scheduler_cooperative.go index 85c8f56f0..bffda7228 100644 --- a/src/runtime/scheduler_cooperative.go +++ b/src/runtime/scheduler_cooperative.go @@ -57,6 +57,11 @@ func Gosched() { task.Pause() } +// NumCPU returns the number of logical CPUs usable by the current process. +func NumCPU() int { + return 1 +} + // Add this task to the sleep queue, assuming its state is set to sleeping. func addSleepTask(t *task.Task, duration timeUnit) { if schedulerDebug { diff --git a/src/runtime/scheduler_none.go b/src/runtime/scheduler_none.go index a5acfd430..7e2ddeb66 100644 --- a/src/runtime/scheduler_none.go +++ b/src/runtime/scheduler_none.go @@ -40,6 +40,11 @@ func Gosched() { // There are no other goroutines, so there's nothing to schedule. } +// NumCPU returns the number of logical CPUs usable by the current process. +func NumCPU() int { + return 1 +} + func addTimer(tim *timerNode) { runtimePanic("timers not supported without a scheduler") } diff --git a/src/runtime/scheduler_threads.go b/src/runtime/scheduler_threads.go index e553a5b9c..292499354 100644 --- a/src/runtime/scheduler_threads.go +++ b/src/runtime/scheduler_threads.go @@ -50,6 +50,11 @@ func Gosched() { // operation, so is probably best not to use. } +// NumCPU returns the number of logical CPUs usable by the current process. +func NumCPU() int { + return task.NumCPU() +} + // Separate goroutine (thread) that runs timer callbacks when they expire. func timerRunner() { for {