Home | History | Annotate | Download | only in runtime
      1 // Copyright 2010 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 
      5 package runtime
      6 
      7 import "unsafe"
      8 
      9 type mOS struct {
     10 	waitsema      int32 // semaphore for parking on locks
     11 	waitsemacount int32
     12 	waitsemalock  int32
     13 }
     14 
     15 func nacl_exception_stack(p uintptr, size int32) int32
     16 func nacl_exception_handler(fn uintptr, arg unsafe.Pointer) int32
     17 func nacl_sem_create(flag int32) int32
     18 func nacl_sem_wait(sem int32) int32
     19 func nacl_sem_post(sem int32) int32
     20 func nacl_mutex_create(flag int32) int32
     21 func nacl_mutex_lock(mutex int32) int32
     22 func nacl_mutex_trylock(mutex int32) int32
     23 func nacl_mutex_unlock(mutex int32) int32
     24 func nacl_cond_create(flag int32) int32
     25 func nacl_cond_wait(cond, n int32) int32
     26 func nacl_cond_signal(cond int32) int32
     27 func nacl_cond_broadcast(cond int32) int32
     28 
     29 //go:noescape
     30 func nacl_cond_timed_wait_abs(cond, lock int32, ts *timespec) int32
     31 func nacl_thread_create(fn uintptr, stk, tls, xx unsafe.Pointer) int32
     32 
     33 //go:noescape
     34 func nacl_nanosleep(ts, extra *timespec) int32
     35 func nanotime() int64
     36 func mmap(addr unsafe.Pointer, n uintptr, prot, flags, fd int32, off uint32) (p unsafe.Pointer, err int)
     37 func exit(code int32)
     38 func osyield()
     39 
     40 //go:noescape
     41 func write(fd uintptr, p unsafe.Pointer, n int32) int32
     42 
     43 //go:linkname os_sigpipe os.sigpipe
     44 func os_sigpipe() {
     45 	throw("too many writes on closed pipe")
     46 }
     47 
     48 func dieFromSignal(sig uint32) {
     49 	exit(2)
     50 }
     51 
     52 func sigpanic() {
     53 	g := getg()
     54 	if !canpanic(g) {
     55 		throw("unexpected signal during runtime execution")
     56 	}
     57 
     58 	// Native Client only invokes the exception handler for memory faults.
     59 	g.sig = _SIGSEGV
     60 	panicmem()
     61 }
     62 
     63 func raiseproc(sig uint32) {
     64 }
     65 
     66 // Stubs so tests can link correctly. These should never be called.
     67 func open(name *byte, mode, perm int32) int32
     68 func closefd(fd int32) int32
     69 func read(fd int32, p unsafe.Pointer, n int32) int32
     70 
     71 type sigset struct{}
     72 
     73 // Called to initialize a new m (including the bootstrap m).
     74 // Called on the parent thread (main thread in case of bootstrap), can allocate memory.
     75 func mpreinit(mp *m) {
     76 	mp.gsignal = malg(32 * 1024)
     77 	mp.gsignal.m = mp
     78 }
     79 
     80 func sigtramp()
     81 
     82 //go:nosplit
     83 func msigsave(mp *m) {
     84 }
     85 
     86 //go:nosplit
     87 func msigrestore(sigmask sigset) {
     88 }
     89 
     90 //go:nosplit
     91 //go:nowritebarrierrec
     92 func clearSignalHandlers() {
     93 }
     94 
     95 //go:nosplit
     96 func sigblock() {
     97 }
     98 
     99 // Called to initialize a new m (including the bootstrap m).
    100 // Called on the new thread, cannot allocate memory.
    101 func minit() {
    102 	_g_ := getg()
    103 
    104 	// Initialize signal handling
    105 	ret := nacl_exception_stack(_g_.m.gsignal.stack.lo, 32*1024)
    106 	if ret < 0 {
    107 		print("runtime: nacl_exception_stack: error ", -ret, "\n")
    108 	}
    109 
    110 	ret = nacl_exception_handler(funcPC(sigtramp), nil)
    111 	if ret < 0 {
    112 		print("runtime: nacl_exception_handler: error ", -ret, "\n")
    113 	}
    114 }
    115 
    116 // Called from dropm to undo the effect of an minit.
    117 func unminit() {
    118 }
    119 
    120 func osinit() {
    121 	ncpu = 1
    122 	getg().m.procid = 2
    123 	//nacl_exception_handler(funcPC(sigtramp), nil);
    124 	physPageSize = 65536
    125 }
    126 
    127 func signame(sig uint32) string {
    128 	if sig >= uint32(len(sigtable)) {
    129 		return ""
    130 	}
    131 	return sigtable[sig].name
    132 }
    133 
    134 func crash() {
    135 	*(*int32)(nil) = 0
    136 }
    137 
    138 //go:noescape
    139 func getRandomData([]byte)
    140 
    141 func goenvs() {
    142 	goenvs_unix()
    143 }
    144 
    145 func initsig(preinit bool) {
    146 }
    147 
    148 //go:nosplit
    149 func usleep(us uint32) {
    150 	var ts timespec
    151 
    152 	ts.tv_sec = int64(us / 1e6)
    153 	ts.tv_nsec = int32(us%1e6) * 1e3
    154 	nacl_nanosleep(&ts, nil)
    155 }
    156 
    157 func mstart_nacl()
    158 
    159 // May run with m.p==nil, so write barriers are not allowed.
    160 //go:nowritebarrier
    161 func newosproc(mp *m, stk unsafe.Pointer) {
    162 	mp.tls[0] = uintptr(unsafe.Pointer(mp.g0))
    163 	mp.tls[1] = uintptr(unsafe.Pointer(mp))
    164 	ret := nacl_thread_create(funcPC(mstart_nacl), stk, unsafe.Pointer(&mp.tls[2]), nil)
    165 	if ret < 0 {
    166 		print("nacl_thread_create: error ", -ret, "\n")
    167 		throw("newosproc")
    168 	}
    169 }
    170 
    171 //go:noescape
    172 func exitThread(wait *uint32)
    173 
    174 //go:nosplit
    175 func semacreate(mp *m) {
    176 	if mp.waitsema != 0 {
    177 		return
    178 	}
    179 	systemstack(func() {
    180 		mu := nacl_mutex_create(0)
    181 		if mu < 0 {
    182 			print("nacl_mutex_create: error ", -mu, "\n")
    183 			throw("semacreate")
    184 		}
    185 		c := nacl_cond_create(0)
    186 		if c < 0 {
    187 			print("nacl_cond_create: error ", -c, "\n")
    188 			throw("semacreate")
    189 		}
    190 		mp.waitsema = c
    191 		mp.waitsemalock = mu
    192 	})
    193 }
    194 
    195 //go:nosplit
    196 func semasleep(ns int64) int32 {
    197 	var ret int32
    198 
    199 	systemstack(func() {
    200 		_g_ := getg()
    201 		if nacl_mutex_lock(_g_.m.waitsemalock) < 0 {
    202 			throw("semasleep")
    203 		}
    204 
    205 		for _g_.m.waitsemacount == 0 {
    206 			if ns < 0 {
    207 				if nacl_cond_wait(_g_.m.waitsema, _g_.m.waitsemalock) < 0 {
    208 					throw("semasleep")
    209 				}
    210 			} else {
    211 				var ts timespec
    212 				end := ns + nanotime()
    213 				ts.tv_sec = end / 1e9
    214 				ts.tv_nsec = int32(end % 1e9)
    215 				r := nacl_cond_timed_wait_abs(_g_.m.waitsema, _g_.m.waitsemalock, &ts)
    216 				if r == -_ETIMEDOUT {
    217 					nacl_mutex_unlock(_g_.m.waitsemalock)
    218 					ret = -1
    219 					return
    220 				}
    221 				if r < 0 {
    222 					throw("semasleep")
    223 				}
    224 			}
    225 		}
    226 
    227 		_g_.m.waitsemacount = 0
    228 		nacl_mutex_unlock(_g_.m.waitsemalock)
    229 		ret = 0
    230 	})
    231 	return ret
    232 }
    233 
    234 //go:nosplit
    235 func semawakeup(mp *m) {
    236 	systemstack(func() {
    237 		if nacl_mutex_lock(mp.waitsemalock) < 0 {
    238 			throw("semawakeup")
    239 		}
    240 		if mp.waitsemacount != 0 {
    241 			throw("semawakeup")
    242 		}
    243 		mp.waitsemacount = 1
    244 		nacl_cond_signal(mp.waitsema)
    245 		nacl_mutex_unlock(mp.waitsemalock)
    246 	})
    247 }
    248 
    249 func memlimit() uintptr {
    250 	return 0
    251 }
    252 
    253 // This runs on a foreign stack, without an m or a g. No stack split.
    254 //go:nosplit
    255 //go:norace
    256 //go:nowritebarrierrec
    257 func badsignal(sig uintptr) {
    258 	cgocallback(unsafe.Pointer(funcPC(badsignalgo)), noescape(unsafe.Pointer(&sig)), unsafe.Sizeof(sig), 0)
    259 }
    260 
    261 func badsignalgo(sig uintptr) {
    262 	if !sigsend(uint32(sig)) {
    263 		// A foreign thread received the signal sig, and the
    264 		// Go code does not want to handle it.
    265 		raisebadsignal(uint32(sig))
    266 	}
    267 }
    268 
    269 // This runs on a foreign stack, without an m or a g. No stack split.
    270 //go:nosplit
    271 func badsignal2() {
    272 	write(2, unsafe.Pointer(&badsignal1[0]), int32(len(badsignal1)))
    273 	exit(2)
    274 }
    275 
    276 var badsignal1 = []byte("runtime: signal received on thread not created by Go.\n")
    277 
    278 func raisebadsignal(sig uint32) {
    279 	badsignal2()
    280 }
    281 
    282 func madvise(addr unsafe.Pointer, n uintptr, flags int32) {}
    283 func munmap(addr unsafe.Pointer, n uintptr)               {}
    284 func setProcessCPUProfiler(hz int32)                      {}
    285 func setThreadCPUProfiler(hz int32)                       {}
    286 func sigdisable(uint32)                                   {}
    287 func sigenable(uint32)                                    {}
    288 func sigignore(uint32)                                    {}
    289 func closeonexec(int32)                                   {}
    290 
    291 // gsignalStack is unused on nacl.
    292 type gsignalStack struct{}
    293 
    294 var writelock uint32 // test-and-set spin lock for write
    295 
    296 /*
    297 An attempt at IRT. Doesn't work. See end of sys_nacl_amd64.s.
    298 
    299 void (*nacl_irt_query)(void);
    300 
    301 int8 nacl_irt_basic_v0_1_str[] = "nacl-irt-basic-0.1";
    302 void *nacl_irt_basic_v0_1[6]; // exit, gettod, clock, nanosleep, sched_yield, sysconf
    303 int32 nacl_irt_basic_v0_1_size = sizeof(nacl_irt_basic_v0_1);
    304 
    305 int8 nacl_irt_memory_v0_3_str[] = "nacl-irt-memory-0.3";
    306 void *nacl_irt_memory_v0_3[3]; // mmap, munmap, mprotect
    307 int32 nacl_irt_memory_v0_3_size = sizeof(nacl_irt_memory_v0_3);
    308 
    309 int8 nacl_irt_thread_v0_1_str[] = "nacl-irt-thread-0.1";
    310 void *nacl_irt_thread_v0_1[3]; // thread_create, thread_exit, thread_nice
    311 int32 nacl_irt_thread_v0_1_size = sizeof(nacl_irt_thread_v0_1);
    312 */
    313