Changeset 2079 for trunk/lang


Ignore:
Timestamp:
Feb 2, 2011, 1:01:51 PM (14 years ago)
Author:
mmc
Message:

Misc fixes that have been pending in my local directory for a while.
Added "usage mark" and "usage measure" options to the usage command,
for better handling of simulation times.

Location:
trunk/lang/tcl
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/lang/tcl/scripts/library.tcl

    r1142 r2079  
    200200    public method copy {path from args}
    201201    public method remove {{path ""}}
    202     public method xml {}
     202    public method xml {{path ""}}
    203203
    204204    public method diff {libobj}
     
    648648
    649649# ----------------------------------------------------------------------
    650 # USAGE: xml
     650# USAGE: xml ?<path>?
    651651#
    652652# Returns a string representing the XML information for the information
    653653# in this library.
    654654# ----------------------------------------------------------------------
    655 itcl::body Rappture::LibraryObj::xml {} {
    656     return [$_node asXML]
     655itcl::body Rappture::LibraryObj::xml {{path ""}} {
     656    if {"" != $path} {
     657        set n [find $path]
     658    } else {
     659        set n $_node
     660    }
     661    return [$n asXML]
    657662}
    658663
  • trunk/lang/tcl/src/RpRusage.c

    r1018 r2079  
    3535
    3636static RpRusageStats RpRusage_Start;      /* time at start of program */
    37 static RpRusageStats RpRusage_MarkStats;  /* stats from last "mark" */
    38 
    3937
    4038static Tcl_ObjCmdProc RpRusageCmd;
     39static Tcl_ObjCmdProc RpRusageForgetOp;
    4140static Tcl_ObjCmdProc RpRusageMarkOp;
    4241static Tcl_ObjCmdProc RpRusageMeasureOp;
     
    4645static double RpRusageTimeDiff _ANSI_ARGS_((struct timeval *currptr,
    4746    struct timeval *prevptr));
     47static void RpDestroyMarkNames _ANSI_ARGS_((ClientData cdata,
     48    Tcl_Interp *interp));
    4849
    4950/*
     
    5152 */
    5253static Rp_OpSpec rusageOps[] = {
    53     {"mark",    2, RpRusageMarkOp, 2, 2, "",},
    54     {"measure", 2, RpRusageMeasureOp, 2, 2, "",},
     54    {"forget", 1, RpRusageForgetOp, 2, 0, "?name...?",},
     55    {"mark",    2, RpRusageMarkOp, 2, 3, "?name?",},
     56    {"measure", 2, RpRusageMeasureOp, 2, 3, "?name?",},
    5557};
    5658static int nRusageOps = sizeof(rusageOps) / sizeof(Rp_OpSpec);
     
    6870    Tcl_Interp *interp;  /* interpreter being initialized */
    6971{
     72    Tcl_HashTable *markNamesPtr;
     73
    7074    Tcl_CreateObjCommand(interp, "::Rappture::rusage", RpRusageCmd,
    7175        NULL, NULL);
    7276
    73     /* set an initial mark automatically */
     77    /* set up a hash table for different mark names */
     78    markNamesPtr = (Tcl_HashTable*)ckalloc(sizeof(Tcl_HashTable));
     79    Tcl_InitHashTable(markNamesPtr, TCL_STRING_KEYS);
     80
     81    Tcl_SetAssocData(interp, "RpRusageMarks",
     82        RpDestroyMarkNames, (ClientData)markNamesPtr);
     83
     84    /* capture the starting time for this program */
     85    if (RpRusageCapture(interp, &RpRusage_Start) != TCL_OK) {
     86        return TCL_ERROR;
     87    }
     88
     89    /* set an initial "global" mark automatically */
    7490    if (RpRusageMarkOp(NULL, interp, 0, (Tcl_Obj**)NULL) != TCL_OK) {
    7591        return TCL_ERROR;
    7692    }
    77 
    78     /* capture the starting time for this program */
    79     memcpy(&RpRusage_Start, &RpRusage_MarkStats, sizeof(RpRusageStats));
    8093
    8194    return TCL_OK;
     
    121134 *  the start of an execution.  Handles the following syntax:
    122135 *
    123  *      rusage mark
     136 *      rusage mark ?name?
    124137 *
    125138 *  Returns TCL_OK on success, and TCL_ERROR (along with an error
     
    132145    Tcl_Interp *interp;       /* interpreter handling this request */
    133146    int objc;                 /* number of command line args */
    134     Tcl_Obj *const *objv;             /* strings for command line args */
    135 {
    136     return RpRusageCapture(interp, &RpRusage_MarkStats);
     147    Tcl_Obj *const *objv;     /* strings for command line args */
     148{
     149    char *markName;
     150    Tcl_HashTable *markNamesPtr;
     151    Tcl_HashEntry *entryPtr;
     152    int newEntry;
     153    RpRusageStats *markPtr;
     154
     155    markNamesPtr = (Tcl_HashTable *)
     156        Tcl_GetAssocData(interp, "RpRusageMarks", NULL);
     157
     158    markName = (objc > 2) ? Tcl_GetString(objv[2]): "global";
     159    entryPtr = Tcl_CreateHashEntry(markNamesPtr, markName, &newEntry);
     160    if (newEntry) {
     161        markPtr = (RpRusageStats*)ckalloc(sizeof(RpRusageStats));
     162        Tcl_SetHashValue(entryPtr, (ClientData)markPtr);
     163    } else {
     164        markPtr = (RpRusageStats*)Tcl_GetHashValue(entryPtr);
     165    }
     166
     167    return RpRusageCapture(interp, markPtr);
    137168}
    138169
     
    145176 *  the following syntax:
    146177 *
    147  *      rusage measure
     178 *      rusage measure ?name?
    148179 *
    149180 *  Returns TCL_OK on success, and TCL_ERROR (along with an error
     
    158189    Tcl_Obj *const *objv;     /* strings for command line args */
    159190{
     191    char *markName;
     192    Tcl_HashTable *markNamesPtr;
     193    Tcl_HashEntry *entryPtr;
     194    RpRusageStats *markPtr;
    160195    double tval;
    161196    RpRusageStats curstats;
     
    166201    }
    167202
     203    markNamesPtr = (Tcl_HashTable *)
     204        Tcl_GetAssocData(interp, "RpRusageMarks", NULL);
     205
     206    markName = (objc > 2) ? Tcl_GetString(objv[2]): "global";
     207    entryPtr = Tcl_FindHashEntry(markNamesPtr, markName);
     208    if (entryPtr == NULL) {
     209        Tcl_AppendResult(interp, "mark \"", markName,
     210            "\" doesn't exist", NULL);
     211        return TCL_ERROR;
     212    }
     213    markPtr = (RpRusageStats*)Tcl_GetHashValue(entryPtr);
     214
    168215    /*
    169216     * Compute: START TIME
    170217     */
    171218    Tcl_AppendElement(interp, "start");
    172     tval = RpRusageTimeDiff(&RpRusage_MarkStats.times, &RpRusage_Start.times);
     219    tval = RpRusageTimeDiff(&markPtr->times, &RpRusage_Start.times);
    173220    Tcl_PrintDouble(interp, tval, buffer);
    174221    Tcl_AppendElement(interp, buffer);
     
    178225     */
    179226    Tcl_AppendElement(interp, "walltime");
    180     tval = RpRusageTimeDiff(&curstats.times, &RpRusage_MarkStats.times);
     227    tval = RpRusageTimeDiff(&curstats.times, &markPtr->times);
    181228    Tcl_PrintDouble(interp, tval, buffer);
    182229    Tcl_AppendElement(interp, buffer);
     
    187234    Tcl_AppendElement(interp, "cputime");
    188235    tval = RpRusageTimeDiff(&curstats.resources.ru_utime,
    189              &RpRusage_MarkStats.resources.ru_utime)
     236             &markPtr->resources.ru_utime)
    190237         + RpRusageTimeDiff(&curstats.resources.ru_stime,
    191              &RpRusage_MarkStats.resources.ru_stime);
     238             &markPtr->resources.ru_stime);
    192239    Tcl_PrintDouble(interp, tval, buffer);
    193240    Tcl_AppendElement(interp, buffer);
    194241
     242    return TCL_OK;
     243}
     244
     245/*
     246 * ------------------------------------------------------------------------
     247 *  RpRusageForgetOp()
     248 *
     249 *  Invoked whenever someone uses the "rusage forget" command to release
     250 *  information previous set by "rusage mark".  With no args, it releases
     251 *  all known marks; otherwise, it releases just the specified mark
     252 *  names.  This isn't usually needed, but if a program creates thousands
     253 *  of marks, this gives a way to avoid a huge memory leak.
     254 *  Handles the following syntax:
     255 *
     256 *      rusage forget ?name name...?
     257 *
     258 *  Returns TCL_OK on success, and TCL_ERROR (along with an error
     259 *  message in the interpreter) if anything goes wrong.
     260 * ------------------------------------------------------------------------
     261 */
     262static int
     263RpRusageForgetOp(cdata, interp, objc, objv)
     264    ClientData cdata;         /* not used */
     265    Tcl_Interp *interp;       /* interpreter handling this request */
     266    int objc;                 /* number of command line args */
     267    Tcl_Obj *const *objv;     /* strings for command line args */
     268{
     269    int i;
     270    char *markName;
     271    Tcl_HashTable *markNamesPtr;
     272    Tcl_HashEntry *entryPtr;
     273    Tcl_HashSearch search;
     274
     275    markNamesPtr = (Tcl_HashTable *)
     276        Tcl_GetAssocData(interp, "RpRusageMarks", NULL);
     277
     278    /*
     279     * No args? Then clear all entries in the hash table.
     280     */
     281    if (objc == 2) {
     282        for (entryPtr = Tcl_FirstHashEntry(markNamesPtr, &search);
     283             entryPtr != NULL;
     284             entryPtr = Tcl_NextHashEntry(&search)) {
     285            ckfree((char *)Tcl_GetHashValue(entryPtr));
     286        }
     287        Tcl_DeleteHashTable(markNamesPtr);
     288        Tcl_InitHashTable(markNamesPtr, TCL_STRING_KEYS);
     289    }
     290
     291    /*
     292     * Otherwise, delete only the specified marks.  Be forgiving.
     293     * If a mark isn't recognized, ignore it.
     294     */
     295    else {
     296        for (i=2; i < objc; i++) {
     297            markName = Tcl_GetString(objv[i]);
     298            entryPtr = Tcl_FindHashEntry(markNamesPtr, markName);
     299            if (entryPtr) {
     300                ckfree((char *)Tcl_GetHashValue(entryPtr));
     301                Tcl_DeleteHashEntry(entryPtr);
     302            }
     303        }
     304    }
    195305    return TCL_OK;
    196306}
     
    256366}
    257367
     368/*
     369 * ------------------------------------------------------------------------
     370 *  RpDestroyMarkNames()
     371 *
     372 *  Used internally to clean up the marker names when the interpreter
     373 *  that owns them is being destroyed.
     374 * ------------------------------------------------------------------------
     375 */
     376static void
     377RpDestroyMarkNames(cdata, interp)
     378    ClientData cdata;         /* data being destroyed */
     379    Tcl_Interp *interp;       /* interpreter that owned the data */
     380{
     381    Tcl_HashTable *markNamesPtr;
     382    Tcl_HashEntry *entryPtr;
     383    Tcl_HashSearch search;
     384
     385    for (entryPtr=Tcl_FirstHashEntry(markNamesPtr, &search);
     386         entryPtr != NULL;
     387         entryPtr = Tcl_NextHashEntry(&search)) {
     388        ckfree( (char*)Tcl_GetHashValue(entryPtr) );
     389    }
     390    Tcl_DeleteHashTable(markNamesPtr);
     391    ckfree((char*)markNamesPtr);
     392}
Note: See TracChangeset for help on using the changeset viewer.