Skip to content

Commit 0f68dfb

Browse files
gyrovorbisQuzarDC
authored andcommitted
Added support for POSIX semaphore API.
Added semaphore.h to the root KOS include directory, which is a tiny little, header-only wrapper that adapts KOS's existing implementation of kernel semaphores in sem.h to a standard POSIX API. This is immediately going to be used to be picked up by at very least SDL2 and SDL3 to back their SDL semaphore types.
1 parent c4c61c9 commit 0f68dfb

1 file changed

Lines changed: 82 additions & 0 deletions

File tree

include/semaphore.h

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
/* KallistiOS ##version##
2+
3+
include/semaphore.h
4+
Copyright (C) 2026 Falco Girgis
5+
*/
6+
7+
/*
8+
This file is an extremely lightweight wrapper which simply "extends" KOS's
9+
existing <kos/sem.h> kernel semaphores, which are already partially POSIX-
10+
compliant, and implements the rest of the missing POSIX functionality as a
11+
light-weight inline function wrapper API around them.
12+
*/
13+
14+
#ifndef __SEMAPHORE_H
15+
#define __SEMAPHORE_H
16+
17+
#include <kos/cdefs.h>
18+
#include <kos/sem.h>
19+
#include <errno.h>
20+
21+
__BEGIN_DECLS
22+
23+
/* POSIX semaphores are type-compatible with kernel semaphores. */
24+
typedef semaphore_t sem_t;
25+
26+
/* Selector macro, which implements function overload resolution for 2 and 3
27+
argument versions of the same function. Uses a "sliding argument" trick so
28+
that NAME is selected based on the number of arguments it gets passed.
29+
*/
30+
#define SEM_INIT_SELECTOR(_1, _2, _3, NAME, ...) NAME
31+
32+
/* Due to the fact that KOS's <kos/sem.h> is technically stomping on the POSIX
33+
symbol, sem_init(), by providing its own two argument version, we must
34+
implement some crazy macro shenanigans to allow both KOS's 2 argument
35+
version of sem_init() and POSIX's 3 argument version of sem_init() to
36+
coexist without causing errors on incompatible function declarations or
37+
duplicate symbols.
38+
39+
What we do here, is use a macro named "sem_init()" to "hide" the KOS
40+
declaration with the same name, forwarding the arguments on as __VA_ARGS__
41+
into the selector macro, which will return either the identifier
42+
"sem_init_posix," in the case when 3 arguments are provided, or
43+
"(sem_init)," in the case when 2 arguments are provided.
44+
45+
Finally, we simply invoke the return expression of SEM_INIT_SELECTOR() as
46+
if it were a function name (because it is). In the case of (sem_init)(),
47+
the parentheses around the identifier name allow us to escape from macro
48+
expansion, avoided infinite macro recursion and unhiding KOS's version of
49+
sem_init(), which we will call into.
50+
*/
51+
#define sem_init(...) \
52+
SEM_INIT_SELECTOR(__VA_ARGS__, sem_init_posix, (sem_init))(__VA_ARGS__)
53+
54+
/* 3-argument POSIX-compliant implementation of sem_init(). */
55+
static inline int sem_init_posix(sem_t *sem, int shared, unsigned int value) {
56+
if(shared) { /* We don't support shared semaphores. */
57+
errno = ENOSYS;
58+
return -1;
59+
}
60+
else
61+
return sem_init(sem, value);
62+
}
63+
64+
/* Forward POSIX sem_close() directly on to KOS's sem_destroy(). */
65+
static inline int sem_close(sem_t* sem) {
66+
return sem_destroy(sem);
67+
}
68+
69+
/* Implement POSIX's sem_getvalue() from KOS's sem_count(). */
70+
static inline int sem_getvalue(sem_t *sem, int *value) {
71+
*value = sem_count(sem);
72+
return 0;
73+
}
74+
75+
/* Forward POSIX's sem_post() on to KOS's sem_signal(). */
76+
static inline int sem_post(sem_t *sem) {
77+
return sem_signal(sem);
78+
}
79+
80+
__END_DECLS
81+
82+
#endif

0 commit comments

Comments
 (0)