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 13struct semaphore { 14 char* name; 15 int32 count; 16 bool inUse; 17}; 18 19static const int kSemaphoreCount = 40960; 20static semaphore sSemaphores[kSemaphoreCount]; 21 22 23static bool 24check_sem(sem_id id) 25{ 26 if (id < 0 || id >= kSemaphoreCount) 27 return false; 28 return sSemaphores[id].inUse; 29} 30 31// create_sem 32sem_id 33create_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 53status_t 54delete_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 67status_t 68acquire_sem(sem_id id) 69{ 70 return acquire_sem_etc(id, 1, 0, 0); 71} 72 73// acquire_sem_etc 74status_t 75acquire_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 130status_t 131release_sem(sem_id id) 132{ 133 return release_sem_etc(id, 1, 0); 134} 135 136// release_sem_etc 137status_t 138release_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 153status_t 154get_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 167status_t 168set_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 177status_t 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 196status_t 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