Hi, the attached is a first implementation of the xsi semaphore. Althought not complete, it has everything it needs to get bonnie++ up and running (which by they way I already ran and it already corrupted my haiku partition on vmware). Regards, -- Salvatore Benedetto (a.k.a. emitrax) Student of Computer Engineer University of Pisa www.haiku-os.it
Index: src/system/kernel/posix/Jamfile =================================================================== --- src/system/kernel/posix/Jamfile (revision 26404) +++ src/system/kernel/posix/Jamfile (working copy) @@ -4,6 +4,7 @@ KernelMergeObject kernel_posix.o : realtime_sem.cpp + xsi_semaphore.cpp : $(TARGET_KERNEL_PIC_CCFLAGS) ; Index: src/system/kernel/posix/xsi_semaphore.cpp =================================================================== --- src/system/kernel/posix/xsi_semaphore.cpp (revision 0) +++ src/system/kernel/posix/xsi_semaphore.cpp (revision 0) @@ -0,0 +1,735 @@ +/* + * Copyright 2008, Haiku Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Salvatore Benedetto <salvatore.benedetto@xxxxxxxxx> + */ + +#include <posix/xsi_semaphore.h> +#include <posix/realtime_sem_defs.h> + +#include <new> + +#include <OS.h> + +#include <kernel.h> +#include <syscall_restart.h> + +#include <sys/ipc.h> +#include <sys/types.h> + +#include <util/DoublyLinkedList.h> +#include <util/OpenHashTable.h> +#include <util/Vector.h> + + +//#define TRACE_XSI_SEM +#ifdef TRACE_XSI_SEM +# define TRACE(x) dprintf x +# define TRACE_ERROR(x) dprintf x +#else +# define TRACE(x) /* nothing */ +# define TRACE_ERROR(x) dprintf x +#endif + +//#define KTRACE_XSI_SEM +#ifdef KTRACE_XSI_SEM +# define KTRACE(x...) ktrace_printf(x) +#else +# define KTRACE(x...) +#endif + +// Queue for holding blocked threads +struct queued_thread : DoublyLinkedListLinkImpl<queued_thread> { + queued_thread(struct thread *thread, int32 count) + : + thread(thread), + count(count), + queued(false) + { + } + + struct thread *thread; + int32 count; + bool queued; + bool destroyed; +}; + +typedef DoublyLinkedList<queued_thread> ThreadQueue; + + +// Xsi semaphore definition +class XsiSemaphore { +public: + XsiSemaphore() + : fLastPidOperation(0), + fProcessesWaitingToIncrease(0), + fProcessesWaitingToBeZero(0), + fValue(0) + { + } + + ~XsiSemaphore() + { + // For some reason the semaphore is getting destroyed. + // Wake up any remaing awaiting threads + GRAB_THREAD_LOCK(); + while (queued_thread *entry = fWaitingToIncreaseQueue.RemoveHead()) { + entry->queued = false; + entry->destroyed = true; + thread_unblock_locked(entry->thread, EIDRM); + } + while (queued_thread *entry = fWaitingToBeZeroQueue.RemoveHead()) { + entry->queued = false; + entry->destroyed = true; + thread_unblock_locked(entry->thread, EIDRM); + } + RELEASE_THREAD_LOCK(); + } + + // We return true in case the operation causes the + // caller to wait, so it can undo all the operations + // previously done, by calling the same function + // with force set to true, which causes the operation + // to take place despite the result of the algebric sum + bool Add(short value, bool force) + { + if (!force) { + if ((int)(fValue + value) < 0) { + TRACE(("XsiSemaphore::Add: going to sleep\n")); + return true; + } else { + fValue += value; + if ((fValue == 0) && (fProcessesWaitingToBeZero > 0)) + WakeUpThread(true); + else if ((fValue > 0) && (fProcessesWaitingToIncrease > 0)) + WakeUpThread(false); + return false; + } + } + // We are being forced to revert our changes + fValue -= value; + return false; + } + + pid_t GetPid() const + { + return fLastPidOperation; + } + + ushort GetProcessesWaitingToIncrease() const + { + return fProcessesWaitingToIncrease; + } + + ushort GetProcessesWaitingToBeZero() const + { + return fProcessesWaitingToBeZero; + } + + ushort GetValue() const + { + return fValue; + } + + void SetPid(pid_t pid) + { + fLastPidOperation = pid; + } + + void SetValue(ushort value) + { + fValue = value; + } + + status_t Wait(int32 count, bool waitForZero) + { + // enqueue the thread in the appropriate + // queue and get ready to wait + struct thread *thread = thread_get_current_thread(); + queued_thread queueEntry(thread, count); + if (waitForZero) { + fWaitingToBeZeroQueue.Add(&queueEntry); + fProcessesWaitingToBeZero++; + } else { + fWaitingToIncreaseQueue.Add(&queueEntry); + fProcessesWaitingToIncrease++; + } + queueEntry.queued = true; + + thread_prepare_to_block(thread, 0, THREAD_BLOCK_TYPE_OTHER, + (void*)"xsi semaphore"); + GRAB_THREAD_LOCK(); + status_t result = thread_block_locked(thread); + RELEASE_THREAD_LOCK(); + + return result; + } + + void WakeUpThread(bool waitingForZero) + { + queued_thread *entry; + bool unblock = false; + + GRAB_THREAD_LOCK(); + if (waitingForZero) { + unblock = true; + entry = fWaitingToBeZeroQueue.RemoveHead(); + } else { + entry = fWaitingToIncreaseQueue.Head(); + if ((entry->count + fValue) > 0) { + unblock = true; + entry = fWaitingToIncreaseQueue.RemoveHead(); + } + } + if (unblock) { + entry->queued = false; + entry->destroyed = true; + thread_unblock_locked(entry->thread, 0); + } + RELEASE_THREAD_LOCK(); + } + +private: + pid_t fLastPidOperation; // sempid + ushort fProcessesWaitingToIncrease; // semncnt + ushort fProcessesWaitingToBeZero; // semzcnt + short fValue; // semval + + ThreadQueue fWaitingToIncreaseQueue; + ThreadQueue fWaitingToBeZeroQueue; +}; + + + +// Xsi semaphore set definition (semid_ds) +class XsiSemaphoreSet { +public: + XsiSemaphoreSet(int nsems, int flags) + : fLastSemctlTime((time_t)real_time_clock()), + fLastSemopTime(0), + fNumberOfSemaphores(nsems), + fSemaphores(0) + { + SetID(); + SetIpcKey((key_t)-1); + SetPermissions(flags); + + for (int i = 0; i < nsems; i++) { + XsiSemaphore *current = new(std::nothrow) XsiSemaphore(); + if (current == NULL) { + TRACE_ERROR(("XsiSemaphoreSet::XsiSemaphore(): failed to allocate " + "XsiSemaphore object\n")); + return; + } + fSemaphores.PushBack(current); + } + } + + ~XsiSemaphoreSet() + { + for (Vector<XsiSemaphore *>::Iterator i = fSemaphores.Begin(); + i != fSemaphores.End(); i++) { + delete (*i); + } + } + + int GetID() const + { + return fID; + } + + key_t GetIpcKey() const + { + return fPermissions.key; + } + + ushort GetNumberOfSemaphores() const + { + return fNumberOfSemaphores; + } + + XsiSemaphore* GetSemaphore(int nth) const + { + return fSemaphores[nth]; + } + + // Implemented after sSemaphoreHashTable is declared + void SetID(); + + void SetIpcKey(key_t key) + { + fPermissions.key = key; + } + + void SetLastSemctlTime() + { + fLastSemctlTime = real_time_clock(); + } + + void SetLastSemopTime() + { + fLastSemopTime = real_time_clock(); + } + + void SetPermissions(int flags) + { + fPermissions.uid = fPermissions.cuid = geteuid(); + fPermissions.gid = fPermissions.cgid = getegid(); + fPermissions.mode = (flags & 0x01ff); + } + + bool HasPermission() const + { + if ((fPermissions.mode & S_IWOTH) != 0) + return true; + + uid_t uid = geteuid(); + if (uid == 0 || (uid == fPermissions.uid && (fPermissions.mode & S_IWUSR) != 0)) + return true; + + gid_t gid = getegid(); + if (gid == fPermissions.gid && (fPermissions.mode & S_IWGRP) != 0) + return true; + + return false; + } + + bool HasReadPermission() const + { + // TODO: fix this + return HasPermission(); + } + + HashTableLink<XsiSemaphoreSet>* Link() + { + return &fLink; + } + +private: + int fID; // semaphore set id + time_t fLastSemctlTime; // sem_ctime + time_t fLastSemopTime; // sem_otime + ushort fNumberOfSemaphores; // sem_nsems + struct ipc_perm fPermissions; // sem_perm + Vector<XsiSemaphore*> fSemaphores; + + ::HashTableLink<XsiSemaphoreSet> fLink; +}; + +// Xsi semaphore set hash table +struct SemaphoreHashTableDefinition { + typedef int KeyType; + typedef XsiSemaphoreSet ValueType; + + size_t HashKey (const int key) const + { + return (size_t)key; + } + size_t Hash(XsiSemaphoreSet* variable) const + { + return (size_t)variable->GetID(); + } + bool Compare(const int key, XsiSemaphoreSet* variable) const + { + return (int)key == (int)variable->GetID(); + } + HashTableLink<XsiSemaphoreSet>* GetLink(XsiSemaphoreSet* variable) const + { + return variable->Link(); + } +}; + +static OpenHashTable<SemaphoreHashTableDefinition> sSemaphoreHashTable; +static int sNextAvailableID = 0; +static spinlock xsi_semaphore_set_spinlock = B_SPINLOCK_INITIALIZER; +#define GRAB_SEM_LOCK() acquire_spinlock(&xsi_semaphore_set_spinlock) +#define RELEASE_SEM_LOCK() release_spinlock(&xsi_sempahore_set_spinlock) + +// Arbitrary limit +#define MAX_XSI_SEMAPHORE 512 +static int sTotalNumberOfXsiSemaphores = 0; + +void +XsiSemaphoreSet::SetID() +{ + // The spinlock is held upon creation of the object + while (true) { + if (sSemaphoreHashTable.Lookup(sNextAvailableID) == NULL) + break; + sNextAvailableID++; + } + fID = sNextAvailableID++; +} + + +// IPC class +class Ipc { +public: + Ipc(key_t key) + : fKey(key), + fSemaphoreSetId(-1) + { + } + + key_t GetKey() const + { + return fKey; + } + + int GetSemaphoreSetID() const + { + return fSemaphoreSetId; + } + + void SetSemaphoreSetID(XsiSemaphoreSet *semaphoreSet) + { + fSemaphoreSetId = semaphoreSet->GetID(); + } + + bool HasSemaphoreSet() + { + if (fSemaphoreSetId != -1) + return true; + return false; + } + + HashTableLink<Ipc>* Link() + { + return &fLink; + } + +private: + key_t fKey; + int fSemaphoreSetId; + HashTableLink<Ipc> fLink; +}; + + +struct IpcHashTableDefinition { + typedef key_t KeyType; + typedef Ipc ValueType; + + size_t HashKey (const key_t key) const + { + // TODO: Define a better hash function + // key_t is a 32 bit integer value. + return (size_t)(key & 0x00000fff) % 32; + } + size_t Hash(Ipc* variable) const + { + return HashKey(variable->GetKey()); + } + bool Compare(const key_t key, Ipc* variable) const + { + return (key_t)key == (key_t)variable->GetKey(); + } + HashTableLink<Ipc>* GetLink(Ipc* variable) const + { + return variable->Link(); + } +}; + +static OpenHashTable<IpcHashTableDefinition> sIpcHashTable; +static spinlock ipc_spinlock = B_SPINLOCK_INITIALIZER; +#define GRAB_IPC_TABLE_LOCK() acquire_spinlock(&ipc_spinlock); +#define RELEASE_IPC_TABLE_LOCK() release_spinlock(&ipc_spinlock); + + +status_t +haiku_xsi_ipc_init(struct kernel_args *args) +{ + // Initialize hash tables + status_t error = sIpcHashTable.Init(); + if (error != B_OK) + return error; + return sSemaphoreHashTable.Init(); +} + + +int +_user_xsi_semget(key_t key, int numberOfSemaphores, int flags) +{ + XsiSemaphoreSet *semaphoreSet = NULL; + Ipc *IpcKey = NULL; + // Default assumptions + bool isPrivate = true; + bool create = true; + + if (key != IPC_PRIVATE) { + isPrivate = false; + // Check if key already have a semaphore + // associated with it + IpcKey = sIpcHashTable.Lookup(key); + if (IpcKey == NULL) { + // The ipc key have probably just been created + // by the caller, add it to the system + IpcKey = new(std::nothrow) Ipc(key); + if (IpcKey == NULL) { + TRACE_ERROR(("xsi_semget: failed to create new Ipc object " + "for key %d\n", (int)key)); + return ENOMEM; + } + sIpcHashTable.Insert(IpcKey); + } else if (IpcKey->HasSemaphoreSet()) { + // The IPC key exist and it already has a semaphore + if ((flags & IPC_CREAT) && (flags & IPC_EXCL)) { + TRACE_ERROR(("xsi_semget: key %d already exist\n", (int)key)); + return EEXIST; + } + int semaphoreSetID = IpcKey->GetSemaphoreSetID(); + semaphoreSet = sSemaphoreHashTable.Lookup(semaphoreSetID); + if (!semaphoreSet->HasPermission()) { + TRACE_ERROR(("xsi_semget: calling process has not permission " + "on semaphore %d, key %d\n", semaphoreSet->GetID(), + (int)semaphoreSet->GetIpcKey())); + return EACCES; + } + if ((semaphoreSet->GetNumberOfSemaphores() < numberOfSemaphores) + && (numberOfSemaphores != 0)) { + TRACE_ERROR(("xsi_semget: nsems greater than the one " + "associated with semaphore %d, key %d\n", + semaphoreSet->GetID(), (int)semaphoreSet->GetIpcKey())); + return EINVAL; + } + create = false; + } else { + // The IPC key exist but it has not semaphore associated with it + if (!(flags & IPC_CREAT)) { + TRACE_ERROR(("xsi_semget: key %d has not semaphore associated " + "with it and caller did not ask for creation\n",(int)key)); + return ENOENT; + } + } + + if (create) { + // Create a new sempahore for this key + if (numberOfSemaphores < 0 + || numberOfSemaphores > MAX_POSIX_SEMS_PER_TEAM) { + TRACE_ERROR(("xsi_semget: nsems out of range\n")); + return EINVAL; + } + if (sTotalNumberOfXsiSemaphores < MAX_XSI_SEMAPHORE) { + TRACE_ERROR(("xsi_semget: reached limit of maximum number of " + "semaphores allowed\n")); + return ENOSPC; + } + sTotalNumberOfXsiSemaphores++; + + semaphoreSet = new(std::nothrow) XsiSemaphoreSet(numberOfSemaphores,flags); + if (semaphoreSet == NULL) { + TRACE_ERROR(("xsi_semget: failed to allocate a new xsi " + "semaphore set\n")); + sTotalNumberOfXsiSemaphores--; + return ENOMEM; + } + if (isPrivate) + semaphoreSet->SetIpcKey((key_t)-1); + else { + semaphoreSet->SetIpcKey(key); + IpcKey->SetSemaphoreSetID(semaphoreSet); + } + } + } + + return semaphoreSet->GetID(); +} + + +int +_user_xsi_semctl(int semaphoreID, int semaphoreNumber, int command, union semun* args) +{ + XsiSemaphoreSet *semaphoreSet = sSemaphoreHashTable.Lookup(semaphoreID); + if (semaphoreSet == NULL) { + TRACE_ERROR(("xsi_semctl: semaphore set id %d not valid\n", semaphoreID)); + return EINVAL; + } + if ((semaphoreNumber < 0) + || (semaphoreNumber >= semaphoreSet->GetNumberOfSemaphores())) { + TRACE_ERROR(("xsi_semctl: semaphore number %d not valid for " + "semaphore %d\n", semaphoreNumber, semaphoreID)); + return EINVAL; + } + + if ((args != 0) && !(IS_USER_ADDRESS(args))) { + TRACE_ERROR(("xsi_semctl: semun address is not valid\n")); + return B_BAD_ADDRESS; + } + + XsiSemaphore *semaphore = semaphoreSet->GetSemaphore(semaphoreNumber); + switch (command) { + case GETVAL: + if (!(semaphoreSet->HasReadPermission())) { + TRACE_ERROR(("xsi_semctl: calling process has not permission " + "on semaphore %d, key %d\n", semaphoreSet->GetID(), + (int)semaphoreSet->GetIpcKey())); + return EACCES; + } + return semaphore->GetValue(); + + case SETVAL: + if (!(semaphoreSet->HasPermission())) { + TRACE_ERROR(("xsi_semctl: calling process has not permission " + "on semaphore %d, key %d\n", semaphoreSet->GetID(), + (int)semaphoreSet->GetIpcKey())); + return EACCES; + } + int value; + user_memcpy(&value, &args->val, sizeof(int)); + if (value > USHRT_MAX) { + TRACE_ERROR(("xsi_semctl: value %d out of range\n", value)); + return ERANGE; + } + semaphore->SetValue(value); + return 0; + + case GETPID: + if (!(semaphoreSet->HasReadPermission())) { + TRACE_ERROR(("xsi_semctl: calling process has not permission " + "on semaphore %d, key %d\n", semaphoreSet->GetID(), + (int)semaphoreSet->GetIpcKey())); + return EACCES; + } + return semaphore->GetPid(); + + case GETNCNT: + if (!(semaphoreSet->HasReadPermission())) { + TRACE_ERROR(("xsi_semctl: calling process has not permission " + "on semaphore %d, key %d\n", semaphoreSet->GetID(), + (int)semaphoreSet->GetIpcKey())); + return EACCES; + } + return semaphore->GetProcessesWaitingToIncrease(); + + case GETZCNT: + if (!(semaphoreSet->HasReadPermission())) { + TRACE_ERROR(("xsi_semctl: calling process has not permission " + "on semaphore %d, key %d\n", semaphoreSet->GetID(), + (int)semaphoreSet->GetIpcKey())); + return EACCES; + } + return semaphore->GetProcessesWaitingToBeZero(); + + case GETALL: + case SETALL: + // TODO + return -1; + + case IPC_STAT: + case IPC_SET: + // TODO + case IPC_RMID: + if (!(semaphoreSet->HasPermission())) { + TRACE_ERROR(("xsi_semctl: calling process has not permission " + "on semaphore %d, key %d\n", semaphoreSet->GetID(), + (int)semaphoreSet->GetIpcKey())); + return EACCES; + } + sSemaphoreHashTable.Remove(semaphoreSet); + delete semaphoreSet; + + + default: + TRACE_ERROR(("xsi_semctl: command %d not valid\n", command)); + return EINVAL; + } +} + + +status_t +_user_xsi_semop(int semaphoreID, struct sembuf *sops, size_t nsops) +{ + XsiSemaphoreSet *semaphoreSet = sSemaphoreHashTable.Lookup(semaphoreID); + if (semaphoreSet == NULL) { + TRACE_ERROR(("xsi_semop: semaphore set id %d not valid\n", semaphoreID)); + return EINVAL; + } + + if (!IS_USER_ADDRESS(sops)) { + TRACE_ERROR(("xsi_semop: sembuf address is not valid\n")); + return B_BAD_ADDRESS; + } + + struct sembuf operations[nsops]; + user_memcpy(&operations[0], sops, (sizeof(struct sembuf) * nsops)); + /* + * We won't do partial request. If we must wait on a + * semaphore, we undo all the operations already done + * and go to sleep. + */ + bool notDone = true; + bool goToSleep = false; + status_t result = 0; + while (notDone) { + XsiSemaphore *semaphore = NULL; + short numberOfSemaphores = semaphoreSet->GetNumberOfSemaphores(); + + int i = 0; + for (; i < nsops; i++) { + short semaphoreNumber = operations[i].sem_num; + if (semaphoreNumber > numberOfSemaphores) { + TRACE_ERROR(("xsi_semop: %d invalid semaphore number\n", i)); + result = EINVAL; + break; + } + semaphore = semaphoreSet->GetSemaphore(semaphoreNumber); + unsigned short value = semaphore->GetValue(); + short operation = operations[i].sem_op; + if (operation < 0) { + if (semaphore->Add(operation, false)) { + goToSleep = true; + break; + } + } else if (operation == 0) { + if (value == 0) + continue; + else if (operations[i].sem_flg & IPC_NOWAIT) { + result = EAGAIN; + break; + } else { + goToSleep = true; + break; + } + } else { + // Operation must be greater than zero, + // just add the value and continue + semaphore->Add(operation, false); + } + } + + // Either we have to wait or an error occured + if (goToSleep || result != 0) { + // Undo all previosly done operations + for (int j = 0; j < i; j++) { + short semaphoreNumber = operations[j].sem_num; + semaphore = semaphoreSet->GetSemaphore(semaphoreNumber); + short operation = operations[j].sem_op; + if (operation != 0) + semaphore->Add(operation, true); + } + if (result != 0) + return result; + + bool waitOnZero = true; + if (operations[i].sem_op != 0) + waitOnZero = false; + + result = semaphore->Wait((int32)operations[i].sem_op, waitOnZero); + + // We are back to life. + // Find out why! + semaphoreSet = sSemaphoreHashTable.Lookup(semaphoreID); + if (semaphoreSet == NULL || result == EIDRM) { + TRACE_ERROR(("xsi_semop: semaphore set id %d got destroyed\n", + semaphoreID)); + result = EIDRM; + notDone = false; + } + } else + // everything worked like a charm + notDone = false; + // TODO: Handle SEM_UNDO requests + } + return result; +} Index: src/system/kernel/syscalls.cpp =================================================================== --- src/system/kernel/syscalls.cpp (revision 26404) +++ src/system/kernel/syscalls.cpp (working copy) @@ -17,6 +17,7 @@ #include <vm.h> #include <thread.h> #include <posix/realtime_sem.h> +#include <posix/xsi_semaphore.h> #include <sem.h> #include <port.h> #include <cpu.h> Index: src/system/libroot/posix/sys/ftok.c =================================================================== --- src/system/libroot/posix/sys/ftok.c (revision 0) +++ src/system/libroot/posix/sys/ftok.c (revision 0) @@ -0,0 +1,22 @@ +/* + * Copyright 2008, Haiku Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Salvatore Benedetto <salvatore.benedetto@xxxxxxxxx> + */ + +#include <sys/ipc.h> +#include <sys/types.h> +#include <sys/stat.h> + +key_t +ftok(const char *path, int id) +{ + struct stat st; + + if (stat(path,&st) < 0) + return (key_t)-1; + + return (key_t) (id << 24 | (st.st_dev & 0xff) << 16 | (st.st_ino & 0xffff)); +} Index: src/system/libroot/posix/sys/xsi_sem.c =================================================================== --- src/system/libroot/posix/sys/xsi_sem.c (revision 0) +++ src/system/libroot/posix/sys/xsi_sem.c (revision 0) @@ -0,0 +1,81 @@ +/* + * Copyright 2008, Haiku Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Salvatore Benedetto <salvatore.benedetto@xxxxxxxxx> + */ + +#include <sys/sem.h> + +#include <errno.h> +#include <fcntl.h> +#include <stdarg.h> +#include <stdlib.h> + +#include <OS.h> + +#include <posix/realtime_sem_defs.h> +#include <syscalls.h> + +#define RETURN_AND_SET_ERRNO(status) \ +{ \ + if (status < 0) { \ + errno = status; \ + return -1; \ + } \ + return status; \ +} + + +/* + * For the semctl option argument, the user + * should declare explicitly the following union + */ +union semun { + int val; + struct semid_ds *buf; + unsigned short *array; +}; + +int +semget(key_t key, int num_sems, int sem_flags) +{ + RETURN_AND_SET_ERRNO(_kern_xsi_semget(key, num_sems, sem_flags)); +} + + +int +semctl(int semId, int sem_num, int command, ...) +{ + union semun arg; + va_list args; + + switch (command) { + case GETVAL: + case GETPID: + case GETNCNT: + case GETZCNT: + case IPC_RMID: + RETURN_AND_SET_ERRNO(_kern_xsi_semctl(semId, sem_num, command, 0)); + + case SETVAL: + case GETALL: + case SETALL: + case IPC_STAT: + case IPC_SET: + va_start(args, command); + arg = va_arg(args, union semun); + va_end(args); + RETURN_AND_SET_ERRNO(_kern_xsi_semctl(semId, sem_num, command, &arg)); + default: + return EINVAL; + } +} + + +int +semop(int sem_id, struct sembuf *sem_ops, size_t num_sem_ops) +{ + RETURN_AND_SET_ERRNO(_kern_xsi_semop(sem_id, sem_ops, num_sem_ops)); +} Index: src/system/libroot/posix/sys/Jamfile =================================================================== --- src/system/libroot/posix/sys/Jamfile (revision 26404) +++ src/system/libroot/posix/sys/Jamfile (working copy) @@ -7,6 +7,7 @@ chmod.c flock.c ftime.c + ftok.c getrusage.c gettimeofday.c itimer.c @@ -23,4 +24,5 @@ uname.c utimes.c wait.c + xsi_sem.c ; Index: headers/posix/sys/ipc.h =================================================================== --- headers/posix/sys/ipc.h (revision 26404) +++ headers/posix/sys/ipc.h (working copy) @@ -6,8 +6,8 @@ #define _SYS_IPC_H +#include <sys/cdefs.h> #include <sys/types.h> -#error functionality has not yet been implemented /* Mode bits for msgget(), semget(), and shmget() */ @@ -17,15 +17,15 @@ /* Control commands for msgctl(), semctl(), and shmctl() */ #define IPC_RMID 0 /* remove identifier */ -#define IPC_SET 1 -#define IPC_STAT 2 +#define IPC_SET 1 /* set options */ +#define IPC_STAT 2 /* get options */ /* Private key */ -#define IPC_PRIVATE 0 +#define IPC_PRIVATE (key_t)0 struct ipc_perm { - key_t key; + key_t key; /* IPC identifier */ uid_t uid; /* owner's user ID */ gid_t gid; /* owner's group ID */ uid_t cuid; /* creator's user ID */ @@ -34,14 +34,10 @@ }; -#ifdef __cplusplus -extern "C" { -#endif +__BEGIN_DECLS key_t ftok(const char *path, int id); -#ifdef __cplusplus -} -#endif +__END_DECLS #endif /* _SYS_IPC_H */ Index: headers/posix/sys/types.h =================================================================== --- headers/posix/sys/types.h (revision 26404) +++ headers/posix/sys/types.h (working copy) @@ -1,5 +1,6 @@ /* - * Distributed under the terms of the OpenBeOS license + * Copyright 2008, Haiku Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. */ #ifndef _SYS_TYPES_H #define _SYS_TYPES_H Index: headers/posix/sys/sem.h =================================================================== --- headers/posix/sys/sem.h (revision 0) +++ headers/posix/sys/sem.h (revision 0) @@ -0,0 +1,63 @@ +/* + * Copyright 2008, Haiku Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + */ +#ifndef _SYS_SEM_H +#define _SYS_SEM_H + +#include <sys/cdefs.h> +#include <sys/ipc.h> +#include <sys/types.h> + + +// Semaphore operation flags +#define SEM_UNDO 10 + +// Command definition for semctl +#define GETPID 3 // Get process ID of last element manipulating +#define GETVAL 4 // Get semval +#define GETALL 5 // Get all semval +#define GETNCNT 6 // Get semncnt +#define GETZCNT 7 // Get semzcnt +#define SETVAL 8 // Set semval +#define SETALL 9 // Set all semval + +struct semid_ds { + struct ipc_perm sem_perm; // Operation permission structure + unsigned short sem_nsems; // Number of semaphores in set + time_t sem_otime; // Last semop + time_t sem_ctime; // Last time changed by semctl +}; + +// Structure passed as parameter to the semop function +struct sembuf { + unsigned short sem_num; // Semaphore number + short sem_op; // Semaphore operation + short sem_flg; // Operation flags +}; + +// Semaphore info structure. Useful for the ipcs +// standard utily +struct seminfo { + int semmni; // Number of semaphore identifies + int semmns; // Number of semaphore in system + int semmnu; // Number of undo structures in system + int semmsl; // Max number of semaphores per id + int semopm; // Max number of operations per semop call + int semume; // Max number of undo entries per process + int semusz; // Size in bytes of undo structure + int semvmx; // Semaphore maximum valure + int semaem; // adjust on exit max value +}; + + +__BEGIN_DECLS + +int semctl(int sem_id, int sem_num, int command, ...); +int semget(key_t key, int num_sems, int sem_flags); +int semop(int sem_id, struct sembuf *sem_ops, size_t num_sem_ops); + +__END_DECLS + + +#endif /* _SYS_SEM_H */ Index: headers/posix/sys/resource.h =================================================================== --- headers/posix/sys/resource.h (revision 26404) +++ headers/posix/sys/resource.h (working copy) @@ -1,10 +1,11 @@ +/* + * Copyright 2008, Haiku Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + */ #ifndef _SYS_RESOURCE_H #define _SYS_RESOURCE_H -/* -** Distributed under the terms of the OpenBeOS License. -*/ - +#include <sys/cdefs.h> #include <sys/time.h> @@ -53,9 +54,7 @@ #define PRIO_USER 2 -#ifdef __cplusplus -extern "C" { -#endif +__BEGIN_DECLS extern int getrusage(int who, struct rusage *rusage); @@ -66,8 +65,6 @@ * int getpriority(int which, id_t who); * int setpriority(int which, id_t who, int priority); */ -#ifdef __cplusplus -} -#endif +__END_DECLS #endif /* _SYS_RESOURCE_H */ Index: headers/private/kernel/posix/xsi_semaphore.h =================================================================== --- headers/private/kernel/posix/xsi_semaphore.h (revision 0) +++ headers/private/kernel/posix/xsi_semaphore.h (revision 0) @@ -0,0 +1,35 @@ +/* + * Copyright 2008, Haiku Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Salvatore Benedetto <salvatore.benedetto@xxxxxxxxx> + */ +#ifndef KERNEL_XSI_H +#define KERNEL_XSI_H + +#include <sys/sem.h> +#include <sys/cdefs.h> + +#include <OS.h> + +struct kernel_args; + +union semun { + int val; + struct semid_ds *buf; + unsigned short *array; +}; + +__BEGIN_DECLS + +extern status_t haiku_xsi_ipc_init(struct kernel_args *args); + +/* user calls */ +int _user_xsi_semget(key_t key, int numberOfSemaphores, int flags); +int _user_xsi_semctl(int semaphoreID, int semaphoreNumber, int command, union semun* args); +status_t _user_xsi_semop(int semaphoreID, struct sembuf *sops, size_t nsops); + +__END_DECLS + +#endif /* KERNEL_XSI_H */ Index: headers/private/kernel/util/OpenHashTable.h =================================================================== --- headers/private/kernel/util/OpenHashTable.h (revision 26404) +++ headers/private/kernel/util/OpenHashTable.h (working copy) @@ -30,7 +30,7 @@ size_t HashKey(int key) const { return key >> 1; } size_t Hash(Foo *value) const { return HashKey(value->bar); } bool Compare(int key, Foo *value) const { return value->bar == key; } - HashTableLink<Foo> *GetLink(Foo *value) const { return value; } + HashTableLink<Foo> *GetLink(Foo *value) const { return &value->otherLink; } }; */ Index: headers/private/system/syscalls.h =================================================================== --- headers/private/system/syscalls.h (revision 26404) +++ headers/private/system/syscalls.h (working copy) @@ -27,6 +27,7 @@ struct net_stat; struct pollfd; struct rlimit; +struct sembuf; struct sigaction; struct stat; struct _sem_t; @@ -38,6 +39,7 @@ struct user_disk_device_job_info; struct user_disk_system_info; +union semun; // This marks the beginning of the syscalls prototypes for gensyscallinfos. // NOTE: // * Nothing but those prototypes may live here. @@ -89,6 +91,11 @@ extern status_t _kern_realtime_sem_post(sem_id semID); extern status_t _kern_realtime_sem_wait(sem_id semID, bigtime_t timeout); +/* POSIX XSI sem syscalls */ +extern int _kern_xsi_semget(key_t key, int numberOfSemaphores, int flags); +extern int _kern_xsi_semctl(int semaphoreID, int semaphoreNumber, int command, union semun* args); +extern status_t _kern_xsi_semop(int semaphoreID, struct sembuf *sops, size_t nsops); + /* team & thread syscalls */ extern thread_id _kern_load_image(const char* const* flatArgs,