github.com/reiver/go@v0.0.0-20150109200633-1d0c7792f172/src/runtime/os1_windows.go (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  package runtime
     6  
     7  import (
     8  	"unsafe"
     9  )
    10  
    11  //go:cgo_import_dynamic runtime._AddVectoredExceptionHandler AddVectoredExceptionHandler "kernel32.dll"
    12  //go:cgo_import_dynamic runtime._CloseHandle CloseHandle "kernel32.dll"
    13  //go:cgo_import_dynamic runtime._CreateEventA CreateEventA "kernel32.dll"
    14  //go:cgo_import_dynamic runtime._CreateThread CreateThread "kernel32.dll"
    15  //go:cgo_import_dynamic runtime._CreateWaitableTimerA CreateWaitableTimerA "kernel32.dll"
    16  //go:cgo_import_dynamic runtime._CryptAcquireContextW CryptAcquireContextW "advapi32.dll"
    17  //go:cgo_import_dynamic runtime._CryptGenRandom CryptGenRandom "advapi32.dll"
    18  //go:cgo_import_dynamic runtime._CryptReleaseContext CryptReleaseContext "advapi32.dll"
    19  //go:cgo_import_dynamic runtime._DuplicateHandle DuplicateHandle "kernel32.dll"
    20  //go:cgo_import_dynamic runtime._ExitProcess ExitProcess "kernel32.dll"
    21  //go:cgo_import_dynamic runtime._FreeEnvironmentStringsW FreeEnvironmentStringsW "kernel32.dll"
    22  //go:cgo_import_dynamic runtime._GetEnvironmentStringsW GetEnvironmentStringsW "kernel32.dll"
    23  //go:cgo_import_dynamic runtime._GetProcAddress GetProcAddress "kernel32.dll"
    24  //go:cgo_import_dynamic runtime._GetStdHandle GetStdHandle "kernel32.dll"
    25  //go:cgo_import_dynamic runtime._GetSystemInfo GetSystemInfo "kernel32.dll"
    26  //go:cgo_import_dynamic runtime._GetThreadContext GetThreadContext "kernel32.dll"
    27  //go:cgo_import_dynamic runtime._LoadLibraryW LoadLibraryW "kernel32.dll"
    28  //go:cgo_import_dynamic runtime._LoadLibraryA LoadLibraryA "kernel32.dll"
    29  //go:cgo_import_dynamic runtime._NtWaitForSingleObject NtWaitForSingleObject "ntdll.dll"
    30  //go:cgo_import_dynamic runtime._ResumeThread ResumeThread "kernel32.dll"
    31  //go:cgo_import_dynamic runtime._SetConsoleCtrlHandler SetConsoleCtrlHandler "kernel32.dll"
    32  //go:cgo_import_dynamic runtime._SetErrorMode SetErrorMode "kernel32.dll"
    33  //go:cgo_import_dynamic runtime._SetEvent SetEvent "kernel32.dll"
    34  //go:cgo_import_dynamic runtime._SetProcessPriorityBoost SetProcessPriorityBoost "kernel32.dll"
    35  //go:cgo_import_dynamic runtime._SetThreadPriority SetThreadPriority "kernel32.dll"
    36  //go:cgo_import_dynamic runtime._SetUnhandledExceptionFilter SetUnhandledExceptionFilter "kernel32.dll"
    37  //go:cgo_import_dynamic runtime._SetWaitableTimer SetWaitableTimer "kernel32.dll"
    38  //go:cgo_import_dynamic runtime._Sleep Sleep "kernel32.dll"
    39  //go:cgo_import_dynamic runtime._SuspendThread SuspendThread "kernel32.dll"
    40  //go:cgo_import_dynamic runtime._WaitForSingleObject WaitForSingleObject "kernel32.dll"
    41  //go:cgo_import_dynamic runtime._WriteFile WriteFile "kernel32.dll"
    42  //go:cgo_import_dynamic runtime._timeBeginPeriod timeBeginPeriod "winmm.dll"
    43  
    44  var (
    45  	_AddVectoredExceptionHandler,
    46  	_CloseHandle,
    47  	_CreateEventA,
    48  	_CreateThread,
    49  	_CreateWaitableTimerA,
    50  	_CryptAcquireContextW,
    51  	_CryptGenRandom,
    52  	_CryptReleaseContext,
    53  	_DuplicateHandle,
    54  	_ExitProcess,
    55  	_FreeEnvironmentStringsW,
    56  	_GetEnvironmentStringsW,
    57  	_GetProcAddress,
    58  	_GetStdHandle,
    59  	_GetSystemInfo,
    60  	_GetThreadContext,
    61  	_LoadLibraryW,
    62  	_LoadLibraryA,
    63  	_NtWaitForSingleObject,
    64  	_ResumeThread,
    65  	_SetConsoleCtrlHandler,
    66  	_SetErrorMode,
    67  	_SetEvent,
    68  	_SetProcessPriorityBoost,
    69  	_SetThreadPriority,
    70  	_SetUnhandledExceptionFilter,
    71  	_SetWaitableTimer,
    72  	_Sleep,
    73  	_SuspendThread,
    74  	_WaitForSingleObject,
    75  	_WriteFile,
    76  	_timeBeginPeriod stdFunction
    77  )
    78  
    79  var _GetQueuedCompletionStatusEx stdFunction
    80  
    81  // in sys_windows_386.s and sys_windows_amd64.s
    82  func externalthreadhandler()
    83  func exceptiontramp()
    84  func firstcontinuetramp()
    85  func lastcontinuetramp()
    86  
    87  //go:nosplit
    88  func getLoadLibrary() uintptr {
    89  	return uintptr(unsafe.Pointer(_LoadLibraryW))
    90  }
    91  
    92  //go:nosplit
    93  func getGetProcAddress() uintptr {
    94  	return uintptr(unsafe.Pointer(_GetProcAddress))
    95  }
    96  
    97  func getproccount() int32 {
    98  	var info systeminfo
    99  	stdcall1(_GetSystemInfo, uintptr(unsafe.Pointer(&info)))
   100  	return int32(info.dwnumberofprocessors)
   101  }
   102  
   103  const (
   104  	currentProcess = ^uintptr(0) // -1 = current process
   105  	currentThread  = ^uintptr(1) // -2 = current thread
   106  )
   107  
   108  const (
   109  	SEM_FAILCRITICALERRORS     = 0x0001
   110  	SEM_NOGPFAULTERRORBOX      = 0x0002
   111  	SEM_NOALIGNMENTFAULTEXCEPT = 0x0004
   112  	SEM_NOOPENFILEERRORBOX     = 0x8000
   113  )
   114  
   115  var (
   116  	kernel32Name                    = []byte("kernel32.dll\x00")
   117  	addVectoredContinueHandlerName  = []byte("AddVectoredContinueHandler\x00")
   118  	getQueuedCompletionStatusExName = []byte("GetQueuedCompletionStatusEx\x00")
   119  )
   120  
   121  func osinit() {
   122  	setBadSignalMsg()
   123  
   124  	kernel32 := stdcall1(_LoadLibraryA, uintptr(unsafe.Pointer(&kernel32Name[0])))
   125  
   126  	// don't display the crash dialog
   127  	errormode := uint32(stdcall1(_SetErrorMode, SEM_NOGPFAULTERRORBOX))
   128  	stdcall1(_SetErrorMode, uintptr(errormode)|SEM_FAILCRITICALERRORS|SEM_NOGPFAULTERRORBOX|SEM_NOOPENFILEERRORBOX)
   129  
   130  	externalthreadhandlerp = funcPC(externalthreadhandler)
   131  
   132  	stdcall2(_AddVectoredExceptionHandler, 1, funcPC(exceptiontramp))
   133  	addVectoredContinueHandler := uintptr(0)
   134  	if kernel32 != 0 {
   135  		addVectoredContinueHandler = stdcall2(_GetProcAddress, kernel32, uintptr(unsafe.Pointer(&addVectoredContinueHandlerName[0])))
   136  	}
   137  	if addVectoredContinueHandler == 0 || unsafe.Sizeof(&kernel32) == 4 {
   138  		// use SetUnhandledExceptionFilter for windows-386 or
   139  		// if VectoredContinueHandler is unavailable.
   140  		// note: SetUnhandledExceptionFilter handler won't be called, if debugging.
   141  		stdcall1(_SetUnhandledExceptionFilter, funcPC(lastcontinuetramp))
   142  	} else {
   143  		stdcall2(stdFunction(unsafe.Pointer(addVectoredContinueHandler)), 1, funcPC(firstcontinuetramp))
   144  		stdcall2(stdFunction(unsafe.Pointer(addVectoredContinueHandler)), 0, funcPC(lastcontinuetramp))
   145  	}
   146  
   147  	stdcall2(_SetConsoleCtrlHandler, funcPC(ctrlhandler), 1)
   148  
   149  	stdcall1(_timeBeginPeriod, 1)
   150  
   151  	ncpu = getproccount()
   152  
   153  	// Windows dynamic priority boosting assumes that a process has different types
   154  	// of dedicated threads -- GUI, IO, computational, etc. Go processes use
   155  	// equivalent threads that all do a mix of GUI, IO, computations, etc.
   156  	// In such context dynamic priority boosting does nothing but harm, so we turn it off.
   157  	stdcall2(_SetProcessPriorityBoost, currentProcess, 1)
   158  
   159  	if kernel32 != 0 {
   160  		_GetQueuedCompletionStatusEx = stdFunction(unsafe.Pointer(stdcall2(_GetProcAddress, kernel32, uintptr(unsafe.Pointer(&getQueuedCompletionStatusExName[0])))))
   161  	}
   162  }
   163  
   164  //go:nosplit
   165  func getRandomData(r []byte) {
   166  	const (
   167  		prov_rsa_full       = 1
   168  		crypt_verifycontext = 0xF0000000
   169  	)
   170  	var handle uintptr
   171  	n := 0
   172  	if stdcall5(_CryptAcquireContextW, uintptr(unsafe.Pointer(&handle)), 0, 0, prov_rsa_full, crypt_verifycontext) != 0 {
   173  		if stdcall3(_CryptGenRandom, handle, uintptr(len(r)), uintptr(unsafe.Pointer(&r[0]))) != 0 {
   174  			n = len(r)
   175  		}
   176  		stdcall2(_CryptReleaseContext, handle, 0)
   177  	}
   178  	extendRandom(r, n)
   179  }
   180  
   181  func goenvs() {
   182  	var p *uint16
   183  
   184  	env := (*uint16)(unsafe.Pointer(stdcall0(_GetEnvironmentStringsW)))
   185  
   186  	n := 0
   187  	for p = env; *p != 0; n++ {
   188  		p = (*uint16)(add(unsafe.Pointer(p), uintptr(findnullw(p)+1)*unsafe.Sizeof(*p)))
   189  	}
   190  
   191  	envs = makeStringSlice(int(n))
   192  
   193  	p = env
   194  	for i := 0; i < n; i++ {
   195  		envs[i] = gostringw(p)
   196  		p = (*uint16)(add(unsafe.Pointer(p), uintptr(findnullw(p)+1)*unsafe.Sizeof(*p)))
   197  	}
   198  
   199  	stdcall1(_FreeEnvironmentStringsW, uintptr(unsafe.Pointer(env)))
   200  }
   201  
   202  //go:nosplit
   203  func exit(code int32) {
   204  	stdcall1(_ExitProcess, uintptr(code))
   205  }
   206  
   207  //go:nosplit
   208  func write(fd uintptr, buf unsafe.Pointer, n int32) int32 {
   209  	const (
   210  		_STD_OUTPUT_HANDLE = ^uintptr(10) // -11
   211  		_STD_ERROR_HANDLE  = ^uintptr(11) // -12
   212  	)
   213  	var handle uintptr
   214  	switch fd {
   215  	case 1:
   216  		handle = stdcall1(_GetStdHandle, _STD_OUTPUT_HANDLE)
   217  	case 2:
   218  		handle = stdcall1(_GetStdHandle, _STD_ERROR_HANDLE)
   219  	default:
   220  		// assume fd is real windows handle.
   221  		handle = fd
   222  	}
   223  	var written uint32
   224  	stdcall5(_WriteFile, handle, uintptr(buf), uintptr(n), uintptr(unsafe.Pointer(&written)), 0)
   225  	return int32(written)
   226  }
   227  
   228  //go:nosplit
   229  func semasleep(ns int64) int32 {
   230  	// store ms in ns to save stack space
   231  	if ns < 0 {
   232  		ns = _INFINITE
   233  	} else {
   234  		ns = int64(timediv(ns, 1000000, nil))
   235  		if ns == 0 {
   236  			ns = 1
   237  		}
   238  	}
   239  	if stdcall2(_WaitForSingleObject, getg().m.waitsema, uintptr(ns)) != 0 {
   240  		return -1 // timeout
   241  	}
   242  	return 0
   243  }
   244  
   245  //go:nosplit
   246  func semawakeup(mp *m) {
   247  	stdcall1(_SetEvent, mp.waitsema)
   248  }
   249  
   250  //go:nosplit
   251  func semacreate() uintptr {
   252  	return stdcall4(_CreateEventA, 0, 0, 0, 0)
   253  }
   254  
   255  func newosproc(mp *m, stk unsafe.Pointer) {
   256  	const _STACK_SIZE_PARAM_IS_A_RESERVATION = 0x00010000
   257  	thandle := stdcall6(_CreateThread, 0, 0x20000,
   258  		funcPC(tstart_stdcall), uintptr(unsafe.Pointer(mp)),
   259  		_STACK_SIZE_PARAM_IS_A_RESERVATION, 0)
   260  	if thandle == 0 {
   261  		println("runtime: failed to create new OS thread (have ", mcount(), " already; errno=", getlasterror(), ")")
   262  		throw("runtime.newosproc")
   263  	}
   264  }
   265  
   266  // Called to initialize a new m (including the bootstrap m).
   267  // Called on the parent thread (main thread in case of bootstrap), can allocate memory.
   268  func mpreinit(mp *m) {
   269  }
   270  
   271  // Called to initialize a new m (including the bootstrap m).
   272  // Called on the new thread, can not allocate memory.
   273  func minit() {
   274  	var thandle uintptr
   275  	stdcall7(_DuplicateHandle, currentProcess, currentThread, currentProcess, uintptr(unsafe.Pointer(&thandle)), 0, 0, _DUPLICATE_SAME_ACCESS)
   276  	atomicstoreuintptr(&getg().m.thread, thandle)
   277  }
   278  
   279  // Called from dropm to undo the effect of an minit.
   280  func unminit() {
   281  	tp := &getg().m.thread
   282  	stdcall1(_CloseHandle, *tp)
   283  	*tp = 0
   284  }
   285  
   286  // Described in http://www.dcl.hpi.uni-potsdam.de/research/WRK/2007/08/getting-os-information-the-kuser_shared_data-structure/
   287  type _KSYSTEM_TIME struct {
   288  	LowPart   uint32
   289  	High1Time int32
   290  	High2Time int32
   291  }
   292  
   293  const (
   294  	_INTERRUPT_TIME = 0x7ffe0008
   295  	_SYSTEM_TIME    = 0x7ffe0014
   296  )
   297  
   298  //go:nosplit
   299  func systime(addr uintptr) int64 {
   300  	timeaddr := (*_KSYSTEM_TIME)(unsafe.Pointer(addr))
   301  
   302  	var t _KSYSTEM_TIME
   303  	for i := 1; i < 10000; i++ {
   304  		// these fields must be read in that order (see URL above)
   305  		t.High1Time = timeaddr.High1Time
   306  		t.LowPart = timeaddr.LowPart
   307  		t.High2Time = timeaddr.High2Time
   308  		if t.High1Time == t.High2Time {
   309  			return int64(t.High1Time)<<32 | int64(t.LowPart)
   310  		}
   311  		if (i % 100) == 0 {
   312  			osyield()
   313  		}
   314  	}
   315  	systemstack(func() {
   316  		throw("interrupt/system time is changing too fast")
   317  	})
   318  	return 0
   319  }
   320  
   321  //go:nosplit
   322  func unixnano() int64 {
   323  	return (systime(_SYSTEM_TIME) - 116444736000000000) * 100
   324  }
   325  
   326  //go:nosplit
   327  func nanotime() int64 {
   328  	return systime(_INTERRUPT_TIME) * 100
   329  }
   330  
   331  // Calling stdcall on os stack.
   332  //go:nosplit
   333  func stdcall(fn stdFunction) uintptr {
   334  	gp := getg()
   335  	mp := gp.m
   336  	mp.libcall.fn = uintptr(unsafe.Pointer(fn))
   337  
   338  	if mp.profilehz != 0 {
   339  		// leave pc/sp for cpu profiler
   340  		mp.libcallg = gp
   341  		mp.libcallpc = getcallerpc(unsafe.Pointer(&fn))
   342  		// sp must be the last, because once async cpu profiler finds
   343  		// all three values to be non-zero, it will use them
   344  		mp.libcallsp = getcallersp(unsafe.Pointer(&fn))
   345  	}
   346  	asmcgocall(unsafe.Pointer(funcPC(asmstdcall)), unsafe.Pointer(&mp.libcall))
   347  	mp.libcallsp = 0
   348  	return mp.libcall.r1
   349  }
   350  
   351  //go:nosplit
   352  func stdcall0(fn stdFunction) uintptr {
   353  	mp := getg().m
   354  	mp.libcall.n = 0
   355  	mp.libcall.args = uintptr(noescape(unsafe.Pointer(&fn))) // it's unused but must be non-nil, otherwise crashes
   356  	return stdcall(fn)
   357  }
   358  
   359  //go:nosplit
   360  func stdcall1(fn stdFunction, a0 uintptr) uintptr {
   361  	mp := getg().m
   362  	mp.libcall.n = 1
   363  	mp.libcall.args = uintptr(noescape(unsafe.Pointer(&a0)))
   364  	return stdcall(fn)
   365  }
   366  
   367  //go:nosplit
   368  func stdcall2(fn stdFunction, a0, a1 uintptr) uintptr {
   369  	mp := getg().m
   370  	mp.libcall.n = 2
   371  	mp.libcall.args = uintptr(noescape(unsafe.Pointer(&a0)))
   372  	return stdcall(fn)
   373  }
   374  
   375  //go:nosplit
   376  func stdcall3(fn stdFunction, a0, a1, a2 uintptr) uintptr {
   377  	mp := getg().m
   378  	mp.libcall.n = 3
   379  	mp.libcall.args = uintptr(noescape(unsafe.Pointer(&a0)))
   380  	return stdcall(fn)
   381  }
   382  
   383  //go:nosplit
   384  func stdcall4(fn stdFunction, a0, a1, a2, a3 uintptr) uintptr {
   385  	mp := getg().m
   386  	mp.libcall.n = 4
   387  	mp.libcall.args = uintptr(noescape(unsafe.Pointer(&a0)))
   388  	return stdcall(fn)
   389  }
   390  
   391  //go:nosplit
   392  func stdcall5(fn stdFunction, a0, a1, a2, a3, a4 uintptr) uintptr {
   393  	mp := getg().m
   394  	mp.libcall.n = 5
   395  	mp.libcall.args = uintptr(noescape(unsafe.Pointer(&a0)))
   396  	return stdcall(fn)
   397  }
   398  
   399  //go:nosplit
   400  func stdcall6(fn stdFunction, a0, a1, a2, a3, a4, a5 uintptr) uintptr {
   401  	mp := getg().m
   402  	mp.libcall.n = 6
   403  	mp.libcall.args = uintptr(noescape(unsafe.Pointer(&a0)))
   404  	return stdcall(fn)
   405  }
   406  
   407  //go:nosplit
   408  func stdcall7(fn stdFunction, a0, a1, a2, a3, a4, a5, a6 uintptr) uintptr {
   409  	mp := getg().m
   410  	mp.libcall.n = 7
   411  	mp.libcall.args = uintptr(noescape(unsafe.Pointer(&a0)))
   412  	return stdcall(fn)
   413  }
   414  
   415  // in sys_windows_386.s and sys_windows_amd64.s
   416  func usleep1(usec uint32)
   417  
   418  //go:nosplit
   419  func osyield() {
   420  	usleep1(1)
   421  }
   422  
   423  //go:nosplit
   424  func usleep(us uint32) {
   425  	// Have 1us units; want 100ns units.
   426  	usleep1(10 * us)
   427  }
   428  
   429  func issigpanic(code uint32) uint32 {
   430  	switch code {
   431  	default:
   432  		return 0
   433  	case _EXCEPTION_ACCESS_VIOLATION:
   434  	case _EXCEPTION_INT_DIVIDE_BY_ZERO:
   435  	case _EXCEPTION_INT_OVERFLOW:
   436  	case _EXCEPTION_FLT_DENORMAL_OPERAND:
   437  	case _EXCEPTION_FLT_DIVIDE_BY_ZERO:
   438  	case _EXCEPTION_FLT_INEXACT_RESULT:
   439  	case _EXCEPTION_FLT_OVERFLOW:
   440  	case _EXCEPTION_FLT_UNDERFLOW:
   441  	case _EXCEPTION_BREAKPOINT:
   442  	}
   443  	return 1
   444  }
   445  
   446  func initsig() {
   447  	/*
   448  		// TODO(brainman): I don't think we need that bit of code
   449  		// following line keeps these functions alive at link stage
   450  		// if there's a better way please write it here
   451  		void *e = runtime·exceptiontramp;
   452  		void *f = runtime·firstcontinuetramp;
   453  		void *l = runtime·lastcontinuetramp;
   454  		USED(e);
   455  		USED(f);
   456  		USED(l);
   457  	*/
   458  }
   459  
   460  func ctrlhandler1(_type uint32) uint32 {
   461  	var s uint32
   462  
   463  	switch _type {
   464  	case _CTRL_C_EVENT, _CTRL_BREAK_EVENT:
   465  		s = _SIGINT
   466  	default:
   467  		return 0
   468  	}
   469  
   470  	if sigsend(s) {
   471  		return 1
   472  	}
   473  	exit(2) // SIGINT, SIGTERM, etc
   474  	return 0
   475  }
   476  
   477  // in sys_windows_386.s and sys_windows_amd64.s
   478  func profileloop()
   479  
   480  var profiletimer uintptr
   481  
   482  func profilem(mp *m) {
   483  	var r *context
   484  	rbuf := make([]byte, unsafe.Sizeof(*r)+15)
   485  
   486  	tls := &mp.tls[0]
   487  	if mp == &m0 {
   488  		tls = &tls0[0]
   489  	}
   490  	gp := *((**g)(unsafe.Pointer(tls)))
   491  
   492  	// align Context to 16 bytes
   493  	r = (*context)(unsafe.Pointer((uintptr(unsafe.Pointer(&rbuf[15]))) &^ 15))
   494  	r.contextflags = _CONTEXT_CONTROL
   495  	stdcall2(_GetThreadContext, mp.thread, uintptr(unsafe.Pointer(r)))
   496  	dosigprof(r, gp, mp)
   497  }
   498  
   499  func profileloop1() {
   500  	stdcall2(_SetThreadPriority, currentThread, _THREAD_PRIORITY_HIGHEST)
   501  
   502  	for {
   503  		stdcall2(_WaitForSingleObject, profiletimer, _INFINITE)
   504  		first := (*m)(atomicloadp(unsafe.Pointer(&allm)))
   505  		for mp := first; mp != nil; mp = mp.alllink {
   506  			thread := atomicloaduintptr(&mp.thread)
   507  			// Do not profile threads blocked on Notes,
   508  			// this includes idle worker threads,
   509  			// idle timer thread, idle heap scavenger, etc.
   510  			if thread == 0 || mp.profilehz == 0 || mp.blocked {
   511  				continue
   512  			}
   513  			stdcall1(_SuspendThread, thread)
   514  			if mp.profilehz != 0 && !mp.blocked {
   515  				profilem(mp)
   516  			}
   517  			stdcall1(_ResumeThread, thread)
   518  		}
   519  	}
   520  }
   521  
   522  var cpuprofilerlock mutex
   523  
   524  func resetcpuprofiler(hz int32) {
   525  	lock(&cpuprofilerlock)
   526  	if profiletimer == 0 {
   527  		timer := stdcall3(_CreateWaitableTimerA, 0, 0, 0)
   528  		atomicstoreuintptr(&profiletimer, timer)
   529  		thread := stdcall6(_CreateThread, 0, 0, funcPC(profileloop), 0, 0, 0)
   530  		stdcall2(_SetThreadPriority, thread, _THREAD_PRIORITY_HIGHEST)
   531  		stdcall1(_CloseHandle, thread)
   532  	}
   533  	unlock(&cpuprofilerlock)
   534  
   535  	ms := int32(0)
   536  	due := ^int64(^uint64(1 << 63))
   537  	if hz > 0 {
   538  		ms = 1000 / hz
   539  		if ms == 0 {
   540  			ms = 1
   541  		}
   542  		due = int64(ms) * -10000
   543  	}
   544  	stdcall6(_SetWaitableTimer, profiletimer, uintptr(unsafe.Pointer(&due)), uintptr(ms), 0, 0, 0)
   545  	atomicstore((*uint32)(unsafe.Pointer(&getg().m.profilehz)), uint32(hz))
   546  }
   547  
   548  func memlimit() uintptr {
   549  	return 0
   550  }
   551  
   552  var (
   553  	badsignalmsg [100]byte
   554  	badsignallen int32
   555  )
   556  
   557  func setBadSignalMsg() {
   558  	const msg = "runtime: signal received on thread not created by Go.\n"
   559  	for i, c := range msg {
   560  		badsignalmsg[i] = byte(c)
   561  		badsignallen++
   562  	}
   563  }
   564  
   565  func crash() {
   566  	// TODO: This routine should do whatever is needed
   567  	// to make the Windows program abort/crash as it
   568  	// would if Go was not intercepting signals.
   569  	// On Unix the routine would remove the custom signal
   570  	// handler and then raise a signal (like SIGABRT).
   571  	// Something like that should happen here.
   572  	// It's okay to leave this empty for now: if crash returns
   573  	// the ordinary exit-after-panic happens.
   574  }