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 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 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 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 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 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 131 release_sem(sem_id id) 132 { 133 return release_sem_etc(id, 1, 0); 134 } 135 136 // release_sem_etc 137 status_t 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 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 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 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 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