void DumperThread(void *arg) { Ns_Time to; Tcl_DString ds; Tcl_DStringInit(&ds); Ns_ThreadSetName("-dumper-"); Ns_MutexLock(&block); Ns_MutexLock(&dlock); while (!dstop) { Ns_GetTime(&to); Ns_IncrTime(&to, 1, 0); Ns_CondTimedWait(&dcond, &dlock, &to); Ns_MutexLock(&mlock); Ns_ThreadList(&ds, NULL); DumpString(&ds); Ns_MutexList(&ds); DumpString(&ds); #if !defined(_WIN32) && defined(USE_THREAD_ALLOC) && (STATIC_BUILD == 0) /* NB: Not yet exported in WIN32 Tcl. */ Tcl_GetMemoryInfo(&ds); #endif DumpString(&ds); Ns_MutexUnlock(&mlock); } Ns_MutexUnlock(&dlock); Ns_MutexUnlock(&block); }
void * Pthread(void *arg) { static Ns_Tls tls; /* * Allocate TLS first time (this is recommended TLS * self-initialization style. */ Ns_ThreadSetName("pthread"); sleep(5); if (tls == NULL) { Ns_MasterLock(); if (tls == NULL) { Ns_TlsAlloc(&tls, PthreadTlsCleanup); } Ns_MasterUnlock(); } Ns_TlsSet(&tls, arg); /* * Wait for exit signal from main(). */ Ns_MutexLock(&plock); while (!pgo) { Ns_CondWait(&pcond, &plock); } Ns_MutexUnlock(&plock); return arg; }
void MemThread(void *arg) { int i; void *ptr; Ns_ThreadSetName("memthread"); Ns_MutexLock(&lock); ++nrunning; Ns_CondBroadcast(&cond); while (!memstart) { Ns_CondWait(&cond, &lock); } Ns_MutexUnlock(&lock); ptr = NULL; for (i = 0; i < NA; ++i) { if (arg) { if (ptr) ns_free(ptr); ptr = ns_malloc(10); } else { if (ptr) free(ptr); ptr = malloc(10); } } }
void CheckStackThread(void *arg) { int n; Ns_ThreadSetName("checkstack"); n = RecursiveStackCheck(0); Ns_ThreadExit((void *) n); }
void NsInitConf(void) { Ns_DString addr; static char cwd[PATH_MAX]; extern char *nsBuildDate; /* NB: Declared in stamp.c */ Ns_ThreadSetName("-main-"); /* * Set various core environment variables. */ nsconf.build = nsBuildDate; nsconf.name = NSD_NAME; nsconf.version = NSD_VERSION; nsconf.tcl.version = TCL_VERSION; nsconf.http.major = HTTP_MAJOR; nsconf.http.minor = HTTP_MINOR; time(&nsconf.boot_t); nsconf.pid = getpid(); nsconf.home = getcwd(cwd, sizeof(cwd)); if (gethostname(nsconf.hostname, sizeof(nsconf.hostname)) != 0) { strcpy(nsconf.hostname, "localhost"); } Ns_DStringInit(&addr); if (Ns_GetAddrByHost(&addr, nsconf.hostname)) { strcpy(nsconf.address, addr.string); } else { strcpy(nsconf.address, "0.0.0.0"); } Ns_DStringFree(&addr); /* * Set various default values. */ nsconf.shutdowntimeout = SHUTDOWNTIMEOUT; nsconf.sched.maxelapsed = SCHED_MAXELAPSED; nsconf.backlog = LISTEN_BACKLOG; nsconf.http.major = HTTP_MAJOR; nsconf.http.minor = HTTP_MINOR; nsconf.tcl.lockoninit = TCL_INITLCK; /* * At library load time the server is considered started. * Normally it's marked stopped immediately by Ns_Main unless * libnsd is being used for some other, non-server program. */ Ns_MutexSetName(&nsconf.state.lock, "nsd:state"); nsconf.state.started = 1; }
int main(int argc, char *argv[]) { int i, code; Ns_Thread threads[10]; Ns_Thread self, dumper; void *arg; char *p; #if PTHREAD_TEST pthread_t tids[10]; #endif NsThreads_LibInit(); Ns_ThreadSetName("-main-"); /* * Jump directly to memory test if requested. */ for (i = 1; i < argc; ++i) { p = argv[i]; switch (*p) { case 'n': break; case 'm': nthreads = atoi(p + 1); goto mem; break; } } Ns_ThreadCreate(DetachedThread, NULL, 0, NULL); Ns_ThreadCreate(DumperThread, NULL, 0, &dumper); Ns_MutexSetName(&lock, "startlock"); Ns_MutexSetName(&dlock, "dumplock"); Ns_MutexSetName(&mlock, "msglock"); Ns_MutexSetName(&block, "busylock"); Ns_ThreadStackSize(81920); Ns_SemaInit(&sema, 3); Msg("sema initialized to 3"); atexit(AtExit); Msg("pid = %d", getpid()); Ns_TlsAlloc(&key, TlsLogArg); for (i = 0; i < 10; ++i) { Msg("starting work thread %d", i); Ns_ThreadCreate(WorkThread, (void *) i, 0, &threads[i]); } sleep(1); /* Ns_CondSignal(&cond); */ Ns_SemaPost(&sema, 10); Msg("sema post 10"); Ns_RWLockWrLock(&rwlock); Msg("rwlock write locked (main thread)"); sleep(1); Ns_RWLockUnlock(&rwlock); Msg("rwlock write unlocked (main thread)"); for (i = 0; i < 10; ++i) { Msg("waiting for thread %d to exit", i); Ns_ThreadJoin(&threads[i], (void **) &code); Msg("thread %d exited - code: %d", i, code); } #if PTHREAD_TEST for (i = 0; i < 10; ++i) { pthread_create(&tids[i], NULL, Pthread, (void *) i); printf("pthread: create %d = %d\n", i, (int) tids[i]); Ns_ThreadYield(); } Ns_MutexLock(&plock); pgo = 1; Ns_MutexUnlock(&plock); Ns_CondBroadcast(&pcond); for (i = 0; i < 10; ++i) { pthread_join(tids[i], &arg); printf("pthread: join %d = %d\n", i, (int) arg); } #endif Ns_ThreadSelf(&self); Ns_MutexLock(&dlock); dstop = 1; Ns_CondSignal(&dcond); Ns_MutexUnlock(&dlock); Ns_ThreadJoin(&dumper, NULL); Msg("threads joined"); for (i = 0; i < 10; ++i) { Ns_ThreadCreate(CheckStackThread, NULL, 8192*(i+1), &threads[i]); } for (i = 0; i < 10; ++i) { Ns_ThreadJoin(&threads[i], &arg); printf("check stack %d = %d\n", i, (int) arg); } /*Ns_ThreadEnum(DumpThreads, NULL);*/ /*Ns_MutexEnum(DumpLocks, NULL);*/ mem: MemTime(0); MemTime(1); return 0; }
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); }