aboutsummaryrefslogtreecommitdiff
path: root/core/sys/posix/sys_sem.odin
blob: 012c0bbdba311a1a9fd6e0719a1dc64978d411fd (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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
#+build linux, darwin, netbsd, openbsd, freebsd, haiku
package posix

import "core:c"

when ODIN_OS == .Darwin {
	foreign import lib "system:System"
} else {
	foreign import lib "system:c"
}

// sys/sem.h - XSI semaphore facility

foreign lib {
	/*
	Provides various semaphore control operation as specified by cmd.

	[[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/semctl.html ]]
	*/
	@(link_name=LSEMCTL)
	semctl :: proc(semid: FD, semnum: c.int, cmd: Sem_Cmd, #c_vararg args: ..semun) -> c.int ---

	/*
	Returns the semaphore identifier associated with key.

	Returns: -1 (setting errno) on failure, a semaphore file descriptor otherwise

	[[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/semget.html ]]
	*/
	semget :: proc(key: key_t, nsems: c.int, semflg: IPC_Flags) -> FD ---

	/*
	Perform atomically a user-defined array of semaphore operations in array order on the set of
	semaphores associated with the semaphore identifier specified by the argument semid.

	[[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/semop.html ]]
	*/
	semop :: proc(semid: FD, sops: [^]sembuf, nsops: c.size_t) -> result ---
}

Sem_Cmd :: enum c.int {
	RMID    = IPC_RMID,
	SET     = IPC_SET,
	STAT    = IPC_STAT,
	// Returns the value of semncnt.
	GETNCNT = GETNCNT,
	// Returns the value of sempid.
	GETPID  = GETPID,
	// Return the value of semval.
	GETVAL  = GETVAL,
	// Returns the value of semval for each semaphore in the semaphore set.
	GETALL  = GETALL,
	// Returns the value of semzcnt.
	GETZCNT = GETZCNT,
	// Sets the value of semval to arg.val.
	SETVAL  = SETVAL,
	// Sets the value of semval for each semaphore in the set.
	SETALL  = SETALL,
}

semun :: struct #raw_union {
	val:   c.int,
	buf:   ^semid_ds,
	array: [^]c.ushort,
}

when ODIN_OS == .NetBSD {
	@(private) LSEMCTL :: "__semctl50"
} else {
	@(private) LSEMCTL :: "semctl"
}

when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD {

	SEM_UNDO :: 0o10000

	GETNCNT :: 3
	GETPID  :: 4
	GETVAL  :: 5
	GETALL  :: 6
	GETZCNT :: 7
	SETVAL  :: 8
	SETALL  :: 9

	when ODIN_OS == .Darwin {
		semid_ds :: struct #max_field_align(4) {
			sem_perm:  ipc_perm,     /* [PSX] operation permission structure */
			sem_base:  c.int32_t,    /* 32 bit base ptr for semaphore set */
			sem_nsems: c.ushort,     /* [PSX] number of semaphores in set */
			sem_otime: time_t,       /* [PSX] last semop() */
			sem_pad1:  c.int32_t,
			sem_ctime: time_t,       /* [PSX] last time changed by semctl() */
			sem_pad2:  c.int32_t,
			sem_pad3:  [4]c.int32_t,
		}
	} else when ODIN_OS == .FreeBSD {
		semid_ds :: struct {
			sem_perm:  ipc_perm, /* [PSX] operation permission structure */
			sem_base:  rawptr,   /* 32 bit base ptr for semaphore set */
			sem_nsems: c.ushort, /* [PSX] number of semaphores in set */
			sem_otime: time_t,   /* [PSX] last semop() */
			sem_ctime: time_t,   /* [PSX] last time changed by semctl() */
		}
	} else when ODIN_OS == .NetBSD {
		semid_ds :: struct {
			sem_perm:  ipc_perm, /* [PSX] operation permission structure */
			sem_nsems: c.ushort, /* [PSX] number of semaphores in set */
			sem_otime: time_t,   /* [PSX] last semop() */
			sem_ctime: time_t,   /* [PSX] last time changed by semctl() */
			_sem_base: rawptr,   /* 32 bit base ptr for semaphore set */
		}
	} else when ODIN_OS == .OpenBSD {
		semid_ds :: struct {
			sem_perm:  ipc_perm, /* [PSX] operation permission structure */
			sem_nsems: c.ushort, /* [PSX] number of semaphores in set */
			sem_otime: time_t,   /* [PSX] last semop() */
			sem_pad1:  c.long,
			sem_ctime: time_t,   /* [PSX] last time changed by semctl() */
			sem_pad2:  c.long,
			sem_pad3:  [4]c.long,
		}
	}

	sembuf :: struct {
		sem_num: c.ushort, /* [PSX] semaphore number */
		sem_op:  c.short,  /* [PSX] semaphore operation */
		sem_flg: c.short,  /* [PSX] operation flags */
	}

} else when ODIN_OS == .Linux {

	SEM_UNDO :: 0x1000 // undo the operation on exit

	// Commands for `semctl'.
	GETPID  :: 11
	GETVAL  :: 12
	GETALL  :: 13
	GETNCNT :: 14
	GETZCNT :: 15
	SETVAL  :: 16
	SETALL  :: 17

	when ODIN_ARCH == .arm64 {
		semid_ds :: struct {
			sem_perm:  ipc_perm,  // [PSX] operation permission structure
			sem_otime: time_t,    // [PSX] last semop()
			sem_ctime: time_t,    // [PSX] last time changed by semctl()
			sem_nsems: c.ulong, // [PSX] number of semaphores in set
			__glibc_reserved3: c.ulong,
			__glibc_reserved4: c.ulong,
		}
	} else {
		semid_ds :: struct {
			sem_perm:  ipc_perm,  // [PSX] operation permission structure
			sem_otime: time_t,    // [PSX] last semop()
			__sem_otime_high: c.ulong,
			sem_ctime: time_t,    // [PSX] last time changed by semctl()
			__sem_ctime_high: c.ulong,
			sem_nsems: c.ulong, // [PSX] number of semaphores in set
			__glibc_reserved3: c.ulong,
			__glibc_reserved4: c.ulong,
		}
	}

	sembuf :: struct {
		sem_num: c.ushort, /* [PSX] semaphore number */
		sem_op:  c.short,  /* [PSX] semaphore operation */
		sem_flg: c.short,  /* [PSX] operation flags */
	}

} else when ODIN_OS == .Haiku {

	SEM_UNDO :: 10 // undo the operation on exit

	// Commands for `semctl'.
	GETPID  :: 3
	GETVAL  :: 4
	GETALL  :: 5
	GETNCNT :: 6
	GETZCNT :: 7
	SETVAL  :: 8
	SETALL  :: 9

	semid_ds :: struct {
		sem_perm:  ipc_perm,  // [PSX] operation permission structure
		sem_nsems: c.ushort, // [PSX] number of semaphores in set
		sem_otime: time_t,    // [PSX] last semop()
		sem_ctime: time_t,    // [PSX] last time changed by semctl()
	}

	sembuf :: struct {
		sem_num: c.ushort, /* [PSX] semaphore number */
		sem_op:  c.short,  /* [PSX] semaphore operation */
		sem_flg: c.short,  /* [PSX] operation flags */
	}

}