aboutsummaryrefslogtreecommitdiff
path: root/core/c/libc/threads.odin
blob: f6aae2e9840ffb8cb43a184e6094cdd97a34aa8d (plain)
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, 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, 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!
}