CALL ldt0setup(SB)
// store through it, to make sure it works
- MOVL $0x123, 0(GS)
+ get_tls(BX)
+ MOVL $0x123, g(BX)
MOVL tls0(SB), AX
CMPL AX, $0x123
JEQ ok
MOVL AX, 0 // abort
ok:
// set up m and g "registers"
+ get_tls(BX)
LEAL g0(SB), CX
- MOVL CX, g
+ MOVL CX, g(BX)
LEAL m0(SB), AX
- MOVL AX, m
+ MOVL AX, m(BX)
// save m->g0 = g0
MOVL CX, m_g0(AX)
MOVL BX, gobuf_sp(AX)
MOVL 0(SP), BX // caller's PC
MOVL BX, gobuf_pc(AX)
- MOVL g, BX
+ get_tls(CX)
+ MOVL g(CX), BX
MOVL BX, gobuf_g(AX)
MOVL $0, AX // return 0
RET
MOVL 4(SP), BX // gobuf
MOVL gobuf_g(BX), DX
MOVL 0(DX), CX // make sure g != nil
- MOVL DX, g
+ get_tls(CX)
+ MOVL DX, g(CX)
MOVL gobuf_sp(BX), SP // restore SP
MOVL gobuf_pc(BX), BX
JMP BX
MOVL 8(SP), AX // fn
MOVL 4(SP), BX // gobuf
MOVL gobuf_g(BX), DX
- MOVL DX, g
+ get_tls(CX)
+ MOVL DX, g(CX)
MOVL 0(DX), CX // make sure g != nil
MOVL gobuf_sp(BX), SP // restore SP
MOVL gobuf_pc(BX), BX
// Called during function prolog when more stack is needed.
TEXT runtime·morestack(SB),7,$0
// Cannot grow scheduler stack (m->g0).
- MOVL m, BX
+ get_tls(CX)
+ MOVL m(CX), BX
MOVL m_g0(BX), SI
- CMPL g, SI
+ CMPL g(CX), SI
JNE 2(PC)
INT $3
LEAL 8(SP), CX // f's caller's SP
MOVL CX, (m_morebuf+gobuf_sp)(BX)
MOVL CX, (m_morefp)(BX)
- MOVL g, SI
+ get_tls(CX)
+ MOVL g(CX), SI
MOVL SI, (m_morebuf+gobuf_g)(BX)
// Set m->morepc to f's PC.
// Call newstack on m's scheduling stack.
MOVL m_g0(BX), BP
- MOVL BP, g
+ MOVL BP, g(CX)
MOVL (m_sched+gobuf_sp)(BX), SP
CALL newstack(SB)
MOVL $0, 0x1003 // crash if newstack returns
//
// func call(fn *byte, arg *byte, argsize uint32).
TEXT reflect·call(SB), 7, $0
- MOVL m, BX
+ get_tls(CX)
+ MOVL m(CX), BX
// Save our caller's state as the PC and SP to
// restore when returning from f.
MOVL AX, (m_morebuf+gobuf_pc)(BX)
LEAL 4(SP), AX // our caller's SP
MOVL AX, (m_morebuf+gobuf_sp)(BX)
- MOVL g, AX
+ MOVL g(CX), AX
MOVL AX, (m_morebuf+gobuf_g)(BX)
// Set up morestack arguments to call f on a new stack.
// Call newstack on m's scheduling stack.
MOVL m_g0(BX), BP
- MOVL BP, g
+ get_tls(CX)
+ MOVL BP, g(CX)
MOVL (m_sched+gobuf_sp)(BX), SP
CALL newstack(SB)
MOVL $0, 0x1103 // crash if newstack returns
// Return point when leaving stack.
TEXT runtime·lessstack(SB), 7, $0
// Save return value in m->cret
- MOVL m, BX
+ get_tls(CX)
+ MOVL m(CX), BX
MOVL AX, m_cret(BX)
// Call oldstack on m's scheduling stack.
MOVL m_g0(BX), DX
- MOVL DX, g
+ MOVL DX, g(CX)
MOVL (m_sched+gobuf_sp)(BX), SP
CALL oldstack(SB)
MOVL $0, 0x1004 // crash if oldstack returns
MOVL $1, AX
RET
+// bool casp(void **p, void *old, void *new)
+// Atomically:
+// if(*p == old){
+// *p = new;
+// return 1;
+// }else
+// return 0;
+TEXT casp(SB), 7, $0
+ MOVL 4(SP), BX
+ MOVL 8(SP), AX
+ MOVL 12(SP), CX
+ LOCK
+ CMPXCHGL CX, 0(BX)
+ JZ 3(PC)
+ MOVL $0, AX
+ RET
+ MOVL $1, AX
+ RET
+
// void jmpdefer(fn, sp);
// called from deferreturn.
// 1. pop the caller
MOVL SP, CX
// Figure out if we need to switch to m->g0 stack.
- MOVL m, DX
+ get_tls(DI)
+ MOVL m(DI), DX
MOVL m_g0(DX), SI
- CMPL g, SI
+ CMPL g(DI), SI
JEQ 2(PC)
MOVL (m_sched+gobuf_sp)(DX), SP
// check that SP is in range [g->stackbase, g->stackguard)
TEXT stackcheck(SB), 7, $0
- MOVL g, AX
+ get_tls(CX)
+ MOVL g(CX), AX
CMPL g_stackbase(AX), SP
JHI 2(PC)
INT $3
# TODO(kaib): fix register allocation to honor extern register so we
# can enable optimizations again.
CFLAGS_arm=-N
-CFLAGS=-I$(GOOS) -I$(GOOS)/$(GOARCH) -wF $(CFLAGS_$(SIZE)) $(CFLAGS_$(GOARCH))
+CFLAGS_mingw=-D__MINGW__
+CFLAGS=-I$(GOOS) -I$(GOOS)/$(GOARCH) -wF $(CFLAGS_$(SIZE)) $(CFLAGS_$(GOARCH)) $(CFLAGS_$(GOOS))
GOFILES=\
extern.go\
# for discovering offsets inside structs when debugging
runtime.acid.$(GOARCH): runtime.h proc.c
- $(QUOTED_GOBIN)/$(CC) -a proc.c >$@
+ $(QUOTED_GOBIN)/$(CC) $(CFLAGS) -a proc.c >$@
MOVW BX, GS
// g = m->gsignal
- MOVL m, BP
+ get_tls(CX)
+ MOVL m(CX), BP
MOVL m_gsignal(BP), BP
- MOVL BP, g
+ MOVL BP, g(CX)
MOVL handler+0(FP), DI
// 4(FP) is sigstyle
CALL DI
// g = m->curg
- MOVL m, BP
+ get_tls(CX)
+ MOVL m(CX), BP
MOVL m_curg(BP), BP
- MOVL BP, g
+ MOVL BP, g(CX)
MOVL context+16(FP), CX
MOVL style+4(FP), BX
POPAL
// Now segment is established. Initialize m, g.
- MOVL AX, g
- MOVL DX, m
+ get_tls(BP)
+ MOVL AX, g(BP)
+ MOVL DX, m(BP)
MOVL BX, m_procid(DX) // m->procid = thread port (for debuggers)
CALL stackcheck(SB) // smashes AX
CALL CX // fn()
}
-// Atomic add and return new value.
-static uint32
-xadd(uint32 volatile *val, int32 delta)
-{
- uint32 oval, nval;
-
- for(;;){
- oval = *val;
- nval = oval + delta;
- if(cas(val, oval, nval))
- return nval;
- }
-}
-
-
// Blocking locks.
// Implement Locks, using semaphores.
POPL AX
POPL AX
POPAL
- MOVL BX, g
- MOVL AX, m
+ get_tls(CX)
+ MOVL BX, g(CX)
+
+ MOVL AX, m(CX)
CALL stackcheck(SB) // smashes AX
CALL mstart(SB)
MOVL 0, AX // crash (not reached)
TEXT sigtramp(SB),7,$40
// g = m->gsignal
- MOVL m, BP
+ get_tls(DX)
+ MOVL m(DX), BP
MOVL m_gsignal(BP), BP
- MOVL BP, g
+ MOVL BP, g(DX)
MOVL signo+0(FP), AX
MOVL siginfo+4(FP), BX
CALL sighandler(SB)
// g = m->curg
- MOVL m, BP
+ get_tls(DX)
+ MOVL m(DX), BP
MOVL m_curg(BP), BP
- MOVL BP, g
+ MOVL BP, g(DX)
MOVL context+8(FP), AX
RET
TEXT sigtramp(SB),7,$0
- MOVL m, BP
+ get_tls(CX)
+ MOVL m(CX), BP
MOVL m_gsignal(BP), AX
- MOVL AX, g
+ MOVL AX, g(CX)
JMP sighandler(SB)
TEXT sigignore(SB),7,$0
TEXT sigreturn(SB),7,$0
// g = m->curg
- MOVL m, BP
+ get_tls(CX)
+ MOVL m(CX), BP
MOVL m_curg(BP), BP
- MOVL BP, g
+ MOVL BP, g(CX)
MOVL $173, AX // rt_sigreturn
INT $0x80
INT $3 // not reached
MOVW DI, GS
// Now segment is established. Initialize m, g.
- MOVL DX, g
- MOVL BX, m
+ get_tls(AX)
+ MOVL DX, g(AX)
+ MOVL BX, m(AX)
CALL stackcheck(SB) // smashes AX
MOVL 0(DX), DX // paranoia; check they are not nil
{
Stktop *stk;
byte *sp;
+ // TODO(rsc): Change 8g not to assume that extern register
+ // variables are directly addressable. Declaring the
+ // local variable here works around the bug.
+ G* gg = g;
- if(gp == g)
+ if(gp == gg)
sp = (byte*)&gp;
else
sp = gp->sched.sp;
static void
mark(void)
{
- G *gp;
+ G* gp;
+ // TODO(rsc): Change 8g not to assume that extern register
+ // variables are directly addressable. Declaring the
+ // local variable here works around the bug.
+ G* gg = g;
// mark data+bss.
// skip mheap itself, which has no interesting pointers
case Gdead:
break;
case Grunning:
- if(gp != g)
+ if(gp != gg)
throw("mark - world not stopped");
scanstack(gp);
break;
--- /dev/null
+// c:\Users\Hector\Code\go\bin\godefs.exe defs.c
+
+// MACHINE GENERATED - DO NOT EDIT.
+
+// Constants
+enum {
+ PROT_NONE = 0,
+ PROT_READ = 0x1,
+ PROT_WRITE = 0x2,
+ PROT_EXEC = 0x4,
+ MAP_ANON = 0x1,
+ MAP_PRIVATE = 0x2,
+};
+
+// Types
+#pragma pack on
+#pragma pack off
--- /dev/null
+// 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.
+
+TEXT _rt0_386_mingw(SB),7,$0
+ JMP _rt0_386(SB)
--- /dev/null
+// 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.
+
+void
+initsig(void)
+{
+}
--- /dev/null
+// 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.
+
+#include "386/asm.h"
+
+TEXT get_kernel_module(SB),7,$0
+ MOVL 0x30(FS), AX // get PEB
+ MOVL 0x0c(AX), AX // get PEB_LDR_DATA
+ MOVL 0x1c(AX), AX // get init order module list
+ MOVL (AX), AX // get next entry (kernel module)
+ MOVL 0x08(AX), AX // get base of module
+ RET
+
+// TODO(rsc,hectorchu): Switch to m stack before call.
+TEXT stdcall(SB),7,$0
+ CALL runtime·entersyscall(SB)
+ get_tls(CX)
+ MOVL m(CX), CX
+ POPL m_return_address(CX) // save return address
+ POPL AX // first arg is function pointer
+ MOVL SP, m_stack_pointer(CX) // save stack pointer
+ CALL AX
+ get_tls(CX)
+ MOVL m(CX), CX
+ MOVL m_stack_pointer(CX), SP
+ PUSHL AX
+ PUSHL m_return_address(CX)
+ CALL runtime·exitsyscall(SB)
+ MOVL 4(SP), AX
+ RET
+
+// TODO(rsc,hectorchu): Switch to m stack before call.
+TEXT stdcall_raw(SB),7,$0
+ get_tls(CX)
+ MOVL m(CX), CX
+ POPL m_return_address(CX) // save return address
+ POPL AX // first arg is function pointer
+ MOVL SP, m_stack_pointer(CX) // save stack pointer
+ CALL AX
+ get_tls(CX)
+ MOVL m(CX), CX
+ MOVL m_stack_pointer(CX), SP
+ PUSHL AX
+ PUSHL m_return_address(CX)
+ RET
+
+TEXT threadstart(SB),7,$0
+ MOVL 4(SP), AX // threadstart param
+ MOVL 0(AX), BX // newosproc arg stack
+ MOVL 0(BX), CX // m
+ MOVL 4(BX), DX // g
+
+ // set up tls
+ LEAL m_tls(CX), SI
+ MOVL SI, 0x2c(FS)
+ MOVL CX, m(SI)
+ MOVL DX, g(SI)
+ MOVL SP, m_os_stack_pointer(CX)
+
+ PUSHL 8(BX) // stk
+ PUSHL 12(BX) // fn
+ PUSHL 4(AX) // event_handle
+
+ // signal that we're done with thread args
+ MOVL SetEvent(SB), BX
+ CALL BX // SetEvent(event_handle)
+ POPL BX // fn
+ POPL SP // stk
+
+ CALL stackcheck(SB) // clobbers AX,CX
+ CALL BX // fn()
+
+ // cleanup stack before returning as we are stdcall
+ get_tls(CX)
+ MOVL m(CX), CX
+ MOVL m_os_stack_pointer(CX), SP
+ POPL AX // return address
+ MOVL AX, (SP)
+ XORL AX, AX
+ RET
+
+// setldt(int entry, int address, int limit)
+TEXT setldt(SB),7,$0
+ MOVL address+4(FP), CX
+ MOVL CX, 0x2c(FS)
+ RET
--- /dev/null
+// 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.
+
+enum {
+ $PROT_NONE = 0,
+ $PROT_READ = 1,
+ $PROT_WRITE = 2,
+ $PROT_EXEC = 4,
+
+ $MAP_ANON = 1,
+ $MAP_PRIVATE = 2,
+};
--- /dev/null
+// 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.
+
+// The following function allows one to dynamically
+// resolve DLL function names.
+// The arguments are strings.
+void *get_proc_addr(void *library, void *name);
+
+// Call a Windows function with stdcall conventions.
+void *stdcall(void *fn, ...);
+void *stdcall_raw(void *fn, ...);
+
+#define goargs mingw_goargs
+void mingw_goargs(void);
+
+// Get start address of symbol data in memory.
+void *get_symdat_addr(void);
--- /dev/null
+// 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.
+
+#include "runtime.h"
+#include "os.h"
+
+#define stdcall stdcall_raw
+
+extern void *get_kernel_module(void);
+
+// Also referenced by external packages
+void *CloseHandle;
+void *ExitProcess;
+void *GetStdHandle;
+void *SetEvent;
+void *WriteFile;
+
+static void *CreateEvent;
+static void *CreateThread;
+static void *GetModuleHandle;
+static void *GetProcAddress;
+static void *LoadLibraryEx;
+static void *VirtualAlloc;
+static void *WaitForSingleObject;
+
+static void*
+get_proc_addr2(byte *base, byte *name)
+{
+ byte *pe_header, *exports;
+ uint32 entries, *addr, *names, i;
+ uint16 *ordinals;
+
+ pe_header = base+*(uint32*)(base+0x3c);
+ exports = base+*(uint32*)(pe_header+0x78);
+ entries = *(uint32*)(exports+0x18);
+ addr = (uint32*)(base+*(uint32*)(exports+0x1c));
+ names = (uint32*)(base+*(uint32*)(exports+0x20));
+ ordinals = (uint16*)(base+*(uint32*)(exports+0x24));
+ for(i=0; i<entries; i++) {
+ byte *s = base+names[i];
+ if(!strcmp(name, s))
+ break;
+ }
+ if(i == entries)
+ return 0;
+ return base+addr[ordinals[i]];
+}
+
+void
+osinit(void)
+{
+ void *base;
+
+ base = get_kernel_module();
+ GetProcAddress = get_proc_addr2(base, (byte*)"GetProcAddress");
+ LoadLibraryEx = get_proc_addr2(base, (byte*)"LoadLibraryExA");
+ CloseHandle = get_proc_addr("kernel32.dll", "CloseHandle");
+ CreateEvent = get_proc_addr("kernel32.dll", "CreateEventA");
+ CreateThread = get_proc_addr("kernel32.dll", "CreateThread");
+ ExitProcess = get_proc_addr("kernel32.dll", "ExitProcess");
+ GetModuleHandle = get_proc_addr("kernel32.dll", "GetModuleHandleA");
+ GetStdHandle = get_proc_addr("kernel32.dll", "GetStdHandle");
+ SetEvent = get_proc_addr("kernel32.dll", "SetEvent");
+ VirtualAlloc = get_proc_addr("kernel32.dll", "VirtualAlloc");
+ WaitForSingleObject = get_proc_addr("kernel32.dll", "WaitForSingleObject");
+ WriteFile = get_proc_addr("kernel32.dll", "WriteFile");
+}
+
+// The arguments are strings.
+void*
+get_proc_addr(void *library, void *name)
+{
+ void *base;
+
+ base = stdcall(LoadLibraryEx, library, 0, 0);
+ return stdcall(GetProcAddress, base, name);
+}
+
+void
+mingw_goargs(void)
+{
+ extern Slice os·Args;
+ extern Slice os·Envs;
+
+ void *gcl, *clta, *ges;
+ uint16 *cmd, *env, **argv;
+ String *gargv;
+ String *genvv;
+ int32 i, argc, envc;
+ uint16 *envp;
+
+ gcl = get_proc_addr("kernel32.dll", "GetCommandLineW");
+ clta = get_proc_addr("shell32.dll", "CommandLineToArgvW");
+ ges = get_proc_addr("kernel32.dll", "GetEnvironmentStringsW");
+
+ cmd = stdcall(gcl);
+ env = stdcall(ges);
+ argv = stdcall(clta, cmd, &argc);
+
+ envc = 0;
+ for(envp=env; *envp; envc++)
+ envp += findnullw(envp)+1;
+
+ gargv = malloc(argc*sizeof gargv[0]);
+ genvv = malloc(envc*sizeof genvv[0]);
+
+ for(i=0; i<argc; i++)
+ gargv[i] = gostringw(argv[i]);
+ os·Args.array = (byte*)gargv;
+ os·Args.len = argc;
+ os·Args.cap = argc;
+
+ envp = env;
+ for(i=0; i<envc; i++) {
+ genvv[i] = gostringw(envp);
+ envp += findnullw(envp)+1;
+ }
+ os·Envs.array = (byte*)genvv;
+ os·Envs.len = envc;
+ os·Envs.cap = envc;
+}
+
+void
+exit(int32 code)
+{
+ stdcall(ExitProcess, code);
+}
+
+int32
+write(int32 fd, void *buf, int32 n)
+{
+ void *handle;
+ uint32 written;
+
+ written = 0;
+ switch(fd) {
+ case 1:
+ handle = stdcall(GetStdHandle, -11);
+ break;
+ case 2:
+ handle = stdcall(GetStdHandle, -12);
+ break;
+ default:
+ return -1;
+ }
+ stdcall(WriteFile, handle, buf, n, &written, 0);
+ return written;
+}
+
+uint8*
+runtime_mmap(byte *addr, uint32 len, int32 prot,
+ int32 flags, int32 fd, uint32 off)
+{
+ USED(prot, flags, fd, off);
+ return stdcall(VirtualAlloc, addr, len, 0x3000, 0x40);
+}
+
+void*
+get_symdat_addr(void)
+{
+ byte *mod, *p;
+ uint32 peh, add;
+ uint16 oph;
+
+ mod = stdcall(GetModuleHandle, 0);
+ peh = *(uint32*)(mod+0x3c);
+ p = mod+peh+4;
+ oph = *(uint16*)(p+0x10);
+ p += 0x14+oph;
+ while(strcmp(p, (byte*)".symdat"))
+ p += 40;
+ add = *(uint32*)(p+0x0c);
+ return mod+add;
+}
+
+// Thread-safe allocation of an event.
+static void
+initevent(void **pevent)
+{
+ void *event;
+
+ event = stdcall(CreateEvent, 0, 0, 0, 0);
+ if(!casp(pevent, 0, event)) {
+ // Someone else filled it in. Use theirs.
+ stdcall(CloseHandle, event);
+ }
+}
+
+static void
+eventlock(Lock *l)
+{
+ // Allocate event if needed.
+ if(l->event == 0)
+ initevent(&l->event);
+
+ if(xadd(&l->key, 1) > 1) // someone else has it; wait
+ stdcall(WaitForSingleObject, l->event, -1);
+}
+
+static void
+eventunlock(Lock *l)
+{
+ if(xadd(&l->key, -1) > 0) // someone else is waiting
+ stdcall(SetEvent, l->event);
+}
+
+void
+lock(Lock *l)
+{
+ if(m->locks < 0)
+ throw("lock count");
+ m->locks++;
+ eventlock(l);
+}
+
+void
+unlock(Lock *l)
+{
+ m->locks--;
+ if(m->locks < 0)
+ throw("lock count");
+ eventunlock(l);
+}
+
+void
+noteclear(Note *n)
+{
+ eventlock(&n->lock);
+}
+
+void
+notewakeup(Note *n)
+{
+ eventunlock(&n->lock);
+}
+
+void
+notesleep(Note *n)
+{
+ eventlock(&n->lock);
+ eventunlock(&n->lock); // Let other sleepers find out too.
+}
+
+void
+newosproc(M *m, G *g, void *stk, void (*fn)(void))
+{
+ struct {
+ void *args;
+ void *event_handle;
+ } param = { &m };
+ extern uint32 threadstart(void *p);
+
+ USED(g, stk, fn);
+ param.event_handle = stdcall(CreateEvent, 0, 0, 0, 0);
+ stdcall(CreateThread, 0, 0, threadstart, ¶m, 0, 0);
+ stdcall(WaitForSingleObject, param.event_handle, -1);
+ stdcall(CloseHandle, param.event_handle);
+}
+
+// Called to initialize a new m (including the bootstrap m).
+void
+minit(void)
+{
+}
# ../../cmd/8l/pass.c:/D_GS
# ../../libcgo/linux_386.c:/^start
# ../../libcgo/darwin_386.c:/^start
- echo '#define g 0(GS)'
- echo '#define m 4(GS)'
+ case "$GOOS" in
+ mingw)
+ echo '#define get_tls(r) MOVL 0x2c(FS), r'
+ echo '#define g(r) 0(r)'
+ echo '#define m(r) 4(r)'
+ ;;
+ *)
+ echo '#define get_tls(r)'
+ echo '#define g(r) 0(GS)'
+ echo '#define m(r) 4(GS)'
+ ;;
+ esac
;;
amd64)
# These registers are also known to:
// license that can be found in the LICENSE file.
#include "runtime.h"
+#include "defs.h"
#include "malloc.h"
+#include "os.h"
typedef struct Sched Sched;
void
mstart(void)
{
- if(g != m->g0)
+ // TODO(rsc): Change 8g not to assume that extern register
+ // variables are directly addressable. Declaring the
+ // local variable here works around the bug.
+ G* gg = g;
+
+ if(gg != m->g0)
throw("bad mstart");
if(m->mcache == nil)
m->mcache = allocmcache();
void
gosched(void)
{
- if(g == m->g0)
+ // TODO(rsc): Change 8g not to assume that extern register
+ // variables are directly addressable. Declaring the
+ // local variable here works around the bug.
+ G* gg = g;
+
+ if(gg == m->g0)
throw("gosched of g0");
if(gosave(&g->sched) == 0)
gogo(&m->sched, 1);
os·Envs.cap = envc;
}
+// Atomic add and return new value.
+uint32
+xadd(uint32 volatile *val, int32 delta)
+{
+ uint32 oval, nval;
+
+ for(;;){
+ oval = *val;
+ nval = oval + delta;
+ if(cas(val, oval, nval))
+ return nval;
+ }
+}
+
byte*
getenv(int8 *s)
{
struct Lock
{
uint32 key;
+#ifdef __MINGW__
+ void* event;
+#else
uint32 sema; // for OS X
+#endif
};
struct Usema
{
uint32 machport; // Return address for Mach IPC (OS X)
MCache *mcache;
G* lockedg;
+#ifdef __MINGW__
+ void* return_address; // saved return address and stack
+ void* stack_pointer; // pointer for Windows stdcall
+ void* os_stack_pointer;
+#endif
};
struct Stktop
{
*/
int32 strcmp(byte*, byte*);
int32 findnull(byte*);
+int32 findnullw(uint16*);
void dump(byte*, int32);
int32 runetochar(byte*, int32);
int32 charntorune(int32*, uint8*, int32);
void* mal(uint32);
uint32 cmpstring(String, String);
String gostring(byte*);
+String gostringw(uint16*);
void initsig(void);
int32 gotraceback(void);
void traceback(uint8 *pc, uint8 *sp, G* gp);
int32 open(byte*, int32, ...);
int32 write(int32, void*, int32);
bool cas(uint32*, uint32, uint32);
+bool casp(void**, void*, void*);
+uint32 xadd(uint32 volatile*, int32);
void jmpdefer(byte*, void*);
void exit1(int32);
void ready(G*);
return l;
}
+int32
+findnullw(uint16 *s)
+{
+ int32 l;
+
+ if(s == nil)
+ return 0;
+ for(l=0; s[l]!=0; l++)
+ ;
+ return l;
+}
+
int32 maxstring;
String
return s;
}
+String
+gostringw(uint16 *str)
+{
+ int32 n, i;
+ byte buf[8];
+ String s;
+
+ n = 0;
+ for(i=0; str[i]; i++)
+ n += runetochar(buf, str[i]);
+ s = gostringsize(n+4);
+ n = 0;
+ for(i=0; str[i]; i++)
+ n += runetochar(s.str+n, str[i]);
+ s.len = n;
+ return s;
+}
+
func catstring(s1 String, s2 String) (s3 String) {
if(s1.len == 0) {
s3 = s2;
// and figure out exactly what we want.
#include "runtime.h"
+#include "defs.h"
+#include "os.h"
// TODO(rsc): Move this *under* the text segment.
// Then define names for these addresses instead of hard-coding magic ones.
if(goos != nil && strcmp((uint8*)goos, (uint8*)"nacl") == 0)
return;
+#ifdef __MINGW__
+ v = get_symdat_addr();
+ p = (byte*)v+8;
+#else
v = SYMCOUNTS;
p = SYMDATA;
+#endif
ep = p + v[0];
while(p < ep) {
if(p + 7 > ep)
return;
// pc/ln table bounds
+#ifdef __MINGW__
+ v = get_symdat_addr();
+ p = (byte*)v+8;
+#else
v = SYMCOUNTS;
p = SYMDATA;
+#endif
p += v[0];
ep = p+v[1];