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 "secure.h"
15#include "str.h"
16
17#include <fcntl.h> // O_* constants
18#include <sys/stat.h> // S_* constants
19#elif defined(CONF_FAMILY_UNIX)
20#include "str.h"
21
22#include <cerrno>
23#endif
24
25#if defined(CONF_FAMILY_WINDOWS)
26void sphore_init(SEMAPHORE *sem)
27{
28 *sem = CreateSemaphoreW(nullptr, 0, std::numeric_limits<LONG>::max(), nullptr);
29 dbg_assert(*sem != nullptr, "CreateSemaphoreW failure");
30}
31void sphore_wait(SEMAPHORE *sem)
32{
33 dbg_assert(WaitForSingleObject((HANDLE)*sem, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failure");
34}
35void sphore_signal(SEMAPHORE *sem)
36{
37 dbg_assert(ReleaseSemaphore((HANDLE)*sem, 1, nullptr), "ReleaseSemaphore failure");
38}
39void sphore_destroy(SEMAPHORE *sem)
40{
41 dbg_assert(CloseHandle((HANDLE)*sem), "CloseHandle failure");
42}
43#elif defined(CONF_PLATFORM_MACOS)
44void sphore_init(SEMAPHORE *sem)
45{
46 unsigned Random;
47 secure_random_fill(&Random, sizeof(Random));
48 char aBuf[32];
49 str_format(aBuf, sizeof(aBuf), "/%d.%08x", process_id(), Random);
50 *sem = sem_open(aBuf, O_CREAT | O_EXCL, S_IRWXU | S_IRWXG, 0);
51 dbg_assert(*sem != SEM_FAILED, "sem_open failure, errno=%d, name='%s'", errno, aBuf);
52 dbg_assert(sem_unlink(aBuf) == 0, "sem_unlink failure, errno=%d, name='%s'", errno, aBuf);
53}
54void sphore_wait(SEMAPHORE *sem)
55{
56 while(true)
57 {
58 if(sem_wait(*sem) == 0)
59 break;
60 dbg_assert(errno == EINTR, "sem_wait failure");
61 }
62}
63void sphore_signal(SEMAPHORE *sem)
64{
65 dbg_assert(sem_post(*sem) == 0, "sem_post failure");
66}
67void sphore_destroy(SEMAPHORE *sem)
68{
69 dbg_assert(sem_close(*sem) == 0, "sem_close failure");
70}
71#elif defined(CONF_FAMILY_UNIX)
72void sphore_init(SEMAPHORE *sem)
73{
74 dbg_assert(sem_init(sem, 0, 0) == 0, "sem_init failure");
75}
76void sphore_wait(SEMAPHORE *sem)
77{
78 while(true)
79 {
80 if(sem_wait(sem: sem) == 0)
81 break;
82 dbg_assert(errno == EINTR, "sem_wait failure");
83 }
84}
85void sphore_signal(SEMAPHORE *sem)
86{
87 dbg_assert(sem_post(sem) == 0, "sem_post failure");
88}
89void sphore_destroy(SEMAPHORE *sem)
90{
91 dbg_assert(sem_destroy(sem) == 0, "sem_destroy failure");
92}
93#endif
94