add: Tcl_SetObjResult(interp, Tcl_NewDoubleObj(d)); } else { Tcl_SetObjResult(interp, Tcl_NewIntObj((int) (d * max))); } return TCL_OK; }    int NsTclRandObjCmd(ClientData arg, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { double d; int max;  if (objc > 2) { Tcl_WrongNumArgs(interp, 1, objv, "?maximum?"); return TCL_ERROR; } if (objc == 2) { if (Tcl_GetIntFromObj(interp, objv[1], &max) != TCL_OK) { return TCL_ERROR; } else if (max <= 0) { Tcl_Obj *result = Tcl_NewObj(); Tcl_AppendStringsToObj(result, "invalid max \"", Tcl_GetString(objv[1]), "\": must be > 0", NULL); Tcl_SetObjResult(interp, result); return TCL_ERROR; } } d = Ns_DRand(); if (objc == 1) {
context: static Ns_ThreadProc CounterThread;static unsigned long TrueRand(void);static unsigned long Roulette(void);/* * Static variables used by Ns_GenSeeds to generate array of random * by utilizing the random nature of the thread scheduler. */static volatile unsigned long counter;  /* Counter in counting thread */static volatile char fRun; /* Flag for counting thread outer loop. */static volatile char fCount; /* Flag for counting thread inner loop. */static Ns_Sema sema;	/* Semaphore that controls counting threads. *//* * Critical section around initial and subsequent seed generation. */static Ns_Cs lock;/* *---------------------------------------------------------------------- * * NsTclRandCmd -- * *	This procedure implements the AOLserver Tcl  * *	    ns_rand ?maximum? * *	command.   * * Results: *	The Tcl result string contains a random number, either a *	double >= 0.0 and < 1.0 or a integer >= 0 and < max. * * Side effects: *	None external. * * Note: *	Interpreters share the static variables which randomizes the *	the random numbers even more. * *---------------------------------------------------------------------- */intNsTclRandCmd(ClientData dummy, Tcl_Interp *interp, int argc, char **argv){    double d;    int max;	    if (argc > 2) {	Tcl_AppendResult(interp, argv[0], ": wrong number args: should be \"", 	    argv[0], " ?maximum?\"", (char *) NULL);	return TCL_ERROR;    }    if (argc == 2) {    	if (Tcl_GetInt(interp, argv[1], &max) != TCL_OK) {	    return TCL_ERROR;	} else if (max <= 0) {	    Tcl_AppendResult(interp, "invalid max \"", argv[1],	    	"\": must be > 0", NULL);	    return TCL_ERROR;	}    }    d = Ns_DRand();    if (argc == 1) {	Tcl_SetObjResult(interp, Tcl_NewDoubleObj(d));    } else {	Tcl_SetObjResult(interp, Tcl_NewIntObj((int) (d * max)));    }    return TCL_OK;}/* *---------------------------------------------------------------------- * * Ns_DRand -- *  *	Return a random double value between 0 and 1.0. * 	 * Results: *  	Random double. * * Side effects: * 	Will generate random seed on first call. * *---------------------------------------------------------------------- */doubleNs_DRand(void){    static int initialized;    if (!initialized) {	Ns_CsEnter(&lock);	if (!initialized) {	    unsigned long seed;	    Ns_GenSeeds(&seed, 1);#ifdef HAVE_RAND48    	    srand48(seed);#elif defined(HAVE_RANDOM)    	    srandom((unsigned int) seed);#else    	    srand((unsigned int) seed);#endif	    initialized = 1;	}	Ns_CsLeave(&lock);    }#if HAVE_RAND48    return drand48();#elif HAVE_RANDOM    return ((double) random() / (LONG_MAX + 1.0));#else    return ((double) rand() / (RAND_MAX + 1.0));#endif}/* *---------------------------------------------------------------------- * * Ns_GenSeeds -- *  *	Calculate an array of random seeds used by both Ns_DRand() and *  	the old SSL module. * 	 * Results: *  	None. * * Side effects: * 	None. * *---------------------------------------------------------------------- */voidNs_GenSeeds(unsigned long *seedsPtr, int nseeds){    Ns_Thread thr;        Ns_Log(Notice, "random: generating %d seed%s", nseeds,	nseeds == 1 ? "" : "s");    Ns_CsEnter(&lock);    Ns_SemaInit(&sema, 0);    fRun = 1;    Ns_ThreadCreate(CounterThread, NULL, 0, &thr);    while (nseeds-- > 0) {    	*seedsPtr++ = TrueRand();    }    fRun = 0;    Ns_SemaPost(&sema, 1);    Ns_ThreadJoin(&thr, NULL);    Ns_SemaDestroy(&sema);    Ns_CsLeave(&lock);}/* *---------------------------------------------------------------------- * * CounterThread -- * *	Generate a random seed.  This routine runs as a separate thread  *	where it imcrements a counter some indeterminate number of times.  *	The assumption is that this thread runs for a sufficiently long time * 	to be preempted an arbitrary number of times by the kernel threads  *	scheduler. * * Results: *	None. * * Side effects: *	None. * *---------------------------------------------------------------------- */static voidCounterThread(void *ignored){    while (fRun) {        Ns_SemaWait(&sema);        if (fRun) {	    while (fCount) {		counter++;            }        }    }}