~ubuntu-branches/ubuntu/utopic/golang/utopic

« back to all changes in this revision

Viewing changes to src/pkg/runtime/thread_windows.c

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2013-08-20 14:06:23 UTC
  • mfrom: (14.1.23 saucy-proposed)
  • Revision ID: package-import@ubuntu.com-20130820140623-b414jfxi3m0qkmrq
Tags: 2:1.1.2-2ubuntu1
* Merge from Debian unstable (LP: #1211749, #1202027). Remaining changes:
  - 016-armhf-elf-header.patch: Use correct ELF header for armhf binaries.
  - d/control,control.cross: Update Breaks/Replaces for Ubuntu
    versions to ensure smooth upgrades, regenerate control file.

Show diffs side-by-side

added added

removed removed

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