15142c2acSIngo Weinhold /* 224df6592SIngo Weinhold * Copyright 2008-2011, Ingo Weinhold, ingo_weinhold@gmx.de. 35142c2acSIngo Weinhold * Distributed under the terms of the MIT License. 45142c2acSIngo Weinhold */ 55142c2acSIngo Weinhold 65142c2acSIngo Weinhold #include <semaphore.h> 75142c2acSIngo Weinhold 85142c2acSIngo Weinhold #include <errno.h> 95142c2acSIngo Weinhold #include <fcntl.h> 105142c2acSIngo Weinhold #include <stdarg.h> 115142c2acSIngo Weinhold #include <stdlib.h> 125142c2acSIngo Weinhold 135142c2acSIngo Weinhold #include <OS.h> 145142c2acSIngo Weinhold 155142c2acSIngo Weinhold #include <AutoDeleter.h> 16ae901935SOliver Tappe #include <errno_private.h> 176b202f4eSIngo Weinhold #include <posix/realtime_sem_defs.h> 185142c2acSIngo Weinhold #include <syscall_utils.h> 195142c2acSIngo Weinhold #include <syscalls.h> 205142c2acSIngo Weinhold 215142c2acSIngo Weinhold 225142c2acSIngo Weinhold sem_t* 235142c2acSIngo Weinhold sem_open(const char* name, int openFlags,...) 245142c2acSIngo Weinhold { 255142c2acSIngo Weinhold if (name == NULL) { 26ae901935SOliver Tappe __set_errno(B_BAD_VALUE); 275142c2acSIngo Weinhold return SEM_FAILED; 285142c2acSIngo Weinhold } 295142c2acSIngo Weinhold 305142c2acSIngo Weinhold // get the mode and semaphore count parameters, if O_CREAT is specified 315142c2acSIngo Weinhold mode_t mode = 0; 325142c2acSIngo Weinhold unsigned semCount = 0; 335142c2acSIngo Weinhold 345142c2acSIngo Weinhold if ((openFlags & O_CREAT) != 0) { 355142c2acSIngo Weinhold va_list args; 365142c2acSIngo Weinhold va_start(args, openFlags); 375142c2acSIngo Weinhold mode = va_arg(args, mode_t); 385142c2acSIngo Weinhold semCount = va_arg(args, unsigned); 395142c2acSIngo Weinhold va_end(args); 40e8f1b18eSIngo Weinhold } else { 41e8f1b18eSIngo Weinhold // clear O_EXCL, if O_CREAT is not given 42e8f1b18eSIngo Weinhold openFlags &= ~O_EXCL; 435142c2acSIngo Weinhold } 445142c2acSIngo Weinhold 455142c2acSIngo Weinhold // Allocate a sem_t structure -- we don't know, whether this is the first 465142c2acSIngo Weinhold // call of this process to open the semaphore. If it is, we will keep the 475142c2acSIngo Weinhold // structure, otherwise we will delete it later. 485142c2acSIngo Weinhold sem_t* sem = (sem_t*)malloc(sizeof(sem_t)); 495142c2acSIngo Weinhold if (sem == NULL) { 50ae901935SOliver Tappe __set_errno(B_NO_MEMORY); 515142c2acSIngo Weinhold return SEM_FAILED; 525142c2acSIngo Weinhold } 535142c2acSIngo Weinhold MemoryDeleter semDeleter(sem); 545142c2acSIngo Weinhold 555142c2acSIngo Weinhold // ask the kernel to open the semaphore 565142c2acSIngo Weinhold sem_t* usedSem; 575142c2acSIngo Weinhold status_t error = _kern_realtime_sem_open(name, openFlags, mode, semCount, 585142c2acSIngo Weinhold sem, &usedSem); 595142c2acSIngo Weinhold if (error != B_OK) { 60ae901935SOliver Tappe __set_errno(error); 615142c2acSIngo Weinhold return SEM_FAILED; 625142c2acSIngo Weinhold } 635142c2acSIngo Weinhold 645142c2acSIngo Weinhold if (usedSem == sem) 655142c2acSIngo Weinhold semDeleter.Detach(); 665142c2acSIngo Weinhold 675142c2acSIngo Weinhold return usedSem; 685142c2acSIngo Weinhold } 695142c2acSIngo Weinhold 705142c2acSIngo Weinhold 715142c2acSIngo Weinhold int 725142c2acSIngo Weinhold sem_close(sem_t* semaphore) 735142c2acSIngo Weinhold { 745142c2acSIngo Weinhold sem_t* deleteSem = NULL; 755142c2acSIngo Weinhold status_t error = _kern_realtime_sem_close(semaphore->id, &deleteSem); 765142c2acSIngo Weinhold if (error == B_OK) 775142c2acSIngo Weinhold free(deleteSem); 785142c2acSIngo Weinhold 795142c2acSIngo Weinhold RETURN_AND_SET_ERRNO(error); 805142c2acSIngo Weinhold } 815142c2acSIngo Weinhold 825142c2acSIngo Weinhold 835142c2acSIngo Weinhold int 845142c2acSIngo Weinhold sem_unlink(const char* name) 855142c2acSIngo Weinhold { 865142c2acSIngo Weinhold RETURN_AND_SET_ERRNO(_kern_realtime_sem_unlink(name)); 875142c2acSIngo Weinhold } 885142c2acSIngo Weinhold 895142c2acSIngo Weinhold 905142c2acSIngo Weinhold int 915142c2acSIngo Weinhold sem_init(sem_t* semaphore, int shared, unsigned value) 925142c2acSIngo Weinhold { 933dfe682fSIngo Weinhold RETURN_AND_SET_ERRNO(_kern_realtime_sem_open(NULL, shared, 0, value, 943dfe682fSIngo Weinhold semaphore, NULL)); 955142c2acSIngo Weinhold } 965142c2acSIngo Weinhold 975142c2acSIngo Weinhold 985142c2acSIngo Weinhold int 995142c2acSIngo Weinhold sem_destroy(sem_t* semaphore) 1005142c2acSIngo Weinhold { 1015142c2acSIngo Weinhold RETURN_AND_SET_ERRNO(_kern_realtime_sem_close(semaphore->id, NULL)); 1025142c2acSIngo Weinhold } 1035142c2acSIngo Weinhold 1045142c2acSIngo Weinhold 1055142c2acSIngo Weinhold int 1065142c2acSIngo Weinhold sem_post(sem_t* semaphore) 1075142c2acSIngo Weinhold { 1085142c2acSIngo Weinhold RETURN_AND_SET_ERRNO(_kern_realtime_sem_post(semaphore->id)); 1095142c2acSIngo Weinhold } 1105142c2acSIngo Weinhold 1115142c2acSIngo Weinhold 1125142c2acSIngo Weinhold int 1135142c2acSIngo Weinhold sem_timedwait(sem_t* semaphore, const struct timespec* timeout) 1145142c2acSIngo Weinhold { 115*3cdae651SSam Toyer if (timeout != NULL && (timeout->tv_nsec < 0 || 116*3cdae651SSam Toyer timeout->tv_nsec >= 1000000000)) { 117*3cdae651SSam Toyer status_t err = _kern_realtime_sem_wait(semaphore->id, 0); 118*3cdae651SSam Toyer if (err == B_WOULD_BLOCK) 119*3cdae651SSam Toyer err = EINVAL; 120*3cdae651SSam Toyer // do nothing, return err as it is. 121*3cdae651SSam Toyer RETURN_AND_SET_ERRNO_TEST_CANCEL(err); 122*3cdae651SSam Toyer } 1235142c2acSIngo Weinhold 124*3cdae651SSam Toyer bigtime_t timeoutMicros = B_INFINITE_TIMEOUT; 125*3cdae651SSam Toyer if (timeout != NULL) { 126*3cdae651SSam Toyer timeoutMicros = ((bigtime_t)timeout->tv_sec) * 1000000 127*3cdae651SSam Toyer + timeout->tv_nsec / 1000; 128*3cdae651SSam Toyer } 129*3cdae651SSam Toyer status_t err = _kern_realtime_sem_wait(semaphore->id, timeoutMicros); 130*3cdae651SSam Toyer if (err == B_WOULD_BLOCK) 131*3cdae651SSam Toyer err = ETIMEDOUT; 132*3cdae651SSam Toyer 133*3cdae651SSam Toyer RETURN_AND_SET_ERRNO_TEST_CANCEL(err); 1345142c2acSIngo Weinhold } 1355142c2acSIngo Weinhold 1365142c2acSIngo Weinhold 1375142c2acSIngo Weinhold int 1385142c2acSIngo Weinhold sem_trywait(sem_t* semaphore) 1395142c2acSIngo Weinhold { 1405142c2acSIngo Weinhold RETURN_AND_SET_ERRNO(_kern_realtime_sem_wait(semaphore->id, 0)); 1415142c2acSIngo Weinhold } 1425142c2acSIngo Weinhold 1435142c2acSIngo Weinhold 1445142c2acSIngo Weinhold int 1455142c2acSIngo Weinhold sem_wait(sem_t* semaphore) 1465142c2acSIngo Weinhold { 14724df6592SIngo Weinhold RETURN_AND_SET_ERRNO_TEST_CANCEL( 14824df6592SIngo Weinhold _kern_realtime_sem_wait(semaphore->id, B_INFINITE_TIMEOUT)); 1495142c2acSIngo Weinhold } 1505142c2acSIngo Weinhold 1515142c2acSIngo Weinhold 1525142c2acSIngo Weinhold int 1535142c2acSIngo Weinhold sem_getvalue(sem_t* semaphore, int* value) 1545142c2acSIngo Weinhold { 1555142c2acSIngo Weinhold RETURN_AND_SET_ERRNO(_kern_realtime_sem_get_value(semaphore->id, value)); 1565142c2acSIngo Weinhold } 157