-
Notifications
You must be signed in to change notification settings - Fork 7
/
outside.c
123 lines (104 loc) · 3 KB
/
outside.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
// Copyright (c) 2013 Tony Wilson. All rights reserved.
// See LICENCE file for permissions and restrictions.
// 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 goauthors-LICENSE file.
#include "runtime.h"
#include "cgocall.h"
void ·asmcall(void *c);
static void endcgo(void);
static FuncVal endcgoV = { endcgo };
// Based on runtime·cgocall (src/pkg/runtime/cgocall.c)
// which is Copyright 2009 The Go Authors.
void ·ccall(void *call) {
Defer d;
if(m->racecall) {
runtime·asmcgocall(·asmcall,call);
return;
}
// TODO(t): fix
// if(!runtime·iscgo && !Windows)
// runtime·throw("cgocall unavailable");
// Redundant in outside
// if(fn == 0)
// runtime·throw("cgocall nil");
// TODO(t): fix
// if(raceenabled)
// runtime·racereleasemerge(&cgosync);
// Create an extra M for callbacks on threads not created by Go on first cgo call.
if(runtime·needextram && runtime·cas(&runtime·needextram, 1, 0))
runtime·newextram();
m->ncgocall++;
/*
* Lock g to m to ensure we stay on the same stack if we do a
* cgo callback. Add entry to defer stack in case of panic.
*/
runtime·lockOSThread();
d.fn = &endcgoV;
d.siz = 0;
d.link = g->defer;
d.argp = (void*)-1; // unused because unlockm never recovers
d.special = true;
d.free = false;
g->defer = &d;
m->ncgo++;
/*
* Announce we are entering a system call
* so that the scheduler knows to create another
* M to run goroutines while we are in the
* foreign code.
*
* The call to asmcall is guaranteed not to
* split the stack and does not allocate memory,
* so it is safe to call while "in a system call", outside
* the $GOMAXPROCS accounting.
*/
runtime·entersyscall();
runtime·asmcgocall(·asmcall,call); //TODO(t): combine asmcall and asmcgocall
runtime·exitsyscall();
if(g->defer != &d || d.fn != &endcgoV)
runtime·throw("runtime: bad defer entry in cgocallback");
g->defer = d.link;
endcgo();
}
// Based on Syscall (src/pkg/runtime/syscall_windows.goc)
// which is Copyright 2009 The Go Authors.
void ·callN(uintptr fn, uintptr nargs, uintptr *args,
uintptr r1, uintptr r2, float64 f, uintptr err) {
struct { // NOTE(t): based on WinCall
void (*fn)(void*);
uintptr n; // number of parameters
void* args; // parameters
uintptr r1; // return values
uintptr r2;
uintptr err; // error number
float64 f;
} c;
c.fn = (void*)fn;
c.n = nargs;
c.args = (void*)args;
·ccall(&c); // TODO(t): inline
err = c.err;
r1 = c.r1;
r2 = c.r2;
f = c.f;
FLUSH(&r1);
FLUSH(&r2);
FLUSH(&err);
FLUSH(&f);
}
// Copyright 2009 The Go Authors.
// (src/pkg/runtime/cgocall.c)
static void endcgo(void) {
runtime·unlockOSThread();
m->ncgo--;
if(m->ncgo == 0) {
// We are going back to Go and are not in a recursive
// call. Let the GC collect any memory allocated via
// _cgo_allocate that is no longer referenced.
m->cgomal = nil;
}
// TODO(t): fix
// if(raceenabled)
// runtime·raceacquire(&cgosync);
}