xref: /haiku/src/system/libroot/posix/semaphore.cpp (revision 6b202f4e3da73d4c131355fcd82b792d153f84f6)
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*6b202f4eSIngo Weinhold #include <posix/realtime_sem_defs.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);
39e8f1b18eSIngo Weinhold 	} else {
40e8f1b18eSIngo Weinhold 		// clear O_EXCL, if O_CREAT is not given
41e8f1b18eSIngo Weinhold 		openFlags &= ~O_EXCL;
425142c2acSIngo Weinhold 	}
435142c2acSIngo Weinhold 
445142c2acSIngo Weinhold 	// Allocate a sem_t structure -- we don't know, whether this is the first
455142c2acSIngo Weinhold 	// call of this process to open the semaphore. If it is, we will keep the
465142c2acSIngo Weinhold 	// structure, otherwise we will delete it later.
475142c2acSIngo Weinhold 	sem_t* sem = (sem_t*)malloc(sizeof(sem_t));
485142c2acSIngo Weinhold 	if (sem == NULL) {
495142c2acSIngo Weinhold 		errno = B_NO_MEMORY;
505142c2acSIngo Weinhold 		return SEM_FAILED;
515142c2acSIngo Weinhold 	}
525142c2acSIngo Weinhold 	MemoryDeleter semDeleter(sem);
535142c2acSIngo Weinhold 
545142c2acSIngo Weinhold 	// ask the kernel to open the semaphore
555142c2acSIngo Weinhold 	sem_t* usedSem;
565142c2acSIngo Weinhold 	status_t error = _kern_realtime_sem_open(name, openFlags, mode, semCount,
575142c2acSIngo Weinhold 		sem, &usedSem);
585142c2acSIngo Weinhold 	if (error != B_OK) {
595142c2acSIngo Weinhold 		errno = error;
605142c2acSIngo Weinhold 		return SEM_FAILED;
615142c2acSIngo Weinhold 	}
625142c2acSIngo Weinhold 
635142c2acSIngo Weinhold 	if (usedSem == sem)
645142c2acSIngo Weinhold 		semDeleter.Detach();
655142c2acSIngo Weinhold 
665142c2acSIngo Weinhold 	return usedSem;
675142c2acSIngo Weinhold }
685142c2acSIngo Weinhold 
695142c2acSIngo Weinhold 
705142c2acSIngo Weinhold int
715142c2acSIngo Weinhold sem_close(sem_t* semaphore)
725142c2acSIngo Weinhold {
735142c2acSIngo Weinhold 	sem_t* deleteSem = NULL;
745142c2acSIngo Weinhold 	status_t error = _kern_realtime_sem_close(semaphore->id, &deleteSem);
755142c2acSIngo Weinhold 	if (error == B_OK)
765142c2acSIngo Weinhold 		free(deleteSem);
775142c2acSIngo Weinhold 
785142c2acSIngo Weinhold 	RETURN_AND_SET_ERRNO(error);
795142c2acSIngo Weinhold }
805142c2acSIngo Weinhold 
815142c2acSIngo Weinhold 
825142c2acSIngo Weinhold int
835142c2acSIngo Weinhold sem_unlink(const char* name)
845142c2acSIngo Weinhold {
855142c2acSIngo Weinhold 	RETURN_AND_SET_ERRNO(_kern_realtime_sem_unlink(name));
865142c2acSIngo Weinhold }
875142c2acSIngo Weinhold 
885142c2acSIngo Weinhold 
895142c2acSIngo Weinhold int
905142c2acSIngo Weinhold sem_init(sem_t* semaphore, int shared, unsigned value)
915142c2acSIngo Weinhold {
923dfe682fSIngo Weinhold 	RETURN_AND_SET_ERRNO(_kern_realtime_sem_open(NULL, shared, 0, value,
933dfe682fSIngo Weinhold 		semaphore, NULL));
945142c2acSIngo Weinhold }
955142c2acSIngo Weinhold 
965142c2acSIngo Weinhold 
975142c2acSIngo Weinhold int
985142c2acSIngo Weinhold sem_destroy(sem_t* semaphore)
995142c2acSIngo Weinhold {
1005142c2acSIngo Weinhold 	RETURN_AND_SET_ERRNO(_kern_realtime_sem_close(semaphore->id, NULL));
1015142c2acSIngo Weinhold }
1025142c2acSIngo Weinhold 
1035142c2acSIngo Weinhold 
1045142c2acSIngo Weinhold int
1055142c2acSIngo Weinhold sem_post(sem_t* semaphore)
1065142c2acSIngo Weinhold {
1075142c2acSIngo Weinhold 	RETURN_AND_SET_ERRNO(_kern_realtime_sem_post(semaphore->id));
1085142c2acSIngo Weinhold }
1095142c2acSIngo Weinhold 
1105142c2acSIngo Weinhold 
1115142c2acSIngo Weinhold int
1125142c2acSIngo Weinhold sem_timedwait(sem_t* semaphore, const struct timespec* timeout)
1135142c2acSIngo Weinhold {
1145142c2acSIngo Weinhold 	bigtime_t timeoutMicros = ((bigtime_t)timeout->tv_sec) * 1000000
1155142c2acSIngo Weinhold 		+ timeout->tv_nsec / 1000;
1165142c2acSIngo Weinhold 
1175142c2acSIngo Weinhold 	RETURN_AND_SET_ERRNO(_kern_realtime_sem_wait(semaphore->id, timeoutMicros));
1185142c2acSIngo Weinhold }
1195142c2acSIngo Weinhold 
1205142c2acSIngo Weinhold 
1215142c2acSIngo Weinhold int
1225142c2acSIngo Weinhold sem_trywait(sem_t* semaphore)
1235142c2acSIngo Weinhold {
1245142c2acSIngo Weinhold 	RETURN_AND_SET_ERRNO(_kern_realtime_sem_wait(semaphore->id, 0));
1255142c2acSIngo Weinhold }
1265142c2acSIngo Weinhold 
1275142c2acSIngo Weinhold 
1285142c2acSIngo Weinhold int
1295142c2acSIngo Weinhold sem_wait(sem_t* semaphore)
1305142c2acSIngo Weinhold {
1315142c2acSIngo Weinhold 	RETURN_AND_SET_ERRNO(_kern_realtime_sem_wait(semaphore->id,
1325142c2acSIngo Weinhold 		B_INFINITE_TIMEOUT));
1335142c2acSIngo Weinhold }
1345142c2acSIngo Weinhold 
1355142c2acSIngo Weinhold 
1365142c2acSIngo Weinhold int
1375142c2acSIngo Weinhold sem_getvalue(sem_t* semaphore, int* value)
1385142c2acSIngo Weinhold {
1395142c2acSIngo Weinhold 	RETURN_AND_SET_ERRNO(_kern_realtime_sem_get_value(semaphore->id, value));
1405142c2acSIngo Weinhold }
141