// 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 

type mOS struct {
	initialized bool
	mutex       pthreadmutex
	cond        pthreadcond
	count       int
}

func ( string) {
	println(, "not implemented")
	*(*int)(unsafe.Pointer(uintptr(1231))) = 1231
}

//go:nosplit
func ( *m) {
	if .initialized {
		return
	}
	.initialized = true
	if  := pthread_mutex_init(&.mutex, nil);  != 0 {
		throw("pthread_mutex_init")
	}
	if  := pthread_cond_init(&.cond, nil);  != 0 {
		throw("pthread_cond_init")
	}
}

//go:nosplit
func ( int64) int32 {
	var  int64
	if  >= 0 {
		 = nanotime()
	}
	 := getg().m
	pthread_mutex_lock(&.mutex)
	for {
		if .count > 0 {
			.count--
			pthread_mutex_unlock(&.mutex)
			return 0
		}
		if  >= 0 {
			 := nanotime() - 
			if  >=  {
				pthread_mutex_unlock(&.mutex)
				return -1
			}
			var  timespec
			.setNsec( - )
			 := pthread_cond_timedwait_relative_np(&.cond, &.mutex, &)
			if  == _ETIMEDOUT {
				pthread_mutex_unlock(&.mutex)
				return -1
			}
		} else {
			pthread_cond_wait(&.cond, &.mutex)
		}
	}
}

//go:nosplit
func ( *m) {
	pthread_mutex_lock(&.mutex)
	.count++
	if .count > 0 {
		pthread_cond_signal(&.cond)
	}
	pthread_mutex_unlock(&.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 (*note) {
	if sigNoteRead != 0 || sigNoteWrite != 0 {
		throw("duplicate sigNoteSetup")
	}
	var  int32
	sigNoteRead, sigNoteWrite,  = pipe()
	if  != 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 (*note) {
	var  byte
	write(uintptr(sigNoteWrite), unsafe.Pointer(&), 1)
}

// sigNoteSleep waits for a note created by sigNoteSetup to be woken.
func (*note) {
	entersyscallblock()
	var  byte
	read(sigNoteRead, unsafe.Pointer(&), 1)
	exitsyscall()
}

// BSD interface for threading.
func () {
	// pthread_create delayed until end of goenvs so that we
	// can look at the environment first.

	ncpu = getncpu()
	physPageSize = getPageSize()
}

func ( []byte) (int32, int32) {
	 := int32(0)
	 := unsafe.Sizeof()
	 := sysctlbyname(&[0], (*byte)(unsafe.Pointer(&)), &, nil, 0)
	return , 
}

//go:linkname internal_cpu_getsysctlbyname internal/cpu.getsysctlbyname
func ( []byte) (int32, int32) {
	return sysctlbynameInt32()
}

const (
	_CTL_HW      = 6
	_HW_NCPU     = 3
	_HW_PAGESIZE = 7
)

func () int32 {
	// Use sysctl to fetch hw.ncpu.
	 := [2]uint32{_CTL_HW, _HW_NCPU}
	 := uint32(0)
	 := unsafe.Sizeof()
	 := sysctl(&[0], 2, (*byte)(unsafe.Pointer(&)), &, nil, 0)
	if  >= 0 && int32() > 0 {
		return int32()
	}
	return 1
}

func () uintptr {
	// Use sysctl to fetch hw.pagesize.
	 := [2]uint32{_CTL_HW, _HW_PAGESIZE}
	 := uint32(0)
	 := unsafe.Sizeof()
	 := sysctl(&[0], 2, (*byte)(unsafe.Pointer(&)), &, nil, 0)
	if  >= 0 && int32() > 0 {
		return uintptr()
	}
	return 0
}

var urandom_dev = []byte("/dev/urandom\x00")

//go:nosplit
func ( []byte) {
	 := open(&urandom_dev[0], 0 /* O_RDONLY */, 0)
	 := read(, unsafe.Pointer(&[0]), int32(len()))
	closefd()
	extendRandom(, int())
}

func () {
	goenvs_unix()
}

// May run with m.p==nil, so write barriers are not allowed.
//go:nowritebarrierrec
func ( *m) {
	 := unsafe.Pointer(.g0.stack.hi)
	if false {
		print("newosproc stk=", , " m=", , " g=", .g0, " id=", .id, " ostk=", &, "\n")
	}

	// Initialize an attribute object.
	var  pthreadattr
	var  int32
	 = pthread_attr_init(&)
	if  != 0 {
		write(2, unsafe.Pointer(&failthreadcreate[0]), int32(len(failthreadcreate)))
		exit(1)
	}

	// Find out OS stack size for our own stack guard.
	var  uintptr
	if pthread_attr_getstacksize(&, &) != 0 {
		write(2, unsafe.Pointer(&failthreadcreate[0]), int32(len(failthreadcreate)))
		exit(1)
	}
	.g0.stack.hi =  // for mstart

	// Tell the pthread library we won't join with this thread.
	if pthread_attr_setdetachstate(&, _PTHREAD_CREATE_DETACHED) != 0 {
		write(2, unsafe.Pointer(&failthreadcreate[0]), int32(len(failthreadcreate)))
		exit(1)
	}

	// Finally, create the thread. It starts at mstart_stub, which does some low-level
	// setup and then calls mstart.
	var  sigset
	sigprocmask(_SIG_SETMASK, &sigset_all, &)
	 = pthread_create(&, funcPC(mstart_stub), unsafe.Pointer())
	sigprocmask(_SIG_SETMASK, &, nil)
	if  != 0 {
		write(2, unsafe.Pointer(&failthreadcreate[0]), int32(len(failthreadcreate)))
		exit(1)
	}
}

// glue code to call mstart from pthread_create.
func ()

// newosproc0 is a version of newosproc that can be called before the runtime
// is initialized.
//
// This function is not safe to use after initialization as it does not pass an M as fnarg.
//
//go:nosplit
func ( uintptr,  uintptr) {
	// Initialize an attribute object.
	var  pthreadattr
	var  int32
	 = pthread_attr_init(&)
	if  != 0 {
		write(2, unsafe.Pointer(&failthreadcreate[0]), int32(len(failthreadcreate)))
		exit(1)
	}

	// The caller passes in a suggested stack size,
	// from when we allocated the stack and thread ourselves,
	// without libpthread. Now that we're using libpthread,
	// we use the OS default stack size instead of the suggestion.
	// Find out that stack size for our own stack guard.
	if pthread_attr_getstacksize(&, &) != 0 {
		write(2, unsafe.Pointer(&failthreadcreate[0]), int32(len(failthreadcreate)))
		exit(1)
	}
	g0.stack.hi =  // for mstart
	memstats.stacks_sys.add(int64())

	// Tell the pthread library we won't join with this thread.
	if pthread_attr_setdetachstate(&, _PTHREAD_CREATE_DETACHED) != 0 {
		write(2, unsafe.Pointer(&failthreadcreate[0]), int32(len(failthreadcreate)))
		exit(1)
	}

	// Finally, create the thread. It starts at mstart_stub, which does some low-level
	// setup and then calls mstart.
	var  sigset
	sigprocmask(_SIG_SETMASK, &sigset_all, &)
	 = pthread_create(&, , nil)
	sigprocmask(_SIG_SETMASK, &, nil)
	if  != 0 {
		write(2, unsafe.Pointer(&failthreadcreate[0]), int32(len(failthreadcreate)))
		exit(1)
	}
}

var failallocatestack = []byte("runtime: failed to allocate stack for the new OS thread\n")
var failthreadcreate = []byte("runtime: failed to create new OS thread\n")

// Called to do synchronous initialization of Go code built with
// -buildmode=c-archive or -buildmode=c-shared.
// None of the Go runtime is initialized.
//go:nosplit
//go:nowritebarrierrec
func () {
	initsig(true)
}

// Called to initialize a new m (including the bootstrap m).
// Called on the parent thread (main thread in case of bootstrap), can allocate memory.
func ( *m) {
	.gsignal = malg(32 * 1024) // OS X wants >= 8K
	.gsignal.m = 
	if GOOS == "darwin" && GOARCH == "arm64" {
		// mlock the signal stack to work around a kernel bug where it may
		// SIGILL when the signal stack is not faulted in while a signal
		// arrives. See issue 42774.
		mlock(unsafe.Pointer(.gsignal.stack.hi-physPageSize), physPageSize)
	}
}

// Called to initialize a new m (including the bootstrap m).
// Called on the new thread, cannot allocate memory.
func () {
	// iOS does not support alternate signal stack.
	// The signal handler handles it directly.
	if !(GOOS == "ios" && GOARCH == "arm64") {
		minitSignalStack()
	}
	minitSignalMask()
	getg().m.procid = uint64(pthread_self())
}

// Called from dropm to undo the effect of an minit.
//go:nosplit
func () {
	// iOS does not support alternate signal stack.
	// See minit.
	if !(GOOS == "ios" && GOARCH == "arm64") {
		unminitSignals()
	}
}

// Called from exitm, but not from drop, to undo the effect of thread-owned
// resources in minit, semacreate, or elsewhere. Do not take locks after calling this.
func ( *m) {
}

//go:nosplit
func () {
	usleep(1)
}

const (
	_NSIG        = 32
	_SI_USER     = 0 /* empirically true, but not what headers say */
	_SIG_BLOCK   = 1
	_SIG_UNBLOCK = 2
	_SIG_SETMASK = 3
	_SS_DISABLE  = 4
)

//extern SigTabTT runtimeĀ·sigtab[];

type sigset uint32

var sigset_all = ^sigset(0)

//go:nosplit
//go:nowritebarrierrec
func ( uint32,  uintptr) {
	var  usigactiont
	.sa_flags = _SA_SIGINFO | _SA_ONSTACK | _SA_RESTART
	.sa_mask = ^uint32(0)
	if  == funcPC(sighandler) {
		if iscgo {
			 = funcPC(cgoSigtramp)
		} else {
			 = funcPC(sigtramp)
		}
	}
	*(*uintptr)(unsafe.Pointer(&.__sigaction_u)) = 
	sigaction(, &, nil)
}

// sigtramp is the callback from libc when a signal is received.
// It is called with the C calling convention.
func ()
func ()

//go:nosplit
//go:nowritebarrierrec
func ( uint32) {
	var  usigactiont
	sigaction(, nil, &)
	 := *(*uintptr)(unsafe.Pointer(&.__sigaction_u))
	if .sa_flags&_SA_ONSTACK != 0 {
		return
	}
	var  usigactiont
	*(*uintptr)(unsafe.Pointer(&.__sigaction_u)) = 
	.sa_mask = .sa_mask
	.sa_flags = .sa_flags | _SA_ONSTACK
	sigaction(, &, nil)
}

//go:nosplit
//go:nowritebarrierrec
func ( uint32) uintptr {
	var  usigactiont
	sigaction(, nil, &)
	return *(*uintptr)(unsafe.Pointer(&.__sigaction_u))
}

// setSignaltstackSP sets the ss_sp field of a stackt.
//go:nosplit
func ( *stackt,  uintptr) {
	*(*uintptr)(unsafe.Pointer(&.ss_sp)) = 
}

//go:nosplit
//go:nowritebarrierrec
func ( *sigset,  int) {
	* |= 1 << (uint32() - 1)
}

func ( *sigset,  int) {
	* &^= 1 << (uint32() - 1)
}

//go:linkname executablePath os.executablePath
var executablePath string

func ( int32,  **byte) {
	// skip over argv, envv and the first string will be the path
	 :=  + 1
	for argv_index(, ) != nil {
		++
	}
	executablePath = gostringnocopy(argv_index(, +1))

	// strip "executable_path=" prefix if available, it's added after OS X 10.11.
	const  = "executable_path="
	if len(executablePath) > len() && executablePath[:len()] ==  {
		executablePath = executablePath[len():]
	}
}

func ( *m,  int) {
	pthread_kill(pthread(.procid), uint32())
}