1
2 #include <BeOSBuildCompatibility.h>
3
4 #include <stdlib.h>
5 #include <string.h>
6
7 #include <OS.h>
8 #include <SupportDefs.h>
9
10 // We assume that everything is single-threaded, so we don't need real
11 // semaphores. Simple fakes are sufficient.
12
13 struct semaphore {
14 char* name;
15 int32 count;
16 bool inUse;
17 };
18
19 static const int kSemaphoreCount = 40960;
20 static semaphore sSemaphores[kSemaphoreCount];
21
22
23 static bool
check_sem(sem_id id)24 check_sem(sem_id id)
25 {
26 if (id < 0 || id >= kSemaphoreCount)
27 return false;
28 return sSemaphores[id].inUse;
29 }
30
31 // create_sem
32 sem_id
create_sem(int32 count,const char * name)33 create_sem(int32 count, const char *name)
34 {
35 for (int i = 0; i < kSemaphoreCount; i++) {
36 semaphore &sem = sSemaphores[i];
37 if (!sem.inUse) {
38 sem.name = strdup(name ? name : "unnamed sem");
39 if (!sem.name)
40 return B_NO_MEMORY;
41
42 sem.inUse = true;
43 sem.count = count;
44
45 return i;
46 }
47 }
48
49 return B_NO_MORE_SEMS;
50 }
51
52 // delete_sem
53 status_t
delete_sem(sem_id id)54 delete_sem(sem_id id)
55 {
56 if (!check_sem(id))
57 return B_BAD_SEM_ID;
58
59 sSemaphores[id].inUse = false;
60 free(sSemaphores[id].name);
61 sSemaphores[id].name = NULL;
62
63 return B_OK;
64 }
65
66 // acquire_sem
67 status_t
acquire_sem(sem_id id)68 acquire_sem(sem_id id)
69 {
70 return acquire_sem_etc(id, 1, 0, 0);
71 }
72
73 // acquire_sem_etc
74 status_t
acquire_sem_etc(sem_id id,int32 count,uint32 flags,bigtime_t timeout)75 acquire_sem_etc(sem_id id, int32 count, uint32 flags, bigtime_t timeout)
76 {
77 if (!check_sem(id))
78 return B_BAD_SEM_ID;
79
80 if (count <= 0)
81 return B_BAD_VALUE;
82
83 semaphore &sem = sSemaphores[id];
84 if (sem.count >= count) {
85 sem.count -= count;
86 return B_OK;
87 }
88
89 if (timeout < 0)
90 timeout = 0;
91
92 bool noTimeout = false;
93 if (flags & B_RELATIVE_TIMEOUT) {
94 // relative timeout: get the absolute time when to time out
95
96 // special case: on timeout == 0 we return B_WOULD_BLOCK
97 if (timeout == 0)
98 return B_WOULD_BLOCK;
99
100 bigtime_t currentTime = system_time();
101 if (timeout > B_INFINITE_TIMEOUT || currentTime >= B_INFINITE_TIMEOUT - timeout) {
102 noTimeout = true;
103 } else {
104 timeout += currentTime;
105 }
106
107 } else if (flags & B_ABSOLUTE_TIMEOUT) {
108 // absolute timeout
109 } else {
110 // no timeout given
111 noTimeout = true;
112 }
113
114 // no timeout?
115 if (noTimeout) {
116 debugger("Would block on a semaphore without timeout in a "
117 "single-threaded context!");
118 return B_ERROR;
119 }
120
121 // wait for the time out time
122 status_t error = snooze_until(timeout, B_SYSTEM_TIMEBASE);
123 if (error != B_OK)
124 return error;
125
126 return B_TIMED_OUT;
127 }
128
129 // release_sem
130 status_t
release_sem(sem_id id)131 release_sem(sem_id id)
132 {
133 return release_sem_etc(id, 1, 0);
134 }
135
136 // release_sem_etc
137 status_t
release_sem_etc(sem_id id,int32 count,uint32 flags)138 release_sem_etc(sem_id id, int32 count, uint32 flags)
139 {
140 if (!check_sem(id))
141 return B_BAD_SEM_ID;
142
143 if (count <= 0)
144 return B_BAD_VALUE;
145
146 semaphore &sem = sSemaphores[id];
147 sem.count += count;
148
149 return B_OK;
150 }
151
152 // get_sem_count
153 status_t
get_sem_count(sem_id id,int32 * threadCount)154 get_sem_count(sem_id id, int32 *threadCount)
155 {
156 if (!check_sem(id))
157 return B_BAD_SEM_ID;
158
159 if (!threadCount)
160 return B_BAD_VALUE;
161
162 *threadCount = sSemaphores[id].count;
163 return B_OK;
164 }
165
166 // set_sem_owner
167 status_t
set_sem_owner(sem_id id,team_id team)168 set_sem_owner(sem_id id, team_id team)
169 {
170 if (!check_sem(id))
171 return B_BAD_SEM_ID;
172
173 return B_OK;
174 }
175
176 // _get_sem_info
177 status_t
_get_sem_info(sem_id id,struct sem_info * info,size_t infoSize)178 _get_sem_info(sem_id id, struct sem_info *info, size_t infoSize)
179 {
180 if (!check_sem(id))
181 return B_BAD_SEM_ID;
182
183 if (!info)
184 return B_BAD_VALUE;
185
186 info->sem = id;
187 info->team = 1;
188 strlcpy(info->name, sSemaphores[id].name, sizeof(info->name));
189 info->count = sSemaphores[id].count;
190 info->latest_holder = -1;
191
192 return B_OK;
193 }
194
195 // _get_next_sem_info
196 status_t
_get_next_sem_info(team_id team,int32 * cookie,struct sem_info * info,size_t infoSize)197 _get_next_sem_info(team_id team, int32 *cookie, struct sem_info *info,
198 size_t infoSize)
199 {
200 if (team < 0 || team > 2)
201 return B_BAD_TEAM_ID;
202
203 for (int i = *cookie; i < kSemaphoreCount; i++) {
204 if (sSemaphores[i].inUse) {
205 *cookie = i + 1;
206 return _get_sem_info(i, info, infoSize);
207 }
208 }
209
210 return B_ENTRY_NOT_FOUND;
211 }
212