PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD, 0);
(PR_TRUE==local)?PR_LOCAL_THREAD:PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD, 0);
launch_threads(    startFn    *startFunc,    PRFileDesc *a,    PRFileDesc *b,    int         c){    int i;    SECStatus rv = SECSuccess;    /* create the thread management serialization structs */    qLock               = PZ_NewLock(nssILockSelfServ);    jobQNotEmptyCv      = PZ_NewCondVar(qLock);    freeListNotEmptyCv  = PZ_NewCondVar(qLock);    threadCountChangeCv = PZ_NewCondVar(qLock);    /* allocate the array of thread slots */    threads = PR_Calloc(maxThreads, sizeof(perThread));    if ( NULL == threads )  {        fprintf(stderr, "Oh Drat! Can't allocate the perThread array\n");        return SECFailure;    }    /* 5 is a little extra, intended to keep the jobQ from underflowing.     ** That is, from going empty while not stopping and clients are still    ** trying to contact us.    */    rv = setupJobs(maxThreads + 5);    if (rv != SECSuccess)    	return rv;    PZ_Lock(qLock);    for (i = 0; i < maxThreads; ++i) {    	perThread * slot = threads + i;	slot->state = rs_running;	slot->a = a;	slot->b = b;	slot->c = c;	slot->startFunc = startFunc;	slot->prThread = PR_CreateThread(PR_USER_THREAD, 			thread_wrapper, slot, PR_PRIORITY_NORMAL, 			PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD, 0);	if (slot->prThread == NULL) {	    printf("selfserv: Failed to launch thread!\n");	    slot->state = rs_idle;	    rv = SECFailure;	    break;	} 	++threadCount;    }    PZ_Unlock(qLock);     return rv;}