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