~ubuntu-branches/ubuntu/saucy/golang/saucy

« back to all changes in this revision

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

  • Committer: Package Import Robot
  • Author(s): Adam Conrad
  • Date: 2013-07-08 05:52:37 UTC
  • mfrom: (29.1.1 sid)
  • Revision ID: package-import@ubuntu.com-20130708055237-at01839e0hp8z3ni
Tags: 2:1.1-1ubuntu1
016-armhf-elf-header.patch: Use correct ELF header for armhf binaries.

Show diffs side-by-side

added added

removed removed

Lines of Context:
6
6
#include "arch_GOARCH.h"
7
7
#include "stack.h"
8
8
#include "cgocall.h"
 
9
#include "race.h"
9
10
 
10
11
// Cgo call and callback support.
11
12
//
41
42
// know about packages).  The gcc-compiled C function f calls GoF.
42
43
//
43
44
// GoF calls crosscall2(_cgoexp_GoF, frame, framesize).  Crosscall2
44
 
// (in cgo/$GOOS.S, a gcc-compiled assembly file) is a two-argument
 
45
// (in cgo/gcc_$GOARCH.S, a gcc-compiled assembly file) is a two-argument
45
46
// adapter from the gcc function call ABI to the 6c function call ABI.
46
47
// It is called from gcc to call 6c functions.  In this case it calls
47
48
// _cgoexp_GoF(frame, framesize), still running on m->g0's stack
82
83
// _cgoexp_GoF immediately returns to crosscall2, which restores the
83
84
// callee-save registers for gcc and returns to GoF, which returns to f.
84
85
 
85
 
void *initcgo;  /* filled in by dynamic linker when Cgo is available */
86
 
 
87
 
static void unlockm(void);
 
86
void *_cgo_init;        /* filled in by dynamic linker when Cgo is available */
 
87
static int64 cgosync;  /* represents possible synchronization in C code */
 
88
 
 
89
// These two are only used by the architecture where TLS based storage isn't
 
90
// the default for g and m (e.g., ARM)
 
91
void *_cgo_load_gm; /* filled in by dynamic linker when Cgo is available */
 
92
void *_cgo_save_gm; /* filled in by dynamic linker when Cgo is available */
 
93
 
88
94
static void unwindm(void);
89
95
 
90
96
// Call from Go to C.
91
97
 
 
98
static void endcgo(void);
 
99
static FuncVal endcgoV = { endcgo };
 
100
 
 
101
// Gives a hint that the next syscall
 
102
// executed by the current goroutine will block.
 
103
// Currently used only on windows.
 
104
void
 
105
net·runtime_blockingSyscallHint(void)
 
106
{
 
107
        g->blockingsyscall = true;
 
108
}
 
109
 
92
110
void
93
111
runtime·cgocall(void (*fn)(void*), void *arg)
94
112
{
95
113
        Defer d;
96
114
 
 
115
        if(m->racecall) {
 
116
                runtime·asmcgocall(fn, arg);
 
117
                return;
 
118
        }
 
119
 
97
120
        if(!runtime·iscgo && !Windows)
98
121
                runtime·throw("cgocall unavailable");
99
122
 
100
123
        if(fn == 0)
101
124
                runtime·throw("cgocall nil");
102
125
 
 
126
        if(raceenabled)
 
127
                runtime·racereleasemerge(&cgosync);
 
128
 
103
129
        m->ncgocall++;
104
130
 
105
131
        /*
106
132
         * Lock g to m to ensure we stay on the same stack if we do a
107
 
         * cgo callback.
 
133
         * cgo callback. Add entry to defer stack in case of panic.
108
134
         */
109
 
        d.nofree = false;
110
 
        if(m->lockedg == nil) {
111
 
                m->lockedg = g;
112
 
                g->lockedm = m;
 
135
        runtime·lockOSThread();
 
136
        d.fn = &endcgoV;
 
137
        d.siz = 0;
 
138
        d.link = g->defer;
 
139
        d.argp = (void*)-1;  // unused because unlockm never recovers
 
140
        d.special = true;
 
141
        d.free = false;
 
142
        g->defer = &d;
113
143
 
114
 
                // Add entry to defer stack in case of panic.
115
 
                d.fn = (byte*)unlockm;
116
 
                d.siz = 0;
117
 
                d.link = g->defer;
118
 
                d.argp = (void*)-1;  // unused because unlockm never recovers
119
 
                d.nofree = true;
120
 
                g->defer = &d;
121
 
        }
 
144
        m->ncgo++;
122
145
 
123
146
        /*
124
147
         * Announce we are entering a system call
131
154
         * so it is safe to call while "in a system call", outside
132
155
         * the $GOMAXPROCS accounting.
133
156
         */
134
 
        runtime·entersyscall();
 
157
        if(g->blockingsyscall) {
 
158
                g->blockingsyscall = false;
 
159
                runtime·entersyscallblock();
 
160
        } else
 
161
                runtime·entersyscall();
135
162
        runtime·asmcgocall(fn, arg);
136
163
        runtime·exitsyscall();
137
164
 
138
 
        if(d.nofree) {
139
 
                if(g->defer != &d || d.fn != (byte*)unlockm)
140
 
                        runtime·throw("runtime: bad defer entry in cgocallback");
141
 
                g->defer = d.link;
142
 
                unlockm();
143
 
        }
 
165
        if(g->defer != &d || d.fn != &endcgoV)
 
166
                runtime·throw("runtime: bad defer entry in cgocallback");
 
167
        g->defer = d.link;
 
168
        endcgo();
144
169
}
145
170
 
146
171
static void
147
 
unlockm(void)
 
172
endcgo(void)
148
173
{
149
 
        m->lockedg = nil;
150
 
        g->lockedm = nil;
 
174
        runtime·unlockOSThread();
 
175
        m->ncgo--;
 
176
        if(m->ncgo == 0) {
 
177
                // We are going back to Go and are not in a recursive
 
178
                // call.  Let the GC collect any memory allocated via
 
179
                // _cgo_allocate that is no longer referenced.
 
180
                m->cgomal = nil;
 
181
        }
 
182
 
 
183
        if(raceenabled)
 
184
                runtime·raceacquire(&cgosync);
151
185
}
152
186
 
153
187
void
154
188
runtime·NumCgoCall(int64 ret)
155
189
{
156
 
        M *m;
 
190
        M *mp;
157
191
 
158
192
        ret = 0;
159
 
        for(m=runtime·atomicloadp(&runtime·allm); m; m=m->alllink)
160
 
                ret += m->ncgocall;
 
193
        for(mp=runtime·atomicloadp(&runtime·allm); mp; mp=mp->alllink)
 
194
                ret += mp->ncgocall;
161
195
        FLUSH(&ret);
162
196
}
163
197
 
188
222
 
189
223
// Call from C back to Go.
190
224
 
 
225
static FuncVal unwindmf = {unwindm};
 
226
 
191
227
void
192
 
runtime·cgocallbackg(void (*fn)(void), void *arg, uintptr argsize)
 
228
runtime·cgocallbackg(FuncVal *fn, void *arg, uintptr argsize)
193
229
{
194
230
        Defer d;
195
231
 
 
232
        if(m->racecall) {
 
233
                reflect·call(fn, arg, argsize);
 
234
                return;
 
235
        }
 
236
 
196
237
        if(g != m->curg)
197
238
                runtime·throw("runtime: bad g in cgocallback");
198
239
 
199
240
        runtime·exitsyscall();  // coming out of cgo call
200
241
 
 
242
        if(m->needextram) {
 
243
                m->needextram = 0;
 
244
                runtime·newextram();
 
245
        }
 
246
 
201
247
        // Add entry to defer stack in case of panic.
202
 
        d.fn = (byte*)unwindm;
 
248
        d.fn = &unwindmf;
203
249
        d.siz = 0;
204
250
        d.link = g->defer;
205
251
        d.argp = (void*)-1;  // unused because unwindm never recovers
206
 
        d.nofree = true;
 
252
        d.special = true;
 
253
        d.free = false;
207
254
        g->defer = &d;
208
255
 
 
256
        if(raceenabled)
 
257
                runtime·raceacquire(&cgosync);
 
258
 
209
259
        // Invoke callback.
210
 
        reflect·call((byte*)fn, arg, argsize);
 
260
        reflect·call(fn, arg, argsize);
 
261
 
 
262
        if(raceenabled)
 
263
                runtime·racereleasemerge(&cgosync);
211
264
 
212
265
        // Pop defer.
213
266
        // Do not unwind m->g0->sched.sp.
214
267
        // Our caller, cgocallback, will do that.
215
 
        if(g->defer != &d || d.fn != (byte*)unwindm)
 
268
        if(g->defer != &d || d.fn != &unwindmf)
216
269
                runtime·throw("runtime: bad defer entry in cgocallback");
217
270
        g->defer = d.link;
218
271
 
229
282
                runtime·throw("runtime: unwindm not implemented");
230
283
        case '8':
231
284
        case '6':
232
 
                m->g0->sched.sp = *(void**)m->g0->sched.sp;
 
285
        case '5':
 
286
                m->g0->sched.sp = *(uintptr*)m->g0->sched.sp;
233
287
                break;
234
288
        }
235
289
}
245
299
{
246
300
        runtime·throw("runtime: cgo not implemented");
247
301
}
 
302
 
 
303
// For cgo-using programs with external linking,
 
304
// export "main" (defined in assembly) so that libc can handle basic
 
305
// C runtime startup and call the Go program as if it were
 
306
// the C main function.
 
307
#pragma cgo_export_static main