Files
org-hyperion-cules/fthreads.h
2014-01-14 06:53:00 -08:00

448 lines
15 KiB
C

/* FTHREADS.H (c) Copyright "Fish" (David B. Trout), 2001-2012 */
/* Fish's WIN32 version of pthreads */
/* */
/* Released under "The Q Public License Version 1" */
/* (http://www.hercules-390.org/herclic.html) as modifications to */
/* Hercules. */
#ifndef _FTHREADS_H_
#define _FTHREADS_H_
#include "hercules.h"
#ifndef _FTHREADS_C_
#ifndef _HUTIL_DLL_
#define FT_DLL_IMPORT DLL_IMPORT
#else /* _HUTIL_DLL_ */
#define FT_DLL_IMPORT extern
#endif /* _HUTIL_DLL_ */
#else
#define FT_DLL_IMPORT DLL_EXPORT
#endif
////////////////////////////////////////////////////////////////////////////////////
// Just a handy macro to have around...
#define RC(rc) (rc)
////////////////////////////////////////////////////////////////////////////////////
#define MyInitializeCriticalSection(pCS) (InitializeCriticalSectionAndSpinCount((CRITICAL_SECTION*)(pCS),3000))
#define MyEnterCriticalSection(pCS) (EnterCriticalSection((CRITICAL_SECTION*)(pCS)))
#define MyTryEnterCriticalSection(pCS) (TryEnterCriticalSection((CRITICAL_SECTION*)(pCS)))
#define MyLeaveCriticalSection(pCS) (LeaveCriticalSection((CRITICAL_SECTION*)(pCS)))
#define MyDeleteCriticalSection(pCS) (DeleteCriticalSection((CRITICAL_SECTION*)(pCS)))
#ifdef _MSVC_
#define MyCreateThread(sec,stack,start,parm,flags,tid) ((HANDLE) _beginthreadex((sec),(unsigned)(stack),(start),(parm),(flags),(tid)))
#define MyExitThread(code) (_endthreadex((code)))
#else // (Cygwin)
#define MyCreateThread(sec,stack,start,parm,flags,tid) (CreateThread((sec),(stack),(start),(parm),(flags),(tid)))
#define MyExitThread(code) (ExitThread((code)))
#endif // _MSVC_
#define MyCreateEvent(sec,man,set,name) (CreateEvent((sec),(man),(set),(name)))
#define MySetEvent(h) (SetEvent((h)))
#define MyResetEvent(h) (ResetEvent((h)))
#define MyDeleteEvent(h) (CloseHandle((h)))
#define MyCloseHandle(h) (CloseHandle((h)))
#define MyWaitForSingleObject(h,millisecs) (WaitForSingleObject((h),(millisecs)))
////////////////////////////////////////////////////////////////////////////////////
// (need struct timespec for fthread_cond_timedwait)
#if !defined(TIMESPEC_IN_SYS_TYPES_H) && !defined(TIMESPEC_IN_TIME_H)
// (need to define it ourselves)
struct timespec
{
time_t tv_sec; // (seconds)
long tv_nsec; // (nanoseconds)
};
#endif
////////////////////////////////////////////////////////////////////////////////////
// fthread typedefs...
typedef void* FT_W32_HANDLE; // HANDLE
typedef unsigned long FT_W32_DWORD; // DWORD
typedef FT_W32_DWORD fthread_t; // thread id
typedef FT_W32_DWORD fthread_mutexattr_t; // mutex attribute
typedef void* (FT_THREAD_FUNC)(void*); // thread function
typedef FT_THREAD_FUNC* PFT_THREAD_FUNC; // thread function ptr
typedef struct _tagFTU_MUTEX // fthread "mutex" structure
{
FT_W32_HANDLE hMutex; // (ptr to actual mutex structure)
}
fthread_mutex_t;
typedef struct _tagFTU_COND // fthread "condition variable" structure
{
FT_W32_HANDLE hCondVar; // (ptr to actual condition variable structure)
}
fthread_cond_t;
typedef struct _tagFTU_ATTR // fthread "thread attribute" structure
{
size_t nStackSize; // (initial stack size in bytes)
int nDetachState; // (requested detach state: detached/joinable)
}
fthread_attr_t;
////////////////////////////////////////////////////////////////////////////////////
// fthread thread attribute types...
#define FTHREAD_CREATE_JOINABLE 0x4A6F696E // "Join" in ASCII
#define FTHREAD_CREATE_DETACHED 0x44697363 // "Disc" in ASCII
#define FTHREAD_CREATE_DEFAULT FTHREAD_CREATE_JOINABLE
////////////////////////////////////////////////////////////////////////////////////
// Initialize a "thread attribute"...
FT_DLL_IMPORT
int fthread_attr_init
(
fthread_attr_t* pThreadAttr
);
////////////////////////////////////////////////////////////////////////////////////
// Destroy a "thread attribute"...
FT_DLL_IMPORT
int fthread_attr_destroy
(
fthread_attr_t* pThreadAttr
);
////////////////////////////////////////////////////////////////////////////////////
// Set a thread's "detachstate" attribute...
FT_DLL_IMPORT
int fthread_attr_setdetachstate
(
fthread_attr_t* pThreadAttr,
int nDetachState
);
////////////////////////////////////////////////////////////////////////////////////
// Retrieve a thread's "detachstate" attribute...
FT_DLL_IMPORT
int fthread_attr_getdetachstate
(
const fthread_attr_t* pThreadAttr,
int* pnDetachState
);
////////////////////////////////////////////////////////////////////////////////////
// Set a thread's initial stack size...
FT_DLL_IMPORT
int fthread_attr_setstacksize
(
fthread_attr_t* pThreadAttr,
size_t nStackSize
);
////////////////////////////////////////////////////////////////////////////////////
// Retrieve a thread's initial stack size...
FT_DLL_IMPORT
int fthread_attr_getstacksize
(
const fthread_attr_t* pThreadAttr,
size_t* pnStackSize
);
////////////////////////////////////////////////////////////////////////////////////
// Join a thread (i.e. wait for a thread's termination)...
FT_DLL_IMPORT
int fthread_join
(
fthread_t dwThreadID,
void** pExitVal
);
////////////////////////////////////////////////////////////////////////////////////
// Detach a thread (i.e. ignore a thread's termination)...
FT_DLL_IMPORT
int fthread_detach
(
fthread_t dwThreadID
);
/////////////////////////////////////////////////////////////////////////////////////
// Get the handle for a specific Thread ID
DLL_EXPORT
HANDLE fthread_get_handle
(
fthread_t dwThreadID // Thread ID
);
////////////////////////////////////////////////////////////////////////////////////
// Create a new thread...
FT_DLL_IMPORT
int fthread_create
(
fthread_t* pdwThreadID,
fthread_attr_t* pThreadAttr,
PFT_THREAD_FUNC pfnThreadFunc,
void* pvThreadArgs,
const char* pszThreadName
);
////////////////////////////////////////////////////////////////////////////////////
// Exit from a thread...
FT_DLL_IMPORT
void fthread_exit
(
void* ExitVal
);
////////////////////////////////////////////////////////////////////////////////////
// Return thread-id...
FT_DLL_IMPORT
fthread_t fthread_self
(
);
////////////////////////////////////////////////////////////////////////////////////
// Compare thread-ids...
FT_DLL_IMPORT
int fthread_equal
(
fthread_t dwThreadID_1,
fthread_t dwThreadID_2
);
////////////////////////////////////////////////////////////////////////////////////
// (thread signalling not [currently] supported (yet); always returns ENOTSUP...)
FT_DLL_IMPORT
int fthread_kill // FIXME: TODO:
(
int dummy1,
int dummy2
);
////////////////////////////////////////////////////////////////////////////////////
// Initialize a "mutex"...
FT_DLL_IMPORT
int fthread_mutex_init
(
fthread_mutex_t* pFT_MUTEX,
const fthread_mutexattr_t* pFT_MUTEX_ATTR
);
////////////////////////////////////////////////////////////////////////////////////
// Destroy a "mutex"...
FT_DLL_IMPORT
int fthread_mutex_destroy
(
fthread_mutex_t* pFT_MUTEX
);
////////////////////////////////////////////////////////////////////////////////////
// Lock a "mutex"...
FT_DLL_IMPORT
int fthread_mutex_lock
(
fthread_mutex_t* pFT_MUTEX
);
////////////////////////////////////////////////////////////////////////////////////
// Try to lock a "mutex"...
FT_DLL_IMPORT
int fthread_mutex_trylock
(
fthread_mutex_t* pFT_MUTEX
);
////////////////////////////////////////////////////////////////////////////////////
// Unlock a "mutex"...
FT_DLL_IMPORT
int fthread_mutex_unlock
(
fthread_mutex_t* pFT_MUTEX
);
////////////////////////////////////////////////////////////////////////////////////
// Initialize a "condition"...
FT_DLL_IMPORT
int fthread_cond_init
(
fthread_cond_t* pFT_COND_VAR
);
////////////////////////////////////////////////////////////////////////////////////
// Destroy a "condition"...
FT_DLL_IMPORT
int fthread_cond_destroy
(
fthread_cond_t* pFT_COND_VAR
);
////////////////////////////////////////////////////////////////////////////////////
// 'Signal' a "condition"... (causes ONE waiting thread to be released)
FT_DLL_IMPORT
int fthread_cond_signal
(
fthread_cond_t* pFT_COND_VAR
);
////////////////////////////////////////////////////////////////////////////////////
// 'Broadcast' a "condition"... (causes ALL waiting threads to be released)
FT_DLL_IMPORT
int fthread_cond_broadcast
(
fthread_cond_t* pFT_COND_VAR
);
////////////////////////////////////////////////////////////////////////////////////
// Wait for a "condition" to occur...
FT_DLL_IMPORT
int fthread_cond_wait
(
fthread_cond_t* pFT_COND_VAR,
fthread_mutex_t* pFT_MUTEX
);
////////////////////////////////////////////////////////////////////////////////////
// Wait (but not forever) for a "condition" to occur...
FT_DLL_IMPORT
int fthread_cond_timedwait
(
fthread_cond_t* pFT_COND_VAR,
fthread_mutex_t* pFT_MUTEX,
const struct timespec* pTimeTimeout
);
////////////////////////////////////////////////////////////////////////////////////
// fthread mutex attribute types...
//
// FTHREAD_MUTEX_NORMAL This type of mutex does not detect deadlock. A thread
// attempting to relock this mutex without first unlocking
// it shall deadlock. Attempting to unlock a mutex locked
// by a different thread results in undefined behavior.
// Attempting to unlock an unlocked mutex results in
// undefined behavior. The FTHREAD_MUTEX_NORMAL mutex type
// is not currently supported by fthreads.
//
// FTHREAD_MUTEX_ERRORCHECK This type of mutex provides error checking. A thread
// attempting to relock this mutex without first unlocking
// it shall return with an error. A thread attempting to
// unlock a mutex which another thread has locked shall
// return with an error. A thread attempting to unlock an
// unlocked mutex shall return with an error.
//
// FTHREAD_MUTEX_RECURSIVE A thread attempting to relock this mutex without first
// unlocking it shall succeed in locking the mutex. The
// relocking deadlock which can occur with mutexes of type
// FTHREAD_MUTEX_NORMAL cannot occur with this type of mutex.
// Multiple locks of this mutex shall require the same number
// of unlocks to release the mutex before another thread
// can acquire the mutex. A thread attempting to unlock a
// mutex which another thread has locked shall return with
// an error. A thread attempting to unlock an unlocked mutex
// shall return with an error.
//
// FTHREAD_MUTEX_DEFAULT Attempting to recursively lock a mutex of this type results
// in undefined behavior. Attempting to unlock a mutex of this
// type which was not locked by the calling thread results
// in undefined behavior. Attempting to unlock a mutex of this
// type which is not locked results in undefined behavior.
// An implementation may map this mutex to one of the other
// mutex types.
#define FTHREAD_MUTEX_NORMAL 0x44656164 // "Dead" in ASCII (*UNSUPPORTED*)
#define FTHREAD_MUTEX_ERRORCHECK 0x4F6E6365 // "Once" in ASCII
#define FTHREAD_MUTEX_RECURSIVE 0x4D616E79 // "Many" in ASCII
#define FTHREAD_MUTEX_DEFAULT FTHREAD_MUTEX_ERRORCHECK
////////////////////////////////////////////////////////////////////////////////////
// Initialize a "mutex" attribute...
FT_DLL_IMPORT
int fthread_mutexattr_init
(
fthread_mutexattr_t* pFT_MUTEX_ATTR
);
////////////////////////////////////////////////////////////////////////////////////
// Destroy a "mutex" attribute...
FT_DLL_IMPORT
int fthread_mutexattr_destroy
(
fthread_mutexattr_t* pFT_MUTEX_ATTR
);
////////////////////////////////////////////////////////////////////////////////////
// Retrieve "mutex" attribute type...
FT_DLL_IMPORT
int fthread_mutexattr_gettype
(
const fthread_mutexattr_t* pFT_MUTEX_ATTR,
int* pnMutexType
);
////////////////////////////////////////////////////////////////////////////////////
// Set "mutex" attribute type...
FT_DLL_IMPORT
int fthread_mutexattr_settype
(
fthread_mutexattr_t* pFT_MUTEX_ATTR,
int nMutexType
);
////////////////////////////////////////////////////////////////////////////////////
// Thread Scheduling...
#define SCHED_FIFO 0 // First in, first out (FIFO) scheduling policy.
#define SCHED_RR 1 // Round robin scheduling policy.
#define SCHED_SPORADIC 2 // Sporadic server scheduling policy.
#define SCHED_OTHER 3 // Another scheduling policy.
#define FTHREAD_SCHED_POLICY SCHED_RR // Our only valid scheduling policy
#define FTHREAD_MIN_PRI (+20) // Same as Hercules
#define FTHREAD_MAX_PRI (-20) // Same as Hercules
struct sched_param // Scheduling parameters structure...
{
int sched_priority; // Thread priority (see fthreads.c for range)
};
typedef struct sched_param sched_param;
FT_DLL_IMPORT int fthread_getschedparam ( fthread_t dwThreadID, int* pnPolicy, struct sched_param* pSCHPARM );
FT_DLL_IMPORT int fthread_setschedparam ( fthread_t dwThreadID, int nPolicy, const struct sched_param* pSCHPARM );
FT_DLL_IMPORT int fthread_setschedprio ( fthread_t dwThreadID, int nPriority );
FT_DLL_IMPORT int fthread_get_min_prio ( int nPolicy );
FT_DLL_IMPORT int fthread_get_max_prio ( int nPolicy );
////////////////////////////////////////////////////////////////////////////////////
#endif // _FTHREADS_H_