mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-21 17:31:17 +00:00
Add OS-abstracted semaphore primitive
* Uses POSIX sem on linux/android, dispatch semaphores on apple, Win32 Semaphores on windows.
This commit is contained in:
@@ -146,6 +146,17 @@ uint64_t AllocateTLSSlot();
|
||||
void *GetTLSValue(uint64_t slot);
|
||||
void SetTLSValue(uint64_t slot, void *value);
|
||||
|
||||
struct Semaphore
|
||||
{
|
||||
static Semaphore *Create();
|
||||
void Destroy();
|
||||
void Wake(uint32_t numToWake);
|
||||
void WaitForWake();
|
||||
protected:
|
||||
Semaphore();
|
||||
~Semaphore();
|
||||
};
|
||||
|
||||
// must typedef CriticalSectionTemplate<X> CriticalSection
|
||||
|
||||
void SetCurrentThreadName(const rdcstr &name);
|
||||
|
||||
@@ -24,6 +24,10 @@
|
||||
|
||||
#include "os/os_specific.h"
|
||||
|
||||
#include "common/common.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <semaphore.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
@@ -42,3 +46,67 @@ uint64_t Timing::GetTick()
|
||||
void Threading::SetCurrentThreadName(const rdcstr &name)
|
||||
{
|
||||
}
|
||||
|
||||
namespace Threading
|
||||
{
|
||||
|
||||
// works for all posix except apple, hence being here
|
||||
struct PosixSemaphore : public Semaphore
|
||||
{
|
||||
~PosixSemaphore() {}
|
||||
|
||||
sem_t h;
|
||||
};
|
||||
|
||||
Semaphore *Semaphore::Create()
|
||||
{
|
||||
PosixSemaphore *sem = new PosixSemaphore();
|
||||
int err = sem_init(&sem->h, 0, 0);
|
||||
// only documented errors are too large initial value (impossible for 0) or for shared semaphores
|
||||
// going wrong (we're not shared)
|
||||
RDCASSERT(err == 0, errno);
|
||||
return sem;
|
||||
}
|
||||
|
||||
void Semaphore::Destroy()
|
||||
{
|
||||
PosixSemaphore *sem = (PosixSemaphore *)this;
|
||||
sem_destroy(&sem->h);
|
||||
delete sem;
|
||||
}
|
||||
|
||||
void Semaphore::Wake(uint32_t numToWake)
|
||||
{
|
||||
PosixSemaphore *sem = (PosixSemaphore *)this;
|
||||
for(uint32_t i = 0; i < numToWake; i++)
|
||||
sem_post(&sem->h);
|
||||
}
|
||||
|
||||
void Semaphore::WaitForWake()
|
||||
{
|
||||
PosixSemaphore *sem = (PosixSemaphore *)this;
|
||||
|
||||
// handle extremely moronic stupid signal interruptions
|
||||
do
|
||||
{
|
||||
int ret = sem_wait(&sem->h);
|
||||
|
||||
if(ret == -1)
|
||||
{
|
||||
if(errno == EINTR)
|
||||
continue;
|
||||
|
||||
RDCWARN("Semaphore wait failed: %d", errno);
|
||||
}
|
||||
} while(false);
|
||||
}
|
||||
|
||||
Semaphore::Semaphore()
|
||||
{
|
||||
}
|
||||
|
||||
Semaphore::~Semaphore()
|
||||
{
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
#include "os/os_specific.h"
|
||||
|
||||
#include <dispatch/dispatch.h>
|
||||
#include <mach/mach_time.h>
|
||||
|
||||
double Timing::GetTickFrequency()
|
||||
@@ -44,3 +45,51 @@ uint64_t Timing::GetTick()
|
||||
void Threading::SetCurrentThreadName(const rdcstr &name)
|
||||
{
|
||||
}
|
||||
|
||||
namespace Threading
|
||||
{
|
||||
|
||||
struct AppleSemaphore : public Semaphore
|
||||
{
|
||||
~AppleSemaphore() {}
|
||||
|
||||
dispatch_semaphore_t h;
|
||||
};
|
||||
|
||||
Semaphore *Semaphore::Create()
|
||||
{
|
||||
AppleSemaphore *sem = new AppleSemaphore();
|
||||
sem->h = dispatch_semaphore_create(0);
|
||||
return sem;
|
||||
}
|
||||
|
||||
void Semaphore::Destroy()
|
||||
{
|
||||
AppleSemaphore *sem = (AppleSemaphore *)this;
|
||||
dispatch_release(sem->h);
|
||||
delete sem;
|
||||
}
|
||||
|
||||
void Semaphore::Wake(uint32_t numToWake)
|
||||
{
|
||||
AppleSemaphore *sem = (AppleSemaphore *)this;
|
||||
for(uint32_t i = 0; i < numToWake; i++)
|
||||
dispatch_semaphore_signal(sem->h);
|
||||
}
|
||||
|
||||
void Semaphore::WaitForWake()
|
||||
{
|
||||
AppleSemaphore *sem = (AppleSemaphore *)this;
|
||||
// no timeout, so no point checking return value as that's the only failure case
|
||||
dispatch_semaphore_wait(sem->h, DISPATCH_TIME_FOREVER);
|
||||
}
|
||||
|
||||
Semaphore::Semaphore()
|
||||
{
|
||||
}
|
||||
|
||||
Semaphore::~Semaphore()
|
||||
{
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@@ -24,6 +24,10 @@
|
||||
|
||||
#include "os/os_specific.h"
|
||||
|
||||
#include "common/common.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <semaphore.h>
|
||||
#include <sys/prctl.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
@@ -44,3 +48,67 @@ void Threading::SetCurrentThreadName(const rdcstr &name)
|
||||
{
|
||||
prctl(PR_SET_NAME, (unsigned long)name.c_str(), 0, 0, 0);
|
||||
}
|
||||
|
||||
namespace Threading
|
||||
{
|
||||
|
||||
// works for all posix except apple, hence being here
|
||||
struct PosixSemaphore : public Semaphore
|
||||
{
|
||||
~PosixSemaphore() {}
|
||||
|
||||
sem_t h;
|
||||
};
|
||||
|
||||
Semaphore *Semaphore::Create()
|
||||
{
|
||||
PosixSemaphore *sem = new PosixSemaphore();
|
||||
int err = sem_init(&sem->h, 0, 0);
|
||||
// only documented errors are too large initial value (impossible for 0) or for shared semaphores
|
||||
// going wrong (we're not shared)
|
||||
RDCASSERT(err == 0, errno);
|
||||
return sem;
|
||||
}
|
||||
|
||||
void Semaphore::Destroy()
|
||||
{
|
||||
PosixSemaphore *sem = (PosixSemaphore *)this;
|
||||
sem_destroy(&sem->h);
|
||||
delete sem;
|
||||
}
|
||||
|
||||
void Semaphore::Wake(uint32_t numToWake)
|
||||
{
|
||||
PosixSemaphore *sem = (PosixSemaphore *)this;
|
||||
for(uint32_t i = 0; i < numToWake; i++)
|
||||
sem_post(&sem->h);
|
||||
}
|
||||
|
||||
void Semaphore::WaitForWake()
|
||||
{
|
||||
PosixSemaphore *sem = (PosixSemaphore *)this;
|
||||
|
||||
// handle extremely moronic stupid signal interruptions
|
||||
do
|
||||
{
|
||||
int ret = sem_wait(&sem->h);
|
||||
|
||||
if(ret == -1)
|
||||
{
|
||||
if(errno == EINTR)
|
||||
continue;
|
||||
|
||||
RDCWARN("Semaphore wait failed: %d", errno);
|
||||
}
|
||||
} while(false);
|
||||
}
|
||||
|
||||
Semaphore::Semaphore()
|
||||
{
|
||||
}
|
||||
|
||||
Semaphore::~Semaphore()
|
||||
{
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@@ -368,4 +368,48 @@ void Sleep(uint32_t milliseconds)
|
||||
{
|
||||
::Sleep((DWORD)milliseconds);
|
||||
}
|
||||
|
||||
struct Win32Semaphore : public Semaphore
|
||||
{
|
||||
~Win32Semaphore() {}
|
||||
|
||||
HANDLE h;
|
||||
};
|
||||
|
||||
Semaphore *Semaphore::Create()
|
||||
{
|
||||
Win32Semaphore *sem = new Win32Semaphore();
|
||||
sem->h = CreateSemaphore(NULL, 0, 0xffff, NULL);
|
||||
return sem;
|
||||
}
|
||||
|
||||
void Semaphore::Destroy()
|
||||
{
|
||||
Win32Semaphore *sem = (Win32Semaphore *)this;
|
||||
CloseHandle(sem->h);
|
||||
delete sem;
|
||||
}
|
||||
|
||||
void Semaphore::Wake(uint32_t numToWake)
|
||||
{
|
||||
Win32Semaphore *sem = (Win32Semaphore *)this;
|
||||
ReleaseSemaphore(sem->h, numToWake, NULL);
|
||||
}
|
||||
|
||||
void Semaphore::WaitForWake()
|
||||
{
|
||||
Win32Semaphore *sem = (Win32Semaphore *)this;
|
||||
DWORD err = WaitForSingleObject(sem->h, INFINITE);
|
||||
if(err == WAIT_FAILED)
|
||||
RDCWARN("Semaphore failed to sleep: %d", GetLastError());
|
||||
}
|
||||
|
||||
Semaphore::Semaphore()
|
||||
{
|
||||
}
|
||||
|
||||
Semaphore::~Semaphore()
|
||||
{
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user