1// Copyright 2009 The Go Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5package runtime 6 7import "unsafe" 8 9type mOS struct { 10 initialized bool 11 mutex pthreadmutex 12 cond pthreadcond 13 count int 14} 15 16func unimplemented(name string) { 17 println(name, "not implemented") 18 *(*int)(unsafe.Pointer(uintptr(1231))) = 1231 19} 20 21//go:nosplit 22func semacreate(mp *m) { 23 if mp.initialized { 24 return 25 } 26 mp.initialized = true 27 if err := pthread_mutex_init(&mp.mutex, nil); err != 0 { 28 throw("pthread_mutex_init") 29 } 30 if err := pthread_cond_init(&mp.cond, nil); err != 0 { 31 throw("pthread_cond_init") 32 } 33} 34 35//go:nosplit 36func semasleep(ns int64) int32 { 37 var start int64 38 if ns >= 0 { 39 start = nanotime() 40 } 41 mp := getg().m 42 pthread_mutex_lock(&mp.mutex) 43 for { 44 if mp.count > 0 { 45 mp.count-- 46 pthread_mutex_unlock(&mp.mutex) 47 return 0 48 } 49 if ns >= 0 { 50 spent := nanotime() - start 51 if spent >= ns { 52 pthread_mutex_unlock(&mp.mutex) 53 return -1 54 } 55 var t timespec 56 t.setNsec(ns - spent) 57 err := pthread_cond_timedwait_relative_np(&mp.cond, &mp.mutex, &t) 58 if err == _ETIMEDOUT { 59 pthread_mutex_unlock(&mp.mutex) 60 return -1 61 } 62 } else { 63 pthread_cond_wait(&mp.cond, &mp.mutex) 64 } 65 } 66} 67 68//go:nosplit 69func semawakeup(mp *m) { 70 pthread_mutex_lock(&mp.mutex) 71 mp.count++ 72 if mp.count > 0 { 73 pthread_cond_signal(&mp.cond) 74 } 75 pthread_mutex_unlock(&mp.mutex) 76} 77 78// The read and write file descriptors used by the sigNote functions. 79var sigNoteRead, sigNoteWrite int32 80 81// sigNoteSetup initializes an async-signal-safe note. 82// 83// The current implementation of notes on Darwin is not async-signal-safe, 84// because the functions pthread_mutex_lock, pthread_cond_signal, and 85// pthread_mutex_unlock, called by semawakeup, are not async-signal-safe. 86// There is only one case where we need to wake up a note from a signal 87// handler: the sigsend function. The signal handler code does not require 88// all the features of notes: it does not need to do a timed wait. 89// This is a separate implementation of notes, based on a pipe, that does 90// not support timed waits but is async-signal-safe. 91func sigNoteSetup(*note) { 92 if sigNoteRead != 0 || sigNoteWrite != 0 { 93 throw("duplicate sigNoteSetup") 94 } 95 var errno int32 96 sigNoteRead, sigNoteWrite, errno = pipe() 97 if errno != 0 { 98 throw("pipe failed") 99 } 100 closeonexec(sigNoteRead) 101 closeonexec(sigNoteWrite) 102 103 // Make the write end of the pipe non-blocking, so that if the pipe 104 // buffer is somehow full we will not block in the signal handler. 105 // Leave the read end of the pipe blocking so that we will block 106 // in sigNoteSleep. 107 setNonblock(sigNoteWrite) 108} 109 110// sigNoteWakeup wakes up a thread sleeping on a note created by sigNoteSetup. 111func sigNoteWakeup(*note) { 112 var b byte 113 write(uintptr(sigNoteWrite), unsafe.Pointer(&b), 1) 114} 115 116// sigNoteSleep waits for a note created by sigNoteSetup to be woken. 117func sigNoteSleep(*note) { 118 entersyscallblock() 119 var b byte 120 read(sigNoteRead, unsafe.Pointer(&b), 1) 121 exitsyscall() 122} 123 124// BSD interface for threading. 125func osinit() { 126 // pthread_create delayed until end of goenvs so that we 127 // can look at the environment first. 128 129 ncpu = getncpu() 130 physPageSize = getPageSize() 131} 132