diff options
| author | Miguel Sofer <miguel.sofer@gmail.com> | 2007-11-09 21:35:16 (GMT) | 
|---|---|---|
| committer | Miguel Sofer <miguel.sofer@gmail.com> | 2007-11-09 21:35:16 (GMT) | 
| commit | b4735e76da5d332e785a396168efb7230a88d8fe (patch) | |
| tree | eb56f5290785cb8ac4ee8de28f240ced1a4fe001 /unix/tclUnixInit.c | |
| parent | 2ebefee1b05df6c41125e6bc8ed768c0cc4f50dc (diff) | |
| download | tcl-b4735e76da5d332e785a396168efb7230a88d8fe.zip tcl-b4735e76da5d332e785a396168efb7230a88d8fe.tar.gz tcl-b4735e76da5d332e785a396168efb7230a88d8fe.tar.bz2 | |
	* generic/tclAsync.c:
	* generic/tclBasic.c:
	* generic/tclExecute.c:
	* generic/tclInt.h:
	* generic/tclUnixInit.c:
	* generic/tclUnixPort.h: new fields in interp (ekeko!) to cache
	TSD data that is accessed at each command invocation, access
	macros to replace Tcl_AsyncReady and TclpCheckStackSpace by much
	faster variants [Patch 1829248]
Diffstat (limited to 'unix/tclUnixInit.c')
| -rw-r--r-- | unix/tclUnixInit.c | 117 | 
1 files changed, 77 insertions, 40 deletions
| diff --git a/unix/tclUnixInit.c b/unix/tclUnixInit.c index 3d554d9..6554a3f 100644 --- a/unix/tclUnixInit.c +++ b/unix/tclUnixInit.c @@ -7,7 +7,7 @@   * Copyright (c) 1999 by Scriptics Corporation.   * All rights reserved.   * - * RCS: @(#) $Id: tclUnixInit.c,v 1.71 2007/07/31 10:04:28 dkf Exp $ + * RCS: @(#) $Id: tclUnixInit.c,v 1.72 2007/11/09 21:35:19 msofer Exp $   */  #include "tclInt.h" @@ -343,6 +343,15 @@ static int		MacOSXGetLibraryPath(Tcl_Interp *interp,  MODULE_SCOPE long tclMacOSXDarwinRelease;  long tclMacOSXDarwinRelease = 0;  #endif + +/* + * Auxiliary function to compute the direction of stack growth, and a static + * variable to cache the result. + */ + +static stackGrowsDown = -1; +static int StackGrowsDown(int *parent); +  /*   *--------------------------------------------------------------------------- @@ -1017,6 +1026,7 @@ TclpFindVariable(   * Side effects:   *	None.   * + * Remark: Unused in the core, to be removed.   *----------------------------------------------------------------------   */ @@ -1034,25 +1044,59 @@ TclpCheckStackSpace(void)  #else +    int localInt, *stackBound; + +    TclpGetCStackParams(&stackBound); + +    if (stackGrowsDown) { +	return (&localInt > stackBound) ; +    } else { +	return (&localInt > stackBound) ; +    } +#endif +} + +/* + *---------------------------------------------------------------------- + * + * TclpGetStackParams -- + * + *        Determine tha stack params for the current thread: in which + *        direction does the stack grow, and what is the stack lower (resp + *        upper) bound for safe invocation of a new command. This is used to + *        cache the values needed for an efficient computation of + *        TclpCheckStackSpace() when the interp is known. + * + *    Results: + *        Returns 1 if the stack grows down, in which case a stack lower bound + *        is stored at stackBoundPtr. If the stack grows up, 0 is returned and + *        an upper bound is stored at stackBoundPtr. If a bound cannot be + *        determined NULL is stored at stackBoundPtr. + */ + +int +TclpGetCStackParams( +    int **stackBoundPtr) +{ +#ifdef TCL_NO_STACK_CHECK +    *stackBoundPtr = NULL; +    return 0; +#else +    int localVar;      ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);  				/* Most variables are actually in a  				 * thread-specific data block to minimise the  				 * impact on the stack. */ -    register size_t stackUsed; -    int localVar;		/* Reference to somewhere on the local stack. -				 * This is declared last so it's as "deep" as -				 * possible. */ - -    if (tsdPtr == NULL) { +	 +    if (stackGrowsDown == -1) {  	/* -	 * This should probably be a panic(); if we're out of stack, we might -	 * have virtually no room to manoeuver at all. +	 * Not initialised!  	 */ -	Tcl_Panic("failed to get thread specific stack check data"); +	stackGrowsDown = StackGrowsDown(&localVar);      } -    /* +        /*       * The first time through, we record the "outermost" stack frame.       */ @@ -1073,41 +1117,34 @@ TclpCheckStackSpace(void)  	tsdPtr->initialised = 1;      } -    switch (tsdPtr->stackDetermineResult) { -    case TCL_BREAK: -	STACK_DEBUG(("skipping stack check with failure\n")); -	return 0; -    case TCL_CONTINUE: -	STACK_DEBUG(("skipping stack check with success\n")); -	return 1; +    if (tsdPtr->stackDetermineResult != TCL_OK) { +	switch (tsdPtr->stackDetermineResult) { +	    case TCL_BREAK: +		STACK_DEBUG(("skipping stack checks with failure\n")); +	    case TCL_CONTINUE: +		STACK_DEBUG(("skipping stack checks with success\n")); +	} +	*stackBoundPtr = NULL; +	return 1; /* so that check always succeeds */      } -    /* -     * Sanity check to see if somehow the stack started going the -     * other way. -     */ - -    if (&localVar > tsdPtr->outerVarPtr) { -	stackUsed = (char *)&localVar - (char *)tsdPtr->outerVarPtr; +    if (stackGrowsDown) { +	*stackBoundPtr = tsdPtr->outerVarPtr - tsdPtr->stackSize;      } else { -	stackUsed = (char *)tsdPtr->outerVarPtr - (char *)&localVar; +	*stackBoundPtr = tsdPtr->outerVarPtr + tsdPtr->stackSize;      } +    return stackGrowsDown; +#endif +} -    /* -     * Now we perform the actual check. Are we about to blow our stack frame? -     */ - -    if (stackUsed < tsdPtr->stackSize) { -	STACK_DEBUG(("stack OK\tin:%p\tout:%p\tuse:%04X\tmax:%04X\n", -		&localVar, tsdPtr->outerVarPtr, stackUsed, tsdPtr->stackSize)); -	return 1; -    } else { -	STACK_DEBUG(("stack OVERFLOW\tin:%p\tout:%p\tuse:%04X\tmax:%04X\n", -		&localVar, tsdPtr->outerVarPtr, stackUsed, tsdPtr->stackSize)); -	return 0; -    } -#endif /* TCL_NO_STACK_CHECK */ +int +StackGrowsDown( +    int *parent) +{ +    int here; +    return (&here < parent);  } +  /*   *---------------------------------------------------------------------- | 
