Initial commit

This commit is contained in:
2026-04-03 00:22:39 -05:00
commit eca1e8c458
945 changed files with 218160 additions and 0 deletions

View 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

View 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;
}

View 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;
}

View 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);
}

View 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);
}

View 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);
}

View 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);
}

View 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();
}

View 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);
}

View 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;
}

View 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;
}

View 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;
}

View 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);
}

View 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);
}

View 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);
}

View 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);
}

View 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);
}

View 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();
}

View 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();
}

View 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 */
}

View 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>

View 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>

Binary file not shown.

Binary file not shown.

View 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

View 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

View 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

View 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

View 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