* Added some padding to the sem_t structure.
* Changed the semantics of unnamed semaphores. Before parent and child of a fork() would always share an earlier created semaphore. Now we do that only, if the "shared" parameter of sem_init() was true. That's still not quite the behavior Linux and Solaris have, but should be perfectly fine with how reasonable code would use the API. * There's a global table for shared unnamed semaphores now. ATM a semaphore is leaked when no one explicitly destroys it (just as with named sems). * Enforce per-team and global semaphore number limits. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@25362 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
01b1098795
commit
3dfe682f55
@ -5,12 +5,14 @@
|
||||
#ifndef _SEMAPHORE_H_
|
||||
#define _SEMAPHORE_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/cdefs.h>
|
||||
#include <time.h>
|
||||
|
||||
|
||||
typedef struct {
|
||||
int id;
|
||||
int32_t id;
|
||||
int32_t _padding[3];
|
||||
} sem_t;
|
||||
|
||||
#define SEM_FAILED ((sem_t*)(long)-1)
|
||||
|
@ -77,9 +77,9 @@ extern status_t _kern_get_next_sem_info(team_id team, int32 *cookie,
|
||||
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_open(const char* name,
|
||||
int openFlagsOrShared, 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);
|
||||
|
@ -29,33 +29,61 @@ class SemInfo {
|
||||
public:
|
||||
SemInfo()
|
||||
:
|
||||
fName(NULL),
|
||||
fRefCount(1),
|
||||
fID(-1)
|
||||
fSemaphoreID(-1)
|
||||
{
|
||||
}
|
||||
|
||||
~SemInfo()
|
||||
virtual ~SemInfo()
|
||||
{
|
||||
if (fSemaphoreID >= 0)
|
||||
delete_sem(fSemaphoreID);
|
||||
}
|
||||
|
||||
sem_id SemaphoreID() const { return fSemaphoreID; }
|
||||
|
||||
status_t Init(int32 semCount, const char* name)
|
||||
{
|
||||
fSemaphoreID = create_sem(semCount, name);
|
||||
if (fSemaphoreID < 0)
|
||||
return fSemaphoreID;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
virtual sem_id ID() const = 0;
|
||||
virtual SemInfo* Clone() = 0;
|
||||
virtual void Delete() = 0;
|
||||
|
||||
private:
|
||||
sem_id fSemaphoreID;
|
||||
};
|
||||
|
||||
|
||||
class NamedSem : public SemInfo {
|
||||
public:
|
||||
NamedSem()
|
||||
:
|
||||
fName(NULL),
|
||||
fRefCount(1)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~NamedSem()
|
||||
{
|
||||
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)
|
||||
{
|
||||
if (name != NULL) {
|
||||
fName = strdup(name);
|
||||
if (fName == NULL)
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
status_t error = SemInfo::Init(semCount, name);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
fID = create_sem(semCount, name);
|
||||
if (fID < 0)
|
||||
return fID;
|
||||
fName = strdup(name);
|
||||
if (fName == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
fUID = geteuid();
|
||||
fGID = getegid();
|
||||
@ -91,7 +119,23 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
HashTableLink<SemInfo>* HashTableLink()
|
||||
virtual sem_id ID() const
|
||||
{
|
||||
return SemaphoreID();
|
||||
}
|
||||
|
||||
virtual SemInfo* Clone()
|
||||
{
|
||||
AcquireReference();
|
||||
return this;
|
||||
}
|
||||
|
||||
virtual void Delete()
|
||||
{
|
||||
ReleaseReference();
|
||||
}
|
||||
|
||||
HashTableLink<NamedSem>* HashTableLink()
|
||||
{
|
||||
return &fHashLink;
|
||||
}
|
||||
@ -99,64 +143,192 @@ public:
|
||||
private:
|
||||
char* fName;
|
||||
vint32 fRefCount;
|
||||
sem_id fID;
|
||||
uid_t fUID;
|
||||
gid_t fGID;
|
||||
mode_t fPermissions;
|
||||
|
||||
::HashTableLink<SemInfo> fHashLink;
|
||||
::HashTableLink<NamedSem> fHashLink;
|
||||
};
|
||||
|
||||
|
||||
class UnnamedSem : public SemInfo {
|
||||
public:
|
||||
UnnamedSem()
|
||||
:
|
||||
fID(0)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~UnnamedSem()
|
||||
{
|
||||
}
|
||||
|
||||
status_t Init(int32 semCount, const char* name)
|
||||
{
|
||||
return SemInfo::Init(semCount, name);
|
||||
}
|
||||
|
||||
void SetID(sem_id id)
|
||||
{
|
||||
fID = id;
|
||||
}
|
||||
|
||||
virtual sem_id ID() const
|
||||
{
|
||||
return fID;
|
||||
}
|
||||
|
||||
virtual SemInfo* Clone()
|
||||
{
|
||||
sem_info info;
|
||||
if (get_sem_info(SemaphoreID(), &info) != B_OK)
|
||||
return NULL;
|
||||
|
||||
UnnamedSem* clone = new(std::nothrow) UnnamedSem;
|
||||
if (clone == NULL)
|
||||
return NULL;
|
||||
|
||||
if (clone->Init(info.count, info.name) != B_OK) {
|
||||
delete clone;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
clone->SetID(fID);
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
virtual void Delete()
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
private:
|
||||
sem_id fID;
|
||||
};
|
||||
|
||||
|
||||
class UnnamedSharedSem : public SemInfo {
|
||||
public:
|
||||
UnnamedSharedSem()
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~UnnamedSharedSem()
|
||||
{
|
||||
}
|
||||
|
||||
status_t Init(int32 semCount, const char* name)
|
||||
{
|
||||
return SemInfo::Init(semCount, name);
|
||||
}
|
||||
|
||||
virtual sem_id ID() const
|
||||
{
|
||||
return SemaphoreID();
|
||||
}
|
||||
|
||||
virtual SemInfo* Clone()
|
||||
{
|
||||
// Can't be cloned.
|
||||
return NULL;
|
||||
}
|
||||
|
||||
virtual void Delete()
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
HashTableLink<UnnamedSharedSem>* HashTableLink()
|
||||
{
|
||||
return &fHashLink;
|
||||
}
|
||||
|
||||
private:
|
||||
::HashTableLink<UnnamedSharedSem> fHashLink;
|
||||
};
|
||||
|
||||
|
||||
struct NamedSemHashDefinition {
|
||||
typedef const char* KeyType;
|
||||
typedef SemInfo ValueType;
|
||||
typedef NamedSem ValueType;
|
||||
|
||||
size_t HashKey(const KeyType& key) const
|
||||
{
|
||||
return hash_hash_string(key);
|
||||
}
|
||||
|
||||
size_t Hash(SemInfo* semaphore) const
|
||||
size_t Hash(NamedSem* semaphore) const
|
||||
{
|
||||
return HashKey(semaphore->Name());
|
||||
}
|
||||
|
||||
bool Compare(const KeyType& key, SemInfo* semaphore) const
|
||||
bool Compare(const KeyType& key, NamedSem* semaphore) const
|
||||
{
|
||||
return strcmp(key, semaphore->Name()) == 0;
|
||||
}
|
||||
|
||||
HashTableLink<SemInfo>* GetLink(SemInfo* semaphore) const
|
||||
HashTableLink<NamedSem>* GetLink(NamedSem* semaphore) const
|
||||
{
|
||||
return semaphore->HashTableLink();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class GlobalRealtimeSemTable {
|
||||
public:
|
||||
GlobalRealtimeSemTable()
|
||||
struct UnnamedSemHashDefinition {
|
||||
typedef sem_id KeyType;
|
||||
typedef UnnamedSharedSem ValueType;
|
||||
|
||||
size_t HashKey(const KeyType& key) const
|
||||
{
|
||||
mutex_init(&fLock, "global realtime sem table");
|
||||
return (size_t)key;
|
||||
}
|
||||
|
||||
~GlobalRealtimeSemTable()
|
||||
size_t Hash(UnnamedSharedSem* semaphore) const
|
||||
{
|
||||
return HashKey(semaphore->SemaphoreID());
|
||||
}
|
||||
|
||||
bool Compare(const KeyType& key, UnnamedSharedSem* semaphore) const
|
||||
{
|
||||
return key == semaphore->SemaphoreID();
|
||||
}
|
||||
|
||||
HashTableLink<UnnamedSharedSem>* GetLink(UnnamedSharedSem* semaphore) const
|
||||
{
|
||||
return semaphore->HashTableLink();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class GlobalSemTable {
|
||||
public:
|
||||
GlobalSemTable()
|
||||
:
|
||||
fSemaphoreCount(0)
|
||||
{
|
||||
mutex_init(&fLock, "global named sem table");
|
||||
}
|
||||
|
||||
~GlobalSemTable()
|
||||
{
|
||||
mutex_destroy(&fLock);
|
||||
}
|
||||
|
||||
status_t Init()
|
||||
{
|
||||
return fSemaphores.InitCheck();
|
||||
status_t error = fNamedSemaphores.InitCheck();
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
return fUnnamedSemaphores.InitCheck();
|
||||
}
|
||||
|
||||
status_t OpenSem(const char* name, int openFlags, mode_t mode,
|
||||
uint32 semCount, SemInfo*& _sem, bool& _created)
|
||||
status_t OpenNamedSem(const char* name, int openFlags, mode_t mode,
|
||||
uint32 semCount, NamedSem*& _sem, bool& _created)
|
||||
{
|
||||
MutexLocker _(fLock);
|
||||
|
||||
SemInfo* sem = fSemaphores.Lookup(name);
|
||||
NamedSem* sem = fNamedSemaphores.Lookup(name);
|
||||
if (sem != NULL) {
|
||||
if ((openFlags & O_EXCL) != 0)
|
||||
return EEXIST;
|
||||
@ -174,8 +346,10 @@ public:
|
||||
return ENOENT;
|
||||
|
||||
// does not exist yet -- create
|
||||
// TODO: Enforce per team semaphore limit!
|
||||
sem = new(std::nothrow) SemInfo;
|
||||
if (fSemaphoreCount >= MAX_POSIX_SEMS)
|
||||
return ENOSPC;
|
||||
|
||||
sem = new(std::nothrow) NamedSem;
|
||||
if (sem == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
@ -185,7 +359,7 @@ public:
|
||||
return error;
|
||||
}
|
||||
|
||||
error = fSemaphores.Insert(sem);
|
||||
error = fNamedSemaphores.Insert(sem);
|
||||
if (error != B_OK) {
|
||||
delete sem;
|
||||
return error;
|
||||
@ -194,38 +368,92 @@ public:
|
||||
// add one reference for the table
|
||||
sem->AcquireReference();
|
||||
|
||||
fSemaphoreCount++;
|
||||
|
||||
_sem = sem;
|
||||
_created = true;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t UnlinkSem(const char* name)
|
||||
status_t UnlinkNamedSem(const char* name)
|
||||
{
|
||||
MutexLocker _(fLock);
|
||||
|
||||
SemInfo* sem = fSemaphores.Lookup(name);
|
||||
NamedSem* sem = fNamedSemaphores.Lookup(name);
|
||||
if (sem == NULL)
|
||||
return ENOENT;
|
||||
|
||||
if (!sem->HasPermissions())
|
||||
return EACCES;
|
||||
|
||||
fSemaphores.Remove(sem);
|
||||
fNamedSemaphores.Remove(sem);
|
||||
sem->ReleaseReference();
|
||||
// release the table reference
|
||||
fSemaphoreCount--;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
typedef OpenHashTable<NamedSemHashDefinition, true> SemTable;
|
||||
status_t CreateUnnamedSem(uint32 semCount, int32_t& _id)
|
||||
{
|
||||
MutexLocker _(fLock);
|
||||
|
||||
mutex fLock;
|
||||
SemTable fSemaphores;
|
||||
if (fSemaphoreCount >= MAX_POSIX_SEMS)
|
||||
return ENOSPC;
|
||||
|
||||
UnnamedSharedSem* sem = new(std::nothrow) UnnamedSharedSem;
|
||||
if (sem == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
status_t error = sem->Init(semCount, "unnamed shared sem");
|
||||
if (error == B_OK)
|
||||
error = fUnnamedSemaphores.Insert(sem);
|
||||
if (error != B_OK) {
|
||||
delete sem;
|
||||
return error;
|
||||
}
|
||||
|
||||
fSemaphoreCount++;
|
||||
|
||||
_id = sem->SemaphoreID();
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t DeleteUnnamedSem(sem_id id)
|
||||
{
|
||||
MutexLocker _(fLock);
|
||||
|
||||
UnnamedSharedSem* sem = fUnnamedSemaphores.Lookup(id);
|
||||
if (sem == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
fUnnamedSemaphores.Remove(sem);
|
||||
delete sem;
|
||||
|
||||
fSemaphoreCount--;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
bool IsUnnamedValidSem(sem_id id)
|
||||
{
|
||||
MutexLocker _(fLock);
|
||||
|
||||
return fUnnamedSemaphores.Lookup(id) != NULL;
|
||||
}
|
||||
|
||||
private:
|
||||
typedef OpenHashTable<NamedSemHashDefinition, true> NamedSemTable;
|
||||
typedef OpenHashTable<UnnamedSemHashDefinition, true> UnnamedSemTable;
|
||||
|
||||
mutex fLock;
|
||||
NamedSemTable fNamedSemaphores;
|
||||
UnnamedSemTable fUnnamedSemaphores;
|
||||
int32 fSemaphoreCount;
|
||||
};
|
||||
|
||||
|
||||
static GlobalRealtimeSemTable sSemTable;
|
||||
static GlobalSemTable sSemTable;
|
||||
|
||||
|
||||
class TeamSemInfo {
|
||||
@ -241,10 +469,11 @@ public:
|
||||
~TeamSemInfo()
|
||||
{
|
||||
if (fSemaphore != NULL)
|
||||
fSemaphore->ReleaseReference();
|
||||
fSemaphore->Delete();
|
||||
}
|
||||
|
||||
SemInfo* Semaphore() const { return fSemaphore; }
|
||||
sem_id ID() const { return fSemaphore->ID(); }
|
||||
sem_id SemaphoreID() const { return fSemaphore->SemaphoreID(); }
|
||||
sem_t* UserSemaphore() const { return fUserSemaphore; }
|
||||
|
||||
void Open()
|
||||
@ -259,15 +488,19 @@ public:
|
||||
|
||||
TeamSemInfo* Clone() const
|
||||
{
|
||||
TeamSemInfo* sem = new(std::nothrow) TeamSemInfo(fSemaphore,
|
||||
fUserSemaphore);
|
||||
SemInfo* sem = fSemaphore->Clone();
|
||||
if (sem == NULL)
|
||||
return NULL;
|
||||
|
||||
sem->fOpenCount = fOpenCount;
|
||||
fSemaphore->AcquireReference();
|
||||
TeamSemInfo* clone = new(std::nothrow) TeamSemInfo(sem, fUserSemaphore);
|
||||
if (clone == NULL) {
|
||||
sem->Delete();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return sem;
|
||||
clone->fOpenCount = fOpenCount;
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
HashTableLink<TeamSemInfo>* HashTableLink()
|
||||
@ -295,12 +528,12 @@ struct TeamSemHashDefinition {
|
||||
|
||||
size_t Hash(TeamSemInfo* semaphore) const
|
||||
{
|
||||
return HashKey(semaphore->Semaphore()->ID());
|
||||
return HashKey(semaphore->ID());
|
||||
}
|
||||
|
||||
bool Compare(const KeyType& key, TeamSemInfo* semaphore) const
|
||||
{
|
||||
return key == semaphore->Semaphore()->ID();
|
||||
return key == semaphore->ID();
|
||||
}
|
||||
|
||||
HashTableLink<TeamSemInfo>* GetLink(TeamSemInfo* semaphore) const
|
||||
@ -312,6 +545,8 @@ struct TeamSemHashDefinition {
|
||||
|
||||
struct realtime_sem_context {
|
||||
realtime_sem_context()
|
||||
:
|
||||
fSemaphoreCount(0)
|
||||
{
|
||||
mutex_init(&fLock, "realtime sem context");
|
||||
}
|
||||
@ -334,6 +569,7 @@ struct realtime_sem_context {
|
||||
|
||||
status_t Init()
|
||||
{
|
||||
fNextPrivateSemID = -1;
|
||||
return fSemaphores.InitCheck();
|
||||
}
|
||||
|
||||
@ -347,6 +583,8 @@ struct realtime_sem_context {
|
||||
|
||||
MutexLocker _(fLock);
|
||||
|
||||
context->fNextPrivateSemID = fNextPrivateSemID;
|
||||
|
||||
// clone all semaphores
|
||||
SemTable::Iterator it = fSemaphores.GetIterator();
|
||||
while (TeamSemInfo* sem = it.Next()) {
|
||||
@ -358,21 +596,24 @@ struct realtime_sem_context {
|
||||
delete clonedSem;
|
||||
return NULL;
|
||||
}
|
||||
context->fSemaphoreCount++;
|
||||
}
|
||||
|
||||
contextDeleter.Detach();
|
||||
return context;
|
||||
}
|
||||
|
||||
status_t CreateAnonymousSem(uint32 semCount, int& _id)
|
||||
status_t CreateUnnamedSem(uint32 semCount, bool shared, int32_t& _id)
|
||||
{
|
||||
// TODO: Enforce per team semaphore limit!
|
||||
SemInfo* sem = new(std::nothrow) SemInfo;
|
||||
if (shared)
|
||||
return sSemTable.CreateUnnamedSem(semCount, _id);
|
||||
|
||||
UnnamedSem* sem = new(std::nothrow) UnnamedSem;
|
||||
if (sem == NULL)
|
||||
return B_NO_MEMORY;
|
||||
ObjectDeleter<SemInfo> semDeleter(sem);
|
||||
ObjectDeleter<UnnamedSem> semDeleter(sem);
|
||||
|
||||
status_t error = sem->Init(NULL, 0, semCount);
|
||||
status_t error = sem->Init(semCount, "unnamed sem");
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
@ -383,23 +624,31 @@ struct realtime_sem_context {
|
||||
|
||||
MutexLocker _(fLock);
|
||||
|
||||
if (fSemaphoreCount >= MAX_POSIX_SEMS_PER_TEAM) {
|
||||
delete teamSem;
|
||||
return ENOSPC;
|
||||
}
|
||||
|
||||
sem->SetID(_NextPrivateSemID());
|
||||
|
||||
error = fSemaphores.Insert(teamSem);
|
||||
if (error != B_OK) {
|
||||
delete teamSem;
|
||||
return error;
|
||||
}
|
||||
|
||||
_id = teamSem->Semaphore()->ID();
|
||||
fSemaphoreCount++;
|
||||
|
||||
_id = teamSem->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,
|
||||
uint32 semCount, sem_t* userSem, sem_t*& _usedUserSem, int32_t& _id,
|
||||
bool& _created)
|
||||
{
|
||||
SemInfo* sem;
|
||||
status_t error = sSemTable.OpenSem(name, openFlags, mode, semCount,
|
||||
NamedSem* sem;
|
||||
status_t error = sSemTable.OpenNamedSem(name, openFlags, mode, semCount,
|
||||
sem, _created);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
@ -412,16 +661,25 @@ struct realtime_sem_context {
|
||||
teamSem->Open();
|
||||
sem->ReleaseReference();
|
||||
_usedUserSem = teamSem->UserSemaphore();
|
||||
_id = teamSem->Semaphore()->ID();
|
||||
_id = teamSem->ID();
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
// not open yet -- create a new team sem
|
||||
|
||||
// first check the semaphore limit, though
|
||||
if (fSemaphoreCount >= MAX_POSIX_SEMS_PER_TEAM) {
|
||||
sem->ReleaseReference();
|
||||
if (_created)
|
||||
sSemTable.UnlinkNamedSem(name);
|
||||
return ENOSPC;
|
||||
}
|
||||
|
||||
teamSem = new(std::nothrow) TeamSemInfo(sem, userSem);
|
||||
if (teamSem == NULL) {
|
||||
sem->ReleaseReference();
|
||||
if (_created)
|
||||
sSemTable.UnlinkSem(name);
|
||||
sSemTable.UnlinkNamedSem(name);
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
|
||||
@ -429,12 +687,14 @@ struct realtime_sem_context {
|
||||
if (error != B_OK) {
|
||||
delete teamSem;
|
||||
if (_created)
|
||||
sSemTable.UnlinkSem(name);
|
||||
sSemTable.UnlinkNamedSem(name);
|
||||
return error;
|
||||
}
|
||||
|
||||
fSemaphoreCount++;
|
||||
|
||||
_usedUserSem = teamSem->UserSemaphore();
|
||||
_id = teamSem->Semaphore()->ID();
|
||||
_id = teamSem->ID();
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
@ -447,11 +707,12 @@ struct realtime_sem_context {
|
||||
|
||||
TeamSemInfo* sem = fSemaphores.Lookup(id);
|
||||
if (sem == NULL)
|
||||
return B_BAD_VALUE;
|
||||
return sSemTable.DeleteUnnamedSem(id);
|
||||
|
||||
if (sem->Close()) {
|
||||
// last reference closed
|
||||
fSemaphores.Remove(sem);
|
||||
fSemaphoreCount--;
|
||||
deleteUserSem = sem->UserSemaphore();
|
||||
delete sem;
|
||||
}
|
||||
@ -463,8 +724,12 @@ struct realtime_sem_context {
|
||||
{
|
||||
MutexLocker locker(fLock);
|
||||
|
||||
if (fSemaphores.Lookup(id) == NULL)
|
||||
return B_BAD_VALUE;
|
||||
TeamSemInfo* sem = fSemaphores.Lookup(id);
|
||||
if (sem == NULL) {
|
||||
if (!sSemTable.IsUnnamedValidSem(id))
|
||||
return B_BAD_VALUE;
|
||||
} else
|
||||
id = sem->SemaphoreID();
|
||||
|
||||
locker.Unlock();
|
||||
|
||||
@ -487,8 +752,12 @@ struct realtime_sem_context {
|
||||
{
|
||||
MutexLocker locker(fLock);
|
||||
|
||||
if (fSemaphores.Lookup(id) == NULL)
|
||||
return B_BAD_VALUE;
|
||||
TeamSemInfo* sem = fSemaphores.Lookup(id);
|
||||
if (sem == NULL) {
|
||||
if (!sSemTable.IsUnnamedValidSem(id))
|
||||
return B_BAD_VALUE;
|
||||
} else
|
||||
id = sem->SemaphoreID();
|
||||
|
||||
locker.Unlock();
|
||||
|
||||
@ -500,8 +769,12 @@ struct realtime_sem_context {
|
||||
{
|
||||
MutexLocker locker(fLock);
|
||||
|
||||
if (fSemaphores.Lookup(id) == NULL)
|
||||
return B_BAD_VALUE;
|
||||
TeamSemInfo* sem = fSemaphores.Lookup(id);
|
||||
if (sem == NULL) {
|
||||
if (!sSemTable.IsUnnamedValidSem(id))
|
||||
return B_BAD_VALUE;
|
||||
} else
|
||||
id = sem->SemaphoreID();
|
||||
|
||||
locker.Unlock();
|
||||
|
||||
@ -514,11 +787,26 @@ struct realtime_sem_context {
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
sem_id _NextPrivateSemID()
|
||||
{
|
||||
while (true) {
|
||||
if (fNextPrivateSemID >= 0)
|
||||
fNextPrivateSemID = -1;
|
||||
|
||||
sem_id id = fNextPrivateSemID--;
|
||||
if (fSemaphores.Lookup(id) == NULL)
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
typedef OpenHashTable<TeamSemHashDefinition, true> SemTable;
|
||||
|
||||
mutex fLock;
|
||||
SemTable fSemaphores;
|
||||
int32 fSemaphoreCount;
|
||||
sem_id fNextPrivateSemID;
|
||||
};
|
||||
|
||||
|
||||
@ -585,9 +873,9 @@ copy_sem_name_to_kernel(const char* userName, KPath& buffer, char*& name)
|
||||
void
|
||||
realtime_sem_init()
|
||||
{
|
||||
new(&sSemTable) GlobalRealtimeSemTable;
|
||||
new(&sSemTable) GlobalSemTable;
|
||||
if (sSemTable.Init() != B_OK)
|
||||
panic("realtime_sem_init() failed to init global table");
|
||||
panic("realtime_sem_init() failed to init global sem table");
|
||||
}
|
||||
|
||||
|
||||
@ -612,23 +900,27 @@ clone_realtime_sem_context(realtime_sem_context* context)
|
||||
|
||||
|
||||
status_t
|
||||
_user_realtime_sem_open(const char* userName, int openFlags, mode_t mode,
|
||||
uint32 semCount, sem_t* userSem, sem_t** _usedUserSem)
|
||||
_user_realtime_sem_open(const char* userName, int openFlagsOrShared,
|
||||
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;
|
||||
|
||||
if (semCount > MAX_POSIX_SEM_VALUE)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
// 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
|
||||
// unnamed semaphores are less work -- deal with them first
|
||||
if (userName == NULL) {
|
||||
int id;
|
||||
status_t error = context->CreateAnonymousSem(semCount, id);
|
||||
int32_t id;
|
||||
status_t error = context->CreateUnnamedSem(semCount, openFlagsOrShared,
|
||||
id);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
@ -657,8 +949,8 @@ _user_realtime_sem_open(const char* userName, int openFlags, mode_t mode,
|
||||
// open the semaphore
|
||||
sem_t* usedUserSem;
|
||||
bool created;
|
||||
int id;
|
||||
error = context->OpenSem(name, openFlags, mode, semCount, userSem,
|
||||
int32_t id;
|
||||
error = context->OpenSem(name, openFlagsOrShared, mode, semCount, userSem,
|
||||
usedUserSem, id, created);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
@ -667,7 +959,7 @@ _user_realtime_sem_open(const char* userName, int openFlags, mode_t mode,
|
||||
if (user_memcpy(&userSem->id, &id, sizeof(int)) != B_OK
|
||||
|| user_memcpy(_usedUserSem, &usedUserSem, sizeof(sem_t*)) != B_OK) {
|
||||
if (created)
|
||||
sSemTable.UnlinkSem(name);
|
||||
sSemTable.UnlinkNamedSem(name);
|
||||
sem_t* dummy;
|
||||
context->CloseSem(id, dummy);
|
||||
return B_BAD_ADDRESS;
|
||||
@ -714,7 +1006,7 @@ _user_realtime_sem_unlink(const char* userName)
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
return sSemTable.UnlinkSem(name);
|
||||
return sSemTable.UnlinkNamedSem(name);
|
||||
}
|
||||
|
||||
|
||||
|
@ -89,8 +89,8 @@ sem_unlink(const char* 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));
|
||||
RETURN_AND_SET_ERRNO(_kern_realtime_sem_open(NULL, shared, 0, value,
|
||||
semaphore, NULL));
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user