void runtime·profileloop1(void) { M *mp, *allm; void *thread; runtime·stdcall(runtime·SetThreadPriority, 2, (uintptr)-2, (uintptr)THREAD_PRIORITY_HIGHEST); for(;;) { runtime·stdcall(runtime·WaitForSingleObject, 2, profiletimer, (uintptr)-1); allm = runtime·atomicloadp(&runtime·allm); for(mp = allm; mp != nil; mp = mp->alllink) { thread = runtime·atomicloadp(&mp->thread); // Do not profile threads blocked on Notes, // this includes idle worker threads, // idle timer thread, idle heap scavenger, etc. if(thread == nil || mp->profilehz == 0 || mp->blocked) continue; runtime·stdcall(runtime·SuspendThread, 1, thread); if(mp->profilehz != 0 && !mp->blocked) profilem(mp); runtime·stdcall(runtime·ResumeThread, 1, thread); } } }
void runtime·osinit(void) { runtime·stdcall(runtime·QueryPerformanceFrequency, 1, &timerfreq); runtime·stdcall(runtime·SetConsoleCtrlHandler, 2, runtime·ctrlhandler, (uintptr)1); runtime·destroylock = destroylock; }
void runtime·resetcpuprofiler(int32 hz) { static Lock lock; void *timer, *thread; int32 ms; int64 due; runtime·lock(&lock); if(profiletimer == nil) { timer = runtime·stdcall(runtime·CreateWaitableTimer, 3, nil, nil, nil); runtime·atomicstorep(&profiletimer, timer); thread = runtime·stdcall(runtime·CreateThread, 6, nil, nil, runtime·profileloop, nil, nil, nil); runtime·stdcall(runtime·CloseHandle, 1, thread); } runtime·unlock(&lock); ms = 0; due = 1LL<<63; if(hz > 0) { ms = 1000 / hz; if(ms == 0) ms = 1; due = ms * -10000; } runtime·stdcall(runtime·SetWaitableTimer, 6, profiletimer, &due, (uintptr)ms, nil, nil, nil); runtime·atomicstore((uint32*)&m->profilehz, hz); }
void runtime·goenvs(void) { extern Slice syscall·envs; uint16 *env; String *s; int32 i, n; uint16 *p; env = runtime·stdcall(runtime·GetEnvironmentStringsW, 0); n = 0; for(p=env; *p; n++) p += runtime·findnullw(p)+1; s = runtime·malloc(n*sizeof s[0]); p = env; for(i=0; i<n; i++) { s[i] = runtime·gostringw(p); p += runtime·findnullw(p)+1; } syscall·envs.array = (byte*)s; syscall·envs.len = n; syscall·envs.cap = n; runtime·stdcall(runtime·FreeEnvironmentStringsW, 1, env); }
// 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); }
// Thread-safe allocation of an event. static void initevent(void **pevent) { void *event; event = runtime·stdcall(runtime·CreateEvent, 4, (uintptr)0, (uintptr)0, (uintptr)0, (uintptr)0); if(!runtime·casp(pevent, 0, event)) { // Someone else filled it in. Use theirs. runtime·stdcall(runtime·CloseHandle, 1, event); } }
// 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); } }
void runtime·osinit(void) { // -1 = current process, -2 = current thread runtime·stdcall(runtime·DuplicateHandle, 7, (uintptr)-1, (uintptr)-2, (uintptr)-1, &m->thread, (uintptr)0, (uintptr)0, (uintptr)DUPLICATE_SAME_ACCESS); runtime·stdcall(runtime·SetConsoleCtrlHandler, 2, runtime·ctrlhandler, (uintptr)1); runtime·stdcall(runtime·timeBeginPeriod, 1, (uintptr)1); runtime·ncpu = getproccount(); }
runtime·SysReserve(void *v, uintptr n) { // v is just a hint. // First try at v. v = runtime·stdcall(runtime·VirtualAlloc, 4, v, n, (uintptr)MEM_RESERVE, (uintptr)PAGE_READWRITE); if(v != nil) return v; // Next let the kernel choose the address. return runtime·stdcall(runtime·VirtualAlloc, 4, nil, n, (uintptr)MEM_RESERVE, (uintptr)PAGE_READWRITE); }
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); }
int32 runtime·netpollopen(uintptr fd, PollDesc *pd) { USED(pd); if(runtime·stdcall(runtime·CreateIoCompletionPort, 4, fd, iocphandle, (uintptr)0, (uintptr)0) == 0) return -runtime·getlasterror(); return 0; }
static int32 getproccount(void) { SystemInfo info; runtime·stdcall(runtime·GetSystemInfo, 1, &info); return info.dwNumberOfProcessors; }
void runtime·get_random_data(byte **rnd, int32 *rnd_len) { uintptr handle; *rnd = nil; *rnd_len = 0; if(runtime·stdcall(runtime·CryptAcquireContextW, 5, &handle, nil, nil, (uintptr)1 /* PROV_RSA_FULL */, (uintptr)0xf0000000U /* CRYPT_VERIFYCONTEXT */) != 0) { static byte random_data[HashRandomBytes]; if(runtime·stdcall(runtime·CryptGenRandom, 3, handle, (uintptr)HashRandomBytes, random_data)) { *rnd = random_data; *rnd_len = HashRandomBytes; } runtime·stdcall(runtime·CryptReleaseContext, 2, handle, (uintptr)0); } }
void runtime·usleep(uint32 us) { us /= 1000; if(us == 0) us = 1; runtime·stdcall(runtime·Sleep, 1, (uintptr)us); }
void runtime·SysUnused(void *v, uintptr n) { void *r; r = runtime·stdcall(runtime·VirtualFree, 3, v, n, (uintptr)MEM_DECOMMIT); if(r == nil) runtime·throw("runtime: failed to decommit pages"); }
void runtime·SysUsed(void *v, uintptr n) { void *r; r = runtime·stdcall(runtime·VirtualAlloc, 4, v, n, (uintptr)MEM_COMMIT, (uintptr)PAGE_READWRITE); if(r != v) runtime·throw("runtime: failed to commit pages"); }
void runtime·netpollinit(void) { iocphandle = (uintptr)runtime·stdcall(runtime·CreateIoCompletionPort, 4, INVALID_HANDLE_VALUE, (uintptr)0, (uintptr)0, (uintptr)DWORD_MAX); if(iocphandle == 0) { runtime·printf("netpoll: failed to create iocp handle (errno=%d)\n", runtime·getlasterror()); runtime·throw("netpoll: failed to create iocp handle"); } return; }
void runtime·SysFree(void *v, uintptr n) { uintptr r; mstats.sys -= n; r = (uintptr)runtime·stdcall(runtime·VirtualFree, 3, v, (uintptr)0, (uintptr)MEM_RELEASE); if(r == 0) runtime·throw("runtime: failed to release pages"); }
void runtime·SysFree(void *v, uintptr n, uint64 *stat) { uintptr r; runtime·xadd64(stat, -(uint64)n); r = (uintptr)runtime·stdcall(runtime·VirtualFree, 3, v, (uintptr)0, (uintptr)MEM_RELEASE); if(r == 0) runtime·throw("runtime: failed to release pages"); }
static void eventlock(Lock *l) { // Allocate event if needed. if(l->event == 0) initevent(&l->event); if(runtime·xadd(&l->key, 1) > 1) // someone else has it; wait runtime·stdcall(runtime·WaitForSingleObject, 2, l->event, (uintptr)-1); }
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); }
void runtime·SysMap(void *v, uintptr n, uint64 *stat) { void *p; runtime·xadd64(stat, n); p = runtime·stdcall(runtime·VirtualAlloc, 4, v, n, (uintptr)MEM_COMMIT, (uintptr)PAGE_READWRITE); if(p != v) runtime·throw("runtime: cannot map pages in arena address space"); }
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 runtime·gettime(int64 *sec, int32 *usec) { int64 count; runtime·stdcall(runtime·QueryPerformanceCounter, 1, &count); *sec = count / timerfreq; count %= timerfreq; *usec = count*1000000 / timerfreq; }
// Called to initialize a new m (including the bootstrap m). // Called on the new thread, can not allocate memory. void runtime·minit(void) { void *thandle; // -1 = current process, -2 = current thread runtime·stdcall(runtime·DuplicateHandle, 7, (uintptr)-1, (uintptr)-2, (uintptr)-1, &thandle, (uintptr)0, (uintptr)0, (uintptr)DUPLICATE_SAME_ACCESS); runtime·atomicstorep(&m->thread, thandle); }
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; }
int64 runtime·nanotime(void) { int64 filetime; runtime·stdcall(runtime·GetSystemTimeAsFileTime, 1, &filetime); // Filetime is 100s of nanoseconds since January 1, 1601. // Convert to nanoseconds since January 1, 1970. return (filetime - 116444736000000000LL) * 100LL; }
int32 runtime·write(int32 fd, void *buf, int32 n) { void *handle; uint32 written; written = 0; switch(fd) { case 1: handle = runtime·stdcall(runtime·GetStdHandle, 1, (uintptr)-11); break; case 2: handle = runtime·stdcall(runtime·GetStdHandle, 1, (uintptr)-12); break; default: return -1; } runtime·stdcall(runtime·WriteFile, 5, handle, buf, (uintptr)n, &written, (uintptr)0); return written; }
void runtime·profileloop1(void) { M *mp, *allm; void *thread; runtime·stdcall(runtime·SetThreadPriority, 2, (uintptr)-2, (uintptr)THREAD_PRIORITY_HIGHEST); for(;;) { runtime·stdcall(runtime·WaitForSingleObject, 2, profiletimer, (uintptr)-1); allm = runtime·atomicloadp(&runtime·allm); for(mp = allm; mp != nil; mp = mp->alllink) { thread = runtime·atomicloadp(&mp->thread); if(thread == nil) continue; runtime·stdcall(runtime·SuspendThread, 1, thread); if(mp->profilehz != 0) profilem(mp); runtime·stdcall(runtime·ResumeThread, 1, thread); } } }
void runtime·newosproc(M *mp, void *stk) { void *thandle; USED(stk); thandle = runtime·stdcall(runtime·CreateThread, 6, nil, (uintptr)0x20000, runtime·tstart_stdcall, mp, STACK_SIZE_PARAM_IS_A_RESERVATION, nil); if(thandle == nil) { runtime·printf("runtime: failed to create new OS thread (have %d already; errno=%d)\n", runtime·mcount(), runtime·getlasterror()); runtime·throw("runtime.newosproc"); } }