1 /* 2 * Copyright 2008-2011, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 #include <semaphore.h> 7 8 #include <errno.h> 9 #include <fcntl.h> 10 #include <stdarg.h> 11 #include <stdlib.h> 12 13 #include <OS.h> 14 15 #include <AutoDeleter.h> 16 #include <posix/realtime_sem_defs.h> 17 #include <syscall_utils.h> 18 #include <syscalls.h> 19 20 21 sem_t* 22 sem_open(const char* name, int openFlags,...) 23 { 24 if (name == NULL) { 25 errno = B_BAD_VALUE; 26 return SEM_FAILED; 27 } 28 29 // get the mode and semaphore count parameters, if O_CREAT is specified 30 mode_t mode = 0; 31 unsigned semCount = 0; 32 33 if ((openFlags & O_CREAT) != 0) { 34 va_list args; 35 va_start(args, openFlags); 36 mode = va_arg(args, mode_t); 37 semCount = va_arg(args, unsigned); 38 va_end(args); 39 } else { 40 // clear O_EXCL, if O_CREAT is not given 41 openFlags &= ~O_EXCL; 42 } 43 44 // Allocate a sem_t structure -- we don't know, whether this is the first 45 // call of this process to open the semaphore. If it is, we will keep the 46 // structure, otherwise we will delete it later. 47 sem_t* sem = (sem_t*)malloc(sizeof(sem_t)); 48 if (sem == NULL) { 49 errno = B_NO_MEMORY; 50 return SEM_FAILED; 51 } 52 MemoryDeleter semDeleter(sem); 53 54 // ask the kernel to open the semaphore 55 sem_t* usedSem; 56 status_t error = _kern_realtime_sem_open(name, openFlags, mode, semCount, 57 sem, &usedSem); 58 if (error != B_OK) { 59 errno = error; 60 return SEM_FAILED; 61 } 62 63 if (usedSem == sem) 64 semDeleter.Detach(); 65 66 return usedSem; 67 } 68 69 70 int 71 sem_close(sem_t* semaphore) 72 { 73 sem_t* deleteSem = NULL; 74 status_t error = _kern_realtime_sem_close(semaphore->id, &deleteSem); 75 if (error == B_OK) 76 free(deleteSem); 77 78 RETURN_AND_SET_ERRNO(error); 79 } 80 81 82 int 83 sem_unlink(const char* name) 84 { 85 RETURN_AND_SET_ERRNO(_kern_realtime_sem_unlink(name)); 86 } 87 88 89 int 90 sem_init(sem_t* semaphore, int shared, unsigned value) 91 { 92 RETURN_AND_SET_ERRNO(_kern_realtime_sem_open(NULL, shared, 0, value, 93 semaphore, NULL)); 94 } 95 96 97 int 98 sem_destroy(sem_t* semaphore) 99 { 100 RETURN_AND_SET_ERRNO(_kern_realtime_sem_close(semaphore->id, NULL)); 101 } 102 103 104 int 105 sem_post(sem_t* semaphore) 106 { 107 RETURN_AND_SET_ERRNO(_kern_realtime_sem_post(semaphore->id)); 108 } 109 110 111 int 112 sem_timedwait(sem_t* semaphore, const struct timespec* timeout) 113 { 114 bigtime_t timeoutMicros = ((bigtime_t)timeout->tv_sec) * 1000000 115 + timeout->tv_nsec / 1000; 116 117 RETURN_AND_SET_ERRNO_TEST_CANCEL( 118 _kern_realtime_sem_wait(semaphore->id, timeoutMicros)); 119 } 120 121 122 int 123 sem_trywait(sem_t* semaphore) 124 { 125 RETURN_AND_SET_ERRNO(_kern_realtime_sem_wait(semaphore->id, 0)); 126 } 127 128 129 int 130 sem_wait(sem_t* semaphore) 131 { 132 RETURN_AND_SET_ERRNO_TEST_CANCEL( 133 _kern_realtime_sem_wait(semaphore->id, B_INFINITE_TIMEOUT)); 134 } 135 136 137 int 138 sem_getvalue(sem_t* semaphore, int* value) 139 { 140 RETURN_AND_SET_ERRNO(_kern_realtime_sem_get_value(semaphore->id, value)); 141 } 142