...

Text file src/runtime/race_ppc64le.s

Documentation: runtime

     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//go:build race
     6
     7#include "go_asm.h"
     8#include "go_tls.h"
     9#include "funcdata.h"
    10#include "textflag.h"
    11#include "asm_ppc64x.h"
    12#include "cgo/abi_ppc64x.h"
    13
    14// The following functions allow calling the clang-compiled race runtime directly
    15// from Go code without going all the way through cgo.
    16// First, it's much faster (up to 50% speedup for real Go programs).
    17// Second, it eliminates race-related special cases from cgocall and scheduler.
    18// Third, in long-term it will allow to remove cyclic runtime/race dependency on cmd/go.
    19
    20// A brief recap of the ppc64le calling convention.
    21// Arguments are passed in R3, R4, R5 ...
    22// SP must be 16-byte aligned.
    23
    24// Note that for ppc64x, LLVM follows the standard ABI and
    25// expects arguments in registers, so these functions move
    26// the arguments from storage to the registers expected
    27// by the ABI.
    28
    29// When calling from Go to Clang tsan code:
    30// R3 is the 1st argument and is usually the ThreadState*
    31// R4-? are the 2nd, 3rd, 4th, etc. arguments
    32
    33// When calling racecalladdr:
    34// R8 is the call target address
    35
    36// The race ctx is passed in R3 and loaded in
    37// racecalladdr.
    38//
    39// The sequence used to get the race ctx:
    40//    MOVD    runtime·tls_g(SB), R10 // Address of TLS variable
    41//    MOVD    0(R10), g              // g = R30
    42//    MOVD    g_racectx(g), R3       // racectx == ThreadState
    43
    44// func runtime·RaceRead(addr uintptr)
    45// Called from instrumented Go code
    46TEXT	runtime·raceread<ABIInternal>(SB), NOSPLIT, $0-8
    47	MOVD	R3, R4 // addr
    48	MOVD	LR, R5 // caller of this?
    49	// void __tsan_read(ThreadState *thr, void *addr, void *pc);
    50	MOVD	$__tsan_read(SB), R8
    51	BR	racecalladdr<>(SB)
    52
    53TEXT    runtime·RaceRead(SB), NOSPLIT, $0-8
    54	BR	runtime·raceread(SB)
    55
    56// void runtime·racereadpc(void *addr, void *callpc, void *pc)
    57TEXT	runtime·racereadpc(SB), NOSPLIT, $0-24
    58	MOVD	addr+0(FP), R4
    59	MOVD	callpc+8(FP), R5
    60	MOVD	pc+16(FP), R6
    61	// void __tsan_read_pc(ThreadState *thr, void *addr, void *callpc, void *pc);
    62	MOVD	$__tsan_read_pc(SB), R8
    63	BR	racecalladdr<>(SB)
    64
    65// func runtime·RaceWrite(addr uintptr)
    66// Called from instrumented Go code
    67TEXT	runtime·racewrite<ABIInternal>(SB), NOSPLIT, $0-8
    68	MOVD	R3, R4 // addr
    69	MOVD	LR, R5 // caller has set LR via BL inst
    70	// void __tsan_write(ThreadState *thr, void *addr, void *pc);
    71	MOVD	$__tsan_write(SB), R8
    72	BR	racecalladdr<>(SB)
    73
    74TEXT    runtime·RaceWrite(SB), NOSPLIT, $0-8
    75	JMP	runtime·racewrite(SB)
    76
    77// void runtime·racewritepc(void *addr, void *callpc, void *pc)
    78TEXT	runtime·racewritepc(SB), NOSPLIT, $0-24
    79	MOVD	addr+0(FP), R4
    80	MOVD	callpc+8(FP), R5
    81	MOVD	pc+16(FP), R6
    82	// void __tsan_write_pc(ThreadState *thr, void *addr, void *callpc, void *pc);
    83	MOVD	$__tsan_write_pc(SB), R8
    84	BR	racecalladdr<>(SB)
    85
    86// func runtime·RaceReadRange(addr, size uintptr)
    87// Called from instrumented Go code.
    88TEXT	runtime·racereadrange<ABIInternal>(SB), NOSPLIT, $0-16
    89	MOVD	R4, R5 // size
    90	MOVD	R3, R4 // addr
    91	MOVD	LR, R6
    92	// void __tsan_read_range(ThreadState *thr, void *addr, uintptr size, void *pc);
    93	MOVD	$__tsan_read_range(SB), R8
    94	BR	racecalladdr<>(SB)
    95
    96// void runtime·racereadrangepc1(void *addr, uintptr sz, void *pc)
    97TEXT	runtime·racereadrangepc1(SB), NOSPLIT, $0-24
    98	MOVD    addr+0(FP), R4
    99	MOVD    size+8(FP), R5
   100	MOVD    pc+16(FP), R6
   101	ADD	$4, R6		// tsan wants return addr
   102	// void __tsan_read_range(ThreadState *thr, void *addr, uintptr size, void *pc);
   103	MOVD    $__tsan_read_range(SB), R8
   104	BR	racecalladdr<>(SB)
   105
   106TEXT    runtime·RaceReadRange(SB), NOSPLIT, $0-16
   107	BR	runtime·racereadrange(SB)
   108
   109// func runtime·RaceWriteRange(addr, size uintptr)
   110// Called from instrumented Go code.
   111TEXT	runtime·racewriterange<ABIInternal>(SB), NOSPLIT, $0-16
   112	MOVD	R4, R5 // size
   113	MOVD	R3, R4 // addr
   114	MOVD	LR, R6
   115	// void __tsan_write_range(ThreadState *thr, void *addr, uintptr size, void *pc);
   116	MOVD	$__tsan_write_range(SB), R8
   117	BR	racecalladdr<>(SB)
   118
   119TEXT    runtime·RaceWriteRange(SB), NOSPLIT, $0-16
   120	BR	runtime·racewriterange(SB)
   121
   122// void runtime·racewriterangepc1(void *addr, uintptr sz, void *pc)
   123// Called from instrumented Go code
   124TEXT	runtime·racewriterangepc1(SB), NOSPLIT, $0-24
   125	MOVD	addr+0(FP), R4
   126	MOVD	size+8(FP), R5
   127	MOVD	pc+16(FP), R6
   128	ADD	$4, R6			// add 4 to inst offset?
   129	// void __tsan_write_range(ThreadState *thr, void *addr, uintptr size, void *pc);
   130	MOVD	$__tsan_write_range(SB), R8
   131	BR	racecalladdr<>(SB)
   132
   133// Call a __tsan function from Go code.
   134// R8 = tsan function address
   135// R3 = *ThreadState a.k.a. g_racectx from g
   136// R4 = addr passed to __tsan function
   137//
   138// Otherwise, setup goroutine context and invoke racecall. Other arguments already set.
   139TEXT	racecalladdr<>(SB), NOSPLIT, $0-0
   140	MOVD    runtime·tls_g(SB), R10
   141	MOVD	0(R10), g
   142	MOVD	g_racectx(g), R3	// goroutine context
   143	// Check that addr is within [arenastart, arenaend) or within [racedatastart, racedataend).
   144	MOVD	runtime·racearenastart(SB), R9
   145	CMP	R4, R9
   146	BLT	data
   147	MOVD	runtime·racearenaend(SB), R9
   148	CMP	R4, R9
   149	BLT	call
   150data:
   151	MOVD	runtime·racedatastart(SB), R9
   152	CMP	R4, R9
   153	BLT	ret
   154	MOVD	runtime·racedataend(SB), R9
   155	CMP	R4, R9
   156	BGT	ret
   157call:
   158	// Careful!! racecall will save LR on its
   159	// stack, which is OK as long as racecalladdr
   160	// doesn't change in a way that generates a stack.
   161	// racecall should return to the caller of
   162	// recalladdr.
   163	BR	racecall<>(SB)
   164ret:
   165	RET
   166
   167// func runtime·racefuncenter(pc uintptr)
   168// Called from instrumented Go code.
   169TEXT	runtime·racefuncenter(SB), NOSPLIT, $0-8
   170	MOVD	callpc+0(FP), R8
   171	BR	racefuncenter<>(SB)
   172
   173// Common code for racefuncenter
   174// R11 = caller's return address
   175TEXT	racefuncenter<>(SB), NOSPLIT, $0-0
   176	MOVD    runtime·tls_g(SB), R10
   177	MOVD    0(R10), g
   178	MOVD    g_racectx(g), R3        // goroutine racectx aka *ThreadState
   179	MOVD	R8, R4			// caller pc set by caller in R8
   180	// void __tsan_func_enter(ThreadState *thr, void *pc);
   181	MOVD	$__tsan_func_enter(SB), R8
   182	BR	racecall<>(SB)
   183	RET
   184
   185// func runtime·racefuncexit()
   186// Called from Go instrumented code.
   187TEXT	runtime·racefuncexit(SB), NOSPLIT, $0-0
   188	MOVD    runtime·tls_g(SB), R10
   189	MOVD    0(R10), g
   190	MOVD    g_racectx(g), R3        // goroutine racectx aka *ThreadState
   191	// void __tsan_func_exit(ThreadState *thr);
   192	MOVD	$__tsan_func_exit(SB), R8
   193	BR	racecall<>(SB)
   194
   195// Atomic operations for sync/atomic package.
   196// Some use the __tsan versions instead
   197// R6 = addr of arguments passed to this function
   198// R3, R4, R5 set in racecallatomic
   199
   200// Load atomic in tsan
   201TEXT	sync∕atomic·LoadInt32(SB), NOSPLIT, $0-12
   202	GO_ARGS
   203	// void __tsan_go_atomic32_load(ThreadState *thr, uptr cpc, uptr pc, u8 *a);
   204	MOVD	$__tsan_go_atomic32_load(SB), R8
   205	ADD	$32, R1, R6	// addr of caller's 1st arg
   206	BR	racecallatomic<>(SB)
   207	RET
   208
   209TEXT	sync∕atomic·LoadInt64(SB), NOSPLIT, $0-16
   210	GO_ARGS
   211	// void __tsan_go_atomic64_load(ThreadState *thr, uptr cpc, uptr pc, u8 *a);
   212	MOVD	$__tsan_go_atomic64_load(SB), R8
   213	ADD	$32, R1, R6	// addr of caller's 1st arg
   214	BR	racecallatomic<>(SB)
   215	RET
   216
   217TEXT	sync∕atomic·LoadUint32(SB), NOSPLIT, $0-12
   218	GO_ARGS
   219	BR	sync∕atomic·LoadInt32(SB)
   220
   221TEXT	sync∕atomic·LoadUint64(SB), NOSPLIT, $0-16
   222	GO_ARGS
   223	BR	sync∕atomic·LoadInt64(SB)
   224
   225TEXT	sync∕atomic·LoadUintptr(SB), NOSPLIT, $0-16
   226	GO_ARGS
   227	BR	sync∕atomic·LoadInt64(SB)
   228
   229TEXT	sync∕atomic·LoadPointer(SB), NOSPLIT, $0-16
   230	GO_ARGS
   231	BR	sync∕atomic·LoadInt64(SB)
   232
   233// Store atomic in tsan
   234TEXT	sync∕atomic·StoreInt32(SB), NOSPLIT, $0-12
   235	GO_ARGS
   236	// void __tsan_go_atomic32_store(ThreadState *thr, uptr cpc, uptr pc, u8 *a);
   237	MOVD	$__tsan_go_atomic32_store(SB), R8
   238	ADD	$32, R1, R6	// addr of caller's 1st arg
   239	BR	racecallatomic<>(SB)
   240
   241TEXT	sync∕atomic·StoreInt64(SB), NOSPLIT, $0-16
   242	GO_ARGS
   243	// void __tsan_go_atomic64_store(ThreadState *thr, uptr cpc, uptr pc, u8 *a);
   244	MOVD	$__tsan_go_atomic64_store(SB), R8
   245	ADD	$32, R1, R6	// addr of caller's 1st arg
   246	BR	racecallatomic<>(SB)
   247
   248TEXT	sync∕atomic·StoreUint32(SB), NOSPLIT, $0-12
   249	GO_ARGS
   250	BR	sync∕atomic·StoreInt32(SB)
   251
   252TEXT	sync∕atomic·StoreUint64(SB), NOSPLIT, $0-16
   253	GO_ARGS
   254	BR	sync∕atomic·StoreInt64(SB)
   255
   256TEXT	sync∕atomic·StoreUintptr(SB), NOSPLIT, $0-16
   257	GO_ARGS
   258	BR	sync∕atomic·StoreInt64(SB)
   259
   260// Swap in tsan
   261TEXT	sync∕atomic·SwapInt32(SB), NOSPLIT, $0-20
   262	GO_ARGS
   263	// void __tsan_go_atomic32_exchange(ThreadState *thr, uptr cpc, uptr pc, u8 *a);
   264	MOVD	$__tsan_go_atomic32_exchange(SB), R8
   265	ADD	$32, R1, R6	// addr of caller's 1st arg
   266	BR	racecallatomic<>(SB)
   267
   268TEXT	sync∕atomic·SwapInt64(SB), NOSPLIT, $0-24
   269	GO_ARGS
   270	// void __tsan_go_atomic64_exchange(ThreadState *thr, uptr cpc, uptr pc, u8 *a)
   271	MOVD	$__tsan_go_atomic64_exchange(SB), R8
   272	ADD	$32, R1, R6	// addr of caller's 1st arg
   273	BR	racecallatomic<>(SB)
   274
   275TEXT	sync∕atomic·SwapUint32(SB), NOSPLIT, $0-20
   276	GO_ARGS
   277	BR	sync∕atomic·SwapInt32(SB)
   278
   279TEXT	sync∕atomic·SwapUint64(SB), NOSPLIT, $0-24
   280	GO_ARGS
   281	BR	sync∕atomic·SwapInt64(SB)
   282
   283TEXT	sync∕atomic·SwapUintptr(SB), NOSPLIT, $0-24
   284	GO_ARGS
   285	BR	sync∕atomic·SwapInt64(SB)
   286
   287// Add atomic in tsan
   288TEXT	sync∕atomic·AddInt32(SB), NOSPLIT, $0-20
   289	GO_ARGS
   290	// void __tsan_go_atomic32_fetch_add(ThreadState *thr, uptr cpc, uptr pc, u8 *a);
   291	MOVD	$__tsan_go_atomic32_fetch_add(SB), R8
   292	ADD	$64, R1, R6	// addr of caller's 1st arg
   293	BL	racecallatomic<>(SB)
   294	// The tsan fetch_add result is not as expected by Go,
   295	// so the 'add' must be added to the result.
   296	MOVW	add+8(FP), R3	// The tsa fetch_add does not return the
   297	MOVW	ret+16(FP), R4	// result as expected by go, so fix it.
   298	ADD	R3, R4, R3
   299	MOVW	R3, ret+16(FP)
   300	RET
   301
   302TEXT	sync∕atomic·AddInt64(SB), NOSPLIT, $0-24
   303	GO_ARGS
   304	// void __tsan_go_atomic64_fetch_add(ThreadState *thr, uptr cpc, uptr pc, u8 *a);
   305	MOVD	$__tsan_go_atomic64_fetch_add(SB), R8
   306	ADD	$64, R1, R6	// addr of caller's 1st arg
   307	BL	racecallatomic<>(SB)
   308	// The tsan fetch_add result is not as expected by Go,
   309	// so the 'add' must be added to the result.
   310	MOVD	add+8(FP), R3
   311	MOVD	ret+16(FP), R4
   312	ADD	R3, R4, R3
   313	MOVD	R3, ret+16(FP)
   314	RET
   315
   316TEXT	sync∕atomic·AddUint32(SB), NOSPLIT, $0-20
   317	GO_ARGS
   318	BR	sync∕atomic·AddInt32(SB)
   319
   320TEXT	sync∕atomic·AddUint64(SB), NOSPLIT, $0-24
   321	GO_ARGS
   322	BR	sync∕atomic·AddInt64(SB)
   323
   324TEXT	sync∕atomic·AddUintptr(SB), NOSPLIT, $0-24
   325	GO_ARGS
   326	BR	sync∕atomic·AddInt64(SB)
   327
   328// CompareAndSwap in tsan
   329TEXT	sync∕atomic·CompareAndSwapInt32(SB), NOSPLIT, $0-17
   330	GO_ARGS
   331	// void __tsan_go_atomic32_compare_exchange(
   332	//   ThreadState *thr, uptr cpc, uptr pc, u8 *a)
   333	MOVD	$__tsan_go_atomic32_compare_exchange(SB), R8
   334	ADD	$32, R1, R6	// addr of caller's 1st arg
   335	BR	racecallatomic<>(SB)
   336
   337TEXT	sync∕atomic·CompareAndSwapInt64(SB), NOSPLIT, $0-25
   338	GO_ARGS
   339	// void __tsan_go_atomic32_compare_exchange(
   340	//   ThreadState *thr, uptr cpc, uptr pc, u8 *a)
   341	MOVD	$__tsan_go_atomic64_compare_exchange(SB), R8
   342	ADD	$32, R1, R6	// addr of caller's 1st arg
   343	BR	racecallatomic<>(SB)
   344
   345TEXT	sync∕atomic·CompareAndSwapUint32(SB), NOSPLIT, $0-17
   346	GO_ARGS
   347	BR	sync∕atomic·CompareAndSwapInt32(SB)
   348
   349TEXT	sync∕atomic·CompareAndSwapUint64(SB), NOSPLIT, $0-25
   350	GO_ARGS
   351	BR	sync∕atomic·CompareAndSwapInt64(SB)
   352
   353TEXT	sync∕atomic·CompareAndSwapUintptr(SB), NOSPLIT, $0-25
   354	GO_ARGS
   355	BR	sync∕atomic·CompareAndSwapInt64(SB)
   356
   357// Common function used to call tsan's atomic functions
   358// R3 = *ThreadState
   359// R4 = TODO: What's this supposed to be?
   360// R5 = caller pc
   361// R6 = addr of incoming arg list
   362// R8 contains addr of target function.
   363TEXT	racecallatomic<>(SB), NOSPLIT, $0-0
   364	// Trigger SIGSEGV early if address passed to atomic function is bad.
   365	MOVD	(R6), R7	// 1st arg is addr
   366	MOVB	(R7), R9	// segv here if addr is bad
   367	// Check that addr is within [arenastart, arenaend) or within [racedatastart, racedataend).
   368	MOVD	runtime·racearenastart(SB), R9
   369	CMP	R7, R9
   370	BLT	racecallatomic_data
   371	MOVD	runtime·racearenaend(SB), R9
   372	CMP	R7, R9
   373	BLT	racecallatomic_ok
   374racecallatomic_data:
   375	MOVD	runtime·racedatastart(SB), R9
   376	CMP	R7, R9
   377	BLT	racecallatomic_ignore
   378	MOVD	runtime·racedataend(SB), R9
   379	CMP	R7, R9
   380	BGE	racecallatomic_ignore
   381racecallatomic_ok:
   382	// Addr is within the good range, call the atomic function.
   383	MOVD    runtime·tls_g(SB), R10
   384	MOVD    0(R10), g
   385	MOVD    g_racectx(g), R3        // goroutine racectx aka *ThreadState
   386	MOVD	R8, R5			// pc is the function called
   387	MOVD	(R1), R4		// caller pc from stack
   388	BL	racecall<>(SB)		// BL needed to maintain stack consistency
   389	RET				//
   390racecallatomic_ignore:
   391	// Addr is outside the good range.
   392	// Call __tsan_go_ignore_sync_begin to ignore synchronization during the atomic op.
   393	// An attempt to synchronize on the address would cause crash.
   394	MOVD	R8, R15	// save the original function
   395	MOVD	R6, R17 // save the original arg list addr
   396	MOVD	$__tsan_go_ignore_sync_begin(SB), R8 // func addr to call
   397	MOVD    runtime·tls_g(SB), R10
   398	MOVD    0(R10), g
   399	MOVD    g_racectx(g), R3        // goroutine context
   400	BL	racecall<>(SB)
   401	MOVD	R15, R8	// restore the original function
   402	MOVD	R17, R6 // restore arg list addr
   403	// Call the atomic function.
   404	// racecall will call LLVM race code which might clobber r30 (g)
   405	MOVD	runtime·tls_g(SB), R10
   406	MOVD	0(R10), g
   407
   408	MOVD	g_racectx(g), R3
   409	MOVD	R8, R4		// pc being called same TODO as above
   410	MOVD	(R1), R5	// caller pc from latest LR
   411	BL	racecall<>(SB)
   412	// Call __tsan_go_ignore_sync_end.
   413	MOVD	$__tsan_go_ignore_sync_end(SB), R8
   414	MOVD	g_racectx(g), R3	// goroutine context g should still be good?
   415	BL	racecall<>(SB)
   416	RET
   417
   418// void runtime·racecall(void(*f)(...), ...)
   419// Calls C function f from race runtime and passes up to 4 arguments to it.
   420// The arguments are never heap-object-preserving pointers, so we pretend there are no arguments.
   421TEXT	runtime·racecall(SB), NOSPLIT, $0-0
   422	MOVD	fn+0(FP), R8
   423	MOVD	arg0+8(FP), R3
   424	MOVD	arg1+16(FP), R4
   425	MOVD	arg2+24(FP), R5
   426	MOVD	arg3+32(FP), R6
   427	JMP	racecall<>(SB)
   428
   429// Finds g0 and sets its stack
   430// Arguments were loaded for call from Go to C
   431TEXT	racecall<>(SB), NOSPLIT, $0-0
   432	// Set the LR slot for the ppc64 ABI
   433	MOVD	LR, R10
   434	MOVD	R10, 0(R1)	// Go expectation
   435	MOVD	R10, 16(R1)	// C ABI
   436	// Get info from the current goroutine
   437	MOVD    runtime·tls_g(SB), R10	// g offset in TLS
   438	MOVD    0(R10), g
   439	MOVD	g_m(g), R7		// m for g
   440	MOVD	R1, R16			// callee-saved, preserved across C call
   441	MOVD	m_g0(R7), R10		// g0 for m
   442	CMP	R10, g			// same g0?
   443	BEQ	call			// already on g0
   444	MOVD	(g_sched+gobuf_sp)(R10), R1 // switch R1
   445call:
   446	// prepare frame for C ABI
   447	SUB	$32, R1			// create frame for callee saving LR, CR, R2 etc.
   448	RLDCR   $0, R1, $~15, R1	// align SP to 16 bytes
   449	MOVD	R8, CTR			// R8 = caller addr
   450	MOVD	R8, R12			// expected by PPC64 ABI
   451	BL	(CTR)
   452	XOR     R0, R0			// clear R0 on return from Clang
   453	MOVD	R16, R1			// restore R1; R16 nonvol in Clang
   454	MOVD    runtime·tls_g(SB), R10	// find correct g
   455	MOVD    0(R10), g
   456	MOVD	16(R1), R10		// LR was saved away, restore for return
   457	MOVD	R10, LR
   458	RET
   459
   460// C->Go callback thunk that allows to call runtime·racesymbolize from C code.
   461// Direct Go->C race call has only switched SP, finish g->g0 switch by setting correct g.
   462// The overall effect of Go->C->Go call chain is similar to that of mcall.
   463// RARG0 contains command code. RARG1 contains command-specific context.
   464// See racecallback for command codes.
   465TEXT	runtime·racecallbackthunk(SB), NOSPLIT|NOFRAME, $0
   466	// Handle command raceGetProcCmd (0) here.
   467	// First, code below assumes that we are on curg, while raceGetProcCmd
   468	// can be executed on g0. Second, it is called frequently, so will
   469	// benefit from this fast path.
   470	MOVD	$0, R0		// clear R0 since we came from C code
   471	CMP	R3, $0
   472	BNE	rest
   473	// Inline raceGetProdCmd without clobbering callee-save registers.
   474	MOVD	runtime·tls_g(SB), R10
   475	MOVD	0(R10), R11
   476	MOVD	g_m(R11), R3
   477	MOVD	m_p(R3), R3
   478	MOVD	p_raceprocctx(R3), R3
   479	MOVD	R3, (R4)
   480	RET
   481
   482rest:
   483	// Save registers according to the host PPC64 ABI
   484	// and reserve 16B for argument storage.
   485	STACK_AND_SAVE_HOST_TO_GO_ABI(16)
   486
   487	// Load g, and switch to g0 if not already on it.
   488	MOVD	runtime·tls_g(SB), R10
   489	MOVD	0(R10), g
   490
   491	MOVD	g_m(g), R7
   492	MOVD	m_g0(R7), R8
   493	CMP	g, R8
   494	BEQ	noswitch
   495
   496	MOVD	R8, g // set g = m->g0
   497
   498noswitch:
   499	BL	runtime·racecallback<ABIInternal>(SB)
   500
   501	UNSTACK_AND_RESTORE_GO_TO_HOST_ABI(16)
   502	RET
   503
   504// tls_g, g value for each thread in TLS
   505GLOBL runtime·tls_g+0(SB), TLSBSS+DUPOK, $8

View as plain text