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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
|
package libc
// 7.26 Threads
thrd_start_t :: proc "c" (rawptr) -> int
tss_dtor_t :: proc "c" (rawptr)
when ODIN_OS == .Windows {
foreign import libc {
"system:libucrt.lib",
"system:msvcprt.lib",
}
thrd_success :: 0 // _Thrd_success
thrd_nomem :: 1 // _Thrd_nomem
thrd_timedout :: 2 // _Thrd_timedout
thrd_busy :: 3 // _Thrd_busy
thrd_error :: 4 // _Thrd_error
mtx_plain :: 1 // _Mtx_plain
mtx_recursive :: 0x100 // _Mtx_recursive
mtx_timed :: 4 // _Mtx_timed
TSS_DTOR_ITERATIONS :: 4 // _TSS_DTOR_ITERATIONS_IMP
once_flag :: distinct i8 // _Once_flag_imp_t
thrd_t :: struct { _: rawptr, _: uint, } // _Thrd_t
tss_t :: distinct int // _Tss_imp_t
cnd_t :: distinct rawptr // _Cnd_imp_t
mtx_t :: distinct rawptr // _Mtx_imp_t
// MSVCRT does not expose the C11 symbol names as what they are in C11
// because they held off implementing <threads.h> and C11 support for so
// long that people started implementing their own. To prevent symbol
// conflict with existing customers code they had to namespace them
// differently. Thus we need to alias the correct symbol names with Odin's
// link_name attribute.
@(default_calling_convention="c")
foreign libc {
// 7.26.2 Initialization functions
@(link_name="_Call_once") call_once :: proc(flag: ^once_flag, func: proc "c" ()) ---
// 7.26.3 Condition variable functions
@(link_name="_Cnd_broadcast") cnd_broadcast :: proc(cond: ^cnd_t) -> int ---
@(link_name="_Cnd_destroy") cnd_destroy :: proc(cond: ^cnd_t) ---
@(link_name="_Cnd_init") cnd_init :: proc(cond: ^cnd_t) -> int ---
@(link_name="_Cnd_signal") cnd_signal :: proc(cond: ^cnd_t) -> int ---
@(link_name="_Cnd_timedwait") cnd_timedwait :: proc(cond: ^cnd_t, mtx: ^mtx_t, ts: ^timespec) -> int ---
@(link_name="_Cnd_wait") cnd_wait :: proc(cond: ^cnd_t, mtx: ^mtx_t) -> int ---
// 7.26.4 Mutex functions
@(link_name="_Mtx_destroy") mtx_destroy :: proc(mtx: ^mtx_t) ---
@(link_name="_Mtx_init") mtx_init :: proc(mtx: ^mtx_t, type: int) -> int ---
@(link_name="_Mtx_lock") mtx_lock :: proc(mtx: ^mtx_t) -> int ---
@(link_name="_Mtx_timedlock") mtx_timedlock :: proc(mtx: ^mtx_t, ts: ^timespec) -> int ---
@(link_name="_Mtx_trylock") mtx_trylock :: proc(mtx: ^mtx_t) -> int ---
@(link_name="_Mtx_unlock") mtx_unlock :: proc(mtx: ^mtx_t) -> int ---
// 7.26.5 Thread functions
@(link_name="_Thrd_create") thrd_create :: proc(thr: ^thrd_t, func: thrd_start_t, arg: rawptr) -> int ---
@(link_name="_Thrd_current") thrd_current :: proc() -> thrd_t ---
@(link_name="_Thrd_detach") thrd_detach :: proc(thr: thrd_t) -> int ---
@(link_name="_Thrd_equal") thrd_equal :: proc(lhs, rhs: thrd_t) -> int ---
@(link_name="_Thrd_exit") thrd_exit :: proc(res: int) -> ! ---
@(link_name="_Thrd_join") thrd_join :: proc(thr: thrd_t, res: ^int) -> int ---
@(link_name="_Thrd_sleep") thrd_sleep :: proc(duration, remaining: ^timespec) -> int ---
@(link_name="_Thrd_yield") thrd_yield :: proc() ---
// 7.26.6 Thread-specific storage functions
@(link_name="_Tss_create") tss_create :: proc(key: ^tss_t, dtor: tss_dtor_t) -> int ---
@(link_name="_Tss_delete") tss_delete :: proc(key: tss_t) ---
@(link_name="_Tss_get") tss_get :: proc(key: tss_t) -> rawptr ---
@(link_name="_Tss_set") tss_set :: proc(key: tss_t, val: rawptr) -> int ---
}
}
// GLIBC and MUSL compatible constants and types.
when ODIN_OS == .Linux {
foreign import libc {
"system:c",
"system:pthread",
}
thrd_success :: 0
thrd_busy :: 1
thrd_error :: 2
thrd_nomem :: 3
thrd_timedout :: 4
mtx_plain :: 0
mtx_recursive :: 1
mtx_timed :: 2
TSS_DTOR_ITERATIONS :: 4
once_flag :: distinct int
thrd_t :: distinct ulong
tss_t :: distinct uint
cnd_t :: struct #raw_union { _: [12]int, _: [12 * size_of(int) / size_of(rawptr)]rawptr, }
mtx_t :: struct #raw_union { _: [10 when size_of(long) == 8 else 6]int, _: [5 when size_of(long) == 8 else 6]rawptr, }
@(default_calling_convention="c")
foreign libc {
// 7.26.2 Initialization functions
call_once :: proc(flag: ^once_flag, func: proc "c" ()) ---
// 7.26.3 Condition variable functions
cnd_broadcast :: proc(cond: ^cnd_t) -> int ---
cnd_destroy :: proc(cond: ^cnd_t) ---
cnd_init :: proc(cond: ^cnd_t) -> int ---
cnd_signal :: proc(cond: ^cnd_t) -> int ---
cnd_timedwait :: proc(cond: ^cnd_t, mtx: ^mtx_t, ts: ^timespec) -> int ---
cnd_wait :: proc(cond: ^cnd_t, mtx: ^mtx_t) -> int ---
// 7.26.4 Mutex functions
mtx_destroy :: proc(mtx: ^mtx_t) ---
mtx_init :: proc(mtx: ^mtx_t, type: int) -> int ---
mtx_lock :: proc(mtx: ^mtx_t) -> int ---
mtx_timedlock :: proc(mtx: ^mtx_t, ts: ^timespec) -> int ---
mtx_trylock :: proc(mtx: ^mtx_t) -> int ---
mtx_unlock :: proc(mtx: ^mtx_t) -> int ---
// 7.26.5 Thread functions
thrd_create :: proc(thr: ^thrd_t, func: thrd_start_t, arg: rawptr) -> int ---
thrd_current :: proc() -> thrd_t ---
thrd_detach :: proc(thr: thrd_t) -> int ---
thrd_equal :: proc(lhs, rhs: thrd_t) -> int ---
thrd_exit :: proc(res: int) -> ! ---
thrd_join :: proc(thr: thrd_t, res: ^int) -> int ---
thrd_sleep :: proc(duration, remaining: ^timespec) -> int ---
thrd_yield :: proc() ---
// 7.26.6 Thread-specific storage functions
tss_create :: proc(key: ^tss_t, dtor: tss_dtor_t) -> int ---
tss_delete :: proc(key: tss_t) ---
tss_get :: proc(key: tss_t) -> rawptr ---
tss_set :: proc(key: tss_t, val: rawptr) -> int ---
}
}
when ODIN_OS == .Darwin {
// TODO: find out what this is meant to be!
}
|