// Copyright 2009 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package runtime import ( "unsafe" ) type mOS struct { initialized bool mutex pthreadmutex cond pthreadcond count int } func unimplemented(name string) { println(name, "not implemented") *(*int)(unsafe.Pointer(uintptr(1231))) = 1231 } //go:nosplit func semacreate(mp *m) { if mp.initialized { return } mp.initialized = true if err := pthread_mutex_init(&mp.mutex, nil); err != 0 { throw("pthread_mutex_init") } if err := pthread_cond_init(&mp.cond, nil); err != 0 { throw("pthread_cond_init") } } //go:nosplit func semasleep(ns int64) int32 { var start int64 if ns >= 0 { start = nanotime() } mp := getg().m pthread_mutex_lock(&mp.mutex) for { if mp.count > 0 { mp.count-- pthread_mutex_unlock(&mp.mutex) return 0 } if ns >= 0 { spent := nanotime() - start if spent >= ns { pthread_mutex_unlock(&mp.mutex) return -1 } var t timespec t.setNsec(ns - spent) err := pthread_cond_timedwait_relative_np(&mp.cond, &mp.mutex, &t) if err == _ETIMEDOUT { pthread_mutex_unlock(&mp.mutex) return -1 } } else { pthread_cond_wait(&mp.cond, &mp.mutex) } } } //go:nosplit func semawakeup(mp *m) { pthread_mutex_lock(&mp.mutex) mp.count++ if mp.count > 0 { pthread_cond_signal(&mp.cond) } pthread_mutex_unlock(&mp.mutex) } // The read and write file descriptors used by the sigNote functions. var sigNoteRead, sigNoteWrite int32 // sigNoteSetup initializes an async-signal-safe note. // // The current implementation of notes on Darwin is not async-signal-safe, // because the functions pthread_mutex_lock, pthread_cond_signal, and // pthread_mutex_unlock, called by semawakeup, are not async-signal-safe. // There is only one case where we need to wake up a note from a signal // handler: the sigsend function. The signal handler code does not require // all the features of notes: it does not need to do a timed wait. // This is a separate implementation of notes, based on a pipe, that does // not support timed waits but is async-signal-safe. func sigNoteSetup(*note) { if sigNoteRead != 0 || sigNoteWrite != 0 { throw("duplicate sigNoteSetup") } var errno int32 sigNoteRead, sigNoteWrite, errno = pipe() if errno != 0 { throw("pipe failed") } closeonexec(sigNoteRead) closeonexec(sigNoteWrite) // Make the write end of the pipe non-blocking, so that if the pipe // buffer is somehow full we will not block in the signal handler. // Leave the read end of the pipe blocking so that we will block // in sigNoteSleep. setNonblock(sigNoteWrite) } // sigNoteWakeup wakes up a thread sleeping on a note created by sigNoteSetup. func sigNoteWakeup(*note) { var b byte write(uintptr(sigNoteWrite), unsafe.Pointer(&b), 1) } // sigNoteSleep waits for a note created by sigNoteSetup to be woken. func sigNoteSleep(*note) { for { var b byte entersyscallblock() n := read(sigNoteRead, unsafe.Pointer(&b), 1) exitsyscall() if n != -_EINTR { return } } } // BSD interface for threading. func osinit() { // pthread_create delayed until end of goenvs so that we // can look at the environment first. ncpu = getncpu() physPageSize = getPageSize() } //go:nosplit func validSIGPROF(mp *m, c *sigctxt) bool { return true }