1/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
2/* If you are missing that file, acquire a complete release at teeworlds.com. */
3
4#include "sphore.h"
5
6#include "dbg.h"
7
8#if defined(CONF_FAMILY_WINDOWS)
9#include <windows.h>
10
11#include <limits>
12#elif defined(CONF_PLATFORM_MACOS)
13#include "process.h"
14#include "str.h"
15
16#include <fcntl.h> // O_* constants
17#include <sys/stat.h> // S_* constants
18#elif defined(CONF_FAMILY_UNIX)
19#include "str.h"
20
21#include <cerrno>
22#endif
23
24#if defined(CONF_FAMILY_WINDOWS)
25void sphore_init(SEMAPHORE *sem)
26{
27 *sem = CreateSemaphoreW(nullptr, 0, std::numeric_limits<LONG>::max(), nullptr);
28 dbg_assert(*sem != nullptr, "CreateSemaphoreW failure");
29}
30void sphore_wait(SEMAPHORE *sem)
31{
32 dbg_assert(WaitForSingleObject((HANDLE)*sem, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failure");
33}
34void sphore_signal(SEMAPHORE *sem)
35{
36 dbg_assert(ReleaseSemaphore((HANDLE)*sem, 1, nullptr), "ReleaseSemaphore failure");
37}
38void sphore_destroy(SEMAPHORE *sem)
39{
40 dbg_assert(CloseHandle((HANDLE)*sem), "CloseHandle failure");
41}
42#elif defined(CONF_PLATFORM_MACOS)
43void sphore_init(SEMAPHORE *sem)
44{
45 char aBuf[64];
46 str_format(aBuf, sizeof(aBuf), "/%d.%p", process_id(), (void *)sem);
47 *sem = sem_open(aBuf, O_CREAT | O_EXCL, S_IRWXU | S_IRWXG, 0);
48 dbg_assert(*sem != SEM_FAILED, "sem_open failure, errno=%d, name='%s'", errno, aBuf);
49}
50void sphore_wait(SEMAPHORE *sem)
51{
52 while(true)
53 {
54 if(sem_wait(*sem) == 0)
55 break;
56 dbg_assert(errno == EINTR, "sem_wait failure");
57 }
58}
59void sphore_signal(SEMAPHORE *sem)
60{
61 dbg_assert(sem_post(*sem) == 0, "sem_post failure");
62}
63void sphore_destroy(SEMAPHORE *sem)
64{
65 dbg_assert(sem_close(*sem) == 0, "sem_close failure");
66 char aBuf[64];
67 str_format(aBuf, sizeof(aBuf), "/%d.%p", process_id(), (void *)sem);
68 dbg_assert(sem_unlink(aBuf) == 0, "sem_unlink failure");
69}
70#elif defined(CONF_FAMILY_UNIX)
71void sphore_init(SEMAPHORE *sem)
72{
73 dbg_assert(sem_init(sem, 0, 0) == 0, "sem_init failure");
74}
75void sphore_wait(SEMAPHORE *sem)
76{
77 while(true)
78 {
79 if(sem_wait(sem: sem) == 0)
80 break;
81 dbg_assert(errno == EINTR, "sem_wait failure");
82 }
83}
84void sphore_signal(SEMAPHORE *sem)
85{
86 dbg_assert(sem_post(sem) == 0, "sem_post failure");
87}
88void sphore_destroy(SEMAPHORE *sem)
89{
90 dbg_assert(sem_destroy(sem) == 0, "sem_destroy failure");
91}
92#endif
93