rem: Ns_TlsSet(&conntls, NULL);
add: Ns_TlsSet(GetConnTls(), connPtr);
context: NsConnThread(void *arg){    Conn            *connPtr, **connPtrPtr;    Ns_Time          wait, ewait, eopen, eclosed, now, *timePtr;    static unsigned  next = 0;    char             thrname[32];    int              new, status;    char            *p;    Ns_Set	    *headers, *outputheaders;    Ns_Thread	     joinThread;    Stats	    *statsPtr;    Ns_Entry	    *entry;        connPtrPtr = (Conn **) arg;    headers = Ns_SetCreate(NULL);    outputheaders = Ns_SetCreate(NULL);    Ns_MutexLock(&lock);    sprintf(thrname, "-conn%d-", next++);    Ns_ThreadSetName(thrname);    Ns_Log(Debug, "serv: starting: waiting for connections");    while (1) {	/*	 * Wait for a connection to arrive, exiting if one doesn't	 * arrive in the configured timeout period.	 */	if (currentThreads <= nsconf.serv.minthreads) {	    timePtr = NULL;	} else {	    Ns_GetTime(&wait);	    Ns_IncrTime(&wait, nsconf.serv.threadtimeout, 0);	    timePtr = &wait;	}	status = NS_OK;    	while (!shutdownPending && status == NS_OK && firstWaitConnPtr == NULL) {	    status = Ns_CondTimedWait(&cond, &lock, timePtr);	}	if (firstWaitConnPtr == NULL) {	    break;	}	/*	 * Pull the first connection of the waiting list.	 */    	connPtr = firstWaitConnPtr;    	firstWaitConnPtr = connPtr->nextPtr;     	if (lastWaitConnPtr == connPtr) {	    lastWaitConnPtr = NULL;    	}	connPtr->nextPtr = NULL;	connPtr->prevPtr = lastActiveConnPtr;	if (lastActiveConnPtr != NULL) {	    lastActiveConnPtr->nextPtr = connPtr;	}	lastActiveConnPtr = connPtr;	if (firstActiveConnPtr == NULL) {	    firstActiveConnPtr = connPtr;	}	idleThreads--;	waitingConns--;	*connPtrPtr = connPtr;    	Ns_MutexUnlock(&lock);		/*	 * Re-initialize and run the connection.	 */	if (nsconf.serv.stats) {	    Ns_GetTime(&connPtr->tstart);	}	connPtr->headers = headers;	connPtr->outputheaders = outputheaders;	Ns_TlsSet(&conntls, connPtr);	ConnRun(connPtr);	Ns_TlsSet(&conntls, NULL);	if (nsconf.serv.stats) {	    Ns_GetTime(&now);	    Ns_DiffTime(&connPtr->tstart, &connPtr->tqueue, &ewait);	    Ns_DiffTime(&connPtr->tclose, &connPtr->tstart, &eopen);	    Ns_DiffTime(&now, &connPtr->tclose, &eclosed);	    if ((nsconf.serv.stats & STATS_PERURL) && connPtr->request && connPtr->request->url) {		Ns_CacheLock(statsCache);	    	entry = Ns_CacheCreateEntry(statsCache, connPtr->request->url, &new);	    	if (!new) {			statsPtr = Ns_CacheGetValue(entry);	    	} else {			statsPtr = ns_calloc(1, sizeof(Stats));			Ns_CacheSetValueSz(entry, statsPtr, 1);	    	}		IncrStats(statsPtr, &ewait, &eopen, &eclosed);	    	Ns_CacheUnlock(statsCache);	    }	}	/*	 * Perform various garbage collection tasks.  Note	 * the order is significant:  The driver freeProc could	 * possibly use Tcl and Tcl deallocate callbacks	 * could possibly access header and/or request data.	 */	if (connPtr->interp != NULL) {            Ns_TclDeAllocateInterp(NULL);	}	if (connPtr->request != NULL) {            Ns_RequestFree(connPtr->request);	}        if (connPtr->authUser != NULL) {	    ns_free(connPtr->authUser);	}        if (connPtr->authPasswd != NULL) {            ns_free(connPtr->authPasswd);	}	if (connPtr->query != NULL) {	    Ns_SetFree(connPtr->query);	}	/*	 * NB: Headers and/or output headers could have been	 * modified by the connection and/or cleanups.	 */	headers = connPtr->headers;	outputheaders = connPtr->outputheaders;        Ns_SetTrunc(headers, 0);        Ns_SetTrunc(outputheaders, 0);	/*	 * Remove from the active list and push on the free list.	 */	Ns_MutexLock(&lock);	if (nsconf.serv.stats & STATS_GLOBAL) {	    IncrStats(&globalStats, &ewait, &eopen, &eclosed);	}	*connPtrPtr = NULL;	if (connPtr->prevPtr != NULL) {	    connPtr->prevPtr->nextPtr = connPtr->nextPtr;	} else {	    firstActiveConnPtr = connPtr->nextPtr;	}	if (connPtr->nextPtr != NULL) {	    connPtr->nextPtr->prevPtr = connPtr->prevPtr;	} else {	    lastActiveConnPtr = connPtr->prevPtr;	}	connPtr->nextPtr = firstFreeConnPtr;	firstFreeConnPtr = connPtr;	idleThreads++;    }    idleThreads--;    currentThreads--;    if (currentThreads == 0) {    	Ns_CondBroadcast(&cond);    }    if (shutdownPending) {	p = "shutdown pending";    } else {	p = "no waiting connections";    }    joinThread = lastThread;    Ns_ThreadSelf(&lastThread);    Ns_MutexUnlock(&lock);    Ns_SetFree(headers);    Ns_SetFree(outputheaders);    if (joinThread != NULL) {	JoinThread(&joinThread);    }    Ns_Log(Debug, "serv: exiting: %s", p);    Ns_ThreadExit(connPtrPtr);}