1 2 #include <BeOSBuildCompatibility.h> 3 4 #include <string.h> 5 6 #include <OS.h> 7 #include <SupportDefs.h> 8 9 // We assume that everything is single-threaded, so we don't need real 10 // semaphores. Simple fakes are sufficient. 11 12 struct semaphore { 13 char name[B_OS_NAME_LENGTH]; 14 int32 count; 15 bool inUse; 16 }; 17 18 static const int kSemaphoreCount = 1024; 19 static semaphore sSemaphores[kSemaphoreCount]; 20 21 22 static bool 23 check_sem(sem_id id) 24 { 25 if (id < 0 || id >= kSemaphoreCount) 26 return false; 27 return sSemaphores[id].inUse; 28 } 29 30 // create_sem 31 sem_id 32 create_sem(int32 count, const char *name) 33 { 34 for (int i = 0; i < kSemaphoreCount; i++) { 35 semaphore &sem = sSemaphores[i]; 36 if (!sem.inUse) { 37 sem.inUse = true; 38 sem.count = count; 39 strlcpy(sem.name, name, sizeof(sem.name)); 40 return i; 41 } 42 } 43 44 return B_NO_MORE_SEMS; 45 } 46 47 // delete_sem 48 status_t 49 delete_sem(sem_id id) 50 { 51 if (!check_sem(id)) 52 return B_BAD_SEM_ID; 53 54 sSemaphores[id].inUse = false; 55 56 return B_OK; 57 } 58 59 // acquire_sem 60 status_t 61 acquire_sem(sem_id id) 62 { 63 return acquire_sem_etc(id, 1, 0, 0); 64 } 65 66 // acquire_sem_etc 67 status_t 68 acquire_sem_etc(sem_id id, int32 count, uint32 flags, bigtime_t timeout) 69 { 70 if (!check_sem(id)) 71 return B_BAD_SEM_ID; 72 73 if (count <= 0) 74 return B_BAD_VALUE; 75 76 semaphore &sem = sSemaphores[id]; 77 if (sem.count >= count) { 78 sem.count -= count; 79 return B_OK; 80 } 81 82 if (timeout < 0) 83 timeout = 0; 84 85 bool noTimeout = false; 86 if (flags & B_RELATIVE_TIMEOUT) { 87 // relative timeout: get the absolute time when to time out 88 89 // special case: on timeout == 0 we return B_WOULD_BLOCK 90 if (timeout == 0) 91 return B_WOULD_BLOCK; 92 93 bigtime_t currentTime = system_time(); 94 if (timeout > B_INFINITE_TIMEOUT || currentTime >= B_INFINITE_TIMEOUT - timeout) { 95 noTimeout = true; 96 } else { 97 timeout += currentTime; 98 } 99 100 } else if (flags & B_ABSOLUTE_TIMEOUT) { 101 // absolute timeout 102 } else { 103 // no timeout given 104 noTimeout = true; 105 } 106 107 // no timeout? 108 if (noTimeout) { 109 debugger("Would block on a semaphore without timeout in a " 110 "single-threaded context!"); 111 return B_ERROR; 112 } 113 114 // wait for the time out time 115 status_t error = snooze_until(timeout, B_SYSTEM_TIMEBASE); 116 if (error != B_OK) 117 return error; 118 119 return B_TIMED_OUT; 120 } 121 122 // release_sem 123 status_t 124 release_sem(sem_id id) 125 { 126 return release_sem_etc(id, 1, 0); 127 } 128 129 // release_sem_etc 130 status_t 131 release_sem_etc(sem_id id, int32 count, uint32 flags) 132 { 133 if (!check_sem(id)) 134 return B_BAD_SEM_ID; 135 136 if (count <= 0) 137 return B_BAD_VALUE; 138 139 semaphore &sem = sSemaphores[id]; 140 sem.count += count; 141 142 return B_OK; 143 } 144 145 // atomic_add 146 int32 147 atomic_add(vint32 *value, int32 addValue) 148 { 149 int32 oldValue = *value; 150 value += addValue; 151 return oldValue; 152 } 153