* Added API to ithread, created the following functions:

- int ithread_initialize_library(void);
	- int ithread_cleanup_library(void);
	- int ithread_initialize_thread(void);
	- int ithread_cleanup_thread(void);
	* SF Bug Tracker [ 2876374 ] Access Violation when compiling with Visual Studio 2008
	Submitted: Stulle ( stulleamgym ) - 2009-10-10 19:05

	Hi,

	I am one of the devs of the MorphXT project and I use this lib in some
	other of my projects, too. When I tried to upgrade the lib earlier for one
	of my projects I had to realise that something did not work at first and
	while most of the things were reasonably ease to be fixed. Now, the last
	thing I encountered was not so easy to fix and I am uncertain if my fix is
	any good so I'll just post it here and wait for some comments.

	The problem was that I got an Access Violation when calling "UpnpInit". It
	would call "ithread_rwlock_init(&GlobalHndRWLock, NULL)" which eventually
	led to calling "pthread_cond_init" and I got the error notice at
	"EnterCriticalSection (&ptw32_cond_list_lock);". It appeared that
	"ptw32_cond_list_lock" was NULL. Now, I found two ways to fix this. Firstly
	moving the whole block after at least one of the "ThreadPoolInit" calls
	will fix the issue. Secondly, you could add:
	#ifdef WIN32
	#ifdef PTW32_STATIC_LIB
	// to get the following working we need this... is it a good patch or
	not... I do not know!
	pthread_win32_process_attach_np();
	#endif
	#endif
	right before "ithread_rwlock_init(&GlobalHndRWLock, NULL)".

	Just so you know, I am using libupnp 1.6.6 and libpthreads 2.8.0 and both
	are linked static into the binaries. I am currently using Visual Studio
	2008 for development with Windows being the target OS. Any comment at your
	end?

	Regards, Stulle



git-svn-id: https://pupnp.svn.sourceforge.net/svnroot/pupnp/trunk@527 119443c7-1b9e-41f8-b6fc-b9c35fce742c
This commit is contained in:
Marcelo Roberto Jimenez 2010-03-27 19:46:16 +00:00
parent 9c440e2cbf
commit 3fb182aa95
5 changed files with 534 additions and 544 deletions

View File

@ -2,7 +2,48 @@
Version 1.8.0 Version 1.8.0
******************************************************************************* *******************************************************************************
2010-03-21 Marcelo Jimenez <mroberto(at)users.sourceforge.net> 2010-03-27 Marcelo Jimenez <mroberto(at)users.sourceforge.net>
* Added API to ithread, created the following functions:
- int ithread_initialize_library(void);
- int ithread_cleanup_library(void);
- int ithread_initialize_thread(void);
- int ithread_cleanup_thread(void);
* SF Bug Tracker [ 2876374 ] Access Violation when compiling with Visual Studio 2008
Submitted: Stulle ( stulleamgym ) - 2009-10-10 19:05
Hi,
I am one of the devs of the MorphXT project and I use this lib in some
other of my projects, too. When I tried to upgrade the lib earlier for one
of my projects I had to realise that something did not work at first and
while most of the things were reasonably ease to be fixed. Now, the last
thing I encountered was not so easy to fix and I am uncertain if my fix is
any good so I'll just post it here and wait for some comments.
The problem was that I got an Access Violation when calling "UpnpInit". It
would call "ithread_rwlock_init(&GlobalHndRWLock, NULL)" which eventually
led to calling "pthread_cond_init" and I got the error notice at
"EnterCriticalSection (&ptw32_cond_list_lock);". It appeared that
"ptw32_cond_list_lock" was NULL. Now, I found two ways to fix this. Firstly
moving the whole block after at least one of the "ThreadPoolInit" calls
will fix the issue. Secondly, you could add:
#ifdef WIN32
#ifdef PTW32_STATIC_LIB
// to get the following working we need this... is it a good patch or
not... I do not know!
pthread_win32_process_attach_np();
#endif
#endif
right before "ithread_rwlock_init(&GlobalHndRWLock, NULL)".
Just so you know, I am using libupnp 1.6.6 and libpthreads 2.8.0 and both
are linked static into the binaries. I am currently using Visual Studio
2008 for development with Windows being the target OS. Any comment at your
end?
Regards, Stulle
2010-03-27 Marcelo Jimenez <mroberto(at)users.sourceforge.net>
* Forward port of svn revision 505: * Forward port of svn revision 505:
SF Patch Tracker [ 2836704 ] Patch for Solaris10 compilation and usage. SF Patch Tracker [ 2836704 ] Patch for Solaris10 compilation and usage.
Submitted By: zephyrus ( zephyrus00jp ) Submitted By: zephyrus ( zephyrus00jp )

View File

@ -154,14 +154,19 @@ dnl # current: 3 -> 4
dnl # revision: 6 -> 0 dnl # revision: 6 -> 0
dnl # - Interface has been removed in upnp dnl # - Interface has been removed in upnp
dnl # age = 0 dnl # age = 0
dnl # - Code has changed in threadutil
dnl # revision: 3 -> 4
dnl # - Interfaces have been changed, added and removed in upnp
dnl # current: 4 -> 5
dnl # revision: 4 -> 0
dnl # dnl #
dnl #AC_SUBST([LT_VERSION_IXML], [2:4:0]) dnl #AC_SUBST([LT_VERSION_IXML], [2:4:0])
dnl #AC_SUBST([LT_VERSION_THREADUTIL], [4:3:2]) dnl #AC_SUBST([LT_VERSION_THREADUTIL], [5:0:2])
dnl #AC_SUBST([LT_VERSION_UPNP], [4:0:0]) dnl #AC_SUBST([LT_VERSION_UPNP], [4:0:0])
dnl # dnl #
dnl ############################################################################ dnl ############################################################################
AC_SUBST([LT_VERSION_IXML], [2:4:0]) AC_SUBST([LT_VERSION_IXML], [2:4:0])
AC_SUBST([LT_VERSION_THREADUTIL], [4:3:2]) AC_SUBST([LT_VERSION_THREADUTIL], [5:0:2])
AC_SUBST([LT_VERSION_UPNP], [4:0:0]) AC_SUBST([LT_VERSION_UPNP], [4:0:0])
dnl ############################################################################ dnl ############################################################################
dnl # Repeating the algorithm to place it closer to the modificatin place: dnl # Repeating the algorithm to place it closer to the modificatin place:

View File

@ -30,19 +30,21 @@
******************************************************************************/ ******************************************************************************/
#ifndef ITHREADH #ifndef ITHREAD_H
#define ITHREADH #define ITHREAD_H
/*! /*!
* \file * \file
*/ */
#if !defined(WIN32) #if !defined(WIN32)
#include <sys/param.h> #include <sys/param.h>
#endif #endif
#include "UpnpGlobal.h" /* For EXPORT_SPEC */
#include "UpnpGlobal.h" /* For UPNP_INLINE, EXPORT_SPEC */
#ifdef __cplusplus #ifdef __cplusplus
@ -94,6 +96,7 @@ extern "C" {
***************************************************************************/ ***************************************************************************/
typedef pthread_t ithread_t; typedef pthread_t ithread_t;
/**************************************************************************** /****************************************************************************
* Name: ithread_attr_t * Name: ithread_attr_t
* *
@ -181,6 +184,95 @@ typedef pthread_rwlockattr_t ithread_rwlockattr_t;
***************************************************************************/ ***************************************************************************/
typedef pthread_rwlock_t ithread_rwlock_t; typedef pthread_rwlock_t ithread_rwlock_t;
/****************************************************************************
* Function: ithread_initialize_library
*
* Description:
* Initializes the library. Does nothing in all implementations, except
* when statically linked for WIN32.
* Parameters:
* none.
* Returns:
* 0 on success, Nonzero on failure.
***************************************************************************/
static UPNP_INLINE int ithread_initialize_library(void) {
int ret = 0;
#if defined(WIN32) && defined(PTW32_STATIC_LIB)
ret = !pthread_win32_process_attach_np();
#endif
return ret;
}
/****************************************************************************
* Function: ithread_cleanup_library
*
* Description:
* Clean up library resources. Does nothing in all implementations, except
* when statically linked for WIN32.
* Parameters:
* none.
* Returns:
* 0 on success, Nonzero on failure.
***************************************************************************/
static UPNP_INLINE int ithread_cleanup_library(void) {
int ret = 0;
#if defined(WIN32) && defined(PTW32_STATIC_LIB)
ret = !pthread_win32_process_detach_np();
#endif
return ret;
}
/****************************************************************************
* Function: ithread_initialize_thread
*
* Description:
* Initializes the thread. Does nothing in all implementations, except
* when statically linked for WIN32.
* Parameters:
* none.
* Returns:
* 0 on success, Nonzero on failure.
***************************************************************************/
static UPNP_INLINE int ithread_initialize_thread(void) {
int ret = 0;
#if defined(WIN32) && defined(PTW32_STATIC_LIB)
ret = !pthread_win32_thread_attach_np();
#endif
return ret;
}
/****************************************************************************
* Function: ithread_cleanup_thread
*
* Description:
* Clean up thread resources. Does nothing in all implementations, except
* when statically linked for WIN32.
* Parameters:
* none.
* Returns:
* 0 on success, Nonzero on failure.
***************************************************************************/
static UPNP_INLINE int ithread_cleanup_thread(void) {
int ret = 0;
#if defined(WIN32) && defined(PTW32_STATIC_LIB)
ret = !pthread_win32_thread_detach_np();
#endif
return ret;
}
/**************************************************************************** /****************************************************************************
* Function: ithread_mutexattr_init * Function: ithread_mutexattr_init
* *
@ -517,7 +609,6 @@ typedef pthread_rwlock_t ithread_rwlock_t;
#define ithread_cond_init pthread_cond_init #define ithread_cond_init pthread_cond_init
/**************************************************************************** /****************************************************************************
* Function: ithread_cond_signal * Function: ithread_cond_signal
* *
@ -577,22 +668,18 @@ typedef pthread_rwlock_t ithread_rwlock_t;
* Function: pthread_cond_timedwait * Function: pthread_cond_timedwait
* *
* Description: * Description:
* Atomically releases the associated mutex and waits on the condition. * Atomically releases the associated mutex and waits on the
* If the condition is not signaled in the specified time * condition.
* than the * If the condition is not signaled in the specified time than the
* call times out and returns. * call times out and returns.
* Associated mutex MUST be locked by thread before entering * Associated mutex MUST be locked by thread before entering this call.
* this call.
* Mutex is reacquired when call returns. * Mutex is reacquired when call returns.
* Parameters: * Parameters:
* ithread_cond_t * cond (must be valid non NULL pointer to * ithread_cond_t *cond (must be valid non NULL pointer to ithread_cond_t)
* ithread_cond_t)
* cond must be initialized * cond must be initialized
* ithread_mutex_t *mutex (must be valid non NULL pointer to * ithread_mutex_t *mutex (must be valid non NULL pointer to ithread_mutex_t)
* ithread_mutex_t)
* Mutex must be locked. * Mutex must be locked.
* const struct timespec *abstime (absolute time, measured * const struct timespec *abstime (absolute time, measured from Jan 1, 1970)
* from Jan 1, 1970)
* Returns: * Returns:
* 0 on success. ETIMEDOUT on timeout. Nonzero on failure. * 0 on success. ETIMEDOUT on timeout. Nonzero on failure.
* See man page for pthread_cond_timedwait * See man page for pthread_cond_timedwait
@ -664,6 +751,7 @@ typedef pthread_rwlock_t ithread_rwlock_t;
***************************************************************************/ ***************************************************************************/
#define ithread_exit pthread_exit #define ithread_exit pthread_exit
/**************************************************************************** /****************************************************************************
* Function: ithread_get_current_thread_id * Function: ithread_get_current_thread_id
* *
@ -687,6 +775,7 @@ typedef pthread_rwlock_t ithread_rwlock_t;
***************************************************************************/ ***************************************************************************/
#define ithread_self pthread_self #define ithread_self pthread_self
/**************************************************************************** /****************************************************************************
* Function: ithread_detach * Function: ithread_detach
* *
@ -700,6 +789,7 @@ typedef pthread_rwlock_t ithread_rwlock_t;
***************************************************************************/ ***************************************************************************/
#define ithread_detach pthread_detach #define ithread_detach pthread_detach
/**************************************************************************** /****************************************************************************
* Function: ithread_join * Function: ithread_join
* *
@ -719,7 +809,6 @@ typedef pthread_rwlock_t ithread_rwlock_t;
#define ithread_join pthread_join #define ithread_join pthread_join
/**************************************************************************** /****************************************************************************
* Function: isleep * Function: isleep
* *
@ -739,6 +828,7 @@ typedef pthread_rwlock_t ithread_rwlock_t;
#define isleep sleep #define isleep sleep
#endif #endif
/**************************************************************************** /****************************************************************************
* Function: isleep * Function: isleep
* *
@ -764,9 +854,11 @@ typedef pthread_rwlock_t ithread_rwlock_t;
EXPORT_SPEC int pthread_mutexattr_setkind_np(pthread_mutexattr_t *attr, int kind); EXPORT_SPEC int pthread_mutexattr_setkind_np(pthread_mutexattr_t *attr, int kind);
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* ITHREADH */
#endif /* ITHREAD_H */

View File

@ -68,9 +68,6 @@ static unsigned long DiffMillis(struct timeval *time1, struct timeval *time2)
{ {
double temp = 0; double temp = 0;
assert(time1 != NULL);
assert(time2 != NULL);
temp = time1->tv_sec - time2->tv_sec; temp = time1->tv_sec - time2->tv_sec;
/* convert to milliseconds */ /* convert to milliseconds */
temp *= 1000; temp *= 1000;
@ -94,8 +91,6 @@ static unsigned long DiffMillis(struct timeval *time1, struct timeval *time2)
*****************************************************************************/ *****************************************************************************/
static void StatsInit(ThreadPoolStats *stats) static void StatsInit(ThreadPoolStats *stats)
{ {
assert(stats != NULL);
stats->totalIdleTime = 0; stats->totalIdleTime = 0;
stats->totalJobsHQ = 0; stats->totalJobsHQ = 0;
stats->totalJobsLQ = 0; stats->totalJobsLQ = 0;
@ -205,9 +200,6 @@ static int CmpThreadPoolJob(void *jobA, void *jobB)
ThreadPoolJob *a = (ThreadPoolJob *)jobA; ThreadPoolJob *a = (ThreadPoolJob *)jobA;
ThreadPoolJob *b = (ThreadPoolJob *)jobB; ThreadPoolJob *b = (ThreadPoolJob *)jobB;
assert(jobA != NULL);
assert(jobB != NULL);
return a->jobId == b->jobId; return a->jobId == b->jobId;
} }
@ -221,8 +213,6 @@ static int CmpThreadPoolJob(void *jobA, void *jobB)
*****************************************************************************/ *****************************************************************************/
static void FreeThreadPoolJob(ThreadPool *tp, ThreadPoolJob *tpj) static void FreeThreadPoolJob(ThreadPool *tp, ThreadPoolJob *tpj)
{ {
assert(tp != NULL);
FreeListFree(&tp->jobFreeList, tpj); FreeListFree(&tp->jobFreeList, tpj);
} }
@ -340,8 +330,6 @@ static void BumpPriority(ThreadPool *tp)
unsigned long diffTime = 0; unsigned long diffTime = 0;
ThreadPoolJob *tempJob = NULL; ThreadPoolJob *tempJob = NULL;
assert(tp != NULL);
gettimeofday(&now, NULL); gettimeofday(&now, NULL);
while (!done) { while (!done) {
if (tp->medJobQ.size) { if (tp->medJobQ.size) {
@ -389,12 +377,9 @@ static void SetRelTimeout( struct timespec *time, int relMillis )
int sec = relMillis / 1000; int sec = relMillis / 1000;
int milliSeconds = relMillis % 1000; int milliSeconds = relMillis % 1000;
assert( time != NULL );
gettimeofday(&now, NULL); gettimeofday(&now, NULL);
time->tv_sec = now.tv_sec + sec; time->tv_sec = now.tv_sec + sec;
time->tv_nsec = ( (now.tv_usec/1000) + milliSeconds ) * 1000000; time->tv_nsec = (now.tv_usec / 1000 + milliSeconds) * 1000000;
} }
/**************************************************************************** /****************************************************************************
@ -420,7 +405,10 @@ static void SetSeed()
srand((unsigned int)t.tv_usec + ithread_get_current_thread_id()); srand((unsigned int)t.tv_usec + ithread_get_current_thread_id());
#else #else
{ {
volatile union { volatile pthread_t tid; volatile unsigned i; } idu; volatile union {
volatile pthread_t tid;
volatile unsigned i;
} idu;
idu.tid = ithread_get_current_thread_id(); idu.tid = ithread_get_current_thread_id();
srand((unsigned int)t.millitm + idu.i); srand((unsigned int)t.millitm + idu.i);
@ -453,15 +441,10 @@ static void *WorkerThread( void *arg )
int retCode = 0; int retCode = 0;
int persistent = -1; int persistent = -1;
ThreadPool *tp = (ThreadPool *) arg; ThreadPool *tp = (ThreadPool *) arg;
// allow static linking
#ifdef WIN32
#ifdef PTW32_STATIC_LIB
pthread_win32_thread_attach_np();
#endif
#endif
assert( tp != NULL );
// Increment total thread count ithread_initialize_thread();
/* Increment total thread count */
ithread_mutex_lock(&tp->mutex); ithread_mutex_lock(&tp->mutex);
tp->totalThreads++; tp->totalThreads++;
ithread_cond_broadcast(&tp->start_and_shutdown); ithread_cond_broadcast(&tp->start_and_shutdown);
@ -482,71 +465,47 @@ static void *WorkerThread( void *arg )
tp->stats.totalWorkTime += ( StatsTime( NULL ) - start ); // work time tp->stats.totalWorkTime += ( StatsTime( NULL ) - start ); // work time
StatsTime( &start ); // idle time StatsTime( &start ); // idle time
if( persistent == 1 ) { if (persistent == 0) {
// Persistent thread tp->stats.workerThreads--;
// becomes a regular thread } else if (persistent == 1) {
/* Persistent thread becomes a regular thread */
tp->persistentThreads--; tp->persistentThreads--;
} }
if( persistent == 0 ) { /* Check for a job or shutdown */
tp->stats.workerThreads--;
}
// Check for a job or shutdown
while (tp->lowJobQ.size == 0 && while (tp->lowJobQ.size == 0 &&
tp->medJobQ.size == 0 && tp->medJobQ.size == 0 &&
tp->highJobQ.size == 0 && tp->highJobQ.size == 0 &&
!tp->persistentJob && !tp->persistentJob && !tp->shutdown) {
!tp->shutdown ) { /* If wait timed out and we currently have more than the
// If wait timed out * min threads, or if we have more than the max threads
// and we currently have more than the * (only possible if the attributes have been reset)
// min threads, or if we have more than the max threads * let this thread die. */
// (only possible if the attributes have been reset)
// let this thread die.
if ((retCode == ETIMEDOUT && if ((retCode == ETIMEDOUT &&
tp->totalThreads > tp->attr.minThreads) || tp->totalThreads > tp->attr.minThreads) ||
(tp->attr.maxThreads != -1 && (tp->attr.maxThreads != -1 &&
tp->totalThreads > tp->attr.maxThreads)) { tp->totalThreads > tp->attr.maxThreads)) {
tp->stats.idleThreads--; tp->stats.idleThreads--;
tp->totalThreads--; goto exit_function;
ithread_cond_broadcast( &tp->start_and_shutdown );
ithread_mutex_unlock( &tp->mutex );
#ifdef WIN32
#ifdef PTW32_STATIC_LIB
// allow static linking
pthread_win32_thread_detach_np ();
#endif
#endif
return NULL;
} }
SetRelTimeout(&timeout, tp->attr.maxIdleTime); SetRelTimeout(&timeout, tp->attr.maxIdleTime);
// wait for a job up to the specified max time /* wait for a job up to the specified max time */
retCode = ithread_cond_timedwait( retCode = ithread_cond_timedwait(
&tp->condition, &tp->mutex, &timeout); &tp->condition, &tp->mutex, &timeout);
} }
tp->stats.idleThreads--; tp->stats.idleThreads--;
tp->stats.totalIdleTime += ( StatsTime( NULL ) - start ); // idle time /* idle time */
StatsTime( &start ); // work time tp->stats.totalIdleTime += StatsTime(NULL) - start;
/* work time */
// bump priority of starved jobs StatsTime(&start);
/* bump priority of starved jobs */
BumpPriority(tp); BumpPriority(tp);
/* if shutdown then stop */
// if shutdown then stop
if (tp->shutdown) { if (tp->shutdown) {
tp->totalThreads--; goto exit_function;
ithread_cond_broadcast( &tp->start_and_shutdown );
ithread_mutex_unlock( &tp->mutex );
#ifdef WIN32
#ifdef PTW32_STATIC_LIB
// allow static linking
pthread_win32_thread_detach_np ();
#endif
#endif
return NULL;
} else { } else {
// Pick up persistent job if available /* Pick up persistent job if available */
if (tp->persistentJob) { if (tp->persistentJob) {
job = tp->persistentJob; job = tp->persistentJob;
tp->persistentJob = NULL; tp->persistentJob = NULL;
@ -556,7 +515,7 @@ static void *WorkerThread( void *arg )
} else { } else {
tp->stats.workerThreads++; tp->stats.workerThreads++;
persistent = 0; persistent = 0;
// Pick the highest priority job /* Pick the highest priority job */
if (tp->highJobQ.size > 0) { if (tp->highJobQ.size > 0) {
head = ListHead(&tp->highJobQ); head = ListHead(&tp->highJobQ);
job = (ThreadPoolJob *) head->item; job = (ThreadPoolJob *) head->item;
@ -573,14 +532,9 @@ static void *WorkerThread( void *arg )
CalcWaitTime(tp, LOW_PRIORITY, job); CalcWaitTime(tp, LOW_PRIORITY, job);
ListDelNode(&tp->lowJobQ, head, 0); ListDelNode(&tp->lowJobQ, head, 0);
} else { } else {
// Should never get here /* Should never get here */
assert( 0 );
tp->stats.workerThreads--; tp->stats.workerThreads--;
tp->totalThreads--; goto exit_function;
ithread_cond_broadcast( &tp->start_and_shutdown );
ithread_mutex_unlock( &tp->mutex );
return NULL;
} }
} }
} }
@ -588,20 +542,23 @@ static void *WorkerThread( void *arg )
tp->busyThreads++; tp->busyThreads++;
ithread_mutex_unlock(&tp->mutex); ithread_mutex_unlock(&tp->mutex);
/* In the future can log info */
if (SetPriority(job->priority) != 0) { if (SetPriority(job->priority) != 0) {
// In the future can log
// info
} else { } else {
// In the future can log
// info
} }
/* run the job */
// run the job
job->func(job->arg); job->func(job->arg);
/* return to Normal */
// return to Normal
SetPriority(DEFAULT_PRIORITY); SetPriority(DEFAULT_PRIORITY);
} }
exit_function:
tp->totalThreads--;
ithread_cond_broadcast(&tp->start_and_shutdown);
ithread_mutex_unlock(&tp->mutex);
ithread_cleanup_thread();
return NULL;
} }
/**************************************************************************** /****************************************************************************
@ -621,9 +578,6 @@ static ThreadPoolJob *CreateThreadPoolJob( ThreadPoolJob *job, int id, ThreadPoo
{ {
ThreadPoolJob *newJob = NULL; ThreadPoolJob *newJob = NULL;
assert( job != NULL );
assert( tp != NULL );
newJob = (ThreadPoolJob *)FreeListAlloc(&tp->jobFreeList); newJob = (ThreadPoolJob *)FreeListAlloc(&tp->jobFreeList);
if (newJob) { if (newJob) {
*newJob = *job; *newJob = *job;
@ -656,13 +610,10 @@ static int CreateWorker( ThreadPool *tp )
int rc = 0; int rc = 0;
int currentThreads = tp->totalThreads + 1; int currentThreads = tp->totalThreads + 1;
assert( tp != NULL );
if (tp->attr.maxThreads != INFINITE_THREADS && if (tp->attr.maxThreads != INFINITE_THREADS &&
currentThreads > tp->attr.maxThreads) { currentThreads > tp->attr.maxThreads) {
return EMAXTHREADS; return EMAXTHREADS;
} }
rc = ithread_create(&temp, NULL, WorkerThread, tp); rc = ithread_create(&temp, NULL, WorkerThread, tp);
if (rc == 0) { if (rc == 0) {
rc = ithread_detach(temp); rc = ithread_detach(temp);
@ -670,7 +621,6 @@ static int CreateWorker( ThreadPool *tp )
ithread_cond_wait(&tp->start_and_shutdown, &tp->mutex); ithread_cond_wait(&tp->start_and_shutdown, &tp->mutex);
} }
} }
if (tp->stats.maxThreads < tp->totalThreads) { if (tp->stats.maxThreads < tp->totalThreads) {
tp->stats.maxThreads = tp->totalThreads; tp->stats.maxThreads = tp->totalThreads;
} }
@ -695,8 +645,6 @@ static void AddWorker(ThreadPool *tp)
int jobs = 0; int jobs = 0;
int threads = 0; int threads = 0;
assert( tp != NULL );
jobs = tp->highJobQ.size + tp->lowJobQ.size + tp->medJobQ.size; jobs = tp->highJobQ.size + tp->lowJobQ.size + tp->medJobQ.size;
threads = tp->totalThreads - tp->persistentThreads; threads = tp->totalThreads - tp->persistentThreads;
while (threads == 0 || while (threads == 0 ||
@ -746,62 +694,38 @@ int ThreadPoolInit( ThreadPool *tp, ThreadPoolAttr *attr )
int retCode = 0; int retCode = 0;
int i = 0; int i = 0;
assert( tp != NULL ); if (!tp) {
if( tp == NULL ) {
return EINVAL; return EINVAL;
} }
#ifdef WIN32
#ifdef PTW32_STATIC_LIB
pthread_win32_process_attach_np();
#endif
#endif
retCode += ithread_mutex_init(&tp->mutex, NULL); retCode += ithread_mutex_init(&tp->mutex, NULL);
assert( retCode == 0 );
retCode += ithread_mutex_lock(&tp->mutex); retCode += ithread_mutex_lock(&tp->mutex);
assert( retCode == 0 );
retCode += ithread_cond_init(&tp->condition, NULL); retCode += ithread_cond_init(&tp->condition, NULL);
assert( retCode == 0 );
retCode += ithread_cond_init(&tp->start_and_shutdown, NULL); retCode += ithread_cond_init(&tp->start_and_shutdown, NULL);
assert( retCode == 0 ); if (retCode) {
if( retCode != 0 ) {
return EAGAIN; return EAGAIN;
} }
if (attr) { if (attr) {
tp->attr = ( *attr ); tp->attr = *attr;
} else { } else {
TPAttrInit(&tp->attr); TPAttrInit(&tp->attr);
} }
if (SetPolicyType(tp->attr.schedPolicy) != 0) { if (SetPolicyType(tp->attr.schedPolicy) != 0) {
ithread_mutex_unlock(&tp->mutex); ithread_mutex_unlock(&tp->mutex);
ithread_mutex_destroy(&tp->mutex); ithread_mutex_destroy(&tp->mutex);
ithread_cond_destroy(&tp->condition); ithread_cond_destroy(&tp->condition);
ithread_cond_destroy(&tp->start_and_shutdown); ithread_cond_destroy(&tp->start_and_shutdown);
return INVALID_POLICY; return INVALID_POLICY;
} }
retCode += FreeListInit( retCode += FreeListInit(
&tp->jobFreeList, sizeof(ThreadPoolJob), JOBFREELISTSIZE); &tp->jobFreeList, sizeof(ThreadPoolJob), JOBFREELISTSIZE);
assert( retCode == 0 );
StatsInit(&tp->stats); StatsInit(&tp->stats);
retCode += ListInit(&tp->highJobQ, CmpThreadPoolJob, NULL); retCode += ListInit(&tp->highJobQ, CmpThreadPoolJob, NULL);
assert( retCode == 0 );
retCode += ListInit(&tp->medJobQ, CmpThreadPoolJob, NULL); retCode += ListInit(&tp->medJobQ, CmpThreadPoolJob, NULL);
assert( retCode == 0 );
retCode += ListInit(&tp->lowJobQ, CmpThreadPoolJob, NULL); retCode += ListInit(&tp->lowJobQ, CmpThreadPoolJob, NULL);
assert( retCode == 0 ); if (retCode) {
if( retCode != 0 ) {
retCode = EAGAIN; retCode = EAGAIN;
} else { } else {
tp->persistentJob = NULL; tp->persistentJob = NULL;
@ -811,7 +735,8 @@ int ThreadPoolInit( ThreadPool *tp, ThreadPoolAttr *attr )
tp->busyThreads = 0; tp->busyThreads = 0;
tp->persistentThreads = 0; tp->persistentThreads = 0;
for (i = 0; i < tp->attr.minThreads; ++i) { for (i = 0; i < tp->attr.minThreads; ++i) {
if( ( retCode = CreateWorker( tp ) ) != 0 ) { retCode = CreateWorker(tp);
if (retCode) {
break; break;
} }
} }
@ -819,8 +744,8 @@ int ThreadPoolInit( ThreadPool *tp, ThreadPoolAttr *attr )
ithread_mutex_unlock(&tp->mutex); ithread_mutex_unlock(&tp->mutex);
if( retCode != 0 ) { if (retCode) {
// clean up if the min threads could not be created /* clean up if the min threads could not be created */
ThreadPoolShutdown(tp); ThreadPoolShutdown(tp);
} }
@ -848,59 +773,51 @@ int ThreadPoolInit( ThreadPool *tp, ThreadPoolAttr *attr )
*****************************************************************************/ *****************************************************************************/
int ThreadPoolAddPersistent(ThreadPool *tp, ThreadPoolJob *job, int *jobId) int ThreadPoolAddPersistent(ThreadPool *tp, ThreadPoolJob *job, int *jobId)
{ {
int ret = 0;
int tempId = -1; int tempId = -1;
ThreadPoolJob *temp = NULL; ThreadPoolJob *temp = NULL;
assert( tp != NULL ); if (!tp || !job) {
assert( job != NULL );
if( ( tp == NULL ) || ( job == NULL ) ) {
return EINVAL; return EINVAL;
} }
if (!jobId) {
if( jobId == NULL ) {
jobId = &tempId; jobId = &tempId;
} }
*jobId = INVALID_JOB_ID; *jobId = INVALID_JOB_ID;
ithread_mutex_lock(&tp->mutex); ithread_mutex_lock(&tp->mutex);
assert( job->priority == LOW_PRIORITY || /* Create A worker if less than max threads running */
job->priority == MED_PRIORITY ||
job->priority == HIGH_PRIORITY );
// Create A worker if less than max threads running
if (tp->totalThreads < tp->attr.maxThreads) { if (tp->totalThreads < tp->attr.maxThreads) {
CreateWorker(tp); CreateWorker(tp);
} else { } else {
// if there is more than one worker thread /* if there is more than one worker thread
// available then schedule job, otherwise fail * available then schedule job, otherwise fail */
if (tp->totalThreads - tp->persistentThreads - 1 == 0) { if (tp->totalThreads - tp->persistentThreads - 1 == 0) {
ithread_mutex_unlock( &tp->mutex ); ret = EMAXTHREADS;
return EMAXTHREADS; goto exit_function;
} }
} }
temp = CreateThreadPoolJob(job, tp->lastJobId, tp); temp = CreateThreadPoolJob(job, tp->lastJobId, tp);
if( temp == NULL ) { if (!temp) {
ithread_mutex_unlock( &tp->mutex ); ret = EOUTOFMEM;
return EOUTOFMEM; goto exit_function;
} }
tp->persistentJob = temp; tp->persistentJob = temp;
// Notify a waiting thread /* Notify a waiting thread */
ithread_cond_signal(&tp->condition); ithread_cond_signal(&tp->condition);
// wait until long job has been picked up /* wait until long job has been picked up */
while( tp->persistentJob != NULL ) { while (tp->persistentJob) {
ithread_cond_wait(&tp->start_and_shutdown, &tp->mutex); ithread_cond_wait(&tp->start_and_shutdown, &tp->mutex);
} }
*jobId = tp->lastJobId++; *jobId = tp->lastJobId++;
exit_function:
ithread_mutex_unlock(&tp->mutex); ithread_mutex_unlock(&tp->mutex);
return 0; return ret;
} }
/**************************************************************************** /****************************************************************************
@ -924,42 +841,29 @@ int ThreadPoolAddPersistent( ThreadPool *tp, ThreadPoolJob *job, int *jobId )
int ThreadPoolAdd(ThreadPool *tp, ThreadPoolJob *job, int *jobId) int ThreadPoolAdd(ThreadPool *tp, ThreadPoolJob *job, int *jobId)
{ {
int rc = EOUTOFMEM; int rc = EOUTOFMEM;
int tempId = -1; int tempId = -1;
int totalJobs; int totalJobs;
ThreadPoolJob *temp = NULL; ThreadPoolJob *temp = NULL;
assert( tp != NULL ); if (!tp || !job) {
assert( job != NULL );
if( ( tp == NULL ) || ( job == NULL ) ) {
return EINVAL; return EINVAL;
} }
ithread_mutex_lock(&tp->mutex); ithread_mutex_lock(&tp->mutex);
assert( job->priority == LOW_PRIORITY ||
job->priority == MED_PRIORITY ||
job->priority == HIGH_PRIORITY );
totalJobs = tp->highJobQ.size + tp->lowJobQ.size + tp->medJobQ.size; totalJobs = tp->highJobQ.size + tp->lowJobQ.size + tp->medJobQ.size;
if (totalJobs >= tp->attr.maxJobsTotal) { if (totalJobs >= tp->attr.maxJobsTotal) {
fprintf(stderr, "total jobs = %d, too many jobs", totalJobs); fprintf(stderr, "total jobs = %d, too many jobs", totalJobs);
ithread_mutex_unlock( &tp->mutex ); goto exit_function;
return rc;
} }
if (!jobId) {
if( jobId == NULL ) {
jobId = &tempId; jobId = &tempId;
} }
*jobId = INVALID_JOB_ID; *jobId = INVALID_JOB_ID;
temp = CreateThreadPoolJob(job, tp->lastJobId, tp); temp = CreateThreadPoolJob(job, tp->lastJobId, tp);
if( temp == NULL ) { if (!temp) {
ithread_mutex_unlock( &tp->mutex ); goto exit_function;
return rc;
} }
if (job->priority == HIGH_PRIORITY) { if (job->priority == HIGH_PRIORITY) {
if (ListAddTail(&tp->highJobQ, temp)) { if (ListAddTail(&tp->highJobQ, temp)) {
rc = 0; rc = 0;
@ -974,10 +878,10 @@ int ThreadPoolAdd( ThreadPool *tp, ThreadPoolJob *job, int *jobId )
} }
} }
// AddWorker if appropriate /* AddWorker if appropriate */
AddWorker(tp); AddWorker(tp);
// Notify a waiting thread /* Notify a waiting thread */
if (rc == 0) { if (rc == 0) {
ithread_cond_signal(&tp->condition); ithread_cond_signal(&tp->condition);
} else { } else {
@ -986,6 +890,7 @@ int ThreadPoolAdd( ThreadPool *tp, ThreadPoolJob *job, int *jobId )
*jobId = tp->lastJobId++; *jobId = tp->lastJobId++;
exit_function:
ithread_mutex_unlock(&tp->mutex); ithread_mutex_unlock(&tp->mutex);
return rc; return rc;
@ -1009,20 +914,17 @@ int ThreadPoolAdd( ThreadPool *tp, ThreadPoolJob *job, int *jobId )
*****************************************************************************/ *****************************************************************************/
int ThreadPoolRemove(ThreadPool *tp, int jobId, ThreadPoolJob *out) int ThreadPoolRemove(ThreadPool *tp, int jobId, ThreadPoolJob *out)
{ {
ThreadPoolJob *temp = NULL;
int ret = INVALID_JOB_ID; int ret = INVALID_JOB_ID;
ThreadPoolJob *temp = NULL;
ListNode *tempNode = NULL; ListNode *tempNode = NULL;
ThreadPoolJob dummy; ThreadPoolJob dummy;
assert( tp != NULL ); if (!tp) {
if( tp == NULL ) {
return EINVAL; return EINVAL;
} }
if (!out) {
if( out == NULL ) {
out = &dummy; out = &dummy;
} }
dummy.jobId = jobId; dummy.jobId = jobId;
ithread_mutex_lock(&tp->mutex); ithread_mutex_lock(&tp->mutex);
@ -1033,9 +935,8 @@ int ThreadPoolRemove( ThreadPool *tp, int jobId, ThreadPoolJob *out )
*out = *temp; *out = *temp;
ListDelNode(&tp->highJobQ, tempNode, 0); ListDelNode(&tp->highJobQ, tempNode, 0);
FreeThreadPoolJob(tp, temp); FreeThreadPoolJob(tp, temp);
ithread_mutex_unlock( &tp->mutex ); ret = 0;
goto exit_function;
return 0;
} }
tempNode = ListFind(&tp->medJobQ, NULL, &dummy); tempNode = ListFind(&tp->medJobQ, NULL, &dummy);
@ -1044,31 +945,27 @@ int ThreadPoolRemove( ThreadPool *tp, int jobId, ThreadPoolJob *out )
*out = *temp; *out = *temp;
ListDelNode(&tp->medJobQ, tempNode, 0); ListDelNode(&tp->medJobQ, tempNode, 0);
FreeThreadPoolJob(tp, temp); FreeThreadPoolJob(tp, temp);
ithread_mutex_unlock( &tp->mutex ); ret = 0;
goto exit_function;
return 0;
} }
tempNode = ListFind(&tp->lowJobQ, NULL, &dummy); tempNode = ListFind(&tp->lowJobQ, NULL, &dummy);
if (tempNode) { if (tempNode) {
temp = (ThreadPoolJob *)tempNode->item; temp = (ThreadPoolJob *)tempNode->item;
*out = *temp; *out = *temp;
ListDelNode(&tp->lowJobQ, tempNode, 0); ListDelNode(&tp->lowJobQ, tempNode, 0);
FreeThreadPoolJob(tp, temp); FreeThreadPoolJob(tp, temp);
ithread_mutex_unlock( &tp->mutex ); ret = 0;
goto exit_function;
return 0;
} }
if (tp->persistentJob && tp->persistentJob->jobId == jobId) { if (tp->persistentJob && tp->persistentJob->jobId == jobId) {
*out = *tp->persistentJob; *out = *tp->persistentJob;
FreeThreadPoolJob(tp, tp->persistentJob); FreeThreadPoolJob(tp, tp->persistentJob);
tp->persistentJob = NULL; tp->persistentJob = NULL;
ithread_mutex_unlock( &tp->mutex ); ret = 0;
goto exit_function;
return 0;
} }
exit_function:
ithread_mutex_unlock(&tp->mutex); ithread_mutex_unlock(&tp->mutex);
return ret; return ret;
@ -1089,18 +986,13 @@ int ThreadPoolRemove( ThreadPool *tp, int jobId, ThreadPoolJob *out )
*****************************************************************************/ *****************************************************************************/
int ThreadPoolGetAttr(ThreadPool *tp, ThreadPoolAttr *out) int ThreadPoolGetAttr(ThreadPool *tp, ThreadPoolAttr *out)
{ {
assert( tp != NULL ); if (!tp || !out) {
assert( out != NULL );
if( tp == NULL || out == NULL ) {
return EINVAL; return EINVAL;
} }
if (!tp->shutdown) { if (!tp->shutdown) {
ithread_mutex_lock(&tp->mutex); ithread_mutex_lock(&tp->mutex);
} }
*out = tp->attr; *out = tp->attr;
if (!tp->shutdown) { if (!tp->shutdown) {
ithread_mutex_unlock(&tp->mutex); ithread_mutex_unlock(&tp->mutex);
} }
@ -1127,42 +1019,39 @@ int ThreadPoolSetAttr( ThreadPool *tp, ThreadPoolAttr *attr )
ThreadPoolAttr temp; ThreadPoolAttr temp;
int i = 0; int i = 0;
assert( tp != NULL ); if (!tp) {
if( tp == NULL ) {
return EINVAL; return EINVAL;
} }
ithread_mutex_lock(&tp->mutex); ithread_mutex_lock(&tp->mutex);
if( attr != NULL ) { if (attr) {
temp = ( *attr ); temp = *attr;
} else { } else {
TPAttrInit(&temp); TPAttrInit(&temp);
} }
if (SetPolicyType(temp.schedPolicy) != 0) { if (SetPolicyType(temp.schedPolicy) != 0) {
ithread_mutex_unlock(&tp->mutex); ithread_mutex_unlock(&tp->mutex);
return INVALID_POLICY; return INVALID_POLICY;
} }
tp->attr = temp;
tp->attr = ( temp ); /* add threads */
if (tp->totalThreads < tp->attr.minThreads) {
// add threads
if( tp->totalThreads < tp->attr.minThreads )
{
for (i = tp->totalThreads; i < tp->attr.minThreads; i++) { for (i = tp->totalThreads; i < tp->attr.minThreads; i++) {
if( ( retCode = CreateWorker( tp ) ) != 0 ) { retCode = CreateWorker(tp);
if (retCode != 0) {
break; break;
} }
} }
} }
/* signal changes */
// signal changes
ithread_cond_signal(&tp->condition); ithread_cond_signal(&tp->condition);
ithread_mutex_unlock(&tp->mutex); ithread_mutex_unlock(&tp->mutex);
if (retCode != 0) { if (retCode != 0) {
// clean up if the min threads could not be created /* clean up if the min threads could not be created */
ThreadPoolShutdown(tp); ThreadPoolShutdown(tp);
} }
@ -1188,14 +1077,13 @@ int ThreadPoolShutdown( ThreadPool *tp )
ListNode *head = NULL; ListNode *head = NULL;
ThreadPoolJob *temp = NULL; ThreadPoolJob *temp = NULL;
assert( tp != NULL ); if (!tp) {
if( tp == NULL ) {
return EINVAL; return EINVAL;
} }
ithread_mutex_lock(&tp->mutex); ithread_mutex_lock(&tp->mutex);
// clean up high priority jobs /* clean up high priority jobs */
while (tp->highJobQ.size) { while (tp->highJobQ.size) {
head = ListHead(&tp->highJobQ); head = ListHead(&tp->highJobQ);
temp = (ThreadPoolJob *)head->item; temp = (ThreadPoolJob *)head->item;
@ -1207,7 +1095,7 @@ int ThreadPoolShutdown( ThreadPool *tp )
} }
ListDestroy(&tp->highJobQ, 0); ListDestroy(&tp->highJobQ, 0);
// clean up med priority jobs /* clean up med priority jobs */
while (tp->medJobQ.size) { while (tp->medJobQ.size) {
head = ListHead(&tp->medJobQ); head = ListHead(&tp->medJobQ);
temp = (ThreadPoolJob *)head->item; temp = (ThreadPoolJob *)head->item;
@ -1219,7 +1107,7 @@ int ThreadPoolShutdown( ThreadPool *tp )
} }
ListDestroy(&tp->medJobQ, 0); ListDestroy(&tp->medJobQ, 0);
// clean up low priority jobs /* clean up low priority jobs */
while (tp->lowJobQ.size) { while (tp->lowJobQ.size) {
head = ListHead(&tp->lowJobQ); head = ListHead(&tp->lowJobQ);
temp = (ThreadPoolJob *)head->item; temp = (ThreadPoolJob *)head->item;
@ -1231,7 +1119,7 @@ int ThreadPoolShutdown( ThreadPool *tp )
} }
ListDestroy(&tp->lowJobQ, 0); ListDestroy(&tp->lowJobQ, 0);
// clean up long term job /* clean up long term job */
if (tp->persistentJob) { if (tp->persistentJob) {
temp = tp->persistentJob; temp = tp->persistentJob;
if (temp->free_func) { if (temp->free_func) {
@ -1240,28 +1128,27 @@ int ThreadPoolShutdown( ThreadPool *tp )
FreeThreadPoolJob(tp, temp); FreeThreadPoolJob(tp, temp);
tp->persistentJob = NULL; tp->persistentJob = NULL;
} }
/* signal shutdown */
// signal shutdown
tp->shutdown = 1; tp->shutdown = 1;
ithread_cond_broadcast(&tp->condition); ithread_cond_broadcast(&tp->condition);
/* wait for all threads to finish */
// wait for all threads to finish
while (tp->totalThreads > 0) { while (tp->totalThreads > 0) {
ithread_cond_wait(&tp->start_and_shutdown, &tp->mutex); ithread_cond_wait(&tp->start_and_shutdown, &tp->mutex);
} }
/* destroy condition */
// destroy condition
while (ithread_cond_destroy(&tp->condition) != 0) { while (ithread_cond_destroy(&tp->condition) != 0) {
/**/
} }
while (ithread_cond_destroy(&tp->start_and_shutdown) != 0) { while (ithread_cond_destroy(&tp->start_and_shutdown) != 0) {
/**/
} }
FreeListDestroy(&tp->jobFreeList); FreeListDestroy(&tp->jobFreeList);
ithread_mutex_unlock(&tp->mutex); ithread_mutex_unlock(&tp->mutex);
// destroy mutex /* destroy mutex */
while (ithread_mutex_destroy(&tp->mutex) != 0) { while (ithread_mutex_destroy(&tp->mutex) != 0) {
/**/
} }
return 0; return 0;
@ -1280,11 +1167,9 @@ int ThreadPoolShutdown( ThreadPool *tp )
*****************************************************************************/ *****************************************************************************/
int TPAttrInit(ThreadPoolAttr *attr) int TPAttrInit(ThreadPoolAttr *attr)
{ {
assert( attr != NULL ); if (!attr) {
if( attr == NULL ) {
return EINVAL; return EINVAL;
} }
attr->jobsPerThread = DEFAULT_JOBS_PER_THREAD; attr->jobsPerThread = DEFAULT_JOBS_PER_THREAD;
attr->maxIdleTime = DEFAULT_IDLE_TIME; attr->maxIdleTime = DEFAULT_IDLE_TIME;
attr->maxThreads = DEFAULT_MAX_THREADS; attr->maxThreads = DEFAULT_MAX_THREADS;
@ -1312,12 +1197,9 @@ int TPAttrInit( ThreadPoolAttr *attr )
*****************************************************************************/ *****************************************************************************/
int TPJobInit(ThreadPoolJob *job, start_routine func, void *arg) int TPJobInit(ThreadPoolJob *job, start_routine func, void *arg)
{ {
assert( job != NULL ); if (!job || !func) {
assert( func != NULL );
if( job == NULL || func == NULL ) {
return EINVAL; return EINVAL;
} }
job->func = func; job->func = func;
job->arg = arg; job->arg = arg;
job->priority = DEFAULT_PRIORITY; job->priority = DEFAULT_PRIORITY;
@ -1340,11 +1222,9 @@ int TPJobInit( ThreadPoolJob *job, start_routine func, void *arg )
*****************************************************************************/ *****************************************************************************/
int TPJobSetPriority(ThreadPoolJob *job, ThreadPriority priority) int TPJobSetPriority(ThreadPoolJob *job, ThreadPriority priority)
{ {
assert( job != NULL ); if (!job) {
if( job == NULL ) {
return EINVAL; return EINVAL;
} }
if (priority == LOW_PRIORITY || if (priority == LOW_PRIORITY ||
priority == MED_PRIORITY || priority == MED_PRIORITY ||
priority == HIGH_PRIORITY) { priority == HIGH_PRIORITY) {
@ -1368,11 +1248,9 @@ int TPJobSetPriority(ThreadPoolJob *job, ThreadPriority priority )
*****************************************************************************/ *****************************************************************************/
int TPJobSetFreeFunction(ThreadPoolJob *job, free_routine func) int TPJobSetFreeFunction(ThreadPoolJob *job, free_routine func)
{ {
assert( job != NULL ); if(!job) {
if( job == NULL ) {
return EINVAL; return EINVAL;
} }
job->free_func = func; job->free_func = func;
return 0; return 0;
@ -1391,11 +1269,9 @@ int TPJobSetFreeFunction( ThreadPoolJob *job, free_routine func )
*****************************************************************************/ *****************************************************************************/
int TPAttrSetMaxThreads(ThreadPoolAttr *attr, int maxThreads) int TPAttrSetMaxThreads(ThreadPoolAttr *attr, int maxThreads)
{ {
assert( attr != NULL ); if (!attr) {
if( attr == NULL ) {
return EINVAL; return EINVAL;
} }
attr->maxThreads = maxThreads; attr->maxThreads = maxThreads;
return 0; return 0;
@ -1414,11 +1290,9 @@ int TPAttrSetMaxThreads( ThreadPoolAttr *attr, int maxThreads )
*****************************************************************************/ *****************************************************************************/
int TPAttrSetMinThreads(ThreadPoolAttr *attr, int minThreads) int TPAttrSetMinThreads(ThreadPoolAttr *attr, int minThreads)
{ {
assert( attr != NULL ); if (!attr) {
if( attr == NULL ) {
return EINVAL; return EINVAL;
} }
attr->minThreads = minThreads; attr->minThreads = minThreads;
return 0; return 0;
@ -1436,11 +1310,9 @@ int TPAttrSetMinThreads( ThreadPoolAttr *attr, int minThreads )
*****************************************************************************/ *****************************************************************************/
int TPAttrSetIdleTime(ThreadPoolAttr *attr, int idleTime) int TPAttrSetIdleTime(ThreadPoolAttr *attr, int idleTime)
{ {
assert( attr != NULL ); if (!attr) {
if( attr == NULL ) {
return EINVAL; return EINVAL;
} }
attr->maxIdleTime = idleTime; attr->maxIdleTime = idleTime;
return 0; return 0;
@ -1458,11 +1330,9 @@ int TPAttrSetIdleTime( ThreadPoolAttr *attr, int idleTime )
*****************************************************************************/ *****************************************************************************/
int TPAttrSetJobsPerThread(ThreadPoolAttr *attr, int jobsPerThread) int TPAttrSetJobsPerThread(ThreadPoolAttr *attr, int jobsPerThread)
{ {
assert( attr != NULL ); if (!attr) {
if( attr == NULL ) {
return EINVAL; return EINVAL;
} }
attr->jobsPerThread = jobsPerThread; attr->jobsPerThread = jobsPerThread;
return 0; return 0;
@ -1480,11 +1350,9 @@ int TPAttrSetJobsPerThread( ThreadPoolAttr *attr, int jobsPerThread )
*****************************************************************************/ *****************************************************************************/
int TPAttrSetStarvationTime(ThreadPoolAttr *attr, int starvationTime) int TPAttrSetStarvationTime(ThreadPoolAttr *attr, int starvationTime)
{ {
assert( attr != NULL ); if (!attr) {
if( attr == NULL ) {
return EINVAL; return EINVAL;
} }
attr->starvationTime = starvationTime; attr->starvationTime = starvationTime;
return 0; return 0;
@ -1503,11 +1371,9 @@ int TPAttrSetStarvationTime( ThreadPoolAttr *attr, int starvationTime )
*****************************************************************************/ *****************************************************************************/
int TPAttrSetSchedPolicy(ThreadPoolAttr *attr, PolicyType schedPolicy) int TPAttrSetSchedPolicy(ThreadPoolAttr *attr, PolicyType schedPolicy)
{ {
assert( attr != NULL ); if (!attr) {
if( attr == NULL ) {
return EINVAL; return EINVAL;
} }
attr->schedPolicy = schedPolicy; attr->schedPolicy = schedPolicy;
return 0; return 0;
@ -1526,11 +1392,9 @@ int TPAttrSetSchedPolicy( ThreadPoolAttr *attr, PolicyType schedPolicy )
*****************************************************************************/ *****************************************************************************/
int TPAttrSetMaxJobsTotal(ThreadPoolAttr *attr, int maxJobsTotal) int TPAttrSetMaxJobsTotal(ThreadPoolAttr *attr, int maxJobsTotal)
{ {
assert( attr != NULL ); if (!attr) {
if( attr == NULL ) {
return EINVAL; return EINVAL;
} }
attr->maxJobsTotal = maxJobsTotal; attr->maxJobsTotal = maxJobsTotal;
return 0; return 0;
@ -1540,11 +1404,9 @@ int TPAttrSetMaxJobsTotal( ThreadPoolAttr *attr, int maxJobsTotal )
#ifdef STATS #ifdef STATS
void ThreadPoolPrintStats(ThreadPoolStats *stats) void ThreadPoolPrintStats(ThreadPoolStats *stats)
{ {
assert( stats != NULL ); if (!stats) {
if (stats == NULL) {
return; return;
} }
/* some OSses time_t length may depending on platform, promote it to long for safety */ /* some OSses time_t length may depending on platform, promote it to long for safety */
printf("ThreadPoolStats at Time: %ld\n", (long)StatsTime(NULL)); printf("ThreadPoolStats at Time: %ld\n", (long)StatsTime(NULL));
printf("High Jobs pending: %d\n", stats->currentJobsHQ); printf("High Jobs pending: %d\n", stats->currentJobsHQ);
@ -1580,13 +1442,11 @@ void ThreadPoolPrintStats(ThreadPoolStats *stats)
#ifdef STATS #ifdef STATS
int ThreadPoolGetStats(ThreadPool *tp, ThreadPoolStats *stats) int ThreadPoolGetStats(ThreadPool *tp, ThreadPoolStats *stats)
{ {
assert(tp != NULL);
assert(stats != NULL);
if (tp == NULL || stats == NULL) { if (tp == NULL || stats == NULL) {
return EINVAL; return EINVAL;
} }
//if not shutdown then acquire mutex /* if not shutdown then acquire mutex */
if (!tp->shutdown) { if (!tp->shutdown) {
ithread_mutex_lock(&tp->mutex); ithread_mutex_lock(&tp->mutex);
} }
@ -1597,26 +1457,22 @@ int ThreadPoolGetStats( ThreadPool *tp, ThreadPoolStats *stats )
} else { } else {
stats->avgWaitHQ = 0; stats->avgWaitHQ = 0;
} }
if (stats->totalJobsMQ > 0) { if (stats->totalJobsMQ > 0) {
stats->avgWaitMQ = stats->totalTimeMQ / stats->totalJobsMQ; stats->avgWaitMQ = stats->totalTimeMQ / stats->totalJobsMQ;
} else { } else {
stats->avgWaitMQ = 0; stats->avgWaitMQ = 0;
} }
if (stats->totalJobsLQ > 0) { if (stats->totalJobsLQ > 0) {
stats->avgWaitLQ = stats->totalTimeLQ / stats->totalJobsLQ; stats->avgWaitLQ = stats->totalTimeLQ / stats->totalJobsLQ;
} else { } else {
stats->avgWaitLQ = 0; stats->avgWaitLQ = 0;
} }
stats->totalThreads = tp->totalThreads; stats->totalThreads = tp->totalThreads;
stats->persistentThreads = tp->persistentThreads; stats->persistentThreads = tp->persistentThreads;
stats->currentJobsHQ = ListSize( &tp->highJobQ ); stats->currentJobsHQ = ListSize( &tp->highJobQ );
stats->currentJobsLQ = ListSize( &tp->lowJobQ ); stats->currentJobsLQ = ListSize( &tp->lowJobQ );
stats->currentJobsMQ = ListSize( &tp->medJobQ ); stats->currentJobsMQ = ListSize( &tp->medJobQ );
/* if not shutdown then release mutex */
//if not shutdown then release mutex
if (!tp->shutdown) { if (!tp->shutdown) {
ithread_mutex_unlock(&tp->mutex); ithread_mutex_unlock(&tp->mutex);
} }
@ -1628,6 +1484,7 @@ int ThreadPoolGetStats( ThreadPool *tp, ThreadPoolStats *stats )
#ifdef WIN32 #ifdef WIN32
#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS) #if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
#define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64 #define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64
#else #else
@ -1640,8 +1497,7 @@ int gettimeofday(struct timeval *tv, struct timezone *tz)
unsigned __int64 tmpres = 0; unsigned __int64 tmpres = 0;
static int tzflag; static int tzflag;
if (NULL != tv) if (tv) {
{
GetSystemTimeAsFileTime(&ft); GetSystemTimeAsFileTime(&ft);
tmpres |= ft.dwHighDateTime; tmpres |= ft.dwHighDateTime;
@ -1654,11 +1510,8 @@ int gettimeofday(struct timeval *tv, struct timezone *tz)
tv->tv_sec = (long)(tmpres / 1000000UL); tv->tv_sec = (long)(tmpres / 1000000UL);
tv->tv_usec = (long)(tmpres % 1000000UL); tv->tv_usec = (long)(tmpres % 1000000UL);
} }
if (tz) {
if (NULL != tz) if (!tzflag) {
{
if (!tzflag)
{
_tzset(); _tzset();
tzflag++; tzflag++;
} }
@ -1669,3 +1522,4 @@ int gettimeofday(struct timeval *tv, struct timezone *tz)
return 0; return 0;
} }
#endif /* WIN32 */ #endif /* WIN32 */

View File

@ -204,6 +204,9 @@ int UpnpInit(const char *HostIP, unsigned short DestPort)
{ {
int retVal = UPNP_E_SUCCESS; int retVal = UPNP_E_SUCCESS;
/* Initializes the ithread library */
ithread_initialize_library();
ithread_mutex_lock(&gSDKInitMutex); ithread_mutex_lock(&gSDKInitMutex);
/* Check if we're already initialized. */ /* Check if we're already initialized. */
@ -257,6 +260,9 @@ int UpnpInit2(const char *IfName, unsigned short DestPort)
{ {
int retVal; int retVal;
/* Initializes the ithread library */
ithread_initialize_library();
ithread_mutex_lock(&gSDKInitMutex); ithread_mutex_lock(&gSDKInitMutex);
/* Check if we're already initialized. */ /* Check if we're already initialized. */
@ -308,10 +314,6 @@ int UpnpFinish(void)
#endif #endif
struct Handle_Info *temp; struct Handle_Info *temp;
#ifdef WIN32
/*WSACleanup();*/
#endif
if( UpnpSdkInit != 1 ) { if( UpnpSdkInit != 1 ) {
return UPNP_E_FINISH; return UPNP_E_FINISH;
} }
@ -361,15 +363,11 @@ int UpnpFinish(void)
ithread_rwlock_destroy(&GlobalHndRWLock); ithread_rwlock_destroy(&GlobalHndRWLock);
ithread_mutex_destroy(&gUUIDMutex); ithread_mutex_destroy(&gUUIDMutex);
// remove all virtual dirs /* remove all virtual dirs */
UpnpRemoveAllVirtualDirs(); UpnpRemoveAllVirtualDirs();
// allow static linking /* Clean-up ithread library resources */
#ifdef WIN32 ithread_cleanup_library();
#ifdef PTW32_STATIC_LIB
pthread_win32_thread_detach_np();
#endif
#endif
UpnpSdkInit = 0; UpnpSdkInit = 0;
UpnpPrintf( UPNP_INFO, API, __FILE__, __LINE__, UpnpPrintf( UPNP_INFO, API, __FILE__, __LINE__,