]> Cypherpunks.ru repositories - gostls13.git/blob - src/runtime/testdata/testprogcgo/bindm.go
runtime/cgo: store M for C-created thread in pthread key
[gostls13.git] / src / runtime / testdata / testprogcgo / bindm.go
1 // Copyright 2023 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 //go:build !plan9 && !windows
6
7 // Test that callbacks from C to Go in the same C-thread always get the same m.
8 // Make sure the extra M bind to the C-thread.
9
10 package main
11
12 /*
13 #include <stdint.h>
14 #include <pthread.h>
15 #include <unistd.h>
16
17 extern void GoCheckBindM();
18
19 #define CTHREADS 2
20 #define CHECKCALLS 100
21
22 static void* checkBindMThread(void* thread) {
23         int i;
24         for (i = 0; i < CHECKCALLS; i++) {
25                 GoCheckBindM((uintptr_t)thread);
26                 usleep(1);
27         }
28         return NULL;
29 }
30
31 static void CheckBindM() {
32         int i;
33         pthread_t s[CTHREADS];
34
35         for (i = 0; i < CTHREADS; i++) {
36                 pthread_create(&s[i], NULL, checkBindMThread, &s[i]);
37         }
38         for (i = 0; i < CTHREADS; i++) {
39                 pthread_join(s[i], NULL);
40         }
41 }
42 */
43 import "C"
44
45 import (
46         "fmt"
47         "os"
48         "runtime"
49         "sync"
50         "sync/atomic"
51 )
52
53 var (
54         mutex      = sync.Mutex{}
55         cThreadToM = map[uintptr]uintptr{}
56         started    = atomic.Uint32{}
57 )
58
59 // same as CTHREADS in C, make sure all the C threads are actually started.
60 const cThreadNum = 2
61
62 func init() {
63         register("EnsureBindM", EnsureBindM)
64 }
65
66 //export GoCheckBindM
67 func GoCheckBindM(thread uintptr) {
68         // Wait all threads start
69         if started.Load() != cThreadNum {
70                 // Only once for each thread, since it will wait all threads start.
71                 started.Add(1)
72                 for started.Load() < cThreadNum {
73                         runtime.Gosched()
74                 }
75         }
76         m := runtime_getm_for_test()
77         mutex.Lock()
78         defer mutex.Unlock()
79         if savedM, ok := cThreadToM[thread]; ok && savedM != m {
80                 fmt.Printf("m == %x want %x\n", m, savedM)
81                 os.Exit(1)
82         }
83         cThreadToM[thread] = m
84 }
85
86 func EnsureBindM() {
87         C.CheckBindM()
88         fmt.Println("OK")
89 }