]> Cypherpunks.ru repositories - gostls13.git/blob - misc/cgo/test/testx.go
runtime/cgo: store M for C-created thread in pthread key
[gostls13.git] / misc / cgo / test / testx.go
1 // Copyright 2011 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 // Test cases for cgo.
6 // Both the import "C" prologue and the main file are sorted by issue number.
7 // This file contains //export directives on Go functions
8 // and so it must NOT contain C definitions (only declarations).
9 // See test.go for C definitions.
10
11 package cgotest
12
13 import (
14         "runtime"
15         "runtime/cgo"
16         "runtime/debug"
17         "strings"
18         "sync"
19         "sync/atomic"
20         "testing"
21         "unsafe"
22 )
23
24 /*
25 // threads
26 extern void doAdd(int, int);
27 extern int callGoInCThread(int);
28
29 // issue 1328
30 void IntoC(void);
31
32 // issue 1560
33 extern void Issue1560InC(void);
34
35 // twoSleep returns the absolute start time of the first sleep
36 // in ms.
37 long long twoSleep(int);
38
39 // issue 3775
40 void lockOSThreadC(void);
41 int usleep(unsigned usec);
42
43 // issue 4054 part 2 - part 1 in test.go
44 typedef enum {
45         A = 0,
46         B,
47         C,
48         D,
49         E,
50         F,
51         G,
52         H,
53         II,
54         J,
55 } issue4054b;
56
57 // issue 5548
58
59 extern int issue5548_in_c(void);
60
61 // issue 6833
62
63 extern unsigned long long issue6833Func(unsigned int, unsigned long long);
64
65 // issue 6907
66
67 extern int CheckIssue6907C(_GoString_);
68
69 // issue 7665
70
71 extern void f7665(void);
72
73 // issue 7978
74 // Stack tracing didn't work during cgo code after calling a Go
75 // callback.  Make sure GC works and the stack trace is correct.
76
77 #include <stdint.h>
78
79 // use ugly atomic variable sync since that doesn't require calling back into
80 // Go code or OS dependencies
81 void issue7978c(uint32_t *sync);
82
83 // issue 8331 part 2 - part 1 in test.go
84 // A typedef of an unnamed struct is the same struct when
85 // #include'd twice.  No runtime test; just make sure it compiles.
86 #include "issue8331.h"
87
88 // issue 8945
89
90 typedef void (*PFunc8945)();
91 extern PFunc8945 func8945; // definition is in test.go
92
93 // issue 20910
94 void callMulti(void);
95
96 // issue 28772 part 2 - part 1 in issuex.go
97 #define issue28772Constant2 2
98
99
100 // issue 31891
101 typedef struct {
102         long obj;
103 } Issue31891A;
104
105 typedef struct {
106         long obj;
107 } Issue31891B;
108
109 void callIssue31891(void);
110
111 typedef struct {
112         int i;
113 } Issue38408, *PIssue38408;
114
115 extern void cfunc49633(void*); // definition is in test.go
116 */
117 import "C"
118
119 // exports
120
121 //export ReturnIntLong
122 func ReturnIntLong() (int, C.long) {
123         return 1, 2
124 }
125
126 //export gc
127 func gc() {
128         runtime.GC()
129 }
130
131 // threads
132
133 var sum struct {
134         sync.Mutex
135         i int
136 }
137
138 //export Add
139 func Add(x int) {
140         defer func() {
141                 recover()
142         }()
143         sum.Lock()
144         sum.i += x
145         sum.Unlock()
146         var p *int
147         *p = 2
148 }
149
150 //export goDummy
151 func goDummy() {
152 }
153
154 func testCthread(t *testing.T) {
155         if (runtime.GOOS == "darwin" || runtime.GOOS == "ios") && runtime.GOARCH == "arm64" {
156                 t.Skip("the iOS exec wrapper is unable to properly handle the panic from Add")
157         }
158         sum.i = 0
159         C.doAdd(10, 6)
160
161         want := 10 * (10 - 1) / 2 * 6
162         if sum.i != want {
163                 t.Fatalf("sum=%d, want %d", sum.i, want)
164         }
165 }
166
167 // Benchmark measuring overhead from C to Go in a C thread.
168 // Create a new C thread and invoke Go function repeatedly in the new C thread.
169 func benchCGoInCthread(b *testing.B) {
170         n := C.callGoInCThread(C.int(b.N))
171         if int(n) != b.N {
172                 b.Fatal("unmatch loop times")
173         }
174 }
175
176 // issue 1328
177
178 //export BackIntoGo
179 func BackIntoGo() {
180         x := 1
181
182         for i := 0; i < 10000; i++ {
183                 xvariadic(x)
184                 if x != 1 {
185                         panic("x is not 1?")
186                 }
187         }
188 }
189
190 func xvariadic(x ...interface{}) {
191 }
192
193 func test1328(t *testing.T) {
194         C.IntoC()
195 }
196
197 // issue 1560
198 // Test that C functions and Go functions run in parallel.
199
200 var (
201         issue1560 int32
202
203         issue1560Ch = make(chan bool, 2)
204 )
205
206 //export Issue1560FromC
207 func Issue1560FromC() {
208         for atomic.LoadInt32(&issue1560) != 1 {
209                 runtime.Gosched()
210         }
211         atomic.AddInt32(&issue1560, 1)
212         for atomic.LoadInt32(&issue1560) != 3 {
213                 runtime.Gosched()
214         }
215         issue1560Ch <- true
216 }
217
218 func Issue1560FromGo() {
219         atomic.AddInt32(&issue1560, 1)
220         for atomic.LoadInt32(&issue1560) != 2 {
221                 runtime.Gosched()
222         }
223         atomic.AddInt32(&issue1560, 1)
224         issue1560Ch <- true
225 }
226
227 func test1560(t *testing.T) {
228         go Issue1560FromGo()
229         go C.Issue1560InC()
230         <-issue1560Ch
231         <-issue1560Ch
232 }
233
234 // issue 2462
235
236 //export exportbyte
237 func exportbyte() byte {
238         return 0
239 }
240
241 //export exportbool
242 func exportbool() bool {
243         return false
244 }
245
246 //export exportrune
247 func exportrune() rune {
248         return 0
249 }
250
251 //export exporterror
252 func exporterror() error {
253         return nil
254 }
255
256 //export exportint
257 func exportint() int {
258         return 0
259 }
260
261 //export exportuint
262 func exportuint() uint {
263         return 0
264 }
265
266 //export exportuintptr
267 func exportuintptr() uintptr {
268         return (uintptr)(0)
269 }
270
271 //export exportint8
272 func exportint8() int8 {
273         return 0
274 }
275
276 //export exportuint8
277 func exportuint8() uint8 {
278         return 0
279 }
280
281 //export exportint16
282 func exportint16() int16 {
283         return 0
284 }
285
286 //export exportuint16
287 func exportuint16() uint16 {
288         return 0
289 }
290
291 //export exportint32
292 func exportint32() int32 {
293         return 0
294 }
295
296 //export exportuint32
297 func exportuint32() uint32 {
298         return 0
299 }
300
301 //export exportint64
302 func exportint64() int64 {
303         return 0
304 }
305
306 //export exportuint64
307 func exportuint64() uint64 {
308         return 0
309 }
310
311 //export exportfloat32
312 func exportfloat32() float32 {
313         return 0
314 }
315
316 //export exportfloat64
317 func exportfloat64() float64 {
318         return 0
319 }
320
321 //export exportcomplex64
322 func exportcomplex64() complex64 {
323         return 0
324 }
325
326 //export exportcomplex128
327 func exportcomplex128() complex128 {
328         return 0
329 }
330
331 // issue 3741
332
333 //export exportSliceIn
334 func exportSliceIn(s []byte) bool {
335         return len(s) == cap(s)
336 }
337
338 //export exportSliceOut
339 func exportSliceOut() []byte {
340         return []byte{1}
341 }
342
343 //export exportSliceInOut
344 func exportSliceInOut(s []byte) []byte {
345         return s
346 }
347
348 // issue 3775
349
350 func init() {
351         if runtime.GOOS == "android" {
352                 return
353         }
354         // Same as test3775 but run during init so that
355         // there are two levels of internal runtime lock
356         // (1 for init, 1 for cgo).
357         // This would have been broken by CL 11663043.
358         C.lockOSThreadC()
359 }
360
361 func test3775(t *testing.T) {
362         if runtime.GOOS == "android" {
363                 return
364         }
365         // Used to panic because of the UnlockOSThread below.
366         C.lockOSThreadC()
367 }
368
369 //export lockOSThreadCallback
370 func lockOSThreadCallback() {
371         runtime.LockOSThread()
372         runtime.UnlockOSThread()
373         go C.usleep(10000)
374         runtime.Gosched()
375 }
376
377 // issue 4054 part 2 - part 1 in test.go
378
379 var issue4054b = []int{C.A, C.B, C.C, C.D, C.E, C.F, C.G, C.H, C.II, C.J}
380
381 //export issue5548FromC
382 func issue5548FromC(s string, i int) int {
383         if len(s) == 4 && s == "test" && i == 42 {
384                 return 12345
385         }
386         println("got", len(s), i)
387         return 9876
388 }
389
390 func test5548(t *testing.T) {
391         if x := C.issue5548_in_c(); x != 12345 {
392                 t.Errorf("issue5548_in_c = %d, want %d", x, 12345)
393         }
394 }
395
396 // issue 6833
397
398 //export GoIssue6833Func
399 func GoIssue6833Func(aui uint, aui64 uint64) uint64 {
400         return aui64 + uint64(aui)
401 }
402
403 func test6833(t *testing.T) {
404         ui := 7
405         ull := uint64(0x4000300020001000)
406         v := uint64(C.issue6833Func(C.uint(ui), C.ulonglong(ull)))
407         exp := uint64(ui) + ull
408         if v != exp {
409                 t.Errorf("issue6833Func() returns %x, expected %x", v, exp)
410         }
411 }
412
413 // issue 6907
414
415 const CString = "C string"
416
417 //export CheckIssue6907Go
418 func CheckIssue6907Go(s string) C.int {
419         if s == CString {
420                 return 1
421         }
422         return 0
423 }
424
425 func test6907Go(t *testing.T) {
426         if got := C.CheckIssue6907C(CString); got != 1 {
427                 t.Errorf("C.CheckIssue6907C() == %d, want %d", got, 1)
428         }
429 }
430
431 // issue 7665
432
433 var bad7665 unsafe.Pointer = C.f7665
434 var good7665 uintptr = uintptr(C.f7665)
435
436 func test7665(t *testing.T) {
437         if bad7665 == nil || uintptr(bad7665) != good7665 {
438                 t.Errorf("ptrs = %p, %#x, want same non-nil pointer", bad7665, good7665)
439         }
440 }
441
442 // issue 7978
443
444 var issue7978sync uint32
445
446 func issue7978check(t *testing.T, wantFunc string, badFunc string, depth int) {
447         runtime.GC()
448         buf := make([]byte, 65536)
449         trace := string(buf[:runtime.Stack(buf, true)])
450         for _, goroutine := range strings.Split(trace, "\n\n") {
451                 if strings.Contains(goroutine, "test.issue7978go") {
452                         trace := strings.Split(goroutine, "\n")
453                         // look for the expected function in the stack
454                         for i := 0; i < depth; i++ {
455                                 if badFunc != "" && strings.Contains(trace[1+2*i], badFunc) {
456                                         t.Errorf("bad stack: found %s in the stack:\n%s", badFunc, goroutine)
457                                         return
458                                 }
459                                 if strings.Contains(trace[1+2*i], wantFunc) {
460                                         return
461                                 }
462                         }
463                         t.Errorf("bad stack: didn't find %s in the stack:\n%s", wantFunc, goroutine)
464                         return
465                 }
466         }
467         t.Errorf("bad stack: goroutine not found. Full stack dump:\n%s", trace)
468 }
469
470 func issue7978wait(store uint32, wait uint32) {
471         if store != 0 {
472                 atomic.StoreUint32(&issue7978sync, store)
473         }
474         for atomic.LoadUint32(&issue7978sync) != wait {
475                 runtime.Gosched()
476         }
477 }
478
479 //export issue7978cb
480 func issue7978cb() {
481         // Force a stack growth from the callback to put extra
482         // pressure on the runtime. See issue #17785.
483         growStack(64)
484         issue7978wait(3, 4)
485 }
486
487 func growStack(n int) int {
488         var buf [128]int
489         if n == 0 {
490                 return 0
491         }
492         return buf[growStack(n-1)]
493 }
494
495 func issue7978go() {
496         C.issue7978c((*C.uint32_t)(&issue7978sync))
497         issue7978wait(7, 8)
498 }
499
500 func test7978(t *testing.T) {
501         if runtime.Compiler == "gccgo" {
502                 t.Skip("gccgo can not do stack traces of C code")
503         }
504         debug.SetTraceback("2")
505         issue7978sync = 0
506         go issue7978go()
507         // test in c code, before callback
508         issue7978wait(0, 1)
509         issue7978check(t, "_Cfunc_issue7978c(", "", 1)
510         // test in go code, during callback
511         issue7978wait(2, 3)
512         issue7978check(t, "test.issue7978cb(", "test.issue7978go", 3)
513         // test in c code, after callback
514         issue7978wait(4, 5)
515         issue7978check(t, "_Cfunc_issue7978c(", "_cgoexpwrap", 1)
516         // test in go code, after return from cgo
517         issue7978wait(6, 7)
518         issue7978check(t, "test.issue7978go(", "", 3)
519         atomic.StoreUint32(&issue7978sync, 8)
520 }
521
522 // issue 8331 part 2
523
524 var issue8331Var C.issue8331
525
526 // issue 8945
527
528 //export Test8945
529 func Test8945() {
530         _ = C.func8945
531 }
532
533 // issue 20910
534
535 //export multi
536 func multi() (*C.char, C.int) {
537         return C.CString("multi"), 0
538 }
539
540 func test20910(t *testing.T) {
541         C.callMulti()
542 }
543
544 // issue 28772 part 2
545
546 const issue28772Constant2 = C.issue28772Constant2
547
548 // issue 31891
549
550 //export useIssue31891A
551 func useIssue31891A(c *C.Issue31891A) {}
552
553 //export useIssue31891B
554 func useIssue31891B(c *C.Issue31891B) {}
555
556 func test31891(t *testing.T) {
557         C.callIssue31891()
558 }
559
560 // issue 37033, check if cgo.Handle works properly
561
562 var issue37033 = 42
563
564 //export GoFunc37033
565 func GoFunc37033(handle C.uintptr_t) {
566         h := cgo.Handle(handle)
567         ch := h.Value().(chan int)
568         ch <- issue37033
569 }
570
571 // issue 38408
572 // A typedef pointer can be used as the element type.
573 // No runtime test; just make sure it compiles.
574 var _ C.PIssue38408 = &C.Issue38408{i: 1}
575
576 // issue 49633, example use of cgo.Handle with void*
577
578 type data49633 struct {
579         msg string
580 }
581
582 //export GoFunc49633
583 func GoFunc49633(context unsafe.Pointer) {
584         h := *(*cgo.Handle)(context)
585         v := h.Value().(*data49633)
586         v.msg = "hello"
587 }
588
589 func test49633(t *testing.T) {
590         v := &data49633{}
591         h := cgo.NewHandle(v)
592         defer h.Delete()
593         C.cfunc49633(unsafe.Pointer(&h))
594         if v.msg != "hello" {
595                 t.Errorf("msg = %q, want 'hello'", v.msg)
596         }
597 }