void CheckStackThread(void *arg) { int n; Ns_ThreadSetName("checkstack"); n = RecursiveStackCheck(0); Ns_ThreadExit((void *) n); }
void WorkThread(void *arg) { int i = (int) arg; int *ip; time_t now; Ns_Thread self; char name[32]; sprintf(name, "-work:%d-", i); Ns_ThreadSetName(name); if (i == 2) { Ns_RWLockWrLock(&rwlock); Msg("rwlock write aquired"); sleep(2); } else { Ns_RWLockRdLock(&rwlock); Msg("rwlock read aquired aquired"); sleep(1); } Ns_CsEnter(&cs); Msg("enter critical section once"); Ns_CsEnter(&cs); Msg("enter critical section twice"); Ns_CsLeave(&cs); Ns_CsLeave(&cs); Ns_ThreadSelf(&self); arg = Ns_TlsGet(&key); Ns_SemaWait(&sema); Msg("got semaphore posted from main"); if (arg == NULL) { arg = ns_malloc(sizeof(int)); Ns_TlsSet(&key, arg); } ip = arg; *ip = i; if (i == 5) { Ns_Time to; int st; Ns_GetTime(&to); Msg("time: %ld %ld", to.sec, to.usec); Ns_IncrTime(&to, 5, 0); Msg("time: %ld %ld", to.sec, to.usec); Ns_MutexLock(&lock); time(&now); Msg("timed wait starts: %s", ns_ctime(&now)); st = Ns_CondTimedWait(&cond, &lock, &to); Ns_MutexUnlock(&lock); time(&now); Msg("timed wait ends: %s - status: %d", ns_ctime(&now), st); } if (i == 9) { Msg("sleep 4 seconds start"); sleep(4); Msg("sleep 4 seconds done"); } time(&now); Ns_RWLockUnlock(&rwlock); Msg("rwlock unlocked"); Msg("exiting"); Ns_ThreadExit((void *) i); }
void NsConnThread(void *arg) { ConnData *dataPtr = arg; Pool *poolPtr = dataPtr->poolPtr; Conn *connPtr; Ns_Time wait, *timePtr; char name[100]; int status, ncons; char *msg; double spread; /* * Set the conn thread name. */ Ns_TlsSet(&ctdtls, dataPtr); Ns_MutexLock(&poolPtr->lock); sprintf(name, "-%s:%d-", poolPtr->name, poolPtr->threads.nextid++); Ns_MutexUnlock(&poolPtr->lock); Ns_ThreadSetName(name); /* spread is a value of 1.0 +- specified percentage, i.e. between 0.0 and 2.0 when the configured percentage is 100 */ spread = 1.0 + (2 * poolPtr->threads.spread * Ns_DRand() - poolPtr->threads.spread) / 100.0; ncons = round(poolPtr->threads.maxconns * spread); msg = "exceeded max connections per thread"; /* * Start handling connections. */ Ns_MutexLock(&poolPtr->lock); poolPtr->threads.starting--; poolPtr->threads.idle++; while (poolPtr->threads.maxconns <= 0 || ncons-- > 0) { /* * Wait for a connection to arrive, exiting if one doesn't * arrive in the configured timeout period. */ if (poolPtr->threads.current <= poolPtr->threads.min) { timePtr = NULL; } else { Ns_GetTime(&wait); Ns_IncrTime(&wait, round(poolPtr->threads.timeout * spread), 0); timePtr = &wait; } status = NS_OK; while (!poolPtr->shutdown && status == NS_OK && poolPtr->queue.wait.firstPtr == NULL) { /* nothing is queued, we wait for a queue entry */ poolPtr->threads.waiting++; status = Ns_CondTimedWait(&poolPtr->cond, &poolPtr->lock, timePtr); poolPtr->threads.waiting--; } if (poolPtr->queue.wait.firstPtr == NULL) { msg = "timeout waiting for connection"; break; } /* * Pull the first connection off the waiting list. */ connPtr = poolPtr->queue.wait.firstPtr; poolPtr->queue.wait.firstPtr = connPtr->nextPtr; if (poolPtr->queue.wait.lastPtr == connPtr) { poolPtr->queue.wait.lastPtr = NULL; } connPtr->nextPtr = NULL; connPtr->prevPtr = poolPtr->queue.active.lastPtr; if (poolPtr->queue.active.lastPtr != NULL) { poolPtr->queue.active.lastPtr->nextPtr = connPtr; } poolPtr->queue.active.lastPtr = connPtr; if (poolPtr->queue.active.firstPtr == NULL) { poolPtr->queue.active.firstPtr = connPtr; } poolPtr->threads.idle--; poolPtr->queue.wait.num--; Ns_MutexUnlock(&poolPtr->lock); /* * Run the connection. */ Ns_MutexLock(&connlock); dataPtr->connPtr = connPtr; Ns_MutexUnlock(&connlock); Ns_GetTime(&connPtr->times.run); ConnRun(connPtr); Ns_MutexLock(&connlock); dataPtr->connPtr = NULL; Ns_MutexUnlock(&connlock); /* * Remove from the active list and push on the free list. */ Ns_MutexLock(&poolPtr->lock); if (connPtr->prevPtr != NULL) { connPtr->prevPtr->nextPtr = connPtr->nextPtr; } else { poolPtr->queue.active.firstPtr = connPtr->nextPtr; } if (connPtr->nextPtr != NULL) { connPtr->nextPtr->prevPtr = connPtr->prevPtr; } else { poolPtr->queue.active.lastPtr = connPtr->prevPtr; } poolPtr->threads.idle++; Ns_MutexUnlock(&poolPtr->lock); NsFreeConn(connPtr); Ns_MutexLock(&poolPtr->lock); } /* * Append this thread to list of threads to reap. */ Ns_MutexLock(&joinlock); dataPtr->nextPtr = joinPtr; joinPtr = dataPtr; Ns_MutexUnlock(&joinlock); /* * Mark this thread as no longer active. */ if (poolPtr->shutdown) { msg = "shutdown pending"; } poolPtr->threads.current--; poolPtr->threads.idle--; if (((poolPtr->queue.wait.num > 0 && poolPtr->threads.idle == 0 && poolPtr->threads.starting == 0 ) || (poolPtr->threads.current < poolPtr->threads.min) ) && !poolPtr->shutdown) { /* Recreate a thread when on of the condings hold - there are more queue entries are still waiting, but no thread is either starting or idle, or - there are less than minthreads connection threads alive. */ poolPtr->threads.current ++; Ns_MutexUnlock(&poolPtr->lock); NsCreateConnThread(poolPtr, 0); /* joinThreads == 0 to avoid deadlock */ } else if (poolPtr->queue.wait.num > 0 && poolPtr->threads.waiting > 0) { /* Wake up a waiting thread */ Ns_CondSignal(&poolPtr->cond); Ns_MutexUnlock(&poolPtr->lock); } else { Ns_MutexUnlock(&poolPtr->lock); } Ns_Log(Notice, "exiting: %s", msg); Ns_ThreadExit(dataPtr); }
void Ns_ExitThread(int exitCode) { Ns_ThreadExit((void *) exitCode); }