...
Run Format

Text file src/runtime/sys_darwin_386.s

Documentation: runtime

     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	
     5	// System calls and other sys.stuff for 386, Darwin
     6	// See http://fxr.watson.org/fxr/source/bsd/kern/syscalls.c?v=xnu-1228
     7	// or /usr/include/sys/syscall.h (on a Mac) for system call numbers.
     8	
     9	#include "go_asm.h"
    10	#include "go_tls.h"
    11	#include "textflag.h"
    12	
    13	// Exit the entire program (like C exit)
    14	TEXT runtime·exit(SB),NOSPLIT,$0
    15		MOVL	$1, AX
    16		INT	$0x80
    17		MOVL	$0xf1, 0xf1  // crash
    18		RET
    19	
    20	// Exit this OS thread (like pthread_exit, which eventually
    21	// calls __bsdthread_terminate).
    22	TEXT exit1<>(SB),NOSPLIT,$16-0
    23		// __bsdthread_terminate takes 4 word-size arguments.
    24		// Set them all to 0. (None are an exit status.)
    25		MOVL	$0, 0(SP)
    26		MOVL	$0, 4(SP)
    27		MOVL	$0, 8(SP)
    28		MOVL	$0, 12(SP)
    29		MOVL	$361, AX
    30		INT	$0x80
    31		JAE 2(PC)
    32		MOVL	$0xf1, 0xf1  // crash
    33		RET
    34	
    35	GLOBL exitStack<>(SB),RODATA,$(4*4)
    36	DATA exitStack<>+0x00(SB)/4, $0
    37	DATA exitStack<>+0x04(SB)/4, $0
    38	DATA exitStack<>+0x08(SB)/4, $0
    39	DATA exitStack<>+0x0c(SB)/4, $0
    40	
    41	// func exitThread(wait *uint32)
    42	TEXT runtime·exitThread(SB),NOSPLIT,$0-4
    43		MOVL	wait+0(FP), AX
    44		// We're done using the stack.
    45		MOVL	$0, (AX)
    46		// __bsdthread_terminate takes 4 arguments, which it expects
    47		// on the stack. They should all be 0, so switch over to a
    48		// fake stack of 0s. It won't write to the stack.
    49		MOVL	$exitStack<>(SB), SP
    50		MOVL	$361, AX	// __bsdthread_terminate
    51		INT	$0x80
    52		MOVL	$0xf1, 0xf1  // crash
    53		JMP	0(PC)
    54	
    55	TEXT runtime·open(SB),NOSPLIT,$0
    56		MOVL	$5, AX
    57		INT	$0x80
    58		JAE	2(PC)
    59		MOVL	$-1, AX
    60		MOVL	AX, ret+12(FP)
    61		RET
    62	
    63	TEXT runtime·closefd(SB),NOSPLIT,$0
    64		MOVL	$6, AX
    65		INT	$0x80
    66		JAE	2(PC)
    67		MOVL	$-1, AX
    68		MOVL	AX, ret+4(FP)
    69		RET
    70	
    71	TEXT runtime·read(SB),NOSPLIT,$0
    72		MOVL	$3, AX
    73		INT	$0x80
    74		JAE	2(PC)
    75		MOVL	$-1, AX
    76		MOVL	AX, ret+12(FP)
    77		RET
    78	
    79	TEXT runtime·write(SB),NOSPLIT,$0
    80		MOVL	$4, AX
    81		INT	$0x80
    82		JAE	2(PC)
    83		MOVL	$-1, AX
    84		MOVL	AX, ret+12(FP)
    85		RET
    86	
    87	TEXT runtime·raise(SB),NOSPLIT,$0
    88		// Ideally we'd send the signal to the current thread,
    89		// not the whole process, but that's too hard on OS X.
    90		JMP	runtime·raiseproc(SB)
    91	
    92	TEXT runtime·raiseproc(SB),NOSPLIT,$16
    93		MOVL	$20, AX // getpid
    94		INT	$0x80
    95		MOVL	AX, 4(SP)	// pid
    96		MOVL	sig+0(FP), AX
    97		MOVL	AX, 8(SP)	// signal
    98		MOVL	$1, 12(SP)	// posix
    99		MOVL	$37, AX // kill
   100		INT	$0x80
   101		RET
   102	
   103	TEXT runtime·mmap(SB),NOSPLIT,$0
   104		MOVL	$197, AX
   105		INT	$0x80
   106		JAE	ok
   107		MOVL	$0, p+24(FP)
   108		MOVL	AX, err+28(FP)
   109		RET
   110	ok:
   111		MOVL	AX, p+24(FP)
   112		MOVL	$0, err+28(FP)
   113		RET
   114	
   115	TEXT runtime·madvise(SB),NOSPLIT,$0
   116		MOVL	$75, AX
   117		INT	$0x80
   118		// ignore failure - maybe pages are locked
   119		RET
   120	
   121	TEXT runtime·munmap(SB),NOSPLIT,$0
   122		MOVL	$73, AX
   123		INT	$0x80
   124		JAE	2(PC)
   125		MOVL	$0xf1, 0xf1  // crash
   126		RET
   127	
   128	TEXT runtime·setitimer(SB),NOSPLIT,$0
   129		MOVL	$83, AX
   130		INT	$0x80
   131		RET
   132	
   133	// OS X comm page time offsets
   134	// http://www.opensource.apple.com/source/xnu/xnu-1699.26.8/osfmk/i386/cpu_capabilities.h
   135	#define	cpu_capabilities	0x20
   136	#define	nt_tsc_base	0x50
   137	#define	nt_scale	0x58
   138	#define	nt_shift	0x5c
   139	#define	nt_ns_base	0x60
   140	#define	nt_generation	0x68
   141	#define	gtod_generation	0x6c
   142	#define	gtod_ns_base	0x70
   143	#define	gtod_sec_base	0x78
   144	
   145	// called from assembly
   146	// 64-bit unix nanoseconds returned in DX:AX.
   147	// I'd much rather write this in C but we need
   148	// assembly for the 96-bit multiply and RDTSC.
   149	//
   150	// Note that we could arrange to return monotonic time here
   151	// as well, but we don't bother, for two reasons:
   152	// 1. macOS only supports 64-bit systems, so no one should
   153	// be using the 32-bit code in production.
   154	// This code is only maintained to make it easier for developers
   155	// using Macs to test the 32-bit compiler.
   156	// 2. On some (probably now unsupported) CPUs,
   157	// the code falls back to the system call always,
   158	// so it can't even use the comm page at all. 
   159	TEXT runtime·now(SB),NOSPLIT,$40
   160		MOVL	$0xffff0000, BP /* comm page base */
   161		
   162		// Test for slow CPU. If so, the math is completely
   163		// different, and unimplemented here, so use the
   164		// system call.
   165		MOVL	cpu_capabilities(BP), AX
   166		TESTL	$0x4000, AX
   167		JNZ	systime
   168	
   169		// Loop trying to take a consistent snapshot
   170		// of the time parameters.
   171	timeloop:
   172		MOVL	gtod_generation(BP), BX
   173		TESTL	BX, BX
   174		JZ	systime
   175		MOVL	nt_generation(BP), CX
   176		TESTL	CX, CX
   177		JZ	timeloop
   178		RDTSC
   179		MOVL	nt_tsc_base(BP), SI
   180		MOVL	(nt_tsc_base+4)(BP), DI
   181		MOVL	SI, 0(SP)
   182		MOVL	DI, 4(SP)
   183		MOVL	nt_scale(BP), SI
   184		MOVL	SI, 8(SP)
   185		MOVL	nt_ns_base(BP), SI
   186		MOVL	(nt_ns_base+4)(BP), DI
   187		MOVL	SI, 12(SP)
   188		MOVL	DI, 16(SP)
   189		CMPL	nt_generation(BP), CX
   190		JNE	timeloop
   191		MOVL	gtod_ns_base(BP), SI
   192		MOVL	(gtod_ns_base+4)(BP), DI
   193		MOVL	SI, 20(SP)
   194		MOVL	DI, 24(SP)
   195		MOVL	gtod_sec_base(BP), SI
   196		MOVL	(gtod_sec_base+4)(BP), DI
   197		MOVL	SI, 28(SP)
   198		MOVL	DI, 32(SP)
   199		CMPL	gtod_generation(BP), BX
   200		JNE	timeloop
   201	
   202		// Gathered all the data we need. Compute time.
   203		//	((tsc - nt_tsc_base) * nt_scale) >> 32 + nt_ns_base - gtod_ns_base + gtod_sec_base*1e9
   204		// The multiply and shift extracts the top 64 bits of the 96-bit product.
   205		SUBL	0(SP), AX // DX:AX = (tsc - nt_tsc_base)
   206		SBBL	4(SP), DX
   207	
   208		// We have x = tsc - nt_tsc_base - DX:AX to be
   209		// multiplied by y = nt_scale = 8(SP), keeping the top 64 bits of the 96-bit product.
   210		// x*y = (x&0xffffffff)*y + (x&0xffffffff00000000)*y
   211		// (x*y)>>32 = ((x&0xffffffff)*y)>>32 + (x>>32)*y
   212		MOVL	DX, CX // SI = (x&0xffffffff)*y >> 32
   213		MOVL	$0, DX
   214		MULL	8(SP)
   215		MOVL	DX, SI
   216	
   217		MOVL	CX, AX // DX:AX = (x>>32)*y
   218		MOVL	$0, DX
   219		MULL	8(SP)
   220	
   221		ADDL	SI, AX	// DX:AX += (x&0xffffffff)*y >> 32
   222		ADCL	$0, DX
   223		
   224		// DX:AX is now ((tsc - nt_tsc_base) * nt_scale) >> 32.
   225		ADDL	12(SP), AX	// DX:AX += nt_ns_base
   226		ADCL	16(SP), DX
   227		SUBL	20(SP), AX	// DX:AX -= gtod_ns_base
   228		SBBL	24(SP), DX
   229		MOVL	AX, SI	// DI:SI = DX:AX
   230		MOVL	DX, DI
   231		MOVL	28(SP), AX	// DX:AX = gtod_sec_base*1e9
   232		MOVL	32(SP), DX
   233		MOVL	$1000000000, CX
   234		MULL	CX
   235		ADDL	SI, AX	// DX:AX += DI:SI
   236		ADCL	DI, DX
   237		RET
   238	
   239	systime:
   240		// Fall back to system call (usually first call in this thread)
   241		LEAL	16(SP), AX	// must be non-nil, unused
   242		MOVL	AX, 4(SP)
   243		MOVL	$0, 8(SP)	// time zone pointer
   244		MOVL	$0, 12(SP)	// required as of Sierra; Issue 16570
   245		MOVL	$116, AX // SYS_GETTIMEOFDAY
   246		INT	$0x80
   247		CMPL	AX, $0
   248		JNE	inreg
   249		MOVL	16(SP), AX
   250		MOVL	20(SP), DX
   251	inreg:
   252		// sec is in AX, usec in DX
   253		// convert to DX:AX nsec
   254		MOVL	DX, BX
   255		MOVL	$1000000000, CX
   256		MULL	CX
   257		IMULL	$1000, BX
   258		ADDL	BX, AX
   259		ADCL	$0, DX
   260		RET
   261	
   262	// func now() (sec int64, nsec int32, mono uint64)
   263	TEXT time·now(SB),NOSPLIT,$0-20
   264		CALL	runtime·now(SB)
   265		MOVL	AX, BX
   266		MOVL	DX, BP
   267		SUBL	runtime·startNano(SB), BX
   268		SBBL	runtime·startNano+4(SB), BP
   269		MOVL	BX, mono+12(FP)
   270		MOVL	BP, mono+16(FP)
   271		MOVL	$1000000000, CX
   272		DIVL	CX
   273		MOVL	AX, sec+0(FP)
   274		MOVL	$0, sec+4(FP)
   275		MOVL	DX, nsec+8(FP)
   276		RET
   277	
   278	// func nanotime() int64
   279	TEXT runtime·nanotime(SB),NOSPLIT,$0
   280		CALL	runtime·now(SB)
   281		SUBL	runtime·startNano(SB), AX
   282		SBBL	runtime·startNano+4(SB), DX
   283		MOVL	AX, ret_lo+0(FP)
   284		MOVL	DX, ret_hi+4(FP)
   285		RET
   286	
   287	TEXT runtime·sigprocmask(SB),NOSPLIT,$0
   288		MOVL	$329, AX  // pthread_sigmask (on OS X, sigprocmask==entire process)
   289		INT	$0x80
   290		JAE	2(PC)
   291		MOVL	$0xf1, 0xf1  // crash
   292		RET
   293	
   294	TEXT runtime·sigaction(SB),NOSPLIT,$0
   295		MOVL	$46, AX
   296		INT	$0x80
   297		JAE	2(PC)
   298		MOVL	$0xf1, 0xf1  // crash
   299		RET
   300	
   301	TEXT runtime·sigfwd(SB),NOSPLIT,$0-16
   302		MOVL	fn+0(FP), AX
   303		MOVL	sig+4(FP), BX
   304		MOVL	info+8(FP), CX
   305		MOVL	ctx+12(FP), DX
   306		MOVL	SP, SI
   307		SUBL	$32, SP
   308		ANDL	$~15, SP	// align stack: handler might be a C function
   309		MOVL	BX, 0(SP)
   310		MOVL	CX, 4(SP)
   311		MOVL	DX, 8(SP)
   312		MOVL	SI, 12(SP)	// save SI: handler might be a Go function
   313		CALL	AX
   314		MOVL	12(SP), AX
   315		MOVL	AX, SP
   316		RET
   317	
   318	// Sigtramp's job is to call the actual signal handler.
   319	// It is called with the following arguments on the stack:
   320	//	0(SP)	"return address" - ignored
   321	//	4(SP)	actual handler
   322	//	8(SP)	siginfo style
   323	//	12(SP)	signal number
   324	//	16(SP)	siginfo
   325	//	20(SP)	context
   326	TEXT runtime·sigtramp(SB),NOSPLIT,$20
   327		MOVL	sig+8(FP), BX
   328		MOVL	BX, 0(SP)
   329		MOVL	info+12(FP), BX
   330		MOVL	BX, 4(SP)
   331		MOVL	ctx+16(FP), BX
   332		MOVL	BX, 8(SP)
   333		CALL	runtime·sigtrampgo(SB)
   334	
   335		// call sigreturn
   336		MOVL	ctx+16(FP), CX
   337		MOVL	infostyle+4(FP), BX
   338		MOVL	$0, 0(SP)	// "caller PC" - ignored
   339		MOVL	CX, 4(SP)
   340		MOVL	BX, 8(SP)
   341		MOVL	$184, AX	// sigreturn(ucontext, infostyle)
   342		INT	$0x80
   343		MOVL	$0xf1, 0xf1  // crash
   344		RET
   345	
   346	TEXT runtime·sigaltstack(SB),NOSPLIT,$0
   347		MOVL	$53, AX
   348		INT	$0x80
   349		JAE	2(PC)
   350		MOVL	$0xf1, 0xf1  // crash
   351		RET
   352	
   353	TEXT runtime·usleep(SB),NOSPLIT,$32
   354		MOVL	$0, DX
   355		MOVL	usec+0(FP), AX
   356		MOVL	$1000000, CX
   357		DIVL	CX
   358		MOVL	AX, 24(SP)  // sec
   359		MOVL	DX, 28(SP)  // usec
   360	
   361		// select(0, 0, 0, 0, &tv)
   362		MOVL	$0, 0(SP)  // "return PC" - ignored
   363		MOVL	$0, 4(SP)
   364		MOVL	$0, 8(SP)
   365		MOVL	$0, 12(SP)
   366		MOVL	$0, 16(SP)
   367		LEAL	24(SP), AX
   368		MOVL	AX, 20(SP)
   369		MOVL	$93, AX
   370		INT	$0x80
   371		RET
   372	
   373	// func bsdthread_create(stk, arg unsafe.Pointer, fn uintptr) int32
   374	// System call args are: func arg stack pthread flags.
   375	TEXT runtime·bsdthread_create(SB),NOSPLIT,$32
   376		MOVL	$360, AX
   377		// 0(SP) is where the caller PC would be; kernel skips it
   378		MOVL	fn+8(FP), BX
   379		MOVL	BX, 4(SP)	// func
   380		MOVL	arg+4(FP), BX
   381		MOVL	BX, 8(SP)	// arg
   382		MOVL	stk+0(FP), BX
   383		MOVL	BX, 12(SP)	// stack
   384		MOVL    $0, 16(SP)      // pthread
   385		MOVL	$0x1000000, 20(SP)	// flags = PTHREAD_START_CUSTOM
   386		INT	$0x80
   387		JAE	4(PC)
   388		NEGL	AX
   389		MOVL	AX, ret+12(FP)
   390		RET
   391		MOVL	$0, AX
   392		MOVL	AX, ret+12(FP)
   393		RET
   394	
   395	// The thread that bsdthread_create creates starts executing here,
   396	// because we registered this function using bsdthread_register
   397	// at startup.
   398	//	AX = "pthread" (= 0x0)
   399	//	BX = mach thread port
   400	//	CX = "func" (= fn)
   401	//	DX = "arg" (= m)
   402	//	DI = stack top
   403	//	SI = flags (= 0x1000000)
   404	//	SP = stack - C_32_STK_ALIGN
   405	TEXT runtime·bsdthread_start(SB),NOSPLIT,$0
   406		// set up ldt 7+id to point at m->tls.
   407		LEAL	m_tls(DX), BP
   408		MOVL	m_id(DX), DI
   409		ADDL	$7, DI	// m0 is LDT#7. count up.
   410		// setldt(tls#, &tls, sizeof tls)
   411		PUSHAL	// save registers
   412		PUSHL	$32	// sizeof tls
   413		PUSHL	BP	// &tls
   414		PUSHL	DI	// tls #
   415		CALL	runtime·setldt(SB)
   416		POPL	AX
   417		POPL	AX
   418		POPL	AX
   419		POPAL
   420	
   421		// Now segment is established. Initialize m, g.
   422		get_tls(BP)
   423		MOVL    m_g0(DX), AX
   424		MOVL	AX, g(BP)
   425		MOVL	DX, g_m(AX)
   426		MOVL	BX, m_procid(DX)	// m->procid = thread port (for debuggers)
   427		CALL	runtime·stackcheck(SB)		// smashes AX
   428		CALL	CX	// fn()
   429		CALL	exit1<>(SB)
   430		RET
   431	
   432	// func bsdthread_register() int32
   433	// registers callbacks for threadstart (see bsdthread_create above
   434	// and wqthread and pthsize (not used).  returns 0 on success.
   435	TEXT runtime·bsdthread_register(SB),NOSPLIT,$40
   436		MOVL	$366, AX
   437		// 0(SP) is where kernel expects caller PC; ignored
   438		MOVL	$runtime·bsdthread_start(SB), 4(SP)	// threadstart
   439		MOVL	$0, 8(SP)	// wqthread, not used by us
   440		MOVL	$0, 12(SP)	// pthsize, not used by us
   441		MOVL	$0, 16(SP)	// dummy_value [sic]
   442		MOVL	$0, 20(SP)	// targetconc_ptr
   443		MOVL	$0, 24(SP)	// dispatchqueue_offset
   444		INT	$0x80
   445		JAE	4(PC)
   446		NEGL	AX
   447		MOVL	AX, ret+0(FP)
   448		RET
   449		MOVL	$0, AX
   450		MOVL	AX, ret+0(FP)
   451		RET
   452	
   453	// Invoke Mach system call.
   454	// Assumes system call number in AX,
   455	// caller PC on stack, caller's caller PC next,
   456	// and then the system call arguments.
   457	//
   458	// Can be used for BSD too, but we don't,
   459	// because if you use this interface the BSD
   460	// system call numbers need an extra field
   461	// in the high 16 bits that seems to be the
   462	// argument count in bytes but is not always.
   463	// INT $0x80 works fine for those.
   464	TEXT runtime·sysenter(SB),NOSPLIT,$0
   465		POPL	DX
   466		MOVL	SP, CX
   467		BYTE $0x0F; BYTE $0x34;  // SYSENTER
   468		// returns to DX with SP set to CX
   469	
   470	TEXT runtime·mach_msg_trap(SB),NOSPLIT,$0
   471		MOVL	$-31, AX
   472		CALL	runtime·sysenter(SB)
   473		MOVL	AX, ret+28(FP)
   474		RET
   475	
   476	TEXT runtime·mach_reply_port(SB),NOSPLIT,$0
   477		MOVL	$-26, AX
   478		CALL	runtime·sysenter(SB)
   479		MOVL	AX, ret+0(FP)
   480		RET
   481	
   482	TEXT runtime·mach_task_self(SB),NOSPLIT,$0
   483		MOVL	$-28, AX
   484		CALL	runtime·sysenter(SB)
   485		MOVL	AX, ret+0(FP)
   486		RET
   487	
   488	// Mach provides trap versions of the semaphore ops,
   489	// instead of requiring the use of RPC.
   490	
   491	// func mach_semaphore_wait(sema uint32) int32
   492	TEXT runtime·mach_semaphore_wait(SB),NOSPLIT,$0
   493		MOVL	$-36, AX
   494		CALL	runtime·sysenter(SB)
   495		MOVL	AX, ret+4(FP)
   496		RET
   497	
   498	// func mach_semaphore_timedwait(sema, sec, nsec uint32) int32
   499	TEXT runtime·mach_semaphore_timedwait(SB),NOSPLIT,$0
   500		MOVL	$-38, AX
   501		CALL	runtime·sysenter(SB)
   502		MOVL	AX, ret+12(FP)
   503		RET
   504	
   505	// func mach_semaphore_signal(sema uint32) int32
   506	TEXT runtime·mach_semaphore_signal(SB),NOSPLIT,$0
   507		MOVL	$-33, AX
   508		CALL	runtime·sysenter(SB)
   509		MOVL	AX, ret+4(FP)
   510		RET
   511	
   512	// func mach_semaphore_signal_all(sema uint32) int32
   513	TEXT runtime·mach_semaphore_signal_all(SB),NOSPLIT,$0
   514		MOVL	$-34, AX
   515		CALL	runtime·sysenter(SB)
   516		MOVL	AX, ret+4(FP)
   517		RET
   518	
   519	// func setldt(entry int, address int, limit int)
   520	// entry and limit are ignored.
   521	TEXT runtime·setldt(SB),NOSPLIT,$32
   522		MOVL	address+4(FP), BX	// aka base
   523	
   524		/*
   525		 * When linking against the system libraries,
   526		 * we use its pthread_create and let it set up %gs
   527		 * for us.  When we do that, the private storage
   528		 * we get is not at 0(GS) but at 0x468(GS).
   529		 * 8l rewrites 0(TLS) into 0x468(GS) for us.
   530		 * To accommodate that rewrite, we translate the
   531		 * address and limit here so that 0x468(GS) maps to 0(address).
   532		 *
   533		 * See cgo/gcc_darwin_386.c:/468 for the derivation
   534		 * of the constant.
   535		 */
   536		SUBL	$0x468, BX
   537	
   538		/*
   539		 * Must set up as USER_CTHREAD segment because
   540		 * Darwin forces that value into %gs for signal handlers,
   541		 * and if we don't set one up, we'll get a recursive
   542		 * fault trying to get into the signal handler.
   543		 * Since we have to set one up anyway, it might as
   544		 * well be the value we want.  So don't bother with
   545		 * i386_set_ldt.
   546		 */
   547		MOVL	BX, 4(SP)
   548		MOVL	$3, AX	// thread_fast_set_cthread_self - machdep call #3
   549		INT	$0x82	// sic: 0x82, not 0x80, for machdep call
   550	
   551		XORL	AX, AX
   552		MOVW	GS, AX
   553		RET
   554	
   555	TEXT runtime·sysctl(SB),NOSPLIT,$0
   556		MOVL	$202, AX
   557		INT	$0x80
   558		JAE	4(PC)
   559		NEGL	AX
   560		MOVL	AX, ret+24(FP)
   561		RET
   562		MOVL	$0, AX
   563		MOVL	AX, ret+24(FP)
   564		RET
   565	
   566	// func kqueue() int32
   567	TEXT runtime·kqueue(SB),NOSPLIT,$0
   568		MOVL	$362, AX
   569		INT	$0x80
   570		JAE	2(PC)
   571		NEGL	AX
   572		MOVL	AX, ret+0(FP)
   573		RET
   574	
   575	// func kevent(kq int32, ch *keventt, nch int32, ev *keventt, nev int32, ts *timespec) int32
   576	TEXT runtime·kevent(SB),NOSPLIT,$0
   577		MOVL	$363, AX
   578		INT	$0x80
   579		JAE	2(PC)
   580		NEGL	AX
   581		MOVL	AX, ret+24(FP)
   582		RET
   583	
   584	// func closeonexec(fd int32)
   585	TEXT runtime·closeonexec(SB),NOSPLIT,$32
   586		MOVL	$92, AX  // fcntl
   587		// 0(SP) is where the caller PC would be; kernel skips it
   588		MOVL	fd+0(FP), BX
   589		MOVL	BX, 4(SP)  // fd
   590		MOVL	$2, 8(SP)  // F_SETFD
   591		MOVL	$1, 12(SP)  // FD_CLOEXEC
   592		INT	$0x80
   593		JAE	2(PC)
   594		NEGL	AX
   595		RET

View as plain text