Diff
Not logged in

Differences From Artifact [6073891048]:

To Artifact [6f4dfaae01]:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/*
 * tclUnixInit.c --
 *
 *	Contains the Unix-specific interpreter initialization functions.
 *
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
 * Copyright (c) 1999 by Scriptics Corporation.
 * All rights reserved.
 *
 * RCS: @(#) $Id: tclUnixInit.c,v 1.71 2007/07/31 10:04:28 dkf Exp $
 */

#include "tclInt.h"
#include <stddef.h>
#include <locale.h>
#ifdef HAVE_LANGINFO
#   include <langinfo.h>









|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/*
 * tclUnixInit.c --
 *
 *	Contains the Unix-specific interpreter initialization functions.
 *
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
 * Copyright (c) 1999 by Scriptics Corporation.
 * All rights reserved.
 *
 * RCS: @(#) $Id: tclUnixInit.c,v 1.72 2007/11/09 21:35:19 msofer Exp $
 */

#include "tclInt.h"
#include <stddef.h>
#include <locale.h>
#ifdef HAVE_LANGINFO
#   include <langinfo.h>
339
340
341
342
343
344
345









346
347
348
349
350
351
352
 * Need to check Darwin release at runtime in tclUnixFCmd.c and tclLoadDyld.c:
 * initialize release global at startup from uname().
 */
#define GET_DARWIN_RELEASE 1
MODULE_SCOPE long tclMacOSXDarwinRelease;
long tclMacOSXDarwinRelease = 0;
#endif










/*
 *---------------------------------------------------------------------------
 *
 * TclpInitPlatform --
 *
 *	Initialize all the platform-dependant things like signals and







>
>
>
>
>
>
>
>
>







339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
 * Need to check Darwin release at runtime in tclUnixFCmd.c and tclLoadDyld.c:
 * initialize release global at startup from uname().
 */
#define GET_DARWIN_RELEASE 1
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);


/*
 *---------------------------------------------------------------------------
 *
 * TclpInitPlatform --
 *
 *	Initialize all the platform-dependant things like signals and
1013
1014
1015
1016
1017
1018
1019

1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036







































1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049

1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075

1076
1077
1078
1079
1080
1081
1082
1083


1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094


1095
1096

1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
 *
 * Results:
 *	1 if there is enough stack space to continue; 0 if not.
 *
 * Side effects:
 *	None.
 *

 *----------------------------------------------------------------------
 */

int
TclpCheckStackSpace(void)
{
#ifdef TCL_NO_STACK_CHECK

    /*
     * This function was normally unimplemented on Unix platforms and this
     * implements old behavior, i.e. no stack checking performed.
     */

    return 1;

#else








































    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) {
	/*
	 * This should probably be a panic(); if we're out of stack, we might
	 * have virtually no room to manoeuver at all.

	 */

	Tcl_Panic("failed to get thread specific stack check data");
    }

    /*
     * The first time through, we record the "outermost" stack frame.
     */

    if (tsdPtr->outerVarPtr == NULL) {
	tsdPtr->outerVarPtr = &localVar;
    }

    if (tsdPtr->initialised == 0) {
	/*
	 * We appear to have not computed the stack size before. Attempt to
	 * retrieve it from either the current thread or, failing that, the
	 * process accounting limit. Note that we assume that stack sizes do
	 * not change throughout the lifespan of the thread/process; this is
	 * almost always true.
	 */

	tsdPtr->stackDetermineResult = GetStackSize(&tsdPtr->stackSize);
	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;
    }



    /*
     * Sanity check to see if somehow the stack started going the
     * other way.
     */

    if (&localVar > tsdPtr->outerVarPtr) {
	stackUsed = (char *)&localVar - (char *)tsdPtr->outerVarPtr;
    } else {
	stackUsed = (char *)tsdPtr->outerVarPtr - (char *)&localVar;
    }



    /*

     * 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 */
}

/*
 *----------------------------------------------------------------------
 *
 * GetStackSize --
 *
 *	Discover what the stack size for the current thread/process actually







>

















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>




<
<
<
<
|
|

<
<
>


|


|




















>
|
|
|
<
|
|
<
|
>
>
|
<
<
<
<

|
|

|

>
>
|
|
>
|
|
|
<
<
<
|
<
<
<
|
|
<
|







1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089




1090
1091
1092


1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123

1124
1125

1126
1127
1128
1129




1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143



1144



1145
1146

1147
1148
1149
1150
1151
1152
1153
1154
 *
 * Results:
 *	1 if there is enough stack space to continue; 0 if not.
 *
 * Side effects:
 *	None.
 *
 * Remark: Unused in the core, to be removed.
 *----------------------------------------------------------------------
 */

int
TclpCheckStackSpace(void)
{
#ifdef TCL_NO_STACK_CHECK

    /*
     * This function was normally unimplemented on Unix platforms and this
     * implements old behavior, i.e. no stack checking performed.
     */

    return 1;

#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. */




	
    if (stackGrowsDown == -1) {
	/*


	 * Not initialised!
	 */

	stackGrowsDown = StackGrowsDown(&localVar);
    }

        /*
     * The first time through, we record the "outermost" stack frame.
     */

    if (tsdPtr->outerVarPtr == NULL) {
	tsdPtr->outerVarPtr = &localVar;
    }

    if (tsdPtr->initialised == 0) {
	/*
	 * We appear to have not computed the stack size before. Attempt to
	 * retrieve it from either the current thread or, failing that, the
	 * process accounting limit. Note that we assume that stack sizes do
	 * not change throughout the lifespan of the thread/process; this is
	 * almost always true.
	 */

	tsdPtr->stackDetermineResult = GetStackSize(&tsdPtr->stackSize);
	tsdPtr->initialised = 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 */
    }





    if (stackGrowsDown) {
	*stackBoundPtr = tsdPtr->outerVarPtr - tsdPtr->stackSize;
    } else {
	*stackBoundPtr = tsdPtr->outerVarPtr + tsdPtr->stackSize;
    }
    return stackGrowsDown;
#endif
}

int
StackGrowsDown(
    int *parent)
{



    int here;



    return (&here < parent);
}



/*
 *----------------------------------------------------------------------
 *
 * GetStackSize --
 *
 *	Discover what the stack size for the current thread/process actually