Added support for POSIX semaphores (the ones from the XSI extension
Realtime option group). The implementation should be complete, but is totally untested yet. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@25326 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2008, Haiku, Inc.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef _SEMAPHORE_H_
|
||||||
|
#define _SEMAPHORE_H_
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int id;
|
||||||
|
} sem_t;
|
||||||
|
|
||||||
|
#define SEM_FAILED ((sem_t*)(long)-1)
|
||||||
|
|
||||||
|
__BEGIN_DECLS
|
||||||
|
|
||||||
|
sem_t* sem_open(const char* name, int openFlags,...);
|
||||||
|
int sem_close(sem_t* semaphore);
|
||||||
|
int sem_unlink(const char* name);
|
||||||
|
|
||||||
|
int sem_init(sem_t* semaphore, int shared, unsigned value);
|
||||||
|
int sem_destroy(sem_t* semaphore);
|
||||||
|
|
||||||
|
int sem_post(sem_t* semaphore);
|
||||||
|
int sem_timedwait(sem_t* semaphore, const struct timespec* timeout);
|
||||||
|
int sem_trywait(sem_t* semaphore);
|
||||||
|
int sem_wait(sem_t* semaphore);
|
||||||
|
int sem_getvalue(sem_t* semaphore, int* value);
|
||||||
|
|
||||||
|
__END_DECLS
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* _SEMAPHORE_H_ */
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2008, Ingo Weinhold, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef KERNEL_REALTIME_SEM_H
|
||||||
|
#define KERNEL_REALTIME_SEM_H
|
||||||
|
|
||||||
|
#include <semaphore.h>
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include <OS.h>
|
||||||
|
|
||||||
|
|
||||||
|
struct realtime_sem_context;
|
||||||
|
|
||||||
|
|
||||||
|
__BEGIN_DECLS
|
||||||
|
|
||||||
|
void realtime_sem_init();
|
||||||
|
void delete_realtime_sem_context(struct realtime_sem_context* context);
|
||||||
|
struct realtime_sem_context* clone_realtime_sem_context(
|
||||||
|
struct realtime_sem_context* context);
|
||||||
|
|
||||||
|
status_t _user_realtime_sem_open(const char* name, int openFlags,
|
||||||
|
mode_t mode, uint32 semCount, sem_t* userSem,
|
||||||
|
sem_t** _usedUserSem);
|
||||||
|
status_t _user_realtime_sem_close(sem_id semID, sem_t** _deleteUserSem);
|
||||||
|
status_t _user_realtime_sem_unlink(const char* name);
|
||||||
|
|
||||||
|
status_t _user_realtime_sem_get_value(sem_id semID, int* value);
|
||||||
|
status_t _user_realtime_sem_post(sem_id semID);
|
||||||
|
status_t _user_realtime_sem_wait(sem_id semID, bigtime_t timeout);
|
||||||
|
|
||||||
|
__END_DECLS
|
||||||
|
|
||||||
|
|
||||||
|
#endif // KERNEL_REALTIME_SEM_H
|
||||||
@@ -20,7 +20,7 @@ struct select_info;
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern status_t sem_init(struct kernel_args *args);
|
extern status_t haiku_sem_init(struct kernel_args *args);
|
||||||
extern int sem_delete_owned_sems(team_id owner);
|
extern int sem_delete_owned_sems(team_id owner);
|
||||||
extern int32 sem_used_sems(void);
|
extern int32 sem_used_sems(void);
|
||||||
extern int32 sem_max_sems(void);
|
extern int32 sem_max_sems(void);
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
#include <OS.h>
|
#include <OS.h>
|
||||||
#include <DiskDeviceDefs.h>
|
#include <DiskDeviceDefs.h>
|
||||||
|
|
||||||
|
#include <semaphore.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
|
||||||
@@ -75,6 +76,18 @@ extern status_t _kern_get_next_sem_info(team_id team, int32 *cookie,
|
|||||||
struct sem_info *info, size_t size);
|
struct sem_info *info, size_t size);
|
||||||
extern status_t _kern_set_sem_owner(sem_id id, team_id proc);
|
extern status_t _kern_set_sem_owner(sem_id id, team_id proc);
|
||||||
|
|
||||||
|
/* POSIX realtime sem syscalls */
|
||||||
|
extern status_t _kern_realtime_sem_open(const char* name, int openFlags,
|
||||||
|
mode_t mode, uint32 semCount, sem_t* userSem,
|
||||||
|
sem_t** _usedUserSem);
|
||||||
|
extern status_t _kern_realtime_sem_close(sem_id semID,
|
||||||
|
sem_t** _deleteUserSem);
|
||||||
|
extern status_t _kern_realtime_sem_unlink(const char* name);
|
||||||
|
|
||||||
|
extern status_t _kern_realtime_sem_get_value(sem_id semID, int* value);
|
||||||
|
extern status_t _kern_realtime_sem_post(sem_id semID);
|
||||||
|
extern status_t _kern_realtime_sem_wait(sem_id semID, bigtime_t timeout);
|
||||||
|
|
||||||
/* team & thread syscalls */
|
/* team & thread syscalls */
|
||||||
|
|
||||||
extern thread_id _kern_load_image(int32 argCount, const char **args,
|
extern thread_id _kern_load_image(int32 argCount, const char **args,
|
||||||
|
|||||||
@@ -68,8 +68,8 @@ enum {
|
|||||||
THREAD_BLOCK_TYPE_USER_BASE = 10000
|
THREAD_BLOCK_TYPE_USER_BASE = 10000
|
||||||
};
|
};
|
||||||
|
|
||||||
struct image;
|
struct image; // defined in image.c
|
||||||
// defined in image.c
|
struct realtime_sem_context; // defined in realtime_sem.cpp
|
||||||
struct select_info;
|
struct select_info;
|
||||||
|
|
||||||
struct death_entry {
|
struct death_entry {
|
||||||
@@ -181,6 +181,7 @@ struct team {
|
|||||||
int state; // current team state, see above
|
int state; // current team state, see above
|
||||||
int32 flags;
|
int32 flags;
|
||||||
void *io_context;
|
void *io_context;
|
||||||
|
struct realtime_sem_context *realtime_sem_context;
|
||||||
sem_id death_sem; // semaphore to wait on for dying threads
|
sem_id death_sem; // semaphore to wait on for dying threads
|
||||||
struct list dead_threads;
|
struct list dead_threads;
|
||||||
int dead_threads_count;
|
int dead_threads_count;
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ KernelMergeObject kernel_core.o :
|
|||||||
Notifications.cpp
|
Notifications.cpp
|
||||||
port.cpp
|
port.cpp
|
||||||
real_time_clock.c
|
real_time_clock.c
|
||||||
|
realtime_sem.cpp
|
||||||
scheduler.cpp
|
scheduler.cpp
|
||||||
sem.cpp
|
sem.cpp
|
||||||
shutdown.c
|
shutdown.c
|
||||||
|
|||||||
@@ -33,6 +33,7 @@
|
|||||||
#include <Notifications.h>
|
#include <Notifications.h>
|
||||||
#include <port.h>
|
#include <port.h>
|
||||||
#include <real_time_clock.h>
|
#include <real_time_clock.h>
|
||||||
|
#include <realtime_sem.h>
|
||||||
#include <sem.h>
|
#include <sem.h>
|
||||||
#include <smp.h>
|
#include <smp.h>
|
||||||
#include <system_info.h>
|
#include <system_info.h>
|
||||||
@@ -137,7 +138,7 @@ _start(kernel_args *bootKernelArgs, int currentCPU)
|
|||||||
rtc_init(&sKernelArgs);
|
rtc_init(&sKernelArgs);
|
||||||
|
|
||||||
TRACE("init semaphores\n");
|
TRACE("init semaphores\n");
|
||||||
sem_init(&sKernelArgs);
|
haiku_sem_init(&sKernelArgs);
|
||||||
condition_variable_init();
|
condition_variable_init();
|
||||||
|
|
||||||
// now we can create and use semaphores
|
// now we can create and use semaphores
|
||||||
@@ -158,6 +159,7 @@ _start(kernel_args *bootKernelArgs, int currentCPU)
|
|||||||
TRACE("init kernel daemons\n");
|
TRACE("init kernel daemons\n");
|
||||||
kernel_daemon_init();
|
kernel_daemon_init();
|
||||||
arch_platform_init_post_thread(&sKernelArgs);
|
arch_platform_init_post_thread(&sKernelArgs);
|
||||||
|
realtime_sem_init();
|
||||||
|
|
||||||
TRACE("init VM threads\n");
|
TRACE("init VM threads\n");
|
||||||
vm_init_post_thread(&sKernelArgs);
|
vm_init_post_thread(&sKernelArgs);
|
||||||
|
|||||||
@@ -0,0 +1,758 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2008, Ingo Weinhold, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <realtime_sem.h>
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
|
||||||
|
#include <OS.h>
|
||||||
|
|
||||||
|
#include <AutoDeleter.h>
|
||||||
|
#include <fs/KPath.h>
|
||||||
|
#include <kernel.h>
|
||||||
|
#include <lock.h>
|
||||||
|
#include <syscall_restart.h>
|
||||||
|
#include <team.h>
|
||||||
|
#include <thread.h>
|
||||||
|
#include <util/atomic.h>
|
||||||
|
#include <util/AutoLock.h>
|
||||||
|
#include <util/khash.h>
|
||||||
|
#include <util/OpenHashTable.h>
|
||||||
|
|
||||||
|
|
||||||
|
class SemInfo {
|
||||||
|
public:
|
||||||
|
SemInfo()
|
||||||
|
:
|
||||||
|
fName(NULL),
|
||||||
|
fRefCount(1),
|
||||||
|
fID(-1)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
~SemInfo()
|
||||||
|
{
|
||||||
|
free(fName);
|
||||||
|
if (fID >= 0)
|
||||||
|
delete_sem(fID);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* Name() const { return fName; }
|
||||||
|
sem_id ID() const { return fID; }
|
||||||
|
|
||||||
|
status_t Init(const char* name, mode_t mode, int32 semCount)
|
||||||
|
{
|
||||||
|
fName = strdup(name);
|
||||||
|
if (fName == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
fID = create_sem(semCount, name);
|
||||||
|
if (fID < 0)
|
||||||
|
return fID;
|
||||||
|
|
||||||
|
fUID = geteuid();
|
||||||
|
fGID = getegid();
|
||||||
|
fPermissions = mode;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AcquireReference()
|
||||||
|
{
|
||||||
|
atomic_add(&fRefCount, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReleaseReference()
|
||||||
|
{
|
||||||
|
if (atomic_add(&fRefCount, -1) == 1)
|
||||||
|
delete this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HasPermissions() const
|
||||||
|
{
|
||||||
|
if ((fPermissions & S_IWOTH) != 0)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
uid_t uid = geteuid();
|
||||||
|
if (uid == 0 || (uid == fUID && (fPermissions & S_IWUSR) != 0))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
gid_t gid = getegid();
|
||||||
|
if (gid == fGID && (fPermissions & S_IWGRP) != 0)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
HashTableLink<SemInfo>* HashTableLink()
|
||||||
|
{
|
||||||
|
return &fHashLink;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
char* fName;
|
||||||
|
vint32 fRefCount;
|
||||||
|
sem_id fID;
|
||||||
|
uid_t fUID;
|
||||||
|
gid_t fGID;
|
||||||
|
mode_t fPermissions;
|
||||||
|
|
||||||
|
::HashTableLink<SemInfo> fHashLink;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct NamedSemHashDefinition {
|
||||||
|
typedef const char* KeyType;
|
||||||
|
typedef SemInfo ValueType;
|
||||||
|
|
||||||
|
size_t HashKey(const KeyType& key) const
|
||||||
|
{
|
||||||
|
return hash_hash_string(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Hash(SemInfo* semaphore) const
|
||||||
|
{
|
||||||
|
return HashKey(semaphore->Name());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Compare(const KeyType& key, SemInfo* semaphore) const
|
||||||
|
{
|
||||||
|
return strcmp(key, semaphore->Name()) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
HashTableLink<SemInfo>* GetLink(SemInfo* semaphore) const
|
||||||
|
{
|
||||||
|
return semaphore->HashTableLink();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class GlobalRealtimeSemTable {
|
||||||
|
public:
|
||||||
|
GlobalRealtimeSemTable()
|
||||||
|
{
|
||||||
|
mutex_init(&fLock, "global realtime sem table");
|
||||||
|
}
|
||||||
|
|
||||||
|
~GlobalRealtimeSemTable()
|
||||||
|
{
|
||||||
|
mutex_destroy(&fLock);
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t Init()
|
||||||
|
{
|
||||||
|
return fSemaphores.InitCheck();
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t OpenSem(const char* name, int openFlags, mode_t mode,
|
||||||
|
uint32 semCount, SemInfo*& _sem, bool& _created)
|
||||||
|
{
|
||||||
|
MutexLocker _(fLock);
|
||||||
|
|
||||||
|
SemInfo* sem = fSemaphores.Lookup(name);
|
||||||
|
if (sem != NULL) {
|
||||||
|
if ((openFlags & O_EXCL) != 0)
|
||||||
|
return EEXIST;
|
||||||
|
|
||||||
|
if (!sem->HasPermissions())
|
||||||
|
return EACCES;
|
||||||
|
|
||||||
|
sem->AcquireReference();
|
||||||
|
_sem = sem;
|
||||||
|
_created = false;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((openFlags & O_CREAT) == 0)
|
||||||
|
return ENOENT;
|
||||||
|
|
||||||
|
// does not exist yet -- create
|
||||||
|
sem = new(std::nothrow) SemInfo;
|
||||||
|
if (sem == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
status_t error = sem->Init(name, mode, semCount);
|
||||||
|
if (error != B_OK) {
|
||||||
|
delete sem;
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
error = fSemaphores.Insert(sem);
|
||||||
|
if (error != B_OK) {
|
||||||
|
delete sem;
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// add one reference for the table
|
||||||
|
sem->AcquireReference();
|
||||||
|
|
||||||
|
_sem = sem;
|
||||||
|
_created = true;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t UnlinkSem(const char* name)
|
||||||
|
{
|
||||||
|
MutexLocker _(fLock);
|
||||||
|
|
||||||
|
SemInfo* sem = fSemaphores.Lookup(name);
|
||||||
|
if (sem == NULL)
|
||||||
|
return ENOENT;
|
||||||
|
|
||||||
|
if (!sem->HasPermissions())
|
||||||
|
return EACCES;
|
||||||
|
|
||||||
|
fSemaphores.Remove(sem);
|
||||||
|
sem->ReleaseReference();
|
||||||
|
// release the table reference
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
typedef OpenHashTable<NamedSemHashDefinition, true> SemTable;
|
||||||
|
|
||||||
|
mutex fLock;
|
||||||
|
SemTable fSemaphores;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static GlobalRealtimeSemTable sSemTable;
|
||||||
|
|
||||||
|
|
||||||
|
class TeamSemInfo {
|
||||||
|
public:
|
||||||
|
TeamSemInfo(SemInfo* semaphore, sem_t* userSem)
|
||||||
|
:
|
||||||
|
fSemaphore(semaphore),
|
||||||
|
fUserSemaphore(userSem),
|
||||||
|
fOpenCount(1)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
~TeamSemInfo()
|
||||||
|
{
|
||||||
|
if (fSemaphore != NULL)
|
||||||
|
fSemaphore->ReleaseReference();
|
||||||
|
}
|
||||||
|
|
||||||
|
SemInfo* Semaphore() const { return fSemaphore; }
|
||||||
|
sem_t* UserSemaphore() const { return fUserSemaphore; }
|
||||||
|
|
||||||
|
void Open()
|
||||||
|
{
|
||||||
|
fOpenCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Close()
|
||||||
|
{
|
||||||
|
return --fOpenCount == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
TeamSemInfo* Clone() const
|
||||||
|
{
|
||||||
|
TeamSemInfo* sem = new(std::nothrow) TeamSemInfo(fSemaphore,
|
||||||
|
fUserSemaphore);
|
||||||
|
if (sem == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
sem->fOpenCount = fOpenCount;
|
||||||
|
fSemaphore->AcquireReference();
|
||||||
|
|
||||||
|
return sem;
|
||||||
|
}
|
||||||
|
|
||||||
|
HashTableLink<TeamSemInfo>* HashTableLink()
|
||||||
|
{
|
||||||
|
return &fHashLink;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
SemInfo* fSemaphore;
|
||||||
|
sem_t* fUserSemaphore;
|
||||||
|
int32 fOpenCount;
|
||||||
|
|
||||||
|
::HashTableLink<TeamSemInfo> fHashLink;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct TeamSemHashDefinition {
|
||||||
|
typedef sem_id KeyType;
|
||||||
|
typedef TeamSemInfo ValueType;
|
||||||
|
|
||||||
|
size_t HashKey(const KeyType& key) const
|
||||||
|
{
|
||||||
|
return (size_t)key;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Hash(TeamSemInfo* semaphore) const
|
||||||
|
{
|
||||||
|
return HashKey(semaphore->Semaphore()->ID());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Compare(const KeyType& key, TeamSemInfo* semaphore) const
|
||||||
|
{
|
||||||
|
return key == semaphore->Semaphore()->ID();
|
||||||
|
}
|
||||||
|
|
||||||
|
HashTableLink<TeamSemInfo>* GetLink(TeamSemInfo* semaphore) const
|
||||||
|
{
|
||||||
|
return semaphore->HashTableLink();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct realtime_sem_context {
|
||||||
|
realtime_sem_context()
|
||||||
|
{
|
||||||
|
mutex_init(&fLock, "realtime sem context");
|
||||||
|
}
|
||||||
|
|
||||||
|
~realtime_sem_context()
|
||||||
|
{
|
||||||
|
mutex_lock(&fLock);
|
||||||
|
|
||||||
|
// delete all semaphores.
|
||||||
|
SemTable::Iterator it = fSemaphores.GetIterator();
|
||||||
|
while (TeamSemInfo* sem = it.Next()) {
|
||||||
|
// Note, this uses internal knowledge about how the iterator works.
|
||||||
|
// Ugly, but there's no good alternative.
|
||||||
|
fSemaphores.RemoveUnchecked(sem);
|
||||||
|
delete sem;
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex_destroy(&fLock);
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t Init()
|
||||||
|
{
|
||||||
|
return fSemaphores.InitCheck();
|
||||||
|
}
|
||||||
|
|
||||||
|
realtime_sem_context* Clone()
|
||||||
|
{
|
||||||
|
// create new context
|
||||||
|
realtime_sem_context* context = new(std::nothrow) realtime_sem_context;
|
||||||
|
if (context == NULL)
|
||||||
|
return NULL;
|
||||||
|
ObjectDeleter<realtime_sem_context> contextDeleter(context);
|
||||||
|
|
||||||
|
MutexLocker _(fLock);
|
||||||
|
|
||||||
|
// clone all semaphores
|
||||||
|
SemTable::Iterator it = fSemaphores.GetIterator();
|
||||||
|
while (TeamSemInfo* sem = it.Next()) {
|
||||||
|
TeamSemInfo* clonedSem = sem->Clone();
|
||||||
|
if (clonedSem == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (context->fSemaphores.Insert(clonedSem) != B_OK) {
|
||||||
|
delete clonedSem;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
contextDeleter.Detach();
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t CreateAnonymousSem(uint32 semCount, int& _id)
|
||||||
|
{
|
||||||
|
SemInfo* sem = new(std::nothrow) SemInfo;
|
||||||
|
if (sem == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
ObjectDeleter<SemInfo> semDeleter(sem);
|
||||||
|
|
||||||
|
status_t error = sem->Init(NULL, 0, semCount);
|
||||||
|
if (error != B_OK) {
|
||||||
|
delete sem;
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
TeamSemInfo* teamSem = new(std::nothrow) TeamSemInfo(sem, NULL);
|
||||||
|
if (teamSem == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
semDeleter.Detach();
|
||||||
|
|
||||||
|
MutexLocker _(fLock);
|
||||||
|
|
||||||
|
error = fSemaphores.Insert(teamSem);
|
||||||
|
if (error != B_OK) {
|
||||||
|
delete teamSem;
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
_id = teamSem->Semaphore()->ID();
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t OpenSem(const char* name, int openFlags, mode_t mode,
|
||||||
|
uint32 semCount, sem_t* userSem, sem_t*& _usedUserSem, int& _id,
|
||||||
|
bool& _created)
|
||||||
|
{
|
||||||
|
SemInfo* sem;
|
||||||
|
status_t error = sSemTable.OpenSem(name, openFlags, mode, semCount,
|
||||||
|
sem, _created);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
MutexLocker _(fLock);
|
||||||
|
|
||||||
|
TeamSemInfo* teamSem = fSemaphores.Lookup(sem->ID());
|
||||||
|
if (teamSem != NULL) {
|
||||||
|
// already open -- just increment the open count
|
||||||
|
teamSem->Open();
|
||||||
|
sem->ReleaseReference();
|
||||||
|
_usedUserSem = teamSem->UserSemaphore();
|
||||||
|
_id = teamSem->Semaphore()->ID();
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// not open yet -- create a new team sem
|
||||||
|
teamSem = new(std::nothrow) TeamSemInfo(sem, NULL);
|
||||||
|
if (teamSem == NULL) {
|
||||||
|
sem->ReleaseReference();
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
error = fSemaphores.Insert(teamSem);
|
||||||
|
if (error != B_OK) {
|
||||||
|
delete teamSem;
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
_usedUserSem = teamSem->UserSemaphore();
|
||||||
|
_id = teamSem->Semaphore()->ID();
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t CloseSem(sem_id id, sem_t*& deleteUserSem)
|
||||||
|
{
|
||||||
|
deleteUserSem = NULL;
|
||||||
|
|
||||||
|
MutexLocker _(fLock);
|
||||||
|
|
||||||
|
TeamSemInfo* sem = fSemaphores.Lookup(id);
|
||||||
|
if (sem == NULL)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
if (sem->Close()) {
|
||||||
|
// last reference closed
|
||||||
|
fSemaphores.Remove(sem);
|
||||||
|
deleteUserSem = sem->UserSemaphore();
|
||||||
|
delete sem;
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t AcquireSem(sem_id id, bigtime_t timeout)
|
||||||
|
{
|
||||||
|
MutexLocker locker(fLock);
|
||||||
|
|
||||||
|
if (fSemaphores.Lookup(id) == NULL)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
locker.Unlock();
|
||||||
|
|
||||||
|
status_t error;
|
||||||
|
if (timeout == 0) {
|
||||||
|
error = acquire_sem_etc(id, 1, B_CAN_INTERRUPT | B_RELATIVE_TIMEOUT,
|
||||||
|
0);
|
||||||
|
} else if (timeout == B_INFINITE_TIMEOUT) {
|
||||||
|
error = acquire_sem_etc(id, 1, B_CAN_INTERRUPT, 0);
|
||||||
|
} else {
|
||||||
|
error = acquire_sem_etc(id, 1, B_CAN_INTERRUPT | B_ABSOLUTE_TIMEOUT,
|
||||||
|
timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
return error == B_BAD_SEM_ID ? B_BAD_VALUE : error;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t ReleaseSem(sem_id id)
|
||||||
|
{
|
||||||
|
MutexLocker locker(fLock);
|
||||||
|
|
||||||
|
if (fSemaphores.Lookup(id) == NULL)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
locker.Unlock();
|
||||||
|
|
||||||
|
status_t error = release_sem(id);
|
||||||
|
return error == B_BAD_SEM_ID ? B_BAD_VALUE : error;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t GetSemCount(sem_id id, int& _count)
|
||||||
|
{
|
||||||
|
MutexLocker locker(fLock);
|
||||||
|
|
||||||
|
if (fSemaphores.Lookup(id) == NULL)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
locker.Unlock();
|
||||||
|
|
||||||
|
int32 count;
|
||||||
|
status_t error = get_sem_count(id, &count);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
_count = count;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
typedef OpenHashTable<TeamSemHashDefinition, true> SemTable;
|
||||||
|
|
||||||
|
mutex fLock;
|
||||||
|
SemTable fSemaphores;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - implementation private
|
||||||
|
|
||||||
|
|
||||||
|
static realtime_sem_context*
|
||||||
|
get_current_team_context()
|
||||||
|
{
|
||||||
|
struct team* team = thread_get_current_thread()->team;
|
||||||
|
|
||||||
|
// get context
|
||||||
|
realtime_sem_context* context = atomic_pointer_get(
|
||||||
|
&team->realtime_sem_context);
|
||||||
|
if (context != NULL)
|
||||||
|
return context;
|
||||||
|
|
||||||
|
// no context yet -- create a new one
|
||||||
|
context = new(std::nothrow) realtime_sem_context;
|
||||||
|
if (context == NULL || context->Init() != B_OK) {
|
||||||
|
delete context;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// set the allocated context
|
||||||
|
realtime_sem_context* oldContext = atomic_pointer_test_and_set(
|
||||||
|
&team->realtime_sem_context, context, (realtime_sem_context*)NULL);
|
||||||
|
if (oldContext == NULL)
|
||||||
|
return context;
|
||||||
|
|
||||||
|
// someone else was quicker
|
||||||
|
delete context;
|
||||||
|
return oldContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
copy_sem_name_to_kernel(const char* userName, KPath& buffer, char*& name)
|
||||||
|
{
|
||||||
|
if (userName == NULL)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
if (!IS_USER_ADDRESS(userName))
|
||||||
|
return B_BAD_ADDRESS;
|
||||||
|
|
||||||
|
if (buffer.InitCheck() != B_OK)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
// copy userland path to kernel
|
||||||
|
name = buffer.LockBuffer();
|
||||||
|
ssize_t actualLength = user_strlcpy(name, userName, buffer.BufferSize());
|
||||||
|
|
||||||
|
if (actualLength < 0)
|
||||||
|
return B_BAD_ADDRESS;
|
||||||
|
if ((size_t)actualLength >= buffer.BufferSize())
|
||||||
|
return ENAMETOOLONG;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - kernel internal
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
realtime_sem_init()
|
||||||
|
{
|
||||||
|
new(&sSemTable) GlobalRealtimeSemTable;
|
||||||
|
if (sSemTable.Init() != B_OK)
|
||||||
|
panic("realtime_sem_init() failed to init global table");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
delete_realtime_sem_context(realtime_sem_context* context)
|
||||||
|
{
|
||||||
|
delete context;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
realtime_sem_context*
|
||||||
|
clone_realtime_sem_context(realtime_sem_context* context)
|
||||||
|
{
|
||||||
|
if (context == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return context->Clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - syscalls
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
_user_realtime_sem_open(const char* userName, int openFlags, mode_t mode,
|
||||||
|
uint32 semCount, sem_t* userSem, sem_t** _usedUserSem)
|
||||||
|
{
|
||||||
|
realtime_sem_context* context = get_current_team_context();
|
||||||
|
if (context == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
// userSem must always be given
|
||||||
|
if (userSem == NULL)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
if (!IS_USER_ADDRESS(userSem))
|
||||||
|
return B_BAD_ADDRESS;
|
||||||
|
|
||||||
|
// anonymous semaphores are less work -- deal with them first
|
||||||
|
if (userName == NULL) {
|
||||||
|
int id;
|
||||||
|
status_t error = context->CreateAnonymousSem(semCount, id);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
if (user_memcpy(&userSem->id, &id, sizeof(int)) != B_OK) {
|
||||||
|
sem_t* dummy;
|
||||||
|
context->CloseSem(id, dummy);
|
||||||
|
return B_BAD_ADDRESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check user pointers
|
||||||
|
if (_usedUserSem == NULL)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
if (!IS_USER_ADDRESS(_usedUserSem) || !IS_USER_ADDRESS(userName))
|
||||||
|
return B_BAD_ADDRESS;
|
||||||
|
|
||||||
|
// copy name to kernel
|
||||||
|
KPath nameBuffer(B_PATH_NAME_LENGTH);
|
||||||
|
char* name;
|
||||||
|
status_t error = copy_sem_name_to_kernel(userName, nameBuffer, name);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
// open the semaphore
|
||||||
|
sem_t* usedUserSem;
|
||||||
|
bool created;
|
||||||
|
int id;
|
||||||
|
error = context->OpenSem(name, openFlags, mode, semCount, userSem,
|
||||||
|
usedUserSem, id, created);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
// copy results back to userland
|
||||||
|
if (user_memcpy(&userSem->id, &id, sizeof(int)) != B_OK
|
||||||
|
|| user_memcpy(_usedUserSem, &usedUserSem, sizeof(sem_t*)) != B_OK) {
|
||||||
|
if (created)
|
||||||
|
sSemTable.UnlinkSem(name);
|
||||||
|
sem_t* dummy;
|
||||||
|
context->CloseSem(id, dummy);
|
||||||
|
return B_BAD_ADDRESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
_user_realtime_sem_close(sem_id semID, sem_t** _deleteUserSem)
|
||||||
|
{
|
||||||
|
if (_deleteUserSem != NULL && !IS_USER_ADDRESS(_deleteUserSem))
|
||||||
|
return B_BAD_ADDRESS;
|
||||||
|
|
||||||
|
realtime_sem_context* context = get_current_team_context();
|
||||||
|
if (context == NULL)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
// close sem
|
||||||
|
sem_t* deleteUserSem;
|
||||||
|
status_t error = context->CloseSem(semID, deleteUserSem);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
// copy back result to userland
|
||||||
|
if (_deleteUserSem != NULL
|
||||||
|
&& user_memcpy(_deleteUserSem, &deleteUserSem, sizeof(sem_t*))
|
||||||
|
!= B_OK) {
|
||||||
|
return B_BAD_ADDRESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
_user_realtime_sem_unlink(const char* userName)
|
||||||
|
{
|
||||||
|
// copy name to kernel
|
||||||
|
KPath nameBuffer(B_PATH_NAME_LENGTH);
|
||||||
|
char* name;
|
||||||
|
status_t error = copy_sem_name_to_kernel(userName, nameBuffer, name);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
return sSemTable.UnlinkSem(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
_user_realtime_sem_get_value(sem_id semID, int* _value)
|
||||||
|
{
|
||||||
|
if (_value == NULL)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
if (!IS_USER_ADDRESS(_value))
|
||||||
|
return B_BAD_ADDRESS;
|
||||||
|
|
||||||
|
realtime_sem_context* context = get_current_team_context();
|
||||||
|
if (context == NULL)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
// get sem count
|
||||||
|
int count;
|
||||||
|
status_t error = context->GetSemCount(semID, count);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
// copy back result to userland
|
||||||
|
if (user_memcpy(_value, &count, sizeof(int)) != B_OK)
|
||||||
|
return B_BAD_ADDRESS;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
_user_realtime_sem_post(sem_id semID)
|
||||||
|
{
|
||||||
|
realtime_sem_context* context = get_current_team_context();
|
||||||
|
if (context == NULL)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
return context->ReleaseSem(semID);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
_user_realtime_sem_wait(sem_id semID, bigtime_t timeout)
|
||||||
|
{
|
||||||
|
realtime_sem_context* context = get_current_team_context();
|
||||||
|
if (context == NULL)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
return syscall_restart_handle_post(context->AcquireSem(semID, timeout));
|
||||||
|
}
|
||||||
@@ -301,7 +301,7 @@ fill_sem_info(struct sem_entry *sem, sem_info *info, size_t size)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
sem_init(kernel_args *args)
|
haiku_sem_init(kernel_args *args)
|
||||||
{
|
{
|
||||||
area_id area;
|
area_id area;
|
||||||
int32 i;
|
int32 i;
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
#include <vfs.h>
|
#include <vfs.h>
|
||||||
#include <vm.h>
|
#include <vm.h>
|
||||||
#include <thread.h>
|
#include <thread.h>
|
||||||
|
#include <realtime_sem.h>
|
||||||
#include <sem.h>
|
#include <sem.h>
|
||||||
#include <port.h>
|
#include <port.h>
|
||||||
#include <cpu.h>
|
#include <cpu.h>
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
#include <kscheduler.h>
|
#include <kscheduler.h>
|
||||||
#include <ksignal.h>
|
#include <ksignal.h>
|
||||||
#include <port.h>
|
#include <port.h>
|
||||||
|
#include <realtime_sem.h>
|
||||||
#include <sem.h>
|
#include <sem.h>
|
||||||
#include <syscall_process_info.h>
|
#include <syscall_process_info.h>
|
||||||
#include <syscall_restart.h>
|
#include <syscall_restart.h>
|
||||||
@@ -822,6 +823,7 @@ create_team_struct(const char *name, bool kernel)
|
|||||||
team->num_threads = 0;
|
team->num_threads = 0;
|
||||||
team->io_context = NULL;
|
team->io_context = NULL;
|
||||||
team->address_space = NULL;
|
team->address_space = NULL;
|
||||||
|
team->realtime_sem_context = NULL;
|
||||||
team->thread_list = NULL;
|
team->thread_list = NULL;
|
||||||
team->main_thread = NULL;
|
team->main_thread = NULL;
|
||||||
team->loading_info = NULL;
|
team->loading_info = NULL;
|
||||||
@@ -1365,6 +1367,8 @@ exec_team(const char *path, int32 argCount, char * const *args,
|
|||||||
sem_delete_owned_sems(team->id);
|
sem_delete_owned_sems(team->id);
|
||||||
remove_images(team);
|
remove_images(team);
|
||||||
vfs_exec_io_context(team->io_context);
|
vfs_exec_io_context(team->io_context);
|
||||||
|
delete_realtime_sem_context(team->realtime_sem_context);
|
||||||
|
team->realtime_sem_context = NULL;
|
||||||
|
|
||||||
user_debug_finish_after_exec();
|
user_debug_finish_after_exec();
|
||||||
|
|
||||||
@@ -1485,6 +1489,16 @@ fork_team(void)
|
|||||||
goto err2;
|
goto err2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// duplicate the realtime sem context
|
||||||
|
if (parentTeam->realtime_sem_context) {
|
||||||
|
team->realtime_sem_context = clone_realtime_sem_context(
|
||||||
|
parentTeam->realtime_sem_context);
|
||||||
|
if (team->realtime_sem_context == NULL) {
|
||||||
|
status = B_NO_MEMORY;
|
||||||
|
goto err25;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// create an address space for this team
|
// create an address space for this team
|
||||||
status = vm_create_address_space(team->id, USER_BASE, USER_SIZE, false,
|
status = vm_create_address_space(team->id, USER_BASE, USER_SIZE, false,
|
||||||
&team->address_space);
|
&team->address_space);
|
||||||
@@ -1540,6 +1554,8 @@ fork_team(void)
|
|||||||
err4:
|
err4:
|
||||||
vm_delete_address_space(team->address_space);
|
vm_delete_address_space(team->address_space);
|
||||||
err3:
|
err3:
|
||||||
|
delete_realtime_sem_context(team->realtime_sem_context);
|
||||||
|
err25:
|
||||||
vfs_free_io_context(team->io_context);
|
vfs_free_io_context(team->io_context);
|
||||||
err2:
|
err2:
|
||||||
free(forkArgs);
|
free(forkArgs);
|
||||||
@@ -2327,6 +2343,7 @@ team_delete_team(struct team *team)
|
|||||||
// free team resources
|
// free team resources
|
||||||
|
|
||||||
vfs_free_io_context(team->io_context);
|
vfs_free_io_context(team->io_context);
|
||||||
|
delete_realtime_sem_context(team->realtime_sem_context);
|
||||||
delete_owned_ports(teamID);
|
delete_owned_ports(teamID);
|
||||||
sem_delete_owned_sems(teamID);
|
sem_delete_owned_sems(teamID);
|
||||||
remove_images(team);
|
remove_images(team);
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ MergeObject posix_main.o :
|
|||||||
inttypes.c
|
inttypes.c
|
||||||
poll.c
|
poll.c
|
||||||
$(PWD_BACKEND)
|
$(PWD_BACKEND)
|
||||||
|
semaphore.cpp
|
||||||
syslog.cpp
|
syslog.cpp
|
||||||
termios.c
|
termios.c
|
||||||
utime.c
|
utime.c
|
||||||
|
|||||||
@@ -0,0 +1,137 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <semaphore.h>
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <OS.h>
|
||||||
|
|
||||||
|
#include <AutoDeleter.h>
|
||||||
|
#include <realtime_sem.h>
|
||||||
|
#include <syscall_utils.h>
|
||||||
|
#include <syscalls.h>
|
||||||
|
|
||||||
|
|
||||||
|
sem_t*
|
||||||
|
sem_open(const char* name, int openFlags,...)
|
||||||
|
{
|
||||||
|
if (name == NULL) {
|
||||||
|
errno = B_BAD_VALUE;
|
||||||
|
return SEM_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the mode and semaphore count parameters, if O_CREAT is specified
|
||||||
|
mode_t mode = 0;
|
||||||
|
unsigned semCount = 0;
|
||||||
|
|
||||||
|
if ((openFlags & O_CREAT) != 0) {
|
||||||
|
va_list args;
|
||||||
|
va_start(args, openFlags);
|
||||||
|
mode = va_arg(args, mode_t);
|
||||||
|
semCount = va_arg(args, unsigned);
|
||||||
|
va_end(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocate a sem_t structure -- we don't know, whether this is the first
|
||||||
|
// call of this process to open the semaphore. If it is, we will keep the
|
||||||
|
// structure, otherwise we will delete it later.
|
||||||
|
sem_t* sem = (sem_t*)malloc(sizeof(sem_t));
|
||||||
|
if (sem == NULL) {
|
||||||
|
errno = B_NO_MEMORY;
|
||||||
|
return SEM_FAILED;
|
||||||
|
}
|
||||||
|
MemoryDeleter semDeleter(sem);
|
||||||
|
|
||||||
|
// ask the kernel to open the semaphore
|
||||||
|
sem_t* usedSem;
|
||||||
|
status_t error = _kern_realtime_sem_open(name, openFlags, mode, semCount,
|
||||||
|
sem, &usedSem);
|
||||||
|
if (error != B_OK) {
|
||||||
|
errno = error;
|
||||||
|
return SEM_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (usedSem == sem)
|
||||||
|
semDeleter.Detach();
|
||||||
|
|
||||||
|
return usedSem;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
sem_close(sem_t* semaphore)
|
||||||
|
{
|
||||||
|
sem_t* deleteSem = NULL;
|
||||||
|
status_t error = _kern_realtime_sem_close(semaphore->id, &deleteSem);
|
||||||
|
if (error == B_OK)
|
||||||
|
free(deleteSem);
|
||||||
|
|
||||||
|
RETURN_AND_SET_ERRNO(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
sem_unlink(const char* name)
|
||||||
|
{
|
||||||
|
RETURN_AND_SET_ERRNO(_kern_realtime_sem_unlink(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
sem_init(sem_t* semaphore, int shared, unsigned value)
|
||||||
|
{
|
||||||
|
RETURN_AND_SET_ERRNO(_kern_realtime_sem_open(NULL, 0, 0, value, semaphore,
|
||||||
|
NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
sem_destroy(sem_t* semaphore)
|
||||||
|
{
|
||||||
|
RETURN_AND_SET_ERRNO(_kern_realtime_sem_close(semaphore->id, NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
sem_post(sem_t* semaphore)
|
||||||
|
{
|
||||||
|
RETURN_AND_SET_ERRNO(_kern_realtime_sem_post(semaphore->id));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
sem_timedwait(sem_t* semaphore, const struct timespec* timeout)
|
||||||
|
{
|
||||||
|
bigtime_t timeoutMicros = ((bigtime_t)timeout->tv_sec) * 1000000
|
||||||
|
+ timeout->tv_nsec / 1000;
|
||||||
|
|
||||||
|
RETURN_AND_SET_ERRNO(_kern_realtime_sem_wait(semaphore->id, timeoutMicros));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
sem_trywait(sem_t* semaphore)
|
||||||
|
{
|
||||||
|
RETURN_AND_SET_ERRNO(_kern_realtime_sem_wait(semaphore->id, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
sem_wait(sem_t* semaphore)
|
||||||
|
{
|
||||||
|
RETURN_AND_SET_ERRNO(_kern_realtime_sem_wait(semaphore->id,
|
||||||
|
B_INFINITE_TIMEOUT));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
sem_getvalue(sem_t* semaphore, int* value)
|
||||||
|
{
|
||||||
|
RETURN_AND_SET_ERRNO(_kern_realtime_sem_get_value(semaphore->id, value));
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user