xref: /haiku/src/system/libroot/posix/semaphore.cpp (revision 98e67131727de15752bc87a530612040c6955d17)
15142c2acSIngo Weinhold /*
25142c2acSIngo Weinhold  * Copyright 2008, 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>
16*98e67131SIngo Weinhold #include <posix/realtime_sem.h>
175142c2acSIngo Weinhold #include <syscall_utils.h>
185142c2acSIngo Weinhold #include <syscalls.h>
195142c2acSIngo Weinhold 
205142c2acSIngo Weinhold 
215142c2acSIngo Weinhold sem_t*
225142c2acSIngo Weinhold sem_open(const char* name, int openFlags,...)
235142c2acSIngo Weinhold {
245142c2acSIngo Weinhold 	if (name == NULL) {
255142c2acSIngo Weinhold 		errno = B_BAD_VALUE;
265142c2acSIngo Weinhold 		return SEM_FAILED;
275142c2acSIngo Weinhold 	}
285142c2acSIngo Weinhold 
295142c2acSIngo Weinhold 	// get the mode and semaphore count parameters, if O_CREAT is specified
305142c2acSIngo Weinhold 	mode_t mode = 0;
315142c2acSIngo Weinhold 	unsigned semCount = 0;
325142c2acSIngo Weinhold 
335142c2acSIngo Weinhold 	if ((openFlags & O_CREAT) != 0) {
345142c2acSIngo Weinhold 		va_list args;
355142c2acSIngo Weinhold 		va_start(args, openFlags);
365142c2acSIngo Weinhold 		mode = va_arg(args, mode_t);
375142c2acSIngo Weinhold 		semCount = va_arg(args, unsigned);
385142c2acSIngo Weinhold 		va_end(args);
395142c2acSIngo Weinhold 	}
405142c2acSIngo Weinhold 
415142c2acSIngo Weinhold 	// Allocate a sem_t structure -- we don't know, whether this is the first
425142c2acSIngo Weinhold 	// call of this process to open the semaphore. If it is, we will keep the
435142c2acSIngo Weinhold 	// structure, otherwise we will delete it later.
445142c2acSIngo Weinhold 	sem_t* sem = (sem_t*)malloc(sizeof(sem_t));
455142c2acSIngo Weinhold 	if (sem == NULL) {
465142c2acSIngo Weinhold 		errno = B_NO_MEMORY;
475142c2acSIngo Weinhold 		return SEM_FAILED;
485142c2acSIngo Weinhold 	}
495142c2acSIngo Weinhold 	MemoryDeleter semDeleter(sem);
505142c2acSIngo Weinhold 
515142c2acSIngo Weinhold 	// ask the kernel to open the semaphore
525142c2acSIngo Weinhold 	sem_t* usedSem;
535142c2acSIngo Weinhold 	status_t error = _kern_realtime_sem_open(name, openFlags, mode, semCount,
545142c2acSIngo Weinhold 		sem, &usedSem);
555142c2acSIngo Weinhold 	if (error != B_OK) {
565142c2acSIngo Weinhold 		errno = error;
575142c2acSIngo Weinhold 		return SEM_FAILED;
585142c2acSIngo Weinhold 	}
595142c2acSIngo Weinhold 
605142c2acSIngo Weinhold 	if (usedSem == sem)
615142c2acSIngo Weinhold 		semDeleter.Detach();
625142c2acSIngo Weinhold 
635142c2acSIngo Weinhold 	return usedSem;
645142c2acSIngo Weinhold }
655142c2acSIngo Weinhold 
665142c2acSIngo Weinhold 
675142c2acSIngo Weinhold int
685142c2acSIngo Weinhold sem_close(sem_t* semaphore)
695142c2acSIngo Weinhold {
705142c2acSIngo Weinhold 	sem_t* deleteSem = NULL;
715142c2acSIngo Weinhold 	status_t error = _kern_realtime_sem_close(semaphore->id, &deleteSem);
725142c2acSIngo Weinhold 	if (error == B_OK)
735142c2acSIngo Weinhold 		free(deleteSem);
745142c2acSIngo Weinhold 
755142c2acSIngo Weinhold 	RETURN_AND_SET_ERRNO(error);
765142c2acSIngo Weinhold }
775142c2acSIngo Weinhold 
785142c2acSIngo Weinhold 
795142c2acSIngo Weinhold int
805142c2acSIngo Weinhold sem_unlink(const char* name)
815142c2acSIngo Weinhold {
825142c2acSIngo Weinhold 	RETURN_AND_SET_ERRNO(_kern_realtime_sem_unlink(name));
835142c2acSIngo Weinhold }
845142c2acSIngo Weinhold 
855142c2acSIngo Weinhold 
865142c2acSIngo Weinhold int
875142c2acSIngo Weinhold sem_init(sem_t* semaphore, int shared, unsigned value)
885142c2acSIngo Weinhold {
895142c2acSIngo Weinhold 	RETURN_AND_SET_ERRNO(_kern_realtime_sem_open(NULL, 0, 0, value, semaphore,
905142c2acSIngo Weinhold 		NULL));
915142c2acSIngo Weinhold }
925142c2acSIngo Weinhold 
935142c2acSIngo Weinhold 
945142c2acSIngo Weinhold int
955142c2acSIngo Weinhold sem_destroy(sem_t* semaphore)
965142c2acSIngo Weinhold {
975142c2acSIngo Weinhold 	RETURN_AND_SET_ERRNO(_kern_realtime_sem_close(semaphore->id, NULL));
985142c2acSIngo Weinhold }
995142c2acSIngo Weinhold 
1005142c2acSIngo Weinhold 
1015142c2acSIngo Weinhold int
1025142c2acSIngo Weinhold sem_post(sem_t* semaphore)
1035142c2acSIngo Weinhold {
1045142c2acSIngo Weinhold 	RETURN_AND_SET_ERRNO(_kern_realtime_sem_post(semaphore->id));
1055142c2acSIngo Weinhold }
1065142c2acSIngo Weinhold 
1075142c2acSIngo Weinhold 
1085142c2acSIngo Weinhold int
1095142c2acSIngo Weinhold sem_timedwait(sem_t* semaphore, const struct timespec* timeout)
1105142c2acSIngo Weinhold {
1115142c2acSIngo Weinhold 	bigtime_t timeoutMicros = ((bigtime_t)timeout->tv_sec) * 1000000
1125142c2acSIngo Weinhold 		+ timeout->tv_nsec / 1000;
1135142c2acSIngo Weinhold 
1145142c2acSIngo Weinhold 	RETURN_AND_SET_ERRNO(_kern_realtime_sem_wait(semaphore->id, timeoutMicros));
1155142c2acSIngo Weinhold }
1165142c2acSIngo Weinhold 
1175142c2acSIngo Weinhold 
1185142c2acSIngo Weinhold int
1195142c2acSIngo Weinhold sem_trywait(sem_t* semaphore)
1205142c2acSIngo Weinhold {
1215142c2acSIngo Weinhold 	RETURN_AND_SET_ERRNO(_kern_realtime_sem_wait(semaphore->id, 0));
1225142c2acSIngo Weinhold }
1235142c2acSIngo Weinhold 
1245142c2acSIngo Weinhold 
1255142c2acSIngo Weinhold int
1265142c2acSIngo Weinhold sem_wait(sem_t* semaphore)
1275142c2acSIngo Weinhold {
1285142c2acSIngo Weinhold 	RETURN_AND_SET_ERRNO(_kern_realtime_sem_wait(semaphore->id,
1295142c2acSIngo Weinhold 		B_INFINITE_TIMEOUT));
1305142c2acSIngo Weinhold }
1315142c2acSIngo Weinhold 
1325142c2acSIngo Weinhold 
1335142c2acSIngo Weinhold int
1345142c2acSIngo Weinhold sem_getvalue(sem_t* semaphore, int* value)
1355142c2acSIngo Weinhold {
1365142c2acSIngo Weinhold 	RETURN_AND_SET_ERRNO(_kern_realtime_sem_get_value(semaphore->id, value));
1375142c2acSIngo Weinhold }
138