Initial commit
This commit is contained in:
42
libsst-concurrency/Makefile
Normal file
42
libsst-concurrency/Makefile
Normal file
@@ -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
|
||||
|
||||
|
||||
138
libsst-concurrency/SST_Event_POSIX.c
Normal file
138
libsst-concurrency/SST_Event_POSIX.c
Normal file
@@ -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;
|
||||
}
|
||||
125
libsst-concurrency/SST_Event_Solaris.c
Normal file
125
libsst-concurrency/SST_Event_Solaris.c
Normal file
@@ -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;
|
||||
}
|
||||
74
libsst-concurrency/SST_Event_Win32.c
Normal file
74
libsst-concurrency/SST_Event_Win32.c
Normal file
@@ -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);
|
||||
}
|
||||
70
libsst-concurrency/SST_Mutex_POSIX.c
Normal file
70
libsst-concurrency/SST_Mutex_POSIX.c
Normal file
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
68
libsst-concurrency/SST_Mutex_Solaris.c
Normal file
68
libsst-concurrency/SST_Mutex_Solaris.c
Normal file
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
77
libsst-concurrency/SST_Mutex_Win32.c
Normal file
77
libsst-concurrency/SST_Mutex_Win32.c
Normal file
@@ -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);
|
||||
}
|
||||
|
||||
89
libsst-concurrency/SST_Once.c
Normal file
89
libsst-concurrency/SST_Once.c
Normal file
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
162
libsst-concurrency/SST_ReadWriteLock.c
Normal file
162
libsst-concurrency/SST_ReadWriteLock.c
Normal file
@@ -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);
|
||||
}
|
||||
164
libsst-concurrency/SST_Semaphore_MacOSX.c
Normal file
164
libsst-concurrency/SST_Semaphore_MacOSX.c
Normal file
@@ -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;
|
||||
}
|
||||
126
libsst-concurrency/SST_Semaphore_POSIX.c
Normal file
126
libsst-concurrency/SST_Semaphore_POSIX.c
Normal file
@@ -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;
|
||||
}
|
||||
127
libsst-concurrency/SST_Semaphore_Solaris.c
Normal file
127
libsst-concurrency/SST_Semaphore_Solaris.c
Normal file
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
66
libsst-concurrency/SST_Semaphore_Win32.c
Normal file
66
libsst-concurrency/SST_Semaphore_Win32.c
Normal file
@@ -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);
|
||||
}
|
||||
70
libsst-concurrency/SST_TLS_POSIX.c
Normal file
70
libsst-concurrency/SST_TLS_POSIX.c
Normal file
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
66
libsst-concurrency/SST_TLS_Solaris.c
Normal file
66
libsst-concurrency/SST_TLS_Solaris.c
Normal file
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
59
libsst-concurrency/SST_TLS_Win32.c
Normal file
59
libsst-concurrency/SST_TLS_Win32.c
Normal file
@@ -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);
|
||||
}
|
||||
150
libsst-concurrency/SST_ThreadBarrier.c
Normal file
150
libsst-concurrency/SST_ThreadBarrier.c
Normal file
@@ -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);
|
||||
}
|
||||
|
||||
158
libsst-concurrency/SST_Thread_POSIX.c
Normal file
158
libsst-concurrency/SST_Thread_POSIX.c
Normal file
@@ -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();
|
||||
}
|
||||
|
||||
127
libsst-concurrency/SST_Thread_Solaris.c
Normal file
127
libsst-concurrency/SST_Thread_Solaris.c
Normal file
@@ -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();
|
||||
}
|
||||
|
||||
166
libsst-concurrency/SST_Thread_Win32.c
Normal file
166
libsst-concurrency/SST_Thread_Win32.c
Normal file
@@ -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 */
|
||||
}
|
||||
183
libsst-concurrency/libsst-concurrency.vcxproj
Normal file
183
libsst-concurrency/libsst-concurrency.vcxproj
Normal file
@@ -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>
|
||||
71
libsst-concurrency/libsst-concurrency.vcxproj.filters
Normal file
71
libsst-concurrency/libsst-concurrency.vcxproj.filters
Normal file
@@ -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>
|
||||
BIN
libsst-concurrency/obj/x86-64/release/SST_Event_POSIX.o
Normal file
BIN
libsst-concurrency/obj/x86-64/release/SST_Event_POSIX.o
Normal file
Binary file not shown.
BIN
libsst-concurrency/obj/x86-64/release/SST_Mutex_POSIX.o
Normal file
BIN
libsst-concurrency/obj/x86-64/release/SST_Mutex_POSIX.o
Normal file
Binary file not shown.
BIN
libsst-concurrency/obj/x86-64/release/SST_Once.o
Normal file
BIN
libsst-concurrency/obj/x86-64/release/SST_Once.o
Normal file
Binary file not shown.
BIN
libsst-concurrency/obj/x86-64/release/SST_ReadWriteLock.o
Normal file
BIN
libsst-concurrency/obj/x86-64/release/SST_ReadWriteLock.o
Normal file
Binary file not shown.
BIN
libsst-concurrency/obj/x86-64/release/SST_Semaphore_POSIX.o
Normal file
BIN
libsst-concurrency/obj/x86-64/release/SST_Semaphore_POSIX.o
Normal file
Binary file not shown.
BIN
libsst-concurrency/obj/x86-64/release/SST_TLS_POSIX.o
Normal file
BIN
libsst-concurrency/obj/x86-64/release/SST_TLS_POSIX.o
Normal file
Binary file not shown.
BIN
libsst-concurrency/obj/x86-64/release/SST_ThreadBarrier.o
Normal file
BIN
libsst-concurrency/obj/x86-64/release/SST_ThreadBarrier.o
Normal file
Binary file not shown.
BIN
libsst-concurrency/obj/x86-64/release/SST_Thread_POSIX.o
Normal file
BIN
libsst-concurrency/obj/x86-64/release/SST_Thread_POSIX.o
Normal file
Binary file not shown.
30
libsst-concurrency/sources-POSIX.mk
Normal file
30
libsst-concurrency/sources-POSIX.mk
Normal file
@@ -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
|
||||
|
||||
23
libsst-concurrency/sources-Solaris.mk
Normal file
23
libsst-concurrency/sources-Solaris.mk
Normal file
@@ -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
|
||||
|
||||
23
libsst-concurrency/sources-Win32.mk
Normal file
23
libsst-concurrency/sources-Win32.mk
Normal file
@@ -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
|
||||
|
||||
21
libsst-concurrency/sources-common.mk
Normal file
21
libsst-concurrency/sources-common.mk
Normal file
@@ -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
|
||||
45
libsst-concurrency/timespecadd.h
Normal file
45
libsst-concurrency/timespecadd.h
Normal file
@@ -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