1// Copyright 2018 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// This file contains main runtime AIX syscalls.
6// Pollset syscalls are in netpoll_aix.go.
7// The implementation is based on Solaris and Windows.
8// Each syscall is made by calling its libc symbol using asmcgocall and asmsyscall6
9// assembly functions.
10
11package runtime
12
13import (
14	"unsafe"
15)
16
17// Symbols imported for __start function.
18
19//go:cgo_import_dynamic libc___n_pthreads __n_pthreads "libpthread.a/shr_xpg5_64.o"
20//go:cgo_import_dynamic libc___mod_init __mod_init "libc.a/shr_64.o"
21//go:linkname libc___n_pthreads libc___n_pthreads
22//go:linkname libc___mod_init libc___mod_init
23
24var (
25	libc___n_pthreads,
26	libc___mod_init libFunc
27)
28
29// Syscalls
30
31//go:cgo_import_dynamic libc__Errno _Errno "libc.a/shr_64.o"
32//go:cgo_import_dynamic libc_clock_gettime clock_gettime "libc.a/shr_64.o"
33//go:cgo_import_dynamic libc_close close "libc.a/shr_64.o"
34//go:cgo_import_dynamic libc_exit _exit "libc.a/shr_64.o"
35//go:cgo_import_dynamic libc_getpid getpid "libc.a/shr_64.o"
36//go:cgo_import_dynamic libc_getsystemcfg getsystemcfg "libc.a/shr_64.o"
37//go:cgo_import_dynamic libc_kill kill "libc.a/shr_64.o"
38//go:cgo_import_dynamic libc_madvise madvise "libc.a/shr_64.o"
39//go:cgo_import_dynamic libc_malloc malloc "libc.a/shr_64.o"
40//go:cgo_import_dynamic libc_mmap mmap "libc.a/shr_64.o"
41//go:cgo_import_dynamic libc_mprotect mprotect "libc.a/shr_64.o"
42//go:cgo_import_dynamic libc_munmap munmap "libc.a/shr_64.o"
43//go:cgo_import_dynamic libc_open open "libc.a/shr_64.o"
44//go:cgo_import_dynamic libc_pipe pipe "libc.a/shr_64.o"
45//go:cgo_import_dynamic libc_raise raise "libc.a/shr_64.o"
46//go:cgo_import_dynamic libc_read read "libc.a/shr_64.o"
47//go:cgo_import_dynamic libc_sched_yield sched_yield "libc.a/shr_64.o"
48//go:cgo_import_dynamic libc_sem_init sem_init "libc.a/shr_64.o"
49//go:cgo_import_dynamic libc_sem_post sem_post "libc.a/shr_64.o"
50//go:cgo_import_dynamic libc_sem_timedwait sem_timedwait "libc.a/shr_64.o"
51//go:cgo_import_dynamic libc_sem_wait sem_wait "libc.a/shr_64.o"
52//go:cgo_import_dynamic libc_setitimer setitimer "libc.a/shr_64.o"
53//go:cgo_import_dynamic libc_sigaction sigaction "libc.a/shr_64.o"
54//go:cgo_import_dynamic libc_sigaltstack sigaltstack "libc.a/shr_64.o"
55//go:cgo_import_dynamic libc_sysconf sysconf "libc.a/shr_64.o"
56//go:cgo_import_dynamic libc_usleep usleep "libc.a/shr_64.o"
57//go:cgo_import_dynamic libc_write write "libc.a/shr_64.o"
58//go:cgo_import_dynamic libc_getuid getuid "libc.a/shr_64.o"
59//go:cgo_import_dynamic libc_geteuid geteuid "libc.a/shr_64.o"
60//go:cgo_import_dynamic libc_getgid getgid "libc.a/shr_64.o"
61//go:cgo_import_dynamic libc_getegid getegid "libc.a/shr_64.o"
62
63//go:cgo_import_dynamic libpthread___pth_init __pth_init "libpthread.a/shr_xpg5_64.o"
64//go:cgo_import_dynamic libpthread_attr_destroy pthread_attr_destroy "libpthread.a/shr_xpg5_64.o"
65//go:cgo_import_dynamic libpthread_attr_init pthread_attr_init "libpthread.a/shr_xpg5_64.o"
66//go:cgo_import_dynamic libpthread_attr_getstacksize pthread_attr_getstacksize "libpthread.a/shr_xpg5_64.o"
67//go:cgo_import_dynamic libpthread_attr_setstacksize pthread_attr_setstacksize "libpthread.a/shr_xpg5_64.o"
68//go:cgo_import_dynamic libpthread_attr_setdetachstate pthread_attr_setdetachstate "libpthread.a/shr_xpg5_64.o"
69//go:cgo_import_dynamic libpthread_attr_setstackaddr pthread_attr_setstackaddr "libpthread.a/shr_xpg5_64.o"
70//go:cgo_import_dynamic libpthread_create pthread_create "libpthread.a/shr_xpg5_64.o"
71//go:cgo_import_dynamic libpthread_sigthreadmask sigthreadmask "libpthread.a/shr_xpg5_64.o"
72//go:cgo_import_dynamic libpthread_self pthread_self "libpthread.a/shr_xpg5_64.o"
73//go:cgo_import_dynamic libpthread_kill pthread_kill "libpthread.a/shr_xpg5_64.o"
74
75//go:linkname libc__Errno libc__Errno
76//go:linkname libc_clock_gettime libc_clock_gettime
77//go:linkname libc_close libc_close
78//go:linkname libc_exit libc_exit
79//go:linkname libc_getpid libc_getpid
80//go:linkname libc_getsystemcfg libc_getsystemcfg
81//go:linkname libc_kill libc_kill
82//go:linkname libc_madvise libc_madvise
83//go:linkname libc_malloc libc_malloc
84//go:linkname libc_mmap libc_mmap
85//go:linkname libc_mprotect libc_mprotect
86//go:linkname libc_munmap libc_munmap
87//go:linkname libc_open libc_open
88//go:linkname libc_pipe libc_pipe
89//go:linkname libc_raise libc_raise
90//go:linkname libc_read libc_read
91//go:linkname libc_sched_yield libc_sched_yield
92//go:linkname libc_sem_init libc_sem_init
93//go:linkname libc_sem_post libc_sem_post
94//go:linkname libc_sem_timedwait libc_sem_timedwait
95//go:linkname libc_sem_wait libc_sem_wait
96//go:linkname libc_setitimer libc_setitimer
97//go:linkname libc_sigaction libc_sigaction
98//go:linkname libc_sigaltstack libc_sigaltstack
99//go:linkname libc_sysconf libc_sysconf
100//go:linkname libc_usleep libc_usleep
101//go:linkname libc_write libc_write
102//go:linkname libc_getuid libc_getuid
103//go:linkname libc_geteuid libc_geteuid
104//go:linkname libc_getgid libc_getgid
105//go:linkname libc_getegid libc_getegid
106
107//go:linkname libpthread___pth_init libpthread___pth_init
108//go:linkname libpthread_attr_destroy libpthread_attr_destroy
109//go:linkname libpthread_attr_init libpthread_attr_init
110//go:linkname libpthread_attr_getstacksize libpthread_attr_getstacksize
111//go:linkname libpthread_attr_setstacksize libpthread_attr_setstacksize
112//go:linkname libpthread_attr_setdetachstate libpthread_attr_setdetachstate
113//go:linkname libpthread_attr_setstackaddr libpthread_attr_setstackaddr
114//go:linkname libpthread_create libpthread_create
115//go:linkname libpthread_sigthreadmask libpthread_sigthreadmask
116//go:linkname libpthread_self libpthread_self
117//go:linkname libpthread_kill libpthread_kill
118
119var (
120	//libc
121	libc__Errno,
122	libc_clock_gettime,
123	libc_close,
124	libc_exit,
125	libc_getpid,
126	libc_getsystemcfg,
127	libc_kill,
128	libc_madvise,
129	libc_malloc,
130	libc_mmap,
131	libc_mprotect,
132	libc_munmap,
133	libc_open,
134	libc_pipe,
135	libc_raise,
136	libc_read,
137	libc_sched_yield,
138	libc_sem_init,
139	libc_sem_post,
140	libc_sem_timedwait,
141	libc_sem_wait,
142	libc_setitimer,
143	libc_sigaction,
144	libc_sigaltstack,
145	libc_sysconf,
146	libc_usleep,
147	libc_write,
148	libc_getuid,
149	libc_geteuid,
150	libc_getgid,
151	libc_getegid,
152	//libpthread
153	libpthread___pth_init,
154	libpthread_attr_destroy,
155	libpthread_attr_init,
156	libpthread_attr_getstacksize,
157	libpthread_attr_setstacksize,
158	libpthread_attr_setdetachstate,
159	libpthread_attr_setstackaddr,
160	libpthread_create,
161	libpthread_sigthreadmask,
162	libpthread_self,
163	libpthread_kill libFunc
164)
165
166type libFunc uintptr
167
168// asmsyscall6 calls the libc symbol using a C convention.
169// It's defined in sys_aix_ppc64.go.
170var asmsyscall6 libFunc
171
172// syscallX functions must always be called with g != nil and m != nil,
173// as it relies on g.m.libcall to pass arguments to asmcgocall.
174// The few cases where syscalls haven't a g or a m must call their equivalent
175// function in sys_aix_ppc64.s to handle them.
176
177//go:nowritebarrier
178//go:nosplit
179func syscall0(fn *libFunc) (r, err uintptr) {
180	gp := getg()
181	mp := gp.m
182	resetLibcall := true
183	if mp.libcallsp == 0 {
184		mp.libcallg.set(gp)
185		mp.libcallpc = getcallerpc()
186		// sp must be the last, because once async cpu profiler finds
187		// all three values to be non-zero, it will use them
188		mp.libcallsp = getcallersp()
189	} else {
190		resetLibcall = false // See comment in sys_darwin.go:libcCall
191	}
192
193	c := libcall{
194		fn:   uintptr(unsafe.Pointer(fn)),
195		n:    0,
196		args: uintptr(unsafe.Pointer(&fn)), // it's unused but must be non-nil, otherwise crashes
197	}
198
199	asmcgocall(unsafe.Pointer(&asmsyscall6), unsafe.Pointer(&c))
200
201	if resetLibcall {
202		mp.libcallsp = 0
203	}
204
205	return c.r1, c.err
206}
207
208//go:nowritebarrier
209//go:nosplit
210func syscall1(fn *libFunc, a0 uintptr) (r, err uintptr) {
211	gp := getg()
212	mp := gp.m
213	resetLibcall := true
214	if mp.libcallsp == 0 {
215		mp.libcallg.set(gp)
216		mp.libcallpc = getcallerpc()
217		// sp must be the last, because once async cpu profiler finds
218		// all three values to be non-zero, it will use them
219		mp.libcallsp = getcallersp()
220	} else {
221		resetLibcall = false // See comment in sys_darwin.go:libcCall
222	}
223
224	c := libcall{
225		fn:   uintptr(unsafe.Pointer(fn)),
226		n:    1,
227		args: uintptr(unsafe.Pointer(&a0)),
228	}
229
230	asmcgocall(unsafe.Pointer(&asmsyscall6), unsafe.Pointer(&c))
231
232	if resetLibcall {
233		mp.libcallsp = 0
234	}
235
236	return c.r1, c.err
237}
238
239//go:nowritebarrier
240//go:nosplit
241//go:cgo_unsafe_args
242func syscall2(fn *libFunc, a0, a1 uintptr) (r, err uintptr) {
243	gp := getg()
244	mp := gp.m
245	resetLibcall := true
246	if mp.libcallsp == 0 {
247		mp.libcallg.set(gp)
248		mp.libcallpc = getcallerpc()
249		// sp must be the last, because once async cpu profiler finds
250		// all three values to be non-zero, it will use them
251		mp.libcallsp = getcallersp()
252	} else {
253		resetLibcall = false // See comment in sys_darwin.go:libcCall
254	}
255
256	c := libcall{
257		fn:   uintptr(unsafe.Pointer(fn)),
258		n:    2,
259		args: uintptr(unsafe.Pointer(&a0)),
260	}
261
262	asmcgocall(unsafe.Pointer(&asmsyscall6), unsafe.Pointer(&c))
263
264	if resetLibcall {
265		mp.libcallsp = 0
266	}
267
268	return c.r1, c.err
269}
270
271//go:nowritebarrier
272//go:nosplit
273//go:cgo_unsafe_args
274func syscall3(fn *libFunc, a0, a1, a2 uintptr) (r, err uintptr) {
275	gp := getg()
276	mp := gp.m
277	resetLibcall := true
278	if mp.libcallsp == 0 {
279		mp.libcallg.set(gp)
280		mp.libcallpc = getcallerpc()
281		// sp must be the last, because once async cpu profiler finds
282		// all three values to be non-zero, it will use them
283		mp.libcallsp = getcallersp()
284	} else {
285		resetLibcall = false // See comment in sys_darwin.go:libcCall
286	}
287
288	c := libcall{
289		fn:   uintptr(unsafe.Pointer(fn)),
290		n:    3,
291		args: uintptr(unsafe.Pointer(&a0)),
292	}
293
294	asmcgocall(unsafe.Pointer(&asmsyscall6), unsafe.Pointer(&c))
295
296	if resetLibcall {
297		mp.libcallsp = 0
298	}
299
300	return c.r1, c.err
301}
302
303//go:nowritebarrier
304//go:nosplit
305//go:cgo_unsafe_args
306func syscall4(fn *libFunc, a0, a1, a2, a3 uintptr) (r, err uintptr) {
307	gp := getg()
308	mp := gp.m
309	resetLibcall := true
310	if mp.libcallsp == 0 {
311		mp.libcallg.set(gp)
312		mp.libcallpc = getcallerpc()
313		// sp must be the last, because once async cpu profiler finds
314		// all three values to be non-zero, it will use them
315		mp.libcallsp = getcallersp()
316	} else {
317		resetLibcall = false // See comment in sys_darwin.go:libcCall
318	}
319
320	c := libcall{
321		fn:   uintptr(unsafe.Pointer(fn)),
322		n:    4,
323		args: uintptr(unsafe.Pointer(&a0)),
324	}
325
326	asmcgocall(unsafe.Pointer(&asmsyscall6), unsafe.Pointer(&c))
327
328	if resetLibcall {
329		mp.libcallsp = 0
330	}
331
332	return c.r1, c.err
333}
334
335//go:nowritebarrier
336//go:nosplit
337//go:cgo_unsafe_args
338func syscall5(fn *libFunc, a0, a1, a2, a3, a4 uintptr) (r, err uintptr) {
339	gp := getg()
340	mp := gp.m
341	resetLibcall := true
342	if mp.libcallsp == 0 {
343		mp.libcallg.set(gp)
344		mp.libcallpc = getcallerpc()
345		// sp must be the last, because once async cpu profiler finds
346		// all three values to be non-zero, it will use them
347		mp.libcallsp = getcallersp()
348	} else {
349		resetLibcall = false // See comment in sys_darwin.go:libcCall
350	}
351
352	c := libcall{
353		fn:   uintptr(unsafe.Pointer(fn)),
354		n:    5,
355		args: uintptr(unsafe.Pointer(&a0)),
356	}
357
358	asmcgocall(unsafe.Pointer(&asmsyscall6), unsafe.Pointer(&c))
359
360	if resetLibcall {
361		mp.libcallsp = 0
362	}
363
364	return c.r1, c.err
365}
366
367//go:nowritebarrier
368//go:nosplit
369//go:cgo_unsafe_args
370func syscall6(fn *libFunc, a0, a1, a2, a3, a4, a5 uintptr) (r, err uintptr) {
371	gp := getg()
372	mp := gp.m
373	resetLibcall := true
374	if mp.libcallsp == 0 {
375		mp.libcallg.set(gp)
376		mp.libcallpc = getcallerpc()
377		// sp must be the last, because once async cpu profiler finds
378		// all three values to be non-zero, it will use them
379		mp.libcallsp = getcallersp()
380	} else {
381		resetLibcall = false // See comment in sys_darwin.go:libcCall
382	}
383
384	c := libcall{
385		fn:   uintptr(unsafe.Pointer(fn)),
386		n:    6,
387		args: uintptr(unsafe.Pointer(&a0)),
388	}
389
390	asmcgocall(unsafe.Pointer(&asmsyscall6), unsafe.Pointer(&c))
391
392	if resetLibcall {
393		mp.libcallsp = 0
394	}
395
396	return c.r1, c.err
397}
398
399func exit1(code int32)
400
401//go:nosplit
402func exit(code int32) {
403	gp := getg()
404
405	// Check the validity of g because without a g during
406	// newosproc0.
407	if gp != nil {
408		syscall1(&libc_exit, uintptr(code))
409		return
410	}
411	exit1(code)
412}
413
414func write2(fd, p uintptr, n int32) int32
415
416//go:nosplit
417func write1(fd uintptr, p unsafe.Pointer, n int32) int32 {
418	gp := getg()
419
420	// Check the validity of g because without a g during
421	// newosproc0.
422	if gp != nil {
423		r, errno := syscall3(&libc_write, uintptr(fd), uintptr(p), uintptr(n))
424		if int32(r) < 0 {
425			return -int32(errno)
426		}
427		return int32(r)
428	}
429	// Note that in this case we can't return a valid errno value.
430	return write2(fd, uintptr(p), n)
431}
432
433//go:nosplit
434func read(fd int32, p unsafe.Pointer, n int32) int32 {
435	r, errno := syscall3(&libc_read, uintptr(fd), uintptr(p), uintptr(n))
436	if int32(r) < 0 {
437		return -int32(errno)
438	}
439	return int32(r)
440}
441
442//go:nosplit
443func open(name *byte, mode, perm int32) int32 {
444	r, _ := syscall3(&libc_open, uintptr(unsafe.Pointer(name)), uintptr(mode), uintptr(perm))
445	return int32(r)
446}
447
448//go:nosplit
449func closefd(fd int32) int32 {
450	r, _ := syscall1(&libc_close, uintptr(fd))
451	return int32(r)
452}
453
454//go:nosplit
455func pipe() (r, w int32, errno int32) {
456	var p [2]int32
457	_, err := syscall1(&libc_pipe, uintptr(noescape(unsafe.Pointer(&p[0]))))
458	return p[0], p[1], int32(err)
459}
460
461// mmap calls the mmap system call.
462// We only pass the lower 32 bits of file offset to the
463// assembly routine; the higher bits (if required), should be provided
464// by the assembly routine as 0.
465// The err result is an OS error code such as ENOMEM.
466//
467//go:nosplit
468func mmap(addr unsafe.Pointer, n uintptr, prot, flags, fd int32, off uint32) (unsafe.Pointer, int) {
469	r, err0 := syscall6(&libc_mmap, uintptr(addr), uintptr(n), uintptr(prot), uintptr(flags), uintptr(fd), uintptr(off))
470	if r == ^uintptr(0) {
471		return nil, int(err0)
472	}
473	return unsafe.Pointer(r), int(err0)
474}
475
476//go:nosplit
477func mprotect(addr unsafe.Pointer, n uintptr, prot int32) (unsafe.Pointer, int) {
478	r, err0 := syscall3(&libc_mprotect, uintptr(addr), uintptr(n), uintptr(prot))
479	if r == ^uintptr(0) {
480		return nil, int(err0)
481	}
482	return unsafe.Pointer(r), int(err0)
483}
484
485//go:nosplit
486func munmap(addr unsafe.Pointer, n uintptr) {
487	r, err := syscall2(&libc_munmap, uintptr(addr), uintptr(n))
488	if int32(r) == -1 {
489		println("syscall munmap failed: ", hex(err))
490		throw("syscall munmap")
491	}
492}
493
494//go:nosplit
495func madvise(addr unsafe.Pointer, n uintptr, flags int32) {
496	r, err := syscall3(&libc_madvise, uintptr(addr), uintptr(n), uintptr(flags))
497	if int32(r) == -1 {
498		println("syscall madvise failed: ", hex(err))
499		throw("syscall madvise")
500	}
501}
502
503func sigaction1(sig, new, old uintptr)
504
505//go:nosplit
506func sigaction(sig uintptr, new, old *sigactiont) {
507	gp := getg()
508
509	// Check the validity of g because without a g during
510	// runtime.libpreinit.
511	if gp != nil {
512		r, err := syscall3(&libc_sigaction, sig, uintptr(unsafe.Pointer(new)), uintptr(unsafe.Pointer(old)))
513		if int32(r) == -1 {
514			println("Sigaction failed for sig: ", sig, " with error:", hex(err))
515			throw("syscall sigaction")
516		}
517		return
518	}
519
520	sigaction1(sig, uintptr(unsafe.Pointer(new)), uintptr(unsafe.Pointer(old)))
521}
522
523//go:nosplit
524func sigaltstack(new, old *stackt) {
525	r, err := syscall2(&libc_sigaltstack, uintptr(unsafe.Pointer(new)), uintptr(unsafe.Pointer(old)))
526	if int32(r) == -1 {
527		println("syscall sigaltstack failed: ", hex(err))
528		throw("syscall sigaltstack")
529	}
530}
531
532//go:nosplit
533//go:linkname internal_cpu_getsystemcfg internal/cpu.getsystemcfg
534func internal_cpu_getsystemcfg(label uint) uint {
535	r, _ := syscall1(&libc_getsystemcfg, uintptr(label))
536	return uint(r)
537}
538
539func usleep1(us uint32)
540
541//go:nosplit
542func usleep_no_g(us uint32) {
543	usleep1(us)
544}
545
546//go:nosplit
547func usleep(us uint32) {
548	r, err := syscall1(&libc_usleep, uintptr(us))
549	if int32(r) == -1 {
550		println("syscall usleep failed: ", hex(err))
551		throw("syscall usleep")
552	}
553}
554
555//go:nosplit
556func clock_gettime(clockid int32, tp *timespec) int32 {
557	r, _ := syscall2(&libc_clock_gettime, uintptr(clockid), uintptr(unsafe.Pointer(tp)))
558	return int32(r)
559}
560
561//go:nosplit
562func setitimer(mode int32, new, old *itimerval) {
563	r, err := syscall3(&libc_setitimer, uintptr(mode), uintptr(unsafe.Pointer(new)), uintptr(unsafe.Pointer(old)))
564	if int32(r) == -1 {
565		println("syscall setitimer failed: ", hex(err))
566		throw("syscall setitimer")
567	}
568}
569
570//go:nosplit
571func malloc(size uintptr) unsafe.Pointer {
572	r, _ := syscall1(&libc_malloc, size)
573	return unsafe.Pointer(r)
574}
575
576//go:nosplit
577func sem_init(sem *semt, pshared int32, value uint32) int32 {
578	r, _ := syscall3(&libc_sem_init, uintptr(unsafe.Pointer(sem)), uintptr(pshared), uintptr(value))
579	return int32(r)
580}
581
582//go:nosplit
583func sem_wait(sem *semt) (int32, int32) {
584	r, err := syscall1(&libc_sem_wait, uintptr(unsafe.Pointer(sem)))
585	return int32(r), int32(err)
586}
587
588//go:nosplit
589func sem_post(sem *semt) int32 {
590	r, _ := syscall1(&libc_sem_post, uintptr(unsafe.Pointer(sem)))
591	return int32(r)
592}
593
594//go:nosplit
595func sem_timedwait(sem *semt, timeout *timespec) (int32, int32) {
596	r, err := syscall2(&libc_sem_timedwait, uintptr(unsafe.Pointer(sem)), uintptr(unsafe.Pointer(timeout)))
597	return int32(r), int32(err)
598}
599
600//go:nosplit
601func raise(sig uint32) {
602	r, err := syscall1(&libc_raise, uintptr(sig))
603	if int32(r) == -1 {
604		println("syscall raise failed: ", hex(err))
605		throw("syscall raise")
606	}
607}
608
609//go:nosplit
610func raiseproc(sig uint32) {
611	pid, err := syscall0(&libc_getpid)
612	if int32(pid) == -1 {
613		println("syscall getpid failed: ", hex(err))
614		throw("syscall raiseproc")
615	}
616
617	syscall2(&libc_kill, pid, uintptr(sig))
618}
619
620func osyield1()
621
622//go:nosplit
623func osyield_no_g() {
624	osyield1()
625}
626
627//go:nosplit
628func osyield() {
629	r, err := syscall0(&libc_sched_yield)
630	if int32(r) == -1 {
631		println("syscall osyield failed: ", hex(err))
632		throw("syscall osyield")
633	}
634}
635
636//go:nosplit
637func sysconf(name int32) uintptr {
638	r, _ := syscall1(&libc_sysconf, uintptr(name))
639	if int32(r) == -1 {
640		throw("syscall sysconf")
641	}
642	return r
643}
644
645// pthread functions returns its error code in the main return value
646// Therefore, err returns by syscall means nothing and must not be used
647
648//go:nosplit
649func pthread_attr_destroy(attr *pthread_attr) int32 {
650	r, _ := syscall1(&libpthread_attr_destroy, uintptr(unsafe.Pointer(attr)))
651	return int32(r)
652}
653
654func pthread_attr_init1(attr uintptr) int32
655
656//go:nosplit
657func pthread_attr_init(attr *pthread_attr) int32 {
658	gp := getg()
659
660	// Check the validity of g because without a g during
661	// newosproc0.
662	if gp != nil {
663		r, _ := syscall1(&libpthread_attr_init, uintptr(unsafe.Pointer(attr)))
664		return int32(r)
665	}
666
667	return pthread_attr_init1(uintptr(unsafe.Pointer(attr)))
668}
669
670func pthread_attr_setdetachstate1(attr uintptr, state int32) int32
671
672//go:nosplit
673func pthread_attr_setdetachstate(attr *pthread_attr, state int32) int32 {
674	gp := getg()
675
676	// Check the validity of g because without a g during
677	// newosproc0.
678	if gp != nil {
679		r, _ := syscall2(&libpthread_attr_setdetachstate, uintptr(unsafe.Pointer(attr)), uintptr(state))
680		return int32(r)
681	}
682
683	return pthread_attr_setdetachstate1(uintptr(unsafe.Pointer(attr)), state)
684}
685
686//go:nosplit
687func pthread_attr_setstackaddr(attr *pthread_attr, stk unsafe.Pointer) int32 {
688	r, _ := syscall2(&libpthread_attr_setstackaddr, uintptr(unsafe.Pointer(attr)), uintptr(stk))
689	return int32(r)
690}
691
692//go:nosplit
693func pthread_attr_getstacksize(attr *pthread_attr, size *uint64) int32 {
694	r, _ := syscall2(&libpthread_attr_getstacksize, uintptr(unsafe.Pointer(attr)), uintptr(unsafe.Pointer(size)))
695	return int32(r)
696}
697
698func pthread_attr_setstacksize1(attr uintptr, size uint64) int32
699
700//go:nosplit
701func pthread_attr_setstacksize(attr *pthread_attr, size uint64) int32 {
702	gp := getg()
703
704	// Check the validity of g because without a g during
705	// newosproc0.
706	if gp != nil {
707		r, _ := syscall2(&libpthread_attr_setstacksize, uintptr(unsafe.Pointer(attr)), uintptr(size))
708		return int32(r)
709	}
710
711	return pthread_attr_setstacksize1(uintptr(unsafe.Pointer(attr)), size)
712}
713
714func pthread_create1(tid, attr, fn, arg uintptr) int32
715
716//go:nosplit
717func pthread_create(tid *pthread, attr *pthread_attr, fn *funcDescriptor, arg unsafe.Pointer) int32 {
718	gp := getg()
719
720	// Check the validity of g because without a g during
721	// newosproc0.
722	if gp != nil {
723		r, _ := syscall4(&libpthread_create, uintptr(unsafe.Pointer(tid)), uintptr(unsafe.Pointer(attr)), uintptr(unsafe.Pointer(fn)), uintptr(arg))
724		return int32(r)
725	}
726
727	return pthread_create1(uintptr(unsafe.Pointer(tid)), uintptr(unsafe.Pointer(attr)), uintptr(unsafe.Pointer(fn)), uintptr(arg))
728}
729
730// On multi-thread program, sigprocmask must not be called.
731// It's replaced by sigthreadmask.
732func sigprocmask1(how, new, old uintptr)
733
734//go:nosplit
735func sigprocmask(how int32, new, old *sigset) {
736	gp := getg()
737
738	// Check the validity of m because it might be called during a cgo
739	// callback early enough where m isn't available yet.
740	if gp != nil && gp.m != nil {
741		r, err := syscall3(&libpthread_sigthreadmask, uintptr(how), uintptr(unsafe.Pointer(new)), uintptr(unsafe.Pointer(old)))
742		if int32(r) != 0 {
743			println("syscall sigthreadmask failed: ", hex(err))
744			throw("syscall sigthreadmask")
745		}
746		return
747	}
748	sigprocmask1(uintptr(how), uintptr(unsafe.Pointer(new)), uintptr(unsafe.Pointer(old)))
749
750}
751
752//go:nosplit
753func pthread_self() pthread {
754	r, _ := syscall0(&libpthread_self)
755	return pthread(r)
756}
757
758//go:nosplit
759func signalM(mp *m, sig int) {
760	syscall2(&libpthread_kill, uintptr(pthread(mp.procid)), uintptr(sig))
761}
762