Initial commit
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
# libsst-concurrency/Source/Makefile
|
||||
# Author: Patrick Baggett <ptbaggett@762studios.com>
|
||||
# Created: 12/23/2011
|
||||
#
|
||||
# Purpose:
|
||||
#
|
||||
# Makefile for libsst-concurrency
|
||||
#
|
||||
# License:
|
||||
#
|
||||
# This program is free software. It comes without any warranty, to
|
||||
# the extent permitted by applicable law. You can redistribute it
|
||||
# and/or modify it under the terms of the Do What The Fuck You Want
|
||||
# To Public License, Version 2, as published by Sam Hocevar. See
|
||||
# http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
|
||||
BINNAME := $(DIST)/libsst-concurrency.a
|
||||
ifeq ($(TARGET),debug)
|
||||
BINNAME := $(subst .a,_d.a, $(BINNAME))
|
||||
endif
|
||||
|
||||
include sources-$(SUBSYSTEM).mk
|
||||
include sources-common.mk
|
||||
|
||||
OBJ := $(addprefix obj/$(ARCH)/$(TARGET)/,$(subst .c,.o,$(SRC)) )
|
||||
|
||||
$(shell mkdir -p obj/$(ARCH)/$(TARGET))
|
||||
|
||||
$(BINNAME): $(OBJ)
|
||||
$(AR) cru $@ $+
|
||||
$(RANLIB) $@
|
||||
|
||||
# CLEAN
|
||||
clean:
|
||||
@-rm -r -f obj $(DIST)/libsst-concurrency*.a
|
||||
|
||||
# *.c files to *.o files
|
||||
obj/$(ARCH)/$(TARGET)/%.o: %.c
|
||||
@echo CC $@
|
||||
@$(CC) $(CFLAGS) -c $*.c -o obj/$(ARCH)/$(TARGET)/$*.o
|
||||
|
||||
|
||||
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
SST_Event_POSIX.c
|
||||
Author: Patrick Baggett <ptbaggett@762studios.com>
|
||||
Created: 12/20/2011
|
||||
|
||||
Purpose:
|
||||
|
||||
libsst-concurrency event functions for POSIX platforms
|
||||
|
||||
License:
|
||||
|
||||
This program is free software. It comes without any warranty, to
|
||||
the extent permitted by applicable law. You can redistribute it
|
||||
and/or modify it under the terms of the Do What The Fuck You Want
|
||||
To Public License, Version 2, as published by Sam Hocevar. See
|
||||
http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
|
||||
*/
|
||||
#include <SST/SST_Event.h> /* Functions being implemented */
|
||||
#include <SST/SST_Concurrency.h> /* SST_WAIT_INFINITE constant */
|
||||
#include <pthread.h> /* POSIX concurrency */
|
||||
#include <time.h> /* clock_gettime() */
|
||||
#include <stdlib.h> /* malloc()/free() */
|
||||
#include "timespecadd.h" /* inline function to add timespec*/
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
/******************************************************************************/
|
||||
|
||||
typedef struct UnixEvent
|
||||
{
|
||||
pthread_mutex_t lock;
|
||||
pthread_cond_t cond;
|
||||
volatile int signaled;
|
||||
} UnixEvent;
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
SST_Event SST_Concurrency_CreateEvent(void)
|
||||
{
|
||||
UnixEvent* ev = (UnixEvent*)malloc(sizeof(UnixEvent));
|
||||
|
||||
pthread_mutex_init(&ev->lock, NULL);
|
||||
pthread_cond_init(&ev->cond, NULL);
|
||||
ev->signaled = 0;
|
||||
|
||||
return (SST_Event)ev;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void SST_Concurrency_DestroyEvent(SST_Event _event)
|
||||
{
|
||||
UnixEvent* ev = (UnixEvent*)_event;
|
||||
|
||||
pthread_mutex_destroy(&ev->lock);
|
||||
pthread_cond_destroy(&ev->cond);
|
||||
free(ev);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void SST_Concurrency_SignalEvent(SST_Event _event)
|
||||
{
|
||||
UnixEvent* ev = (UnixEvent*)_event;
|
||||
|
||||
pthread_mutex_lock(&ev->lock);
|
||||
|
||||
ev->signaled = 1;
|
||||
|
||||
pthread_cond_broadcast(&ev->cond);
|
||||
pthread_mutex_unlock(&ev->lock);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void SST_Concurrency_ResetEvent(SST_Event _event)
|
||||
{
|
||||
UnixEvent* ev = (UnixEvent*)_event;
|
||||
|
||||
/* TODO: Optimization opportunity here: These locks aren't needed except to serialize set/reset calls. However,
|
||||
if we can leave the behavior 'undefined' for concurrent set/reset, then all that is needed is a set + membar. */
|
||||
pthread_mutex_lock(&ev->lock);
|
||||
ev->signaled = 0;
|
||||
pthread_mutex_unlock(&ev->lock);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
int SST_Concurrency_WaitEvent(SST_Event _event, uint32_t _ticks)
|
||||
{
|
||||
int result = 0;
|
||||
UnixEvent* ev = (UnixEvent*)_event;
|
||||
|
||||
pthread_mutex_lock(&ev->lock);
|
||||
|
||||
/* Infinite wait */
|
||||
if(_ticks == SST_WAIT_INFINITE)
|
||||
{
|
||||
while(ev->signaled == 0)
|
||||
pthread_cond_wait(&ev->cond, &ev->lock);
|
||||
|
||||
result = 1;
|
||||
}
|
||||
else /* Maximum wait measured in milliseconds */
|
||||
{
|
||||
struct timespec ts, tswait;
|
||||
int retval = 0;
|
||||
|
||||
#ifdef __APPLE__
|
||||
/* Less precise, but getting nanosecond precision out of mach was proving exceedingly painful.*/
|
||||
struct timeval tv;
|
||||
struct timezone tz;
|
||||
tz.tz_minuteswest = 0; tz.tz_dsttime = 0;
|
||||
gettimeofday(&tv, &tz);
|
||||
ts.tv_sec = tv.tv_sec;
|
||||
ts.tv_nsec = tv.tv_usec * 1000;
|
||||
#else
|
||||
clock_gettime(CLOCK_REALTIME, &ts);
|
||||
#endif
|
||||
tswait.tv_sec = (_ticks / 1000); /* add whole seconds */
|
||||
tswait.tv_nsec = (_ticks % 1000) * 1000 * 1000; /* add remaining milliseconds (converted to nanosecs by factor of 10^6) */
|
||||
|
||||
_sst_add_timespec(&ts, &tswait);
|
||||
|
||||
/* timedwait() returns 0 on success, and non-zero on failure. Spurious wakeups return 0 (success)
|
||||
while timeouts don't. A spurious wakeup won't have ev->signaled though, so it will go back to waiting */
|
||||
while(retval == 0 && ev->signaled == 0)
|
||||
retval = pthread_cond_timedwait(&ev->cond, &ev->lock, &ts);
|
||||
|
||||
/* If this returned success, then the condition is met AND the timeout did not expire -> success */
|
||||
result = (retval == 0);
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&ev->lock);
|
||||
return result;
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
SST_Event_Solaris.c
|
||||
Author: Patrick Baggett <ptbaggett@762studios.com>
|
||||
Created: 4/11/2012
|
||||
|
||||
Purpose:
|
||||
|
||||
libsst-concurrency event functions using native Solaris primitives
|
||||
|
||||
License:
|
||||
|
||||
This program is free software. It comes without any warranty, to
|
||||
the extent permitted by applicable law. You can redistribute it
|
||||
and/or modify it under the terms of the Do What The Fuck You Want
|
||||
To Public License, Version 2, as published by Sam Hocevar. See
|
||||
http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
|
||||
*/
|
||||
#include <SST/SST_Event.h> /* Functions being implemented */
|
||||
#include <SST/SST_Concurrency.h> /* SST_WAIT_INFINITE constant */
|
||||
#include <thread.h> /* POSIX concurrency */
|
||||
#include <time.h> /* clock_gettime() */
|
||||
#include <stdlib.h> /* malloc()/free() */
|
||||
#include "timespecadd.h" /* inline function to add timespec*/
|
||||
#include <atomic.h> /* membar_producer() */
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
typedef struct SolarisEvent
|
||||
{
|
||||
mutex_t lock;
|
||||
cond_t cond;
|
||||
volatile int signaled;
|
||||
} SolarisEvent;
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
SST_Event SST_Concurrency_CreateEvent(void)
|
||||
{
|
||||
SolarisEvent* ev = (SolarisEvent*)malloc(sizeof(SolarisEvent));
|
||||
|
||||
mutex_init(&ev->lock, USYNC_THREAD, NULL);
|
||||
cond_init(&ev->cond, USYNC_THREAD, NULL);
|
||||
ev->signaled = 0;
|
||||
|
||||
return (SST_Event)ev;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void SST_Concurrency_DestroyEvent(SST_Event _event)
|
||||
{
|
||||
SolarisEvent* ev = (SolarisEvent*)_event;
|
||||
|
||||
mutex_destroy(&ev->lock);
|
||||
cond_destroy(&ev->cond);
|
||||
free(ev);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void SST_Concurrency_SignalEvent(SST_Event _event)
|
||||
{
|
||||
SolarisEvent* ev = (SolarisEvent*)_event;
|
||||
|
||||
mutex_lock(&ev->lock);
|
||||
|
||||
ev->signaled = 1;
|
||||
|
||||
cond_broadcast(&ev->cond);
|
||||
mutex_unlock(&ev->lock);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void SST_Concurrency_ResetEvent(SST_Event _event)
|
||||
{
|
||||
SolarisEvent* ev = (SolarisEvent*)_event;
|
||||
|
||||
|
||||
ev->signaled = 0;
|
||||
membar_producer(); /* all stores reach global visibility before new stores */
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
int SST_Concurrency_WaitEvent(SST_Event _event, uint32_t _ticks)
|
||||
{
|
||||
int result = 0;
|
||||
SolarisEvent* ev = (SolarisEvent*)_event;
|
||||
|
||||
mutex_lock(&ev->lock);
|
||||
|
||||
/* Infinite wait */
|
||||
if(_ticks == SST_WAIT_INFINITE)
|
||||
{
|
||||
while(ev->signaled == 0)
|
||||
cond_wait(&ev->cond, &ev->lock);
|
||||
|
||||
result = 1;
|
||||
}
|
||||
else /* Maximum wait measured in milliseconds */
|
||||
{
|
||||
struct timespec ts, tswait;
|
||||
int retval = 0;
|
||||
|
||||
clock_gettime(CLOCK_REALTIME, &ts);
|
||||
|
||||
tswait.tv_sec = (_ticks / 1000); /* add whole seconds */
|
||||
tswait.tv_nsec = (_ticks % 1000) * 1000 * 1000; /* add remaining milliseconds (converted to nanosecs by factor of 10^6) */
|
||||
|
||||
_sst_add_timespec(&ts, &tswait);
|
||||
|
||||
/* timedwait() returns 0 on success, and non-zero on failure. Spurious wakeups return 0 (success)
|
||||
while timeouts don't. A spurious wakeup won't have ev->signaled though, so it will go back to waiting */
|
||||
while(retval == 0 && ev->signaled == 0)
|
||||
retval = cond_timedwait(&ev->cond, &ev->lock, &ts);
|
||||
|
||||
/* If this returned success, then the condition is met AND the timeout did not expire -> success */
|
||||
result = (retval == 0);
|
||||
}
|
||||
|
||||
mutex_unlock(&ev->lock);
|
||||
return result;
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
SST_Event_Win32.c
|
||||
Author: Patrick Baggett <ptbaggett@762studios.com>
|
||||
Created: 12/20/2011
|
||||
|
||||
Purpose:
|
||||
|
||||
libsst-concurrency event functions for Win32 platforms (Windows 7 or later)
|
||||
|
||||
License:
|
||||
|
||||
This program is free software. It comes without any warranty, to
|
||||
the extent permitted by applicable law. You can redistribute it
|
||||
and/or modify it under the terms of the Do What The Fuck You Want
|
||||
To Public License, Version 2, as published by Sam Hocevar. See
|
||||
http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
|
||||
*/
|
||||
|
||||
#include <SST/SST_Concurrency.h> /* SST_WAIT_INFINITE */
|
||||
|
||||
#define _WIN32_WINNT 0x0601 /* Windows 7 or later */
|
||||
#include <windows.h>
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
SST_Event SST_Concurrency_CreateEvent(void)
|
||||
{
|
||||
HANDLE hEvent = CreateEventA(NULL, TRUE, FALSE, NULL);
|
||||
|
||||
return (SST_Event)hEvent;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void SST_Concurrency_DestroyEvent(SST_Event _event)
|
||||
{
|
||||
HANDLE hEvent = (HANDLE)_event;
|
||||
|
||||
CloseHandle(hEvent);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void SST_Concurrency_SignalEvent(SST_Event _event)
|
||||
{
|
||||
HANDLE hEvent = (HANDLE)_event;
|
||||
|
||||
SetEvent(hEvent);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void SST_Concurrency_ResetEvent(SST_Event _event)
|
||||
{
|
||||
HANDLE hEvent = (HANDLE)_event;
|
||||
|
||||
ResetEvent(hEvent);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
int SST_Concurrency_WaitEvent(SST_Event _event, uint32_t _ticks)
|
||||
{
|
||||
HANDLE hEvent = (HANDLE)_event;
|
||||
DWORD dwTime;
|
||||
|
||||
if(_ticks == SST_WAIT_INFINITE)
|
||||
dwTime = INFINITE;
|
||||
else
|
||||
dwTime = (DWORD)_ticks;
|
||||
|
||||
return (WaitForSingleObject(hEvent, dwTime) == WAIT_OBJECT_0);
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
SST_Mutex_POSIX.c
|
||||
Author: Patrick Baggett <ptbaggett@762studios.com>
|
||||
Created: 12/20/2011
|
||||
|
||||
Purpose:
|
||||
|
||||
libsst-concurrency mutex functions for POSIX platforms
|
||||
|
||||
License:
|
||||
|
||||
This program is free software. It comes without any warranty, to
|
||||
the extent permitted by applicable law. You can redistribute it
|
||||
and/or modify it under the terms of the Do What The Fuck You Want
|
||||
To Public License, Version 2, as published by Sam Hocevar. See
|
||||
http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
|
||||
*/
|
||||
|
||||
#include <SST/SST_Mutex.h>
|
||||
#include <pthread.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
SST_Mutex SST_Concurrency_CreateMutex(void)
|
||||
{
|
||||
pthread_mutex_t* mutex = (pthread_mutex_t*)malloc(sizeof(pthread_mutex_t));
|
||||
|
||||
pthread_mutex_init(mutex, NULL);
|
||||
return (SST_Mutex)mutex;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void SST_Concurrency_DestroyMutex(SST_Mutex _mutex)
|
||||
{
|
||||
pthread_mutex_t* mutex = (pthread_mutex_t*)_mutex;
|
||||
|
||||
pthread_mutex_destroy(mutex);
|
||||
free(mutex);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void SST_Concurrency_LockMutex(SST_Mutex _mutex)
|
||||
{
|
||||
pthread_mutex_t* mutex = (pthread_mutex_t*)_mutex;
|
||||
pthread_mutex_lock(mutex);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
int SST_Concurrency_TryLockMutex(SST_Mutex _mutex)
|
||||
{
|
||||
pthread_mutex_t* mutex = (pthread_mutex_t*)_mutex;
|
||||
return (pthread_mutex_trylock(mutex) == 0);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void SST_Concurrency_UnlockMutex(SST_Mutex _mutex)
|
||||
{
|
||||
pthread_mutex_t* mutex = (pthread_mutex_t*)_mutex;
|
||||
pthread_mutex_unlock(mutex);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
SST_Mutex_Solaris.c
|
||||
Author: Patrick Baggett <ptbaggett@762studios.com>
|
||||
Created: 4/11/2012
|
||||
|
||||
Purpose:
|
||||
|
||||
libsst-concurrency mutex functions using native Solaris mutexes
|
||||
|
||||
License:
|
||||
|
||||
This program is free software. It comes without any warranty, to
|
||||
the extent permitted by applicable law. You can redistribute it
|
||||
and/or modify it under the terms of the Do What The Fuck You Want
|
||||
To Public License, Version 2, as published by Sam Hocevar. See
|
||||
http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
|
||||
*/
|
||||
|
||||
#include <SST/SST_Mutex.h>
|
||||
#include <synch.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
SST_Mutex SST_Concurrency_CreateMutex(void)
|
||||
{
|
||||
mutex_t* mutex = (mutex_t*)malloc(sizeof(mutex_t));
|
||||
|
||||
mutex_init(mutex, USYNC_THREAD, NULL);
|
||||
return (SST_Mutex)mutex;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void SST_Concurrency_DestroyMutex(SST_Mutex _mutex)
|
||||
{
|
||||
mutex_t* mutex = (mutex_t*)_mutex;
|
||||
|
||||
mutex_destroy(mutex);
|
||||
free(mutex);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void SST_Concurrency_LockMutex(SST_Mutex _mutex)
|
||||
{
|
||||
mutex_t* mutex = (mutex_t*)_mutex;
|
||||
mutex_lock(mutex);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
int SST_Concurrency_TryLockMutex(SST_Mutex _mutex)
|
||||
{
|
||||
mutex_t* mutex = (mutex_t*)_mutex;
|
||||
return (mutex_trylock(mutex) == 0);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void SST_Concurrency_UnlockMutex(SST_Mutex _mutex)
|
||||
{
|
||||
mutex_t* mutex = (mutex_t*)_mutex;
|
||||
mutex_unlock(mutex);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
SST_Mutex_Win32.c
|
||||
Author: Patrick Baggett <ptbaggett@762studios.com>
|
||||
Created: 12/20/2011
|
||||
|
||||
Purpose:
|
||||
|
||||
libsst-concurrency mutex functions for Win32 platforms (Windows 7 or later)
|
||||
|
||||
License:
|
||||
|
||||
This program is free software. It comes without any warranty, to
|
||||
the extent permitted by applicable law. You can redistribute it
|
||||
and/or modify it under the terms of the Do What The Fuck You Want
|
||||
To Public License, Version 2, as published by Sam Hocevar. See
|
||||
http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
|
||||
*/
|
||||
|
||||
#include <SST/SST_Mutex.h>
|
||||
|
||||
#define _WIN32_WINNT 0x0601 /* Windows 7 or later */
|
||||
#include <windows.h>
|
||||
|
||||
#define SST_DEFAULT_SPINCOUNT 5500
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
SST_Mutex SST_Concurrency_CreateMutex(void)
|
||||
{
|
||||
CRITICAL_SECTION* cs = HeapAlloc(GetProcessHeap(), 0, sizeof(CRITICAL_SECTION));
|
||||
|
||||
/* No memory? */
|
||||
if(!cs)
|
||||
return NULL;
|
||||
|
||||
InitializeCriticalSectionAndSpinCount(cs, SST_DEFAULT_SPINCOUNT);
|
||||
|
||||
return (SST_Mutex)cs;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void SST_Concurrency_DestroyMutex(SST_Mutex _mutex)
|
||||
{
|
||||
CRITICAL_SECTION* cs = (CRITICAL_SECTION*)_mutex;
|
||||
|
||||
DeleteCriticalSection(cs);
|
||||
HeapFree(GetProcessHeap(), 0, cs);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void SST_Concurrency_LockMutex(SST_Mutex _mutex)
|
||||
{
|
||||
CRITICAL_SECTION* cs = (CRITICAL_SECTION*)_mutex;
|
||||
|
||||
EnterCriticalSection(cs);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
int SST_Concurrency_TryLockMutex(SST_Mutex _mutex)
|
||||
{
|
||||
CRITICAL_SECTION* cs = (CRITICAL_SECTION*)_mutex;
|
||||
|
||||
return (int)TryEnterCriticalSection(cs);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void SST_Concurrency_UnlockMutex(SST_Mutex _mutex)
|
||||
{
|
||||
CRITICAL_SECTION* cs = (CRITICAL_SECTION*)_mutex;
|
||||
LeaveCriticalSection(cs);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
SST_Once.c
|
||||
Author: Patrick Baggett <ptbaggett@762studios.com>
|
||||
Created: 12/20/2011
|
||||
|
||||
Purpose:
|
||||
|
||||
libsst-concurrency "once" functions. This requires libsst-atomic.
|
||||
|
||||
License:
|
||||
|
||||
This program is free software. It comes without any warranty, to
|
||||
the extent permitted by applicable law. You can redistribute it
|
||||
and/or modify it under the terms of the Do What The Fuck You Want
|
||||
To Public License, Version 2, as published by Sam Hocevar. See
|
||||
http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
|
||||
*/
|
||||
|
||||
#include <SST/SST_Once.h>
|
||||
#include <SST/SST_Atomic.h>
|
||||
#include <SST/SST_Concurrency.h>
|
||||
#include <SST/SST_MemBarrier.h>
|
||||
|
||||
#define SST_ONCE_INPROGRESS_BIT 0x80000000 /* Highest bit */
|
||||
#define SST_ONCE_DONE_BIT 0x00000001 /* Lowest bit */
|
||||
|
||||
#define SST_ONCE_DONE 0xd1d d0
|
||||
#ifdef _DEBUG
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
static void wait_done(volatile int* vonce)
|
||||
{
|
||||
/* Spin carefully */
|
||||
while((*vonce & SST_ONCE_DONE_BIT) == 0)
|
||||
{
|
||||
SST_Concurrency_YieldThread();
|
||||
SST_Concurrency_Spin();
|
||||
}
|
||||
}
|
||||
|
||||
void SST_Concurrency_ExecOnce(SST_Once* once, SST_OnceFunc once_func, void* arg)
|
||||
{
|
||||
int state;
|
||||
volatile int* vonce = (volatile int*)once;
|
||||
|
||||
/* Take a snapshot of the current state */
|
||||
state = *vonce;
|
||||
|
||||
|
||||
/* Already done? */
|
||||
if((state & SST_ONCE_DONE_BIT) != 0)
|
||||
return;
|
||||
|
||||
/* In progress? */
|
||||
if((state & SST_ONCE_INPROGRESS_BIT) != 0)
|
||||
{
|
||||
wait_done(vonce);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Not done, not yet started -> attempt to set SST_ONCE_INPROGRESS bit. */
|
||||
if(SST_Atomic_CAS(vonce, SST_ONCE_INIT, SST_ONCE_INIT | SST_ONCE_INPROGRESS_BIT) == SST_ONCE_INIT)
|
||||
{
|
||||
/* Success: call user's once function */
|
||||
once_func(arg);
|
||||
|
||||
/* Done, so set that we are done */
|
||||
SST_Atomic_Or(vonce, SST_ONCE_DONE_BIT);
|
||||
}
|
||||
else /* Already started or done, so just chill */
|
||||
wait_done(vonce);
|
||||
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void SST_Concurrency_InitOnceHandle(SST_Once* once)
|
||||
{
|
||||
*once = SST_ONCE_INIT;
|
||||
|
||||
/* This is the only tricky part -- a memory barrier. An atomic
|
||||
operation could be used, but honestly, that's overkill for just
|
||||
ensuring an atomic write. */
|
||||
SST_Concurrency_MemoryBarrier();
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,162 @@
|
||||
/*
|
||||
SST_ReadWriteLock.c
|
||||
|
||||
License:
|
||||
|
||||
This program is free software. It comes without any warranty, to
|
||||
the extent permitted by applicable law. You can redistribute it
|
||||
and/or modify it under the terms of the Do What The Fuck You Want
|
||||
To Public License, Version 2, as published by Sam Hocevar. See
|
||||
http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
*/
|
||||
#ifndef __APPLE_CC__
|
||||
#include <malloc.h>
|
||||
#else
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#include <SST/SST_Build.h>
|
||||
#include <SST/SST_Concurrency.h>
|
||||
|
||||
/* Leading (negative) bit is used to signal write lock */
|
||||
#define SST_RWL_WRITE_BIT (0x80000000u)
|
||||
|
||||
/* ReadWriteLock implementation structure */
|
||||
typedef struct SST_ReadWriteLockImpl {
|
||||
volatile uint32_t state; /* state flag in the form 0xWRRRRRRR, i.e., write flag and then number of readers */
|
||||
} SST_ReadWriteLockImpl;
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
extern SST_ReadWriteLock SST_Concurrency_CreateReadWriteLock( void )
|
||||
{
|
||||
SST_ReadWriteLockImpl *lock_impl = (SST_ReadWriteLockImpl*)malloc(sizeof(SST_ReadWriteLockImpl));
|
||||
|
||||
/* Check for allocation failure */
|
||||
if (lock_impl == NULL)
|
||||
return NULL;
|
||||
|
||||
/* Initialize the impl */
|
||||
lock_impl->state = 0;
|
||||
|
||||
/* Make sure that goes out to memory */
|
||||
SST_Concurrency_MemoryBarrier();
|
||||
|
||||
return lock_impl;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
extern void SST_Concurrency_DestroyReadWriteLock( SST_ReadWriteLock lock )
|
||||
{
|
||||
SST_ReadWriteLockImpl* lock_impl;
|
||||
|
||||
if (lock == NULL)
|
||||
return;
|
||||
|
||||
lock_impl = (SST_ReadWriteLockImpl*)lock;
|
||||
|
||||
free(lock_impl);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
extern int SST_Concurrency_LockForReading( SST_ReadWriteLock lock, uint32_t ticks )
|
||||
{
|
||||
uint64_t startTicks, currentTicks;
|
||||
SST_ReadWriteLockImpl* lock_impl;
|
||||
|
||||
if (lock == NULL)
|
||||
return 0;
|
||||
|
||||
startTicks = (uint32_t)SST_Concurrency_GetTicks();
|
||||
|
||||
lock_impl = (SST_ReadWriteLockImpl*)lock;
|
||||
|
||||
/* Spin (and yield) until we are not writing */
|
||||
while (lock_impl->state & SST_RWL_WRITE_BIT)
|
||||
{
|
||||
if (ticks != SST_WAIT_INFINITE)
|
||||
{
|
||||
currentTicks = SST_Concurrency_GetTicks();
|
||||
|
||||
if ((uint32_t)(currentTicks - startTicks) > ticks)
|
||||
return 0;
|
||||
}
|
||||
|
||||
SST_Concurrency_YieldThread();
|
||||
}
|
||||
|
||||
/* Increment the reader count by incrementing the state variable */
|
||||
SST_Atomic_Inc(&lock_impl->state);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
extern int SST_Concurrency_LockForWriting( SST_ReadWriteLock lock, uint32_t ticks )
|
||||
{
|
||||
uint64_t startTicks, currentTicks;
|
||||
SST_ReadWriteLockImpl* lock_impl;
|
||||
|
||||
if (lock == NULL)
|
||||
return 0;
|
||||
|
||||
startTicks = SST_Concurrency_GetTicks();
|
||||
|
||||
lock_impl = (SST_ReadWriteLockImpl*)lock;
|
||||
|
||||
/* If we are already locked for writing, return */
|
||||
if (lock_impl->state & SST_RWL_WRITE_BIT)
|
||||
return 0;
|
||||
|
||||
/* Set the write flag */
|
||||
SST_Atomic_Or((volatile int*)&lock_impl->state, SST_RWL_WRITE_BIT);
|
||||
|
||||
/* Spin (and yield) until we have no more readers */
|
||||
while (lock_impl->state & ~SST_RWL_WRITE_BIT)
|
||||
{
|
||||
if (ticks != SST_WAIT_INFINITE)
|
||||
{
|
||||
currentTicks = SST_Concurrency_GetTicks();
|
||||
|
||||
if ((uint32_t)(currentTicks - startTicks) > ticks)
|
||||
return 0;
|
||||
}
|
||||
|
||||
SST_Concurrency_YieldThread();
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
extern void SST_Concurrency_EndReading( SST_ReadWriteLock lock )
|
||||
{
|
||||
SST_ReadWriteLockImpl* lock_impl;
|
||||
|
||||
if (lock == NULL)
|
||||
return;
|
||||
|
||||
lock_impl = (SST_ReadWriteLockImpl*)lock;
|
||||
|
||||
/* Decrement the readers counter */
|
||||
SST_Atomic_Dec(&lock_impl->state);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
extern void SST_Concurrency_EndWriting( SST_ReadWriteLock lock )
|
||||
{
|
||||
SST_ReadWriteLockImpl* lock_impl;
|
||||
|
||||
if (lock == NULL)
|
||||
return;
|
||||
|
||||
lock_impl = (SST_ReadWriteLockImpl*)lock;
|
||||
|
||||
/* Signal that we are free to read */
|
||||
SST_Atomic_And((volatile int*)&lock_impl->state, ~SST_RWL_WRITE_BIT);
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
SST_Semaphore_MacOSX.c
|
||||
Author: Patrick Baggett <ptbaggett@762studios.com>
|
||||
Created: 11/27/2012
|
||||
|
||||
Purpose:
|
||||
|
||||
libsst-concurrency semaphore functions for MacOS X platform
|
||||
|
||||
License:
|
||||
|
||||
This program is free software. It comes without any warranty, to
|
||||
the extent permitted by applicable law. You can redistribute it
|
||||
and/or modify it under the terms of the Do What The Fuck You Want
|
||||
To Public License, Version 2, as published by Sam Hocevar. See
|
||||
http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
MacOS X doesn't implement named POSIX semaphores, nor does it have
|
||||
a timed wait, making it utterly useless for any practical purposes.
|
||||
This implementation uses pthread condition variables/mutexes to implement
|
||||
a semaphore. It may end up replacing the POSIX semaphores implementation
|
||||
on other platforms if their implementation is crap, too.
|
||||
*/
|
||||
|
||||
#include <SST/SST_Concurrency.h>
|
||||
#include <pthread.h> /* POSIX threads stuff */
|
||||
#include <sys/time.h> /* gettimeofday() */
|
||||
#include <stdlib.h> /* malloc()/free() */
|
||||
#include <errno.h> /* ETIMEDOUT */
|
||||
#include "timespecadd.h"
|
||||
|
||||
/* Semaphore implementation */
|
||||
typedef struct SST_Semaphore_MacOSX
|
||||
{
|
||||
pthread_mutex_t mutex;
|
||||
pthread_cond_t cond;
|
||||
volatile uint32_t semaCount; /* Semaphore's value */
|
||||
volatile uint32_t waiters; /* Number of waiters */
|
||||
} SST_Semaphore_MacOSX;
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
SST_Semaphore SST_Concurrency_CreateSemaphore(uint32_t _initialCount)
|
||||
{
|
||||
SST_Semaphore_MacOSX* sema = malloc(sizeof(SST_Semaphore_MacOSX));
|
||||
|
||||
if(sema != NULL)
|
||||
{
|
||||
pthread_mutex_init(&sema->mutex, NULL);
|
||||
pthread_cond_init(&sema->cond, NULL);
|
||||
sema->semaCount = _initialCount;
|
||||
sema->waiters = 0;
|
||||
}
|
||||
|
||||
return (SST_Semaphore)sema;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void SST_Concurrency_DestroySemaphore(SST_Semaphore _sema)
|
||||
{
|
||||
SST_Semaphore_MacOSX* sema = (SST_Semaphore_MacOSX*)_sema;
|
||||
|
||||
pthread_mutex_destroy(&sema->mutex);
|
||||
pthread_cond_destroy(&sema->cond);
|
||||
free(sema);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void SST_Concurrency_PostSemaphore(SST_Semaphore _sema, uint32_t _count)
|
||||
{
|
||||
SST_Semaphore_MacOSX* sema = (SST_Semaphore_MacOSX*)_sema;
|
||||
|
||||
pthread_mutex_lock(&sema->mutex);
|
||||
|
||||
if(sema->waiters > 0)
|
||||
{
|
||||
if(_count <= 1) /* Typically wake one */
|
||||
pthread_cond_signal(&sema->cond);
|
||||
else /* But if > 1, use broadcast */
|
||||
pthread_cond_broadcast(&sema->cond);
|
||||
}
|
||||
|
||||
/* Post the count to the semaphore */
|
||||
sema->semaCount += _count;
|
||||
|
||||
|
||||
/* After this unlock, threads are scheduled again */
|
||||
pthread_mutex_unlock(&sema->mutex);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
int SST_Concurrency_WaitSemaphore(SST_Semaphore _sema, uint32_t _ticks)
|
||||
{
|
||||
int result = 0;
|
||||
SST_Semaphore_MacOSX* sema = (SST_Semaphore_MacOSX*)_sema;
|
||||
|
||||
/* Infinite wait */
|
||||
if(_ticks == SST_WAIT_INFINITE)
|
||||
{
|
||||
pthread_mutex_lock(&sema->mutex);
|
||||
sema->waiters++;
|
||||
|
||||
while(sema->semaCount == 0)
|
||||
{
|
||||
pthread_cond_wait(&sema->cond, &sema->mutex);
|
||||
}
|
||||
|
||||
/* Drop count by 1 (we still hold lock) */
|
||||
sema->semaCount--;
|
||||
sema->waiters--;
|
||||
result = 1;
|
||||
}
|
||||
else /* Maximum wait measured in milliseconds */
|
||||
{
|
||||
struct timespec ts, tswait;
|
||||
struct timeval tv;
|
||||
int timeout = 0;
|
||||
|
||||
/* Get absolute time in the future */
|
||||
gettimeofday(&tv, NULL);
|
||||
ts.tv_sec = tv.tv_sec;
|
||||
ts.tv_nsec = tv.tv_usec * 1000;
|
||||
tswait.tv_sec = (_ticks / 1000);
|
||||
tswait.tv_nsec = (_ticks % 1000) * 1000 * 1000;
|
||||
|
||||
_sst_add_timespec(&ts, &tswait);
|
||||
|
||||
/* We do the locking now just in case locking takes a significant
|
||||
amount of time */
|
||||
pthread_mutex_lock(&sema->mutex);
|
||||
|
||||
/* Wait for the condition to be signaled or a timeout */
|
||||
while(sema->semaCount == 0)
|
||||
{
|
||||
/* This is one the few POSIX functions that doesn't use errno */
|
||||
int err = pthread_cond_timedwait(&sema->cond, &sema->mutex, &ts);
|
||||
|
||||
if(err == ETIMEDOUT)
|
||||
{
|
||||
timeout = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Only decrease count if we didn't time out on the wait */
|
||||
if(!timeout)
|
||||
{
|
||||
sema->semaCount--;
|
||||
sema->waiters--;
|
||||
result = 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&sema->mutex);
|
||||
return result;
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
SST_Semaphore_POSIX.c
|
||||
Author: Patrick Baggett <ptbaggett@762studios.com>
|
||||
Created: 12/20/2011
|
||||
|
||||
Purpose:
|
||||
|
||||
libsst-concurrency semaphore functions for POSIX platforms
|
||||
|
||||
License:
|
||||
|
||||
This program is free software. It comes without any warranty, to
|
||||
the extent permitted by applicable law. You can redistribute it
|
||||
and/or modify it under the terms of the Do What The Fuck You Want
|
||||
To Public License, Version 2, as published by Sam Hocevar. See
|
||||
http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
|
||||
*/
|
||||
|
||||
#include <SST/SST_Concurrency.h>
|
||||
#include <SST/SST_Semaphore.h>
|
||||
#include <semaphore.h> /* POSIX semaphores */
|
||||
#include <time.h>
|
||||
#include <stdlib.h> /* malloc()/free() */
|
||||
#include <errno.h> /* errno */
|
||||
#include "timespecadd.h"
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
SST_Semaphore SST_Concurrency_CreateSemaphore(uint32_t _initialCount)
|
||||
{
|
||||
sem_t* sema;
|
||||
|
||||
sema = (sem_t*)malloc(sizeof(sem_t));
|
||||
if(sema)
|
||||
{
|
||||
sem_init(sema, 0, (unsigned int)_initialCount);
|
||||
}
|
||||
|
||||
return (SST_Semaphore)sema;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void SST_Concurrency_DestroySemaphore(SST_Semaphore _sema)
|
||||
{
|
||||
sem_t* sema = (sem_t*)_sema;
|
||||
sem_destroy(sema);
|
||||
free(sema);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void SST_Concurrency_PostSemaphore(SST_Semaphore _sema, uint32_t _count)
|
||||
{
|
||||
sem_t* sema = (sem_t*)_sema;
|
||||
while(_count)
|
||||
{
|
||||
/* The Open Group doesn't define a sem_post() that allows
|
||||
larger than incrementing by 1, so loop. */
|
||||
sem_post(sema);
|
||||
_count--;
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
int SST_Concurrency_WaitSemaphore(SST_Semaphore _sema, uint32_t _ticks)
|
||||
{
|
||||
int result = 0;
|
||||
sem_t* sema = (sem_t*)_sema;
|
||||
int ok;
|
||||
|
||||
/* Infinite wait */
|
||||
if(_ticks == SST_WAIT_INFINITE)
|
||||
{
|
||||
/* Wait in a loop until we get a value OTHER than EINTR,
|
||||
or the function succeeds.
|
||||
Basically, EINTR means a signal interrupted this function,
|
||||
so we can retry the wait */
|
||||
do
|
||||
{
|
||||
ok = sem_wait(sema);
|
||||
if(ok == 0)
|
||||
break;
|
||||
|
||||
} while(errno == EINTR);
|
||||
|
||||
/* sem_wait() returns 0 on success, so see if successful */
|
||||
result = (ok == 0);
|
||||
}
|
||||
else /* Maximum wait measured in milliseconds */
|
||||
{
|
||||
struct timespec ts, tswait;
|
||||
|
||||
clock_gettime(CLOCK_REALTIME, &ts);
|
||||
tswait.tv_sec = (_ticks / 1000);
|
||||
tswait.tv_nsec = (_ticks % 1000) * 1000 * 1000;
|
||||
|
||||
_sst_add_timespec(&ts, &tswait);
|
||||
|
||||
/* EINTER = signal interrupted the function. Loop until we get
|
||||
something other than a signal interruption */
|
||||
do
|
||||
{
|
||||
ok = sem_timedwait(sema, &ts);
|
||||
if(ok == 0)
|
||||
break;
|
||||
} while(errno == EINTR);
|
||||
|
||||
/* Either success or timeout, trap legitimate errors (which
|
||||
are due to invalid conditions -> bug) */
|
||||
if(ok < 0 && errno != ETIMEDOUT)
|
||||
{
|
||||
result = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If this returned success, then save that result
|
||||
as TRUE */
|
||||
result = (ok == 0);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
SST_Semaphore_Solaris.c
|
||||
Author: Patrick Baggett <ptbaggett@762studios.com>
|
||||
Created: 4/11/2012
|
||||
|
||||
Purpose:
|
||||
|
||||
libsst-concurrency semaphore functions using native Solaris semaphores
|
||||
|
||||
License:
|
||||
|
||||
This program is free software. It comes without any warranty, to
|
||||
the extent permitted by applicable law. You can redistribute it
|
||||
and/or modify it under the terms of the Do What The Fuck You Want
|
||||
To Public License, Version 2, as published by Sam Hocevar. See
|
||||
http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
|
||||
*/
|
||||
|
||||
#include <SST/SST_Concurrency.h>
|
||||
#include <SST/SST_Semaphore.h>
|
||||
#include <synch.h> /* native Solaris semaphores */
|
||||
#include <time.h>
|
||||
#include <stdlib.h> /* malloc()/free() */
|
||||
#include <errno.h> /* errno */
|
||||
#include "timespecadd.h" /* add struct timespec */
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
SST_Semaphore SST_Concurrency_CreateSemaphore(uint32_t _initialCount)
|
||||
{
|
||||
|
||||
sema_t* sema = (sema_t*)malloc(sizeof(sema_t));
|
||||
|
||||
if(sema)
|
||||
{
|
||||
if(sema_init(sema, (unsigned int)_initialCount, USYNC_THREAD, NULL) == 0)
|
||||
return (SST_Semaphore)sema;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void SST_Concurrency_DestroySemaphore(SST_Semaphore _sema)
|
||||
{
|
||||
sema_t* sema = (sema_t*)_sema;
|
||||
sema_destroy(sema);
|
||||
free(sema);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void SST_Concurrency_PostSemaphore(SST_Semaphore _sema, uint32_t _count)
|
||||
{
|
||||
sema_t* sema = (sema_t*)_sema;
|
||||
while(_count)
|
||||
{
|
||||
/* sema_post() only allows 1 increment, so loop */
|
||||
sema_post(sema);
|
||||
_count--;
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
int SST_Concurrency_WaitSemaphore(SST_Semaphore _sema, uint32_t _ticks)
|
||||
{
|
||||
int result = 0;
|
||||
sema_t* sema = (sema_t*)_sema;
|
||||
int ok;
|
||||
|
||||
if(_ticks == SST_WAIT_INFINITE)
|
||||
{
|
||||
/* Wait in a loop until we get a value OTHER than EINTR,
|
||||
or the function succeeds.
|
||||
Basically, EINTR means a signal interrupted this function,
|
||||
so we can retry the wait */
|
||||
do
|
||||
{
|
||||
ok = sema_wait(sema);
|
||||
if(ok == 0)
|
||||
break;
|
||||
|
||||
} while(errno == EINTR);
|
||||
|
||||
/* sema_wait() returns 0 on success, so see if successful */
|
||||
result = (ok == 0);
|
||||
}
|
||||
else /* Maximum wait measured in milliseconds */
|
||||
{
|
||||
struct timespec ts, tswait;
|
||||
|
||||
/* get absolute time in the future */
|
||||
clock_gettime(CLOCK_REALTIME, &ts);
|
||||
tswait.tv_sec = (_ticks / 1000);
|
||||
tswait.tv_nsec = (_ticks % 1000) * 1000 * 1000;
|
||||
|
||||
_sst_add_timespec(&ts, &tswait);
|
||||
/* EINTR = signal interrupted the function. Loop until we get
|
||||
something other than a signal interruption */
|
||||
do
|
||||
{
|
||||
ok = sema_timedwait(sema, &ts);
|
||||
if(ok == 0)
|
||||
break;
|
||||
} while(errno == EINTR);
|
||||
|
||||
/* Either success or timeout, trap legitimate errors (which
|
||||
are due to invalid conditions -> bug) */
|
||||
if(ok < 0 && errno != ETIMEDOUT)
|
||||
{
|
||||
result = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If this returned success, then save that result
|
||||
as TRUE */
|
||||
result = (ok == 0);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
SST_Semaphore_Win32.c
|
||||
Author: Patrick Baggett <ptbaggett@762studios.com>
|
||||
Created: 12/20/2011
|
||||
|
||||
Purpose:
|
||||
|
||||
libsst-concurrency semaphore functions for Win32 platforms (Windows 7 or later)
|
||||
|
||||
License:
|
||||
|
||||
This program is free software. It comes without any warranty, to
|
||||
the extent permitted by applicable law. You can redistribute it
|
||||
and/or modify it under the terms of the Do What The Fuck You Want
|
||||
To Public License, Version 2, as published by Sam Hocevar. See
|
||||
http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
|
||||
*/
|
||||
|
||||
#include <SST/SST_Concurrency.h> /* SST_WAIT_INFINITE */
|
||||
|
||||
#define _WIN32_WINNT 0x0601 /* Windows 7 or later */
|
||||
#include <windows.h>
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
SST_Semaphore SST_Concurrency_CreateSemaphore(uint32_t _initialCount)
|
||||
{
|
||||
/* Windows wants a maximum count, so 2^31-1 */
|
||||
HANDLE hSema = CreateSemaphoreA(NULL, _initialCount, (LONG)INT32_MAX, NULL);
|
||||
|
||||
return (SST_Semaphore)hSema;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void SST_Concurrency_DestroySemaphore(SST_Semaphore _sema)
|
||||
{
|
||||
HANDLE hSema = (HANDLE)_sema;
|
||||
|
||||
CloseHandle(hSema);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void SST_Concurrency_PostSemaphore(SST_Semaphore _sema, uint32_t _count)
|
||||
{
|
||||
HANDLE hSema = (HANDLE)_sema;
|
||||
|
||||
ReleaseSemaphore(hSema, _count, NULL);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
int SST_Concurrency_WaitSemaphore(SST_Semaphore _sema, uint32_t _ticks)
|
||||
{
|
||||
HANDLE hSema = (HANDLE)_sema;
|
||||
DWORD dwTime;
|
||||
|
||||
if(_ticks == SST_WAIT_INFINITE)
|
||||
dwTime = INFINITE;
|
||||
else
|
||||
dwTime = (DWORD)_ticks;
|
||||
|
||||
return (WaitForSingleObject(hSema, dwTime) == WAIT_OBJECT_0);
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
SST_TLS_POSIX.c
|
||||
Author: Patrick Baggett <ptbaggett@762studios.com>
|
||||
Created: 12/20/2011
|
||||
|
||||
Purpose:
|
||||
|
||||
libsst-concurrency thread local storage functions for POSIX platforms
|
||||
|
||||
License:
|
||||
|
||||
This program is free software. It comes without any warranty, to
|
||||
the extent permitted by applicable law. You can redistribute it
|
||||
and/or modify it under the terms of the Do What The Fuck You Want
|
||||
To Public License, Version 2, as published by Sam Hocevar. See
|
||||
http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
|
||||
*/
|
||||
|
||||
#include <SST/SST_TLS.h>
|
||||
#include <pthread.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
SST_TLS SST_Concurrency_CreateTLS(void)
|
||||
{
|
||||
pthread_key_t* key = (pthread_key_t*)malloc(sizeof(pthread_key_t));
|
||||
|
||||
if(key == NULL)
|
||||
return NULL;
|
||||
|
||||
if(pthread_key_create(key, NULL) != 0)
|
||||
{
|
||||
free(key);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (SST_TLS)key;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void SST_Concurrency_DestroyTLS(SST_TLS tls)
|
||||
{
|
||||
pthread_key_t* key = (pthread_key_t*)tls;
|
||||
|
||||
pthread_key_delete(*key);
|
||||
free(key);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void* SST_Concurrency_GetTLSValue(SST_TLS tls)
|
||||
{
|
||||
pthread_key_t* key = (pthread_key_t*)tls;
|
||||
|
||||
return pthread_getspecific(*key);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void SST_Concurrency_SetTLSValue(SST_TLS tls, void* value)
|
||||
{
|
||||
pthread_key_t* key = (pthread_key_t*)tls;
|
||||
|
||||
pthread_setspecific(*key, value);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
SST_TLS_POSIX.c
|
||||
Author: Patrick Baggett <ptbaggett@762studios.com>
|
||||
Created: 4/11/2012
|
||||
|
||||
Purpose:
|
||||
|
||||
libsst-concurrency thread local storage functions using native Solaris TLS
|
||||
|
||||
License:
|
||||
|
||||
This program is free software. It comes without any warranty, to
|
||||
the extent permitted by applicable law. You can redistribute it
|
||||
and/or modify it under the terms of the Do What The Fuck You Want
|
||||
To Public License, Version 2, as published by Sam Hocevar. See
|
||||
http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
|
||||
*/
|
||||
|
||||
#include <SST/SST_TLS.h>
|
||||
#include <thread.h>
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
SST_TLS SST_Concurrency_CreateTLS(void)
|
||||
{
|
||||
thread_key_t key;
|
||||
|
||||
if(thr_keycreate(&key, NULL) != 0)
|
||||
return NULL;
|
||||
|
||||
return (SST_TLS)key;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void SST_Concurrency_DestroyTLS(SST_TLS tls)
|
||||
{
|
||||
/* As noted in Solaris's source code, there is no function to destroy keys.
|
||||
This is done for performance. Even the good old pthread_key_destroy()
|
||||
interface does nothing on Solaris. Well. Hmm. */
|
||||
(void)tls;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void* SST_Concurrency_GetTLSValue(SST_TLS tls)
|
||||
{
|
||||
thread_key_t key = (thread_key_t)tls;
|
||||
void* value = NULL;
|
||||
|
||||
thr_getspecific(key, &value);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void SST_Concurrency_SetTLSValue(SST_TLS tls, void* value)
|
||||
{
|
||||
thread_key_t key = (thread_key_t)tls;
|
||||
|
||||
thr_setspecific(key, value);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
SST_TLS_Win32.c
|
||||
Author: Patrick Baggett <ptbaggett@762studios.com>
|
||||
Created: 12/20/2011
|
||||
|
||||
Purpose:
|
||||
|
||||
libsst-concurrency thread local storage functions for Win32 platforms (Windows 7 or later)
|
||||
|
||||
License:
|
||||
|
||||
This program is free software. It comes without any warranty, to
|
||||
the extent permitted by applicable law. You can redistribute it
|
||||
and/or modify it under the terms of the Do What The Fuck You Want
|
||||
To Public License, Version 2, as published by Sam Hocevar. See
|
||||
http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
|
||||
*/
|
||||
|
||||
#include <SST/SST_TLS.h>
|
||||
|
||||
#define _WIN32_WINNT 0x0601 /* Windows 7 or later */
|
||||
#include <windows.h>
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
SST_TLS SST_Concurrency_CreateTLS(void)
|
||||
{
|
||||
DWORD slot = TlsAlloc();
|
||||
|
||||
return (SST_TLS)slot;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void SST_Concurrency_DestroyTLS(SST_TLS tls)
|
||||
{
|
||||
DWORD slot = (DWORD)tls;
|
||||
|
||||
TlsFree(slot);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void* SST_Concurrency_GetTLSValue(SST_TLS tls)
|
||||
{
|
||||
DWORD slot = (DWORD)tls;
|
||||
|
||||
return TlsGetValue(slot);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void SST_Concurrency_SetTLSValue(SST_TLS tls, void* value)
|
||||
{
|
||||
DWORD slot = (DWORD)tls;
|
||||
|
||||
TlsSetValue(slot, value);
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
SST_ThreadBarrier.c
|
||||
Author: Patrick Baggett <ptbaggett@762studios.com>
|
||||
Created: 12/20/2011
|
||||
|
||||
Purpose:
|
||||
|
||||
libsst-concurrency thread barrier functions
|
||||
|
||||
License:
|
||||
|
||||
This program is free software. It comes without any warranty, to
|
||||
the extent permitted by applicable law. You can redistribute it
|
||||
and/or modify it under the terms of the Do What The Fuck You Want
|
||||
To Public License, Version 2, as published by Sam Hocevar. See
|
||||
http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
|
||||
*/
|
||||
|
||||
#include <SST/SST_Concurrency.h> /* SST_WAIT_INFINITE */
|
||||
#include <SST/SST_ThreadBarrier.h> /* Functions being implemented */
|
||||
#include <SST/SST_Atomic.h> /* Needed for atomic operations */
|
||||
#include <stdlib.h>
|
||||
|
||||
#define WAKEUP_UNSIGNALED (-1)
|
||||
#define WAKEUP_CANCELED 0
|
||||
#define WAKEUP_SUCCESS 1
|
||||
|
||||
typedef struct SST_ThreadBarrierImpl
|
||||
{
|
||||
SST_Event event;
|
||||
uint32_t count;
|
||||
volatile int wakeup_reason;
|
||||
uint32_t threshold;
|
||||
} SST_ThreadBarrierImpl;
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
SST_ThreadBarrier SST_Concurrency_CreateThreadBarrier(uint32_t threshold)
|
||||
{
|
||||
SST_ThreadBarrierImpl* barrier;
|
||||
|
||||
/* Allocate barrier */
|
||||
barrier = (SST_ThreadBarrierImpl*)malloc(sizeof(SST_ThreadBarrierImpl));
|
||||
if(barrier == NULL)
|
||||
return NULL;
|
||||
|
||||
barrier->event = SST_Concurrency_CreateEvent();
|
||||
if(barrier->event == NULL) /* Out of memory */
|
||||
{
|
||||
free(barrier);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
barrier->count = 0;
|
||||
barrier->wakeup_reason = WAKEUP_UNSIGNALED; /* == error condition */
|
||||
barrier->threshold = threshold;
|
||||
|
||||
/* Ensure all memory operations are visible by the time this returns */
|
||||
SST_Concurrency_MemoryBarrier();
|
||||
|
||||
return (SST_ThreadBarrier)barrier;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
int SST_Concurrency_WaitThreadBarrier(SST_ThreadBarrier _barrier)
|
||||
{
|
||||
SST_ThreadBarrierImpl* barrier = (SST_ThreadBarrierImpl*)_barrier;
|
||||
uint32_t newValue;
|
||||
const int reason = barrier->wakeup_reason;
|
||||
int retval;
|
||||
|
||||
/* Already canceled? */
|
||||
if(reason == WAKEUP_CANCELED)
|
||||
return 0;
|
||||
|
||||
/* Already successful? */
|
||||
if(reason == WAKEUP_SUCCESS)
|
||||
return (int)barrier->threshold;
|
||||
|
||||
/* At this point, we believe the barrier has not yet been canceled/finished. Due to
|
||||
multithreading, it could have been though. */
|
||||
|
||||
/* Increment barrier count, see if we've exceeded the threshold */
|
||||
newValue = (uint32_t)SST_Atomic_AddReturn((volatile int*)&barrier->count, 1);
|
||||
if(newValue == barrier->threshold)
|
||||
{
|
||||
/* Yes -- but is it already canceled/finished? */
|
||||
const int state = SST_Atomic_CAS(&barrier->wakeup_reason, WAKEUP_UNSIGNALED, WAKEUP_SUCCESS);
|
||||
|
||||
/*
|
||||
'state' can only be WAKEUP_SUCCESS or WAKEUP_CANCELED at this point. Don't
|
||||
(redundantly) signal the event if it was canceled.
|
||||
*/
|
||||
|
||||
if(state == WAKEUP_SUCCESS)
|
||||
SST_Concurrency_SignalEvent(barrier->event);
|
||||
|
||||
retval = SST_BARRIER_SINGLE;
|
||||
}
|
||||
else /* either newValue < threshold newValue > threshold or */
|
||||
{
|
||||
/* No not yet. Wait. */
|
||||
SST_Concurrency_WaitEvent(barrier->event, SST_WAIT_INFINITE);
|
||||
retval = 1;
|
||||
}
|
||||
|
||||
/* Threads could have been woken up due to a cancel or due to the count being exceeded. */
|
||||
if(barrier->wakeup_reason == WAKEUP_UNSIGNALED) /* error? */
|
||||
return -1;
|
||||
if(barrier->wakeup_reason == WAKEUP_CANCELED) /* canceled */
|
||||
return 0;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void SST_Concurrency_ResetThreadBarrier(SST_ThreadBarrier _barrier, uint32_t newThreshold)
|
||||
{
|
||||
SST_ThreadBarrierImpl* barrier = (SST_ThreadBarrierImpl*)_barrier;
|
||||
barrier->count = 0;
|
||||
barrier->threshold = newThreshold;
|
||||
barrier->wakeup_reason = WAKEUP_UNSIGNALED; /* == error condition */
|
||||
|
||||
SST_Concurrency_ResetEvent(barrier->event);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void SST_Concurrency_CancelThreadBarrier(SST_ThreadBarrier _barrier)
|
||||
{
|
||||
SST_ThreadBarrierImpl* barrier = (SST_ThreadBarrierImpl*)_barrier;
|
||||
barrier->wakeup_reason = WAKEUP_CANCELED; /* == barrier canceled */
|
||||
SST_Concurrency_SignalEvent(barrier->event);
|
||||
|
||||
/* NOTE: SignalEvent() provides a memory barrier so that barrier->wakeup_reason is globally
|
||||
visible before the event is signaled. */
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void SST_Concurrency_DestroyThreadBarrier(SST_ThreadBarrier _barrier)
|
||||
{
|
||||
SST_ThreadBarrierImpl* barrier = (SST_ThreadBarrierImpl*)_barrier;
|
||||
SST_Concurrency_DestroyEvent(barrier->event);
|
||||
free(barrier);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
SST_Thread_POSIX.c
|
||||
Author: Patrick Baggett <ptbaggett@762studios.com>
|
||||
Created: 12/20/2011
|
||||
|
||||
Purpose:
|
||||
|
||||
libsst-concurrency thread functions for POSIX platforms
|
||||
|
||||
License:
|
||||
|
||||
This program is free software. It comes without any warranty, to
|
||||
the extent permitted by applicable law. You can redistribute it
|
||||
and/or modify it under the terms of the Do What The Fuck You Want
|
||||
To Public License, Version 2, as published by Sam Hocevar. See
|
||||
http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
|
||||
*/
|
||||
#include <pthread.h> /* POSIX threads API */
|
||||
#include <unistd.h> /* usleep() */
|
||||
#include <stdlib.h> /* malloc()/free() */
|
||||
#include <sched.h> /* sched_yield() */
|
||||
#include <errno.h> /* system error codes */
|
||||
#include <time.h> /* nanosleep() */
|
||||
|
||||
#include <pstdint.h>
|
||||
#include <SST/SST_Thread.h>
|
||||
|
||||
/* Less-than-POSIX madness. Used for getting the thread ID, which POSIX decided to leave out... /rage */
|
||||
#if defined(__linux__) && !defined(__ANDROID__)
|
||||
#include <sys/syscall.h>
|
||||
#endif
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#include <sys/thr.h>
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <sys/time.h>
|
||||
#include <mach/mach_init.h>
|
||||
#endif
|
||||
|
||||
SST_Thread SST_Concurrency_CreateThread(int(*_func)(void*), void *_arg)
|
||||
{
|
||||
pthread_t* thr;
|
||||
|
||||
#ifdef _DEBUG
|
||||
if(_func == (int(*)(void*))NULL)
|
||||
return NULL;
|
||||
#endif
|
||||
|
||||
thr =(pthread_t*)malloc(sizeof(pthread_t));
|
||||
|
||||
/* Create the thread */
|
||||
if(pthread_create(thr, NULL, (void*(*)(void*))_func, _arg) != 0)
|
||||
{
|
||||
free(thr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (SST_Thread)thr;
|
||||
}
|
||||
|
||||
void SST_Concurrency_DestroyThread(SST_Thread _thr)
|
||||
{
|
||||
pthread_t* thr = (pthread_t*)_thr;
|
||||
|
||||
pthread_detach(*thr);
|
||||
|
||||
free(thr);
|
||||
}
|
||||
|
||||
void SST_Concurrency_SleepThread(uint32_t _ms)
|
||||
{
|
||||
struct timespec req, rem;
|
||||
long msecs = _ms % 1000; /* milliseconds that are less than 1 sec (0-999) */
|
||||
rem.tv_sec = _ms / 1000; /* msec -> sec by mult 1e-3 */
|
||||
rem.tv_nsec = msecs * (1000 * 1000); /* msec -> nsec by mult 1e6 */
|
||||
|
||||
|
||||
/* Sleep, continuing if woken up by EINTR (POSIX signal) */
|
||||
do
|
||||
{
|
||||
/* On EINTR, 'rem' contains the remaining time that has not yet
|
||||
been slept. */
|
||||
req = rem;
|
||||
if(nanosleep(&req, &rem) == 0) /* 0 == success */
|
||||
break;
|
||||
} while(errno == EINTR);
|
||||
|
||||
}
|
||||
|
||||
uint32_t SST_Concurrency_GetThreadId()
|
||||
{
|
||||
#if defined(__APPLE__)
|
||||
return (uint32_t)mach_thread_self();
|
||||
#elif defined(__FreeBSD__)
|
||||
long lwpid;
|
||||
|
||||
thr_self(&lwpid);
|
||||
return (uint32_t)lwpid;
|
||||
#elif defined(__ANDROID__)
|
||||
return (uint32_t)pthread_self(); /* Android uses integer as pthread_t */
|
||||
#elif defined(__linux__)
|
||||
return (uint32_t)syscall(SYS_gettid); /* kinda hacky but works */
|
||||
#else
|
||||
#error Need Thread ID implementation for your OS
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
uint64_t SST_Concurrency_GetTicks(void)
|
||||
{
|
||||
#if defined(__APPLE__)
|
||||
struct timeval tv;
|
||||
struct timezone tz; tz.tz_minuteswest = 0; tz.tz_dsttime = 0;
|
||||
gettimeofday(&tv, &tz);
|
||||
|
||||
return ((uint64_t) tv.tv_sec * 1000) + ((uint64_t)tv.tv_usec / 1000);
|
||||
|
||||
#else
|
||||
|
||||
struct timespec tv;
|
||||
|
||||
clock_gettime(CLOCK_REALTIME, &tv);
|
||||
|
||||
return ((uint64_t)tv.tv_sec * 1000) + ((uint64_t)tv.tv_nsec / 1000000);
|
||||
#endif
|
||||
}
|
||||
|
||||
int SST_Concurrency_WaitThread(SST_Thread _thr, int* _retval)
|
||||
{
|
||||
pthread_t* thr = (pthread_t*)_thr;
|
||||
void* thrRetval;
|
||||
int join_retval;
|
||||
|
||||
/* Join, capturing the return value */
|
||||
if(_retval)
|
||||
{
|
||||
uintptr_t masked;
|
||||
join_retval = pthread_join(*thr, &thrRetval);
|
||||
|
||||
|
||||
masked = (uintptr_t)thrRetval;
|
||||
*_retval = (int)masked;
|
||||
}
|
||||
else
|
||||
join_retval = pthread_join(*thr, NULL);
|
||||
|
||||
|
||||
return (join_retval == 0);
|
||||
}
|
||||
|
||||
void SST_Concurrency_YieldThread(void)
|
||||
{
|
||||
sched_yield();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
SST_Thread_Solaris.c
|
||||
Author: Patrick Baggett <ptbaggett@762studios.com>
|
||||
Created: 4/11/2012
|
||||
|
||||
Purpose:
|
||||
|
||||
libsst-concurrency thread functions using Solaris native threads
|
||||
|
||||
License:
|
||||
|
||||
This program is free software. It comes without any warranty, to
|
||||
the extent permitted by applicable law. You can redistribute it
|
||||
and/or modify it under the terms of the Do What The Fuck You Want
|
||||
To Public License, Version 2, as published by Sam Hocevar. See
|
||||
http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
|
||||
*/
|
||||
#include <thread.h> /* Solaris native threads */
|
||||
#include <unistd.h> /* usleep() */
|
||||
#include <errno.h> /* system error codes */
|
||||
#include <time.h> /* nanosleep() */
|
||||
#include <sys/syscall.h>
|
||||
|
||||
#include <pstdint.h>
|
||||
#include <SST/SST_Thread.h>
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
SST_Thread SST_Concurrency_CreateThread(int(*_func)(void*), void *_arg)
|
||||
{
|
||||
thread_t thr;
|
||||
|
||||
#ifdef _DEBUG
|
||||
if(_func == (int(*)(void*))NULL)
|
||||
return NULL;
|
||||
#endif
|
||||
|
||||
/* Create the thread */
|
||||
if(thr_create(NULL, 0, (void*(*)(void*))_func, _arg, THR_BOUND, &thr) != 0)
|
||||
return NULL;
|
||||
|
||||
return (SST_Thread)thr;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void SST_Concurrency_DestroyThread(SST_Thread _thr)
|
||||
{
|
||||
/* Detach the thread. This uses the direct system call
|
||||
since there is no thr_detach() function. This has
|
||||
been tested to work on Solaris 10. */
|
||||
syscall(SYS_lwp_detach, (thread_t)_thr);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void SST_Concurrency_SleepThread(uint32_t _ms)
|
||||
{
|
||||
struct timespec req, rem;
|
||||
long msecs = _ms % 1000; /* milliseconds that are less than 1 sec (0-999) */
|
||||
rem.tv_sec = _ms / 1000; /* msec -> sec by mult 1e-3 */
|
||||
rem.tv_nsec = msecs * (1000 * 1000); /* msec -> nsec by mult 1e6 */
|
||||
|
||||
/* Sleep, continuing if woken up by EINTR (POSIX signal) */
|
||||
do
|
||||
{
|
||||
/* On EINTR, 'rem' contains the remaining time that has not yet
|
||||
been slept. */
|
||||
req = rem;
|
||||
if(nanosleep(&req, &rem) == 0) /* 0 == success */
|
||||
break;
|
||||
} while(errno == EINTR);
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
uint32_t SST_Concurrency_GetThreadId()
|
||||
{
|
||||
return (uint32_t)thr_self();
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
uint64_t SST_Concurrency_GetTicks(void)
|
||||
{
|
||||
struct timespec tv;
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC, &tv);
|
||||
|
||||
return ((uint64_t)tv.tv_sec * 1000) + ((uint64_t)tv.tv_nsec / 1000000);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
int SST_Concurrency_WaitThread(SST_Thread _thr, int* _retval)
|
||||
{
|
||||
thread_t thr = (thread_t)_thr;
|
||||
thread_t departed = 0;
|
||||
void* thrRetval;
|
||||
int join_retval;
|
||||
|
||||
/* Join, capturing the return value */
|
||||
if(_retval)
|
||||
{
|
||||
uintptr_t masked;
|
||||
join_retval = thr_join(thr, &departed, &thrRetval);
|
||||
|
||||
|
||||
masked = (uintptr_t)thrRetval;
|
||||
*_retval = (int)masked;
|
||||
}
|
||||
else
|
||||
join_retval = thr_join(thr, &departed, NULL);
|
||||
|
||||
|
||||
return (join_retval == 0 && thr == departed);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void SST_Concurrency_YieldThread(void)
|
||||
{
|
||||
thr_yield();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,166 @@
|
||||
/*
|
||||
SST_Thread_Win32.c
|
||||
Author: Patrick Baggett <ptbaggett@762studios.com>
|
||||
Created: 12/20/2011
|
||||
|
||||
Purpose:
|
||||
|
||||
libsst-concurrency thread functions for Win32 platforms (Windows 7 or later)
|
||||
|
||||
License:
|
||||
|
||||
This program is free software. It comes without any warranty, to
|
||||
the extent permitted by applicable law. You can redistribute it
|
||||
and/or modify it under the terms of the Do What The Fuck You Want
|
||||
To Public License, Version 2, as published by Sam Hocevar. See
|
||||
http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
|
||||
*/
|
||||
|
||||
#include <SST/SST_Thread.h>
|
||||
|
||||
#define _WIN32_WINNT 0x0601 /* Windows 7 or later */
|
||||
#include <windows.h>
|
||||
#include <process.h> /* _beginthreadex() */
|
||||
|
||||
struct WrapStdcallData
|
||||
{
|
||||
int (*func)(void*); /* Function to call */
|
||||
void* arg; /* Arg for said function */
|
||||
};
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* OS really need "unsigned int" data type here, don't change! */
|
||||
static unsigned int __stdcall wrapStdcall(void* arg)
|
||||
{
|
||||
struct WrapStdcallData* info = (struct WrapStdcallData*)arg;
|
||||
struct WrapStdcallData thrData;
|
||||
int retval;
|
||||
|
||||
/* Copy data to local variable */
|
||||
thrData.arg = info->arg;
|
||||
thrData.func = info->func;
|
||||
|
||||
/* Free the allocated copy */
|
||||
HeapFree(GetProcessHeap(), 0, arg);
|
||||
|
||||
/* Call user supplied function */
|
||||
retval = thrData.func(thrData.arg);
|
||||
|
||||
/* This actually kills the thread */
|
||||
return (unsigned int)retval;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
SST_Thread SST_Concurrency_CreateThread(SST_ThreadFunc _func, void *_arg)
|
||||
{
|
||||
HANDLE hNewThread;
|
||||
struct WrapStdcallData* info;
|
||||
|
||||
/* Allocate heap structure to pass between threads */
|
||||
info = HeapAlloc(GetProcessHeap(), 0, sizeof(struct WrapStdcallData));
|
||||
if(!info)
|
||||
return NULL;
|
||||
info->arg = _arg;
|
||||
info->func = _func;
|
||||
|
||||
/* Create the thread, and return the handle immediately on success */
|
||||
hNewThread = (HANDLE)_beginthreadex(NULL, 0, wrapStdcall, info, 0, NULL);
|
||||
if(hNewThread != NULL)
|
||||
return (SST_Thread)hNewThread;
|
||||
|
||||
/* Not successful -- don't leak memory */
|
||||
free(info);
|
||||
return (SST_Thread)NULL;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void SST_Concurrency_DestroyThread(SST_Thread _thr)
|
||||
{
|
||||
HANDLE hThread = (HANDLE)_thr;
|
||||
|
||||
CloseHandle(hThread);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void SST_Concurrency_SleepThread(uint32_t _ms)
|
||||
{
|
||||
ULONGLONG now;
|
||||
ULONGLONG done;
|
||||
|
||||
/* Get the time now, and the time in the future for when it should be done */
|
||||
now = SST_Concurrency_GetTicks();
|
||||
done = now + (ULONGLONG)_ms;
|
||||
|
||||
/* Do a cursory sleep. This can sleep less than the required time, per MSDN.*/
|
||||
Sleep((DWORD)_ms);
|
||||
|
||||
/* Now, if didn't sleep enough, then do small sleeps until we did. */
|
||||
while(SST_Concurrency_GetTicks() < done)
|
||||
Sleep(1);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
uint32_t SST_Concurrency_GetThreadId()
|
||||
{
|
||||
return (uint32_t)GetCurrentThreadId();
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
uint64_t SST_Concurrency_GetTicks(void)
|
||||
{
|
||||
#if defined(__GNUC__)
|
||||
static ULONGLONG (WINAPI* pf_GetTickCount64)(void) = NULL;
|
||||
|
||||
if(pf_GetTickCount64 == NULL)
|
||||
{
|
||||
pf_GetTickCount64 = (ULONGLONG (WINAPI*)(void))GetProcAddress(GetModuleHandleA("kernel32.dll"), "GetTickCount64");
|
||||
}
|
||||
return (uint64_t)pf_GetTickCount64();
|
||||
#else
|
||||
return (uint64_t)GetTickCount64();
|
||||
#endif
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
int SST_Concurrency_WaitThread(SST_Thread _thr, int* _retval)
|
||||
{
|
||||
HANDLE hThread = (HANDLE)_thr;
|
||||
DWORD exitCode;
|
||||
int waitOk = 0;
|
||||
|
||||
/* Wait for the thread to exit */
|
||||
if(WaitForSingleObject(hThread, INFINITE) == WAIT_OBJECT_0)
|
||||
{
|
||||
/* Is a return value wanted? */
|
||||
if(_retval)
|
||||
{
|
||||
/* OK, try and get it */
|
||||
if(GetExitCodeThread(hThread, &exitCode))
|
||||
{
|
||||
*_retval = (int)exitCode;
|
||||
waitOk = 1;
|
||||
}
|
||||
}
|
||||
else /* No return code wanted, so we're good */
|
||||
waitOk = 1;
|
||||
}
|
||||
|
||||
return waitOk;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void SST_Concurrency_YieldThread(void)
|
||||
{
|
||||
/* Attempt to schedule a different thread. False -> nothing to do */
|
||||
if(SwitchToThread() == FALSE)
|
||||
Sleep(1); /* Nothing to do -> sleeeeeep */
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{7AF55FF8-2F78-42EC-8A05-7FA1AE514814}</ProjectGuid>
|
||||
<RootNamespace>libsstconcurrency</RootNamespace>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup>
|
||||
<_ProjectFileVersion>11.0.50727.1</_ProjectFileVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<OutDir>$(SolutionDir)\Lib\x86\</OutDir>
|
||||
<IntDir>$(SolutionDir)Intermediate\$(Configuration)\$(Platform)\$(ProjectName)\</IntDir>
|
||||
<TargetName>$(ProjectName)-debug</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<OutDir>$(SolutionDir)\Lib\x86\</OutDir>
|
||||
<IntDir>$(SolutionDir)Intermediate\$(Configuration)\$(Platform)\$(ProjectName)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<OutDir>$(SolutionDir)\Lib\x64\</OutDir>
|
||||
<IntDir>$(SolutionDir)Intermediate\$(Configuration)\$(Platform)\$(ProjectName)\</IntDir>
|
||||
<TargetName>$(ProjectName)-debug</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<OutDir>$(SolutionDir)\Lib\x64\</OutDir>
|
||||
<IntDir>$(SolutionDir)Intermediate\$(Configuration)\$(Platform)\$(ProjectName)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)Lib\Include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
</ClCompile>
|
||||
<Lib />
|
||||
<Lib>
|
||||
<LinkTimeCodeGeneration>true</LinkTimeCodeGeneration>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)Lib\Include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Midl>
|
||||
<TargetEnvironment>X64</TargetEnvironment>
|
||||
</Midl>
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)Lib\Include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
</ClCompile>
|
||||
<Lib />
|
||||
<Lib>
|
||||
<LinkTimeCodeGeneration>true</LinkTimeCodeGeneration>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Midl>
|
||||
<TargetEnvironment>X64</TargetEnvironment>
|
||||
</Midl>
|
||||
<ClCompile>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)Lib\Include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="SST_Event_Win32.c" />
|
||||
<ClCompile Include="SST_Mutex_Win32.c" />
|
||||
<ClCompile Include="SST_Once.c" />
|
||||
<ClCompile Include="SST_ReadWriteLock.c" />
|
||||
<ClCompile Include="SST_Semaphore_Win32.c" />
|
||||
<ClCompile Include="SST_Thread_Win32.c" />
|
||||
<ClCompile Include="SST_ThreadBarrier.c" />
|
||||
<ClCompile Include="SST_TLS_Win32.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\Lib\Include\SST\SST_Concurrency.h" />
|
||||
<ClInclude Include="..\Lib\Include\SST\SST_Event.h" />
|
||||
<ClInclude Include="..\Lib\Include\SST\SST_MemBarrier.h" />
|
||||
<ClInclude Include="..\Lib\Include\SST\SST_Mutex.h" />
|
||||
<ClInclude Include="..\Lib\Include\SST\SST_Once.h" />
|
||||
<ClInclude Include="..\Lib\Include\SST\SST_ReadWriteLock.h" />
|
||||
<ClInclude Include="..\Lib\Include\SST\SST_Semaphore.h" />
|
||||
<ClInclude Include="..\Lib\Include\SST\SST_Thread.h" />
|
||||
<ClInclude Include="..\Lib\Include\SST\SST_ThreadBarrier.h" />
|
||||
<ClInclude Include="..\Lib\Include\SST\SST_TLS.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\libsst-atomic\libsst-atomic.vcxproj">
|
||||
<Project>{43ed481f-c4a3-40ed-81a3-46c43dc4eb1e}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,71 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="SST_Event_Win32.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SST_Mutex_Win32.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SST_Once.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SST_ReadWriteLock.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SST_Semaphore_Win32.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SST_Thread_Win32.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SST_ThreadBarrier.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SST_TLS_Win32.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\Lib\Include\SST\SST_Concurrency.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Lib\Include\SST\SST_Event.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Lib\Include\SST\SST_MemBarrier.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Lib\Include\SST\SST_Mutex.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Lib\Include\SST\SST_Once.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Lib\Include\SST\SST_ReadWriteLock.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Lib\Include\SST\SST_Semaphore.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Lib\Include\SST\SST_Thread.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Lib\Include\SST\SST_ThreadBarrier.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Lib\Include\SST\SST_TLS.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,30 @@
|
||||
# libsst-concurrency/sources-POSIX.mk
|
||||
# Author: Patrick Baggett <ptbaggett@762studios.com>
|
||||
# Created: 12/23/2011
|
||||
#
|
||||
# Purpose:
|
||||
#
|
||||
# List of source files for POSIX-compliant systems. This reduces the amount
|
||||
# of copy/pasting for different UNIX configurations
|
||||
#
|
||||
# License:
|
||||
#
|
||||
# This program is free software. It comes without any warranty, to
|
||||
# the extent permitted by applicable law. You can redistribute it
|
||||
# and/or modify it under the terms of the Do What The Fuck You Want
|
||||
# To Public License, Version 2, as published by Sam Hocevar. See
|
||||
# http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
|
||||
SRC := \
|
||||
SST_Mutex_POSIX.c \
|
||||
SST_Event_POSIX.c \
|
||||
SST_Thread_POSIX.c \
|
||||
SST_ReadWriteLock.c \
|
||||
SST_TLS_POSIX.c \
|
||||
SST_Semaphore_POSIX.c
|
||||
|
||||
# MacOS X doesn't have decent semaphore implementation, use home-rolled solution
|
||||
ifeq ($(OS),Darwin)
|
||||
SRC := $(subst SST_Semaphore_POSIX.c,SST_Semaphore_MacOSX.c, $(SRC))
|
||||
endif
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
# libsst-concurrency/sources-Solaris.mk
|
||||
# Author: Patrick Baggett <ptbaggett@762studios.com>
|
||||
# Created: 6/21/2012
|
||||
#
|
||||
# Purpose:
|
||||
#
|
||||
# List of source files for Solaris
|
||||
#
|
||||
# License:
|
||||
#
|
||||
# This program is free software. It comes without any warranty, to
|
||||
# the extent permitted by applicable law. You can redistribute it
|
||||
# and/or modify it under the terms of the Do What The Fuck You Want
|
||||
# To Public License, Version 2, as published by Sam Hocevar. See
|
||||
# http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
|
||||
SRC := \
|
||||
SST_Mutex_Solaris.c \
|
||||
SST_Event_Solaris.c \
|
||||
SST_Thread_Solaris.c \
|
||||
SST_TLS_Solaris.c \
|
||||
SST_Semaphore_Solaris.c
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
# libsst-concurrency/sources-Win32.mk
|
||||
# Author: Patrick Baggett <ptbaggett@762studios.com>
|
||||
# Created: 11/09/2012
|
||||
#
|
||||
# Purpose:
|
||||
#
|
||||
# List of source files for Win32 systems
|
||||
#
|
||||
# License:
|
||||
#
|
||||
# This program is free software. It comes without any warranty, to
|
||||
# the extent permitted by applicable law. You can redistribute it
|
||||
# and/or modify it under the terms of the Do What The Fuck You Want
|
||||
# To Public License, Version 2, as published by Sam Hocevar. See
|
||||
# http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
|
||||
SRC := \
|
||||
SST_Mutex_Win32.c \
|
||||
SST_Event_Win32.c \
|
||||
SST_Thread_Win32.c \
|
||||
SST_TLS_Win32.c \
|
||||
SST_Semaphore_Win32.c
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
# libsst-concurrency/sources-common.mk
|
||||
# Author: Patrick Baggett <ptbaggett@762studios.com>
|
||||
# Created: 12/23/2011
|
||||
#
|
||||
# Purpose:
|
||||
#
|
||||
# List of source files for common to all systems. This reduces the amount
|
||||
# of copy/pasting for different OS configurations.
|
||||
#
|
||||
# License:
|
||||
#
|
||||
# This program is free software. It comes without any warranty, to
|
||||
# the extent permitted by applicable law. You can redistribute it
|
||||
# and/or modify it under the terms of the Do What The Fuck You Want
|
||||
# To Public License, Version 2, as published by Sam Hocevar. See
|
||||
# http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
|
||||
SRC += \
|
||||
SST_Once.c \
|
||||
SST_ReadWriteLock.c \
|
||||
SST_ThreadBarrier.c
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
timespecadd.h
|
||||
Author: Patrick Baggett <ptbaggett@762studios.com>
|
||||
Created: 4/11/2012
|
||||
|
||||
Purpose:
|
||||
|
||||
Inline code for adding struct timespec, common in UNIX APIs.
|
||||
|
||||
License:
|
||||
|
||||
This program is free software. It comes without any warranty, to
|
||||
the extent permitted by applicable law. You can redistribute it
|
||||
and/or modify it under the terms of the Do What The Fuck You Want
|
||||
To Public License, Version 2, as published by Sam Hocevar. See
|
||||
http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef _SST_CONCURRENCY_TIMESPECADD_H
|
||||
#define _SST_CONCURRENCY_TIMESPECADD_H
|
||||
#include <SST/SST_Build.h> /* INLINE definition */
|
||||
|
||||
/*
|
||||
Compute t1 += t2 in a way that UNIX doesn't bitch. Adding the
|
||||
tv_nsec fields is bad when they exceed 1B nsec (i.e. 1 sec), so
|
||||
one must add and then check for overflow. Assumed that t1, t2
|
||||
have tv_nsec fields that are each < 1e9
|
||||
*/
|
||||
static INLINE void _sst_add_timespec(struct timespec* t1, const struct timespec* t2)
|
||||
{
|
||||
t1->tv_sec += t2->tv_sec;
|
||||
t1->tv_nsec += t2->tv_nsec;
|
||||
|
||||
if(t1->tv_nsec > 1000000000)
|
||||
{
|
||||
t1->tv_nsec -= 1000000000;
|
||||
t1->tv_sec += 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user