Change TclXOSElapsedTime to better handles clock_t being too narrow
(32-bit on FreeBSD).

Getting it committed upstream...

	-mi

--- unix/tclXunixOS.c	2005-07-12 15:03:15.000000000 -0400
+++ unix/tclXunixOS.c	2009-11-27 02:00:57.000000000 -0500
@@ -550,4 +550,10 @@
  *   o realTime - Elapsed real time, in milliseconds is returned here.
  *   o cpuTime - Elapsed CPU time, in milliseconds is returned here.
+ *
+ * XXX In some cases, clock_t may not be wide enough, such as when it is
+ * XXX a signed 32-bit value, its maximum is 2^31 or 2147483648. There
+ * XXX are more milliseconds in 25 days: 25*1000*60*60*24 = 2160000000.
+ * XXX If a profile-session is to last longer than that, the API needs
+ * XXX to use 64-bit values. -mi Nov 27, 2009
  *-----------------------------------------------------------------------------
  */
@@ -557,4 +563,5 @@
     clock_t *cpuTime;
 {
+    struct tms cpuTimes;
 /*
  * If times returns elapsed real time, this is easy.  If it returns a status,
@@ -562,25 +569,34 @@
  */
 #ifndef TIMES_RETS_STATUS
-    struct tms cpuTimes;
+    static clock_t startTime;
+    clock_t currentTime;
 
-    *realTime = TclXOSTicksToMS (times (&cpuTimes));
-    *cpuTime = TclXOSTicksToMS (cpuTimes.tms_utime + cpuTimes.tms_stime);
+    /*
+     * If this is the first call, get base time.
+     */
+    currentTime = times (&cpuTimes);
+    if (startTime == 0) {
+	startTime = currentTime;
+        *realTime = 0;
+    } else
+	*realTime = TclXOSTicksToMS (currentTime - startTime);
 #else
     static struct timeval startTime = {0, 0};
     struct timeval currentTime;
-    struct tms cpuTimes;
 
     /*
      * If this is the first call, get base time.
      */
-    if ((startTime.tv_sec == 0) && (startTime.tv_usec == 0))
+    if ((startTime.tv_sec == 0) && (startTime.tv_usec == 0)) {
         gettimeofday (&startTime, NULL);
-    
-    gettimeofday (&currentTime, NULL);
-    currentTime.tv_sec  = currentTime.tv_sec  - startTime.tv_sec;
-    currentTime.tv_usec = currentTime.tv_usec - startTime.tv_usec;
-    *realTime = (currentTime.tv_sec  * 1000) + (currentTime.tv_usec / 1000);
+	*realTime = 0;
+    } else {
+	gettimeofday (&currentTime, NULL);
+	currentTime.tv_sec  = currentTime.tv_sec  - startTime.tv_sec;
+	currentTime.tv_usec = currentTime.tv_usec - startTime.tv_usec;
+	*realTime = (currentTime.tv_sec  * 1000) + (currentTime.tv_usec / 1000);
+    }
     times (&cpuTimes);
-    *cpuTime = TclXOSTicksToMS (cpuTimes.tms_utime + cpuTimes.tms_stime);
 #endif
+    *cpuTime = TclXOSTicksToMS (cpuTimes.tms_utime + cpuTimes.tms_stime);
 }
--- unix/tclXunixPort.h	2005-10-07 19:30:28.000000000 -0400
+++ unix/tclXunixPort.h	2009-11-27 02:31:15.000000000 -0500
@@ -66,4 +66,10 @@
  * Make sure CLK_TCK is defined.
  */
+#ifdef __FreeBSD__
+#	if defined(CLK_TCK) && CLK_TCK == 128
+#		undef CLK_TCK
+#		define CLK_TCK	sysconf(_SC_CLK_TCK)
+#	endif
+#endif
 #ifndef CLK_TCK
 #    ifdef HZ

See:

http://core.tcl.tk/tcl/tktview?name=cd82cec7ce46a55af099b32b798398a78a505ef4

for background of this patch.

	-mi

--- generic/tclXprofile.c	2012-11-06 18:00:07.000000000 -0500
+++ generic/tclXprofile.c	2014-08-01 20:10:11.000000000 -0400
@@ -68,9 +68,6 @@
     int             commandMode;           /* Prof all commands?             */
     int             evalMode;              /* Use eval stack.                */
-    Command        *currentCmdPtr;         /* Current command table entry.   */
-    Tcl_CmdProc    *savedStrCmdProc;       /* Saved string command function  */
-    ClientData      savedStrCmdClientData; /* and clientData.                */
-    Tcl_ObjCmdProc *savedObjCmdProc;       /* Saved object command function  */
-    ClientData      savedObjCmdClientData; /* and clientData.                */
+    Tcl_Command     currentCmd;            /* Current command table entry.   */
+    Tcl_CmdInfo     savedCmdInfo;          /* Details about the current cmd. */
     int             evalLevel;             /* Eval level when invoked.       */
     clock_t         realTime;              /* Current real and CPU time.     */
@@ -89,5 +86,5 @@
  * Argument to panic on logic errors.  Takes an id number.
  */
-static char *PROF_PANIC = "TclX profile bug id = %d\n";
+static const char *PROF_PANIC = "TclX profile bug id = %d\n";
 
 /*
@@ -96,5 +93,5 @@
 static void
 PushEntry _ANSI_ARGS_((profInfo_t *infoPtr,
-                       char       *cmdName,
+                       const char *cmdName,
                        int         isProc,
                        int         procLevel,
@@ -112,5 +109,5 @@
 UpdateTOSTimes _ANSI_ARGS_((profInfo_t *infoPtr));
 
-static Command *
+static void
 ProfCommandEvalSetup _ANSI_ARGS_((profInfo_t *infoPtr,
                                   int        *isProcPtr));
@@ -132,13 +129,5 @@
                                 Tcl_Obj      *CONST objv[]));
 
-static void
-ProfTraceRoutine _ANSI_ARGS_((ClientData    clientData,
-                              Tcl_Interp   *interp,
-                              int           evalLevel,
-                              char         *command,
-                              Tcl_CmdProc  *cmdProc,
-                              ClientData    cmdClientData,
-                              int           argc,
-                              char        **argv));
+static Tcl_CmdObjTraceProc ProfTraceRoutine;
 
 static void
@@ -194,5 +183,5 @@
 PushEntry (infoPtr, cmdName, isProc, procLevel, scopeLevel, evalLevel)
     profInfo_t *infoPtr;
-    char       *cmdName;
+    const char *cmdName;
     int         isProc;
     int         procLevel;
@@ -396,5 +385,5 @@
  *-----------------------------------------------------------------------------
  */
-static Command *
+static void
 ProfCommandEvalSetup (infoPtr, isProcPtr)
     profInfo_t *infoPtr;
@@ -402,31 +391,33 @@
 {
     Interp *iPtr = (Interp *) infoPtr->interp;
-    Command *currentCmdPtr;
+    Tcl_CmdInfo cmdInfo;
     CallFrame *framePtr;
     int procLevel, scopeLevel, isProc;
     Tcl_Obj *fullCmdNamePtr;
-    char *fullCmdName;
+    const char *fullCmdName;
 
+    Tcl_GetCommandInfoFromToken(infoPtr->currentCmd, &cmdInfo);
     /*
      * Restore the command table entry.  If the command has modified it, don't
      * mess with it.
      */
-    currentCmdPtr = infoPtr->currentCmdPtr;
-    if (currentCmdPtr->proc == ProfStrCommandEval)
-        currentCmdPtr->proc = infoPtr->savedStrCmdProc;
-    if (currentCmdPtr->clientData == (ClientData) infoPtr)
-        currentCmdPtr->clientData = infoPtr->savedStrCmdClientData;
-    if (currentCmdPtr->objProc == ProfObjCommandEval)
-        currentCmdPtr->objProc = infoPtr->savedObjCmdProc;
-    if (currentCmdPtr->objClientData == (ClientData) infoPtr)
-        currentCmdPtr->objClientData = infoPtr->savedObjCmdClientData;
-    infoPtr->currentCmdPtr = NULL;
-    infoPtr->savedStrCmdProc = NULL;
-    infoPtr->savedStrCmdClientData = NULL;
-    infoPtr->savedObjCmdProc = NULL;
-    infoPtr->savedObjCmdClientData = NULL;
+    if (cmdInfo.proc == ProfStrCommandEval)
+        cmdInfo.proc = infoPtr->savedCmdInfo.proc;
+    if (cmdInfo.clientData == (ClientData) infoPtr)
+        cmdInfo.clientData = infoPtr->savedCmdInfo.clientData;
+    if (cmdInfo.objProc == ProfObjCommandEval)
+        cmdInfo.objProc = infoPtr->savedCmdInfo.objProc;
+    if (cmdInfo.objClientData == (ClientData) infoPtr)
+        cmdInfo.objClientData = infoPtr->savedCmdInfo.objClientData;
+    if (cmdInfo.deleteProc == NULL)
+        cmdInfo.deleteProc = infoPtr->savedCmdInfo.deleteProc;
+    if (cmdInfo.deleteData == NULL)
+        cmdInfo.deleteData = infoPtr->savedCmdInfo.deleteData;
+    cmdInfo.isNativeObjectProc = infoPtr->savedCmdInfo.isNativeObjectProc;
+
+    Tcl_SetCommandInfoFromToken(infoPtr->currentCmd, &cmdInfo);
 
     fullCmdNamePtr = Tcl_NewObj ();
-    Tcl_GetCommandFullName (infoPtr->interp, (Tcl_Command) currentCmdPtr, 
+    Tcl_GetCommandFullName (infoPtr->interp, infoPtr->currentCmd, 
                             fullCmdNamePtr);
     fullCmdName = Tcl_GetStringFromObj (fullCmdNamePtr, NULL);
@@ -447,10 +438,11 @@
      * on the stack before we started.  Pop those entries.
      */
-    if (infoPtr->stackPtr->procLevel > procLevel)
+    if (infoPtr->stackPtr->procLevel > procLevel) {
         UpdateTOSTimes (infoPtr);
-    while (infoPtr->stackPtr->procLevel > procLevel) {
-        if (infoPtr->stackPtr->evalLevel != UNKNOWN_LEVEL) 
-            panic (PROF_PANIC, 2);  /* Not an initial entry */
-        PopEntry (infoPtr);
+        do {
+            if (infoPtr->stackPtr->evalLevel != UNKNOWN_LEVEL) 
+                panic (PROF_PANIC, 2);  /* Not an initial entry */
+            PopEntry (infoPtr);
+        } while (infoPtr->stackPtr->procLevel > procLevel);
     }
 
@@ -479,5 +471,4 @@
 
     Tcl_DecrRefCount (fullCmdNamePtr);
-    return currentCmdPtr;
 }
 
@@ -528,10 +519,9 @@
 {
     profInfo_t *infoPtr = (profInfo_t *) clientData;
-    Command *currentCmdPtr;
     int isProc, result;
 
-    currentCmdPtr = ProfCommandEvalSetup (infoPtr, &isProc);
+    ProfCommandEvalSetup (infoPtr, &isProc);
 
-    result = (*currentCmdPtr->proc) (currentCmdPtr->clientData, interp,
+    result = (*infoPtr->savedCmdInfo.proc)(infoPtr->savedCmdInfo.clientData, interp,
                                      argc, argv);
 
@@ -560,11 +550,9 @@
 {
     profInfo_t *infoPtr = (profInfo_t *) clientData;
-    Command *currentCmdPtr;
     int isProc, result;
 
-    currentCmdPtr = ProfCommandEvalSetup (infoPtr,
-                                          &isProc);
+    ProfCommandEvalSetup (infoPtr, &isProc);
 
-    result = (*currentCmdPtr->objProc) (currentCmdPtr->objClientData, interp,
+    result = (*infoPtr->savedCmdInfo.objProc)(infoPtr->savedCmdInfo.objClientData, interp,
                                         objc, objv);
 
@@ -579,54 +567,41 @@
  *-----------------------------------------------------------------------------
  */
-static void
-ProfTraceRoutine (clientData, interp, evalLevel, command, cmdProc,
-                  cmdClientData, argc, argv)
+static int
+ProfTraceRoutine (clientData, interp, evalLevel, command, cmd,
+                  objc, objv)
     ClientData    clientData;
     Tcl_Interp   *interp;
     int           evalLevel;
-    char         *command;
-    Tcl_CmdProc  *cmdProc;
-    ClientData    cmdClientData;
-    int           argc;
-    char        **argv;
+    const char   *command;
+    Tcl_Command   cmd;
+    int           objc;
+    struct Tcl_Obj * const *objv;
 {
     profInfo_t *infoPtr = (profInfo_t *) clientData;
-    Command *cmdPtr;
-    Tcl_Command cmd;
-
-    if (infoPtr->currentCmdPtr != NULL)
-        panic (PROF_PANIC, 3);
+    Tcl_CmdInfo cmdInfo;
 
-    cmd = Tcl_FindCommand (interp, argv [0], NULL, 0);
     if (cmd == NULL)
         panic (PROF_PANIC, 4);
-    cmdPtr = (Command *) cmd;
-
-    if ((cmdPtr->proc != cmdProc) || (cmdPtr->clientData != cmdClientData))
-        panic (PROF_PANIC, 5);
-
-    /*
-     * If command is to be compiled, we can't profile it.
-     */
-    if (cmdPtr->compileProc != NULL)
-        return;
 
     /*
      * Save current state information.
      */
-    infoPtr->currentCmdPtr = cmdPtr;
-    infoPtr->savedStrCmdProc = cmdPtr->proc;
-    infoPtr->savedStrCmdClientData = cmdPtr->clientData;
-    infoPtr->savedObjCmdProc = cmdPtr->objProc;
-    infoPtr->savedObjCmdClientData = cmdPtr->objClientData;
+    Tcl_GetCommandInfoFromToken(cmd, &(infoPtr->savedCmdInfo));
     infoPtr->evalLevel = evalLevel;
+    infoPtr->currentCmd = cmd;
 
     /*
      * Force our routines to be called.
      */
-    cmdPtr->proc = ProfStrCommandEval;
-    cmdPtr->clientData = (ClientData) infoPtr;
-    cmdPtr->objProc = ProfObjCommandEval;
-    cmdPtr->objClientData = (ClientData) infoPtr;
+    cmdInfo.proc = ProfStrCommandEval;
+    cmdInfo.clientData = (ClientData) infoPtr;
+    cmdInfo.objProc = ProfObjCommandEval;
+    cmdInfo.objClientData = (ClientData) infoPtr;
+    cmdInfo.isNativeObjectProc = infoPtr->savedCmdInfo.isNativeObjectProc;
+    cmdInfo.deleteProc = NULL;
+    cmdInfo.deleteData = NULL;
+    Tcl_SetCommandInfoFromToken(cmd, &cmdInfo);
+
+    return TCL_OK;
 }
 
@@ -712,7 +687,7 @@
 
     infoPtr->traceHandle =
-        Tcl_CreateTrace (infoPtr->interp, MAXINT,
-                         (Tcl_CmdTraceProc *) ProfTraceRoutine,
-                         (ClientData) infoPtr);
+        Tcl_CreateObjTrace (infoPtr->interp, 0,
+                         TCL_ALLOW_INLINE_COMPILATION, ProfTraceRoutine,
+                         (ClientData) infoPtr, NULL);
     infoPtr->commandMode = commandMode;
     infoPtr->evalMode = evalMode;
@@ -974,9 +949,5 @@
     infoPtr->commandMode = FALSE;
     infoPtr->evalMode = FALSE;
-    infoPtr->currentCmdPtr = NULL;
-    infoPtr->savedStrCmdProc = NULL;
-    infoPtr->savedStrCmdClientData = NULL;
-    infoPtr->savedObjCmdProc = NULL;
-    infoPtr->savedObjCmdClientData = NULL;
+    infoPtr->currentCmd = NULL;
     infoPtr->evalLevel = UNKNOWN_LEVEL;
     infoPtr->realTime = 0;
@@ -998,5 +969,2 @@
 			  (Tcl_CmdDeleteProc*) NULL);
 }
-
-
-
