github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/src/pkg/runtime/os_windows.c (about) 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 #include "runtime.h" 6 #include "type.h" 7 #include "defs_GOOS_GOARCH.h" 8 #include "os_GOOS.h" 9 10 #pragma dynimport runtime·CloseHandle CloseHandle "kernel32.dll" 11 #pragma dynimport runtime·CreateEvent CreateEventA "kernel32.dll" 12 #pragma dynimport runtime·CreateThread CreateThread "kernel32.dll" 13 #pragma dynimport runtime·CreateWaitableTimer CreateWaitableTimerA "kernel32.dll" 14 #pragma dynimport runtime·CryptAcquireContextW CryptAcquireContextW "advapi32.dll" 15 #pragma dynimport runtime·CryptGenRandom CryptGenRandom "advapi32.dll" 16 #pragma dynimport runtime·CryptReleaseContext CryptReleaseContext "advapi32.dll" 17 #pragma dynimport runtime·DuplicateHandle DuplicateHandle "kernel32.dll" 18 #pragma dynimport runtime·ExitProcess ExitProcess "kernel32.dll" 19 #pragma dynimport runtime·FreeEnvironmentStringsW FreeEnvironmentStringsW "kernel32.dll" 20 #pragma dynimport runtime·GetEnvironmentStringsW GetEnvironmentStringsW "kernel32.dll" 21 #pragma dynimport runtime·GetProcAddress GetProcAddress "kernel32.dll" 22 #pragma dynimport runtime·GetStdHandle GetStdHandle "kernel32.dll" 23 #pragma dynimport runtime·GetSystemInfo GetSystemInfo "kernel32.dll" 24 #pragma dynimport runtime·GetSystemTimeAsFileTime GetSystemTimeAsFileTime "kernel32.dll" 25 #pragma dynimport runtime·GetThreadContext GetThreadContext "kernel32.dll" 26 #pragma dynimport runtime·LoadLibrary LoadLibraryW "kernel32.dll" 27 #pragma dynimport runtime·ResumeThread ResumeThread "kernel32.dll" 28 #pragma dynimport runtime·SetConsoleCtrlHandler SetConsoleCtrlHandler "kernel32.dll" 29 #pragma dynimport runtime·SetEvent SetEvent "kernel32.dll" 30 #pragma dynimport runtime·SetThreadPriority SetThreadPriority "kernel32.dll" 31 #pragma dynimport runtime·SetWaitableTimer SetWaitableTimer "kernel32.dll" 32 #pragma dynimport runtime·Sleep Sleep "kernel32.dll" 33 #pragma dynimport runtime·SuspendThread SuspendThread "kernel32.dll" 34 #pragma dynimport runtime·timeBeginPeriod timeBeginPeriod "winmm.dll" 35 #pragma dynimport runtime·WaitForSingleObject WaitForSingleObject "kernel32.dll" 36 #pragma dynimport runtime·WriteFile WriteFile "kernel32.dll" 37 #pragma dynimport runtime·NtWaitForSingleObject NtWaitForSingleObject "ntdll.dll" 38 39 extern void *runtime·NtWaitForSingleObject; 40 41 extern void *runtime·CloseHandle; 42 extern void *runtime·CreateEvent; 43 extern void *runtime·CreateThread; 44 extern void *runtime·CreateWaitableTimer; 45 extern void *runtime·CryptAcquireContextW; 46 extern void *runtime·CryptGenRandom; 47 extern void *runtime·CryptReleaseContext; 48 extern void *runtime·DuplicateHandle; 49 extern void *runtime·ExitProcess; 50 extern void *runtime·FreeEnvironmentStringsW; 51 extern void *runtime·GetEnvironmentStringsW; 52 extern void *runtime·GetProcAddress; 53 extern void *runtime·GetStdHandle; 54 extern void *runtime·GetSystemInfo; 55 extern void *runtime·GetSystemTimeAsFileTime; 56 extern void *runtime·GetThreadContext; 57 extern void *runtime·LoadLibrary; 58 extern void *runtime·ResumeThread; 59 extern void *runtime·SetConsoleCtrlHandler; 60 extern void *runtime·SetEvent; 61 extern void *runtime·SetThreadPriority; 62 extern void *runtime·SetWaitableTimer; 63 extern void *runtime·Sleep; 64 extern void *runtime·SuspendThread; 65 extern void *runtime·timeBeginPeriod; 66 extern void *runtime·WaitForSingleObject; 67 extern void *runtime·WriteFile; 68 69 static int32 70 getproccount(void) 71 { 72 SystemInfo info; 73 74 runtime·stdcall(runtime·GetSystemInfo, 1, &info); 75 return info.dwNumberOfProcessors; 76 } 77 78 void 79 runtime·osinit(void) 80 { 81 // -1 = current process, -2 = current thread 82 runtime·stdcall(runtime·DuplicateHandle, 7, 83 (uintptr)-1, (uintptr)-2, (uintptr)-1, &m->thread, 84 (uintptr)0, (uintptr)0, (uintptr)DUPLICATE_SAME_ACCESS); 85 runtime·stdcall(runtime·SetConsoleCtrlHandler, 2, runtime·ctrlhandler, (uintptr)1); 86 runtime·stdcall(runtime·timeBeginPeriod, 1, (uintptr)1); 87 runtime·ncpu = getproccount(); 88 } 89 90 void 91 runtime·get_random_data(byte **rnd, int32 *rnd_len) 92 { 93 uintptr handle; 94 *rnd = nil; 95 *rnd_len = 0; 96 if(runtime·stdcall(runtime·CryptAcquireContextW, 5, &handle, nil, nil, 97 (uintptr)1 /* PROV_RSA_FULL */, 98 (uintptr)0xf0000000U /* CRYPT_VERIFYCONTEXT */) != 0) { 99 static byte random_data[HashRandomBytes]; 100 if(runtime·stdcall(runtime·CryptGenRandom, 3, handle, (uintptr)HashRandomBytes, random_data)) { 101 *rnd = random_data; 102 *rnd_len = HashRandomBytes; 103 } 104 runtime·stdcall(runtime·CryptReleaseContext, 2, handle, (uintptr)0); 105 } 106 } 107 108 void 109 runtime·goenvs(void) 110 { 111 extern Slice syscall·envs; 112 113 uint16 *env; 114 String *s; 115 int32 i, n; 116 uint16 *p; 117 118 env = runtime·stdcall(runtime·GetEnvironmentStringsW, 0); 119 120 n = 0; 121 for(p=env; *p; n++) 122 p += runtime·findnullw(p)+1; 123 124 s = runtime·malloc(n*sizeof s[0]); 125 126 p = env; 127 for(i=0; i<n; i++) { 128 s[i] = runtime·gostringw(p); 129 p += runtime·findnullw(p)+1; 130 } 131 syscall·envs.array = (byte*)s; 132 syscall·envs.len = n; 133 syscall·envs.cap = n; 134 135 runtime·stdcall(runtime·FreeEnvironmentStringsW, 1, env); 136 } 137 138 void 139 runtime·exit(int32 code) 140 { 141 runtime·stdcall(runtime·ExitProcess, 1, (uintptr)code); 142 } 143 144 int32 145 runtime·write(int32 fd, void *buf, int32 n) 146 { 147 void *handle; 148 uint32 written; 149 150 written = 0; 151 switch(fd) { 152 case 1: 153 handle = runtime·stdcall(runtime·GetStdHandle, 1, (uintptr)-11); 154 break; 155 case 2: 156 handle = runtime·stdcall(runtime·GetStdHandle, 1, (uintptr)-12); 157 break; 158 default: 159 return -1; 160 } 161 runtime·stdcall(runtime·WriteFile, 5, handle, buf, (uintptr)n, &written, (uintptr)0); 162 return written; 163 } 164 165 #define INFINITE ((uintptr)0xFFFFFFFF) 166 167 int32 168 runtime·semasleep(int64 ns) 169 { 170 uintptr ms; 171 172 if(ns < 0) 173 ms = INFINITE; 174 else if(ns/1000000 > 0x7fffffffLL) 175 ms = 0x7fffffff; 176 else { 177 ms = ns/1000000; 178 if(ms == 0) 179 ms = 1; 180 } 181 if(runtime·stdcall(runtime·WaitForSingleObject, 2, m->waitsema, ms) != 0) 182 return -1; // timeout 183 return 0; 184 } 185 186 void 187 runtime·semawakeup(M *mp) 188 { 189 runtime·stdcall(runtime·SetEvent, 1, mp->waitsema); 190 } 191 192 uintptr 193 runtime·semacreate(void) 194 { 195 return (uintptr)runtime·stdcall(runtime·CreateEvent, 4, (uintptr)0, (uintptr)0, (uintptr)0, (uintptr)0); 196 } 197 198 #define STACK_SIZE_PARAM_IS_A_RESERVATION ((uintptr)0x00010000) 199 200 void 201 runtime·newosproc(M *mp, void *stk) 202 { 203 void *thandle; 204 205 USED(stk); 206 207 thandle = runtime·stdcall(runtime·CreateThread, 6, 208 nil, (uintptr)0x20000, runtime·tstart_stdcall, mp, 209 STACK_SIZE_PARAM_IS_A_RESERVATION, nil); 210 if(thandle == nil) { 211 runtime·printf("runtime: failed to create new OS thread (have %d already; errno=%d)\n", runtime·mcount(), runtime·getlasterror()); 212 runtime·throw("runtime.newosproc"); 213 } 214 runtime·atomicstorep(&mp->thread, thandle); 215 } 216 217 // Called to initialize a new m (including the bootstrap m). 218 // Called on the parent thread (main thread in case of bootstrap), can allocate memory. 219 void 220 runtime·mpreinit(M *mp) 221 { 222 USED(mp); 223 } 224 225 // Called to initialize a new m (including the bootstrap m). 226 // Called on the new thread, can not allocate memory. 227 void 228 runtime·minit(void) 229 { 230 runtime·install_exception_handler(); 231 } 232 233 // Called from dropm to undo the effect of an minit. 234 void 235 runtime·unminit(void) 236 { 237 runtime·remove_exception_handler(); 238 } 239 240 int64 241 runtime·nanotime(void) 242 { 243 int64 filetime; 244 245 runtime·stdcall(runtime·GetSystemTimeAsFileTime, 1, &filetime); 246 247 // Filetime is 100s of nanoseconds since January 1, 1601. 248 // Convert to nanoseconds since January 1, 1970. 249 return (filetime - 116444736000000000LL) * 100LL; 250 } 251 252 void 253 time·now(int64 sec, int32 usec) 254 { 255 int64 ns; 256 257 ns = runtime·nanotime(); 258 sec = ns / 1000000000LL; 259 usec = ns - sec * 1000000000LL; 260 FLUSH(&sec); 261 FLUSH(&usec); 262 } 263 264 // Calling stdcall on os stack. 265 #pragma textflag 7 266 void * 267 runtime·stdcall(void *fn, int32 count, ...) 268 { 269 WinCall c; 270 271 c.fn = fn; 272 c.n = count; 273 c.args = (uintptr*)&count + 1; 274 runtime·asmcgocall(runtime·asmstdcall, &c); 275 return (void*)c.r1; 276 } 277 278 uint32 279 runtime·issigpanic(uint32 code) 280 { 281 switch(code) { 282 case EXCEPTION_ACCESS_VIOLATION: 283 case EXCEPTION_INT_DIVIDE_BY_ZERO: 284 case EXCEPTION_INT_OVERFLOW: 285 case EXCEPTION_FLT_DENORMAL_OPERAND: 286 case EXCEPTION_FLT_DIVIDE_BY_ZERO: 287 case EXCEPTION_FLT_INEXACT_RESULT: 288 case EXCEPTION_FLT_OVERFLOW: 289 case EXCEPTION_FLT_UNDERFLOW: 290 return 1; 291 } 292 return 0; 293 } 294 295 void 296 runtime·sigpanic(void) 297 { 298 switch(g->sig) { 299 case EXCEPTION_ACCESS_VIOLATION: 300 if(g->sigcode1 < 0x1000) { 301 if(g->sigpc == 0) 302 runtime·panicstring("call of nil func value"); 303 runtime·panicstring("invalid memory address or nil pointer dereference"); 304 } 305 runtime·printf("unexpected fault address %p\n", g->sigcode1); 306 runtime·throw("fault"); 307 case EXCEPTION_INT_DIVIDE_BY_ZERO: 308 runtime·panicstring("integer divide by zero"); 309 case EXCEPTION_INT_OVERFLOW: 310 runtime·panicstring("integer overflow"); 311 case EXCEPTION_FLT_DENORMAL_OPERAND: 312 case EXCEPTION_FLT_DIVIDE_BY_ZERO: 313 case EXCEPTION_FLT_INEXACT_RESULT: 314 case EXCEPTION_FLT_OVERFLOW: 315 case EXCEPTION_FLT_UNDERFLOW: 316 runtime·panicstring("floating point error"); 317 } 318 runtime·throw("fault"); 319 } 320 321 extern void *runtime·sigtramp; 322 323 void 324 runtime·initsig(void) 325 { 326 // following line keeps sigtramp alive at link stage 327 // if there's a better way please write it here 328 void *p = runtime·sigtramp; 329 USED(p); 330 } 331 332 uint32 333 runtime·ctrlhandler1(uint32 type) 334 { 335 int32 s; 336 337 switch(type) { 338 case CTRL_C_EVENT: 339 case CTRL_BREAK_EVENT: 340 s = SIGINT; 341 break; 342 default: 343 return 0; 344 } 345 346 if(runtime·sigsend(s)) 347 return 1; 348 runtime·exit(2); // SIGINT, SIGTERM, etc 349 return 0; 350 } 351 352 extern void runtime·dosigprof(Context *r, G *gp); 353 extern void runtime·profileloop(void); 354 static void *profiletimer; 355 356 static void 357 profilem(M *mp) 358 { 359 extern M runtime·m0; 360 extern uint32 runtime·tls0[]; 361 byte rbuf[sizeof(Context)+15]; 362 Context *r; 363 void *tls; 364 G *gp; 365 366 tls = mp->tls; 367 if(mp == &runtime·m0) 368 tls = runtime·tls0; 369 gp = *(G**)tls; 370 371 if(gp != nil && gp != mp->g0 && gp->status != Gsyscall) { 372 // align Context to 16 bytes 373 r = (Context*)((uintptr)(&rbuf[15]) & ~15); 374 r->ContextFlags = CONTEXT_CONTROL; 375 runtime·stdcall(runtime·GetThreadContext, 2, mp->thread, r); 376 runtime·dosigprof(r, gp); 377 } 378 } 379 380 void 381 runtime·profileloop1(void) 382 { 383 M *mp, *allm; 384 void *thread; 385 386 runtime·stdcall(runtime·SetThreadPriority, 2, 387 (uintptr)-2, (uintptr)THREAD_PRIORITY_HIGHEST); 388 389 for(;;) { 390 runtime·stdcall(runtime·WaitForSingleObject, 2, profiletimer, (uintptr)-1); 391 allm = runtime·atomicloadp(&runtime·allm); 392 for(mp = allm; mp != nil; mp = mp->alllink) { 393 thread = runtime·atomicloadp(&mp->thread); 394 if(thread == nil) 395 continue; 396 runtime·stdcall(runtime·SuspendThread, 1, thread); 397 if(mp->profilehz != 0) 398 profilem(mp); 399 runtime·stdcall(runtime·ResumeThread, 1, thread); 400 } 401 } 402 } 403 404 void 405 runtime·resetcpuprofiler(int32 hz) 406 { 407 static Lock lock; 408 void *timer, *thread; 409 int32 ms; 410 int64 due; 411 412 runtime·lock(&lock); 413 if(profiletimer == nil) { 414 timer = runtime·stdcall(runtime·CreateWaitableTimer, 3, nil, nil, nil); 415 runtime·atomicstorep(&profiletimer, timer); 416 thread = runtime·stdcall(runtime·CreateThread, 6, 417 nil, nil, runtime·profileloop, nil, nil, nil); 418 runtime·stdcall(runtime·CloseHandle, 1, thread); 419 } 420 runtime·unlock(&lock); 421 422 ms = 0; 423 due = 1LL<<63; 424 if(hz > 0) { 425 ms = 1000 / hz; 426 if(ms == 0) 427 ms = 1; 428 due = ms * -10000; 429 } 430 runtime·stdcall(runtime·SetWaitableTimer, 6, 431 profiletimer, &due, (uintptr)ms, nil, nil, nil); 432 runtime·atomicstore((uint32*)&m->profilehz, hz); 433 } 434 435 void 436 os·sigpipe(void) 437 { 438 runtime·throw("too many writes on closed pipe"); 439 } 440 441 uintptr 442 runtime·memlimit(void) 443 { 444 return 0; 445 } 446 447 void 448 runtime·setprof(bool on) 449 { 450 USED(on); 451 } 452 453 int8 runtime·badcallbackmsg[] = "runtime: cgo callback on thread not created by Go.\n"; 454 int32 runtime·badcallbacklen = sizeof runtime·badcallbackmsg - 1; 455 456 int8 runtime·badsignalmsg[] = "runtime: signal received on thread not created by Go.\n"; 457 int32 runtime·badsignallen = sizeof runtime·badsignalmsg - 1; 458 459 void 460 runtime·crash(void) 461 { 462 // TODO: This routine should do whatever is needed 463 // to make the Windows program abort/crash as it 464 // would if Go was not intercepting signals. 465 // On Unix the routine would remove the custom signal 466 // handler and then raise a signal (like SIGABRT). 467 // Something like that should happen here. 468 // It's okay to leave this empty for now: if crash returns 469 // the ordinary exit-after-panic happens. 470 }