From stdcxx-commits-return-932-apmail-incubator-stdcxx-commits-archive=incubator.apache.org@incubator.apache.org Fri Sep 15 19:04:07 2006 Return-Path: Delivered-To: apmail-incubator-stdcxx-commits-archive@www.apache.org Received: (qmail 8510 invoked from network); 15 Sep 2006 19:04:07 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (209.237.227.199) by minotaur.apache.org with SMTP; 15 Sep 2006 19:04:07 -0000 Received: (qmail 50428 invoked by uid 500); 15 Sep 2006 19:03:49 -0000 Delivered-To: apmail-incubator-stdcxx-commits-archive@incubator.apache.org Received: (qmail 50395 invoked by uid 500); 15 Sep 2006 19:03:49 -0000 Mailing-List: contact stdcxx-commits-help@incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: stdcxx-dev@incubator.apache.org Delivered-To: mailing list stdcxx-commits@incubator.apache.org Received: (qmail 50274 invoked by uid 99); 15 Sep 2006 19:03:47 -0000 X-ASF-Spam-Status: No, hits=-9.4 required=10.0 tests=ALL_TRUSTED,NO_REAL_NAME X-Spam-Check-By: apache.org Received-SPF: pass (hermes.apache.org: local policy) Received: from [140.211.166.113] (HELO eris.apache.org) (140.211.166.113) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 15 Sep 2006 12:03:46 -0700 Received: by eris.apache.org (Postfix, from userid 65534) id 1545A1A981C; Fri, 15 Sep 2006 12:02:56 -0700 (PDT) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r446689 - in /incubator/stdcxx/trunk/util: display.cpp display.h exec.cpp exec.h runall.cpp Date: Fri, 15 Sep 2006 19:02:55 -0000 To: stdcxx-commits@incubator.apache.org From: sebor@apache.org X-Mailer: svnmailer-1.1.0 Message-Id: <20060915190256.1545A1A981C@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org X-Spam-Rating: minotaur.apache.org 1.6.2 0/1000/N Author: sebor Date: Fri Sep 15 12:02:55 2006 New Revision: 446689 URL: http://svn.apache.org/viewvc?view=rev&rev=446689 Log: 2006-09-15 Andrew Black * display.h (unistd.h) [!_WIN32 && !_WIN64]: Include. (sys/time.h) [_XOPEN_UNIX]: Include. (rw_time_t, rw_suseconds_t, struct rw_timeval) [!_XOPEN_UNIX]: Define placeholder structures. (rw_timeval): Define abstraction typedef. (struct target_status): Add run, user, sys elements. * display.cpp (unistd.h) [!_WIN32 && !_WIN64]: Include. print_header_plain: Alter cols for process times. print_target_plain: Partition output column printing by section, add timing output. * exec.h (exec_file): Alter signature to accept target_status rather than char**. * exec.cpp (display.h): Include. (calculate_usage) [!_WIN32 && !_WIN64]: Define function to populate user and sys fields of provided target_status struct (if _XOPEN_UNIX is defined). (exec_file): Alter to accept target_status rather than char**, use argv element in place of old char** argument. (exec_file) [!_WIN32 && !_WIN64]: call calculate_usage after wait_for_child. * runall.cpp (run_target): Pass target_status struct rather than argv element. Modified: incubator/stdcxx/trunk/util/display.cpp incubator/stdcxx/trunk/util/display.h incubator/stdcxx/trunk/util/exec.cpp incubator/stdcxx/trunk/util/exec.h incubator/stdcxx/trunk/util/runall.cpp Modified: incubator/stdcxx/trunk/util/display.cpp URL: http://svn.apache.org/viewvc/incubator/stdcxx/trunk/util/display.cpp?view=diff&rev=446689&r1=446688&r2=446689 ============================================================================== --- incubator/stdcxx/trunk/util/display.cpp (original) +++ incubator/stdcxx/trunk/util/display.cpp Fri Sep 15 12:02:55 2006 @@ -26,6 +26,9 @@ #include #include /* for fflush(), printf(), puts(), ... */ +#if !defined (_WIN32) && !defined (_WIN64) +# include /* for _XOPEN_UNIX */ +#endif #include "cmdopt.h" /* for target_name -should this be moved? */ #include "exec.h" /* for get_signame */ @@ -34,7 +37,8 @@ void print_header_plain () { - puts ("NAME STATUS ASSERTS FAILED PERCNT"); + puts ("NAME STATUS ASSERTS FAILED PERCNT USER " + "SYS"); } void print_target_plain (const struct target_status*) @@ -45,23 +49,38 @@ void print_status_plain (const struct target_status* status) { + unsigned valid_timing; + assert (0 != status); assert (ST_OK <= status->status && ST_LAST > status->status); + valid_timing = status->run && ST_NOT_KILLED != status->status; + if (status->status) /* if status is set, print it */ - printf ("%6s\n", short_st_name [status->status]); + printf ("%6s", short_st_name [status->status]); else if (status->exit) /* if exit code is non-zero, print it */ - printf ("%6d\n", status->exit); + printf ("%6d", status->exit); else if (status->signal) /* if exit signal is non-zero, print it */ - printf ("%6s\n", get_signame (status->signal)); - else if (!status->assert) /* if the assertion count is 0, it's an example */ - puts (" 0"); + printf ("%6s", get_signame (status->signal)); + else + printf (" 0"); + + /* Print assetions, if any registered */ + if (status->assert) { + printf (" %7u %6u %5d%%", status->assert, status->failed, + 100 * (status->assert - status->failed) / status->assert); + } + else if (valid_timing) + printf (" "); + + /* Print timings, if available */ + if (valid_timing) + printf (" %3ld.%03ld %3ld.%03ld\n", status->user.tv_sec, + status->user.tv_usec/1000, status->sys.tv_sec, + status->sys.tv_usec/1000); else { - unsigned pcnt = 0; - if (status->assert) { - pcnt = 100 * (status->assert - status->failed) / status->assert; - } - printf (" 0 %7u %6u %5d%%\n", status->assert, status->failed, pcnt); + puts (""); } + } void print_footer_plain () {} Modified: incubator/stdcxx/trunk/util/display.h URL: http://svn.apache.org/viewvc/incubator/stdcxx/trunk/util/display.h?view=diff&rev=446689&r1=446688&r2=446689 ============================================================================== --- incubator/stdcxx/trunk/util/display.h (original) +++ incubator/stdcxx/trunk/util/display.h Fri Sep 15 12:02:55 2006 @@ -27,6 +27,38 @@ #ifndef RW_DISPLAY_H #define RW_DISPLAY_H +#if !defined (_WIN32) && !defined (_WIN64) +# include /* for _XOPEN_UNIX */ +#endif + +#ifdef _XOPEN_UNIX +# include /* for struct timeval */ +/** + Abstraction typedef for struct timeval using real struct +*/ +typedef struct timeval rw_timeval; +#else +/** + Placeholder time_t for use in rw_timeval +*/ +typedef long rw_time_t; +/** + Placeholder suseconds_t for use in rw_timeval +*/ +typedef long rw_suseconds_t; +/** + Placeholder struct timeval to use if _XOPEN_UNIX isn't defined +*/ +struct rw_timeval { + rw_time_t tv_sec; + rw_suseconds_t tv_usec; +}; +/** + Abstraction typedef for struct timeval using placeholder struct +*/ +typedef struct rw_timeval rw_timeval; +#endif + /** Output format mode enumeration. @@ -74,7 +106,10 @@ char** argv; /**< Target argv array. */ int exit; /**< exit code for process. */ int signal; /**< Termination signal for process. */ + int run; /**< Flag indicating if the process executed. */ enum ProcessStatus status; /**< Textual process status. */ + rw_timeval user; /**< Elapsed user time spent in execution. */ + rw_timeval sys; /**< Elapsed system time spent in execution. */ unsigned warn; /**< Number of (test) warnings. */ unsigned assert; /**< Number of (test) assertions. */ unsigned failed; /**< Number of failed (test) assertions. */ Modified: incubator/stdcxx/trunk/util/exec.cpp URL: http://svn.apache.org/viewvc/incubator/stdcxx/trunk/util/exec.cpp?view=diff&rev=446689&r1=446688&r2=446689 ============================================================================== --- incubator/stdcxx/trunk/util/exec.cpp (original) +++ incubator/stdcxx/trunk/util/exec.cpp Fri Sep 15 12:02:55 2006 @@ -51,6 +51,7 @@ #include #include "cmdopt.h" +#include "display.h" /* for struct target_status */ #include "util.h" #include "exec.h" @@ -697,6 +698,62 @@ #endif /* _XOPEN_UNIX */ /** + Calculates the amount of resources used by the child processes. + + This method uses the getrusage() system call to calculate the resources + used by the child process. However, getrusage() only is able to calcualte + agragate usage by all child processes, not usage by a specific child process. + Therefore, we must keep a running tally of how many resources had been used + the previous time we calculated the usage. This difference is the resources + that were used by the process that just completed. + + @param result target_status structure to populate with process usage. +*/ +static void +calculate_usage (struct target_status* result) +{ +#ifdef _XOPEN_UNIX + static bool init = 0; + static struct rusage history; + struct rusage now; + + assert (0 != result); + + if (!init) { + memset (&history, 0, sizeof history); + init = 1; + } + + if (0 != getrusage (RUSAGE_CHILDREN, &now)) { + warn ("Failed to retrieve child resource usage: %s", strerror (errno)); + return; + } + + /* time calculations */ + result->user.tv_sec = now.ru_utime.tv_sec - history.ru_utime.tv_sec; + result->user.tv_usec = now.ru_utime.tv_usec - history.ru_utime.tv_usec; + result->sys.tv_sec = now.ru_stime.tv_sec - history.ru_stime.tv_sec; + result->sys.tv_usec = now.ru_stime.tv_usec - history.ru_stime.tv_usec; + + /* Adjust seconds/microseconds */ + if (now.ru_utime.tv_usec < history.ru_utime.tv_usec) { + --result->user.tv_sec; + result->user.tv_usec += 1000000; + } + if (now.ru_stime.tv_usec < history.ru_stime.tv_usec) { + --result->sys.tv_sec; + result->sys.tv_usec += 1000000; + } + + /* Tag result as having run */ + result->run = 1; + + /* Cache the values retrieved */ + memcpy (&history, &now, sizeof (struct rusage)); +#endif /* _XOPEN_UNIX */ +} + +/** Entry point to the child process (watchdog) subsystem. This method fork ()s, creating a child process. This child process becomes @@ -712,15 +769,17 @@ @see wait_for_child () */ struct exec_attrs -exec_file (char** argv) +exec_file (struct target_status* result) { const pid_t child_pid = fork (); + assert (0 != result); + assert (0 != result->argv); + assert (0 != result->argv [0]); + if (0 == child_pid) { /* child */ FILE* error_file; - assert (0 != argv); - assert (0 != argv [0]); assert (0 != target_name); /* Set process group ID (so entire group can be killed)*/ @@ -752,7 +811,7 @@ /* Redirect stdout */ { - char* const tmp_name = output_name (argv [0]); + char* const tmp_name = output_name (result->argv [0]); int intermit; intermit = open (tmp_name, O_WRONLY | O_CREAT | O_TRUNC, @@ -776,10 +835,10 @@ limit_process (); #endif /* _XOPEN_UNIX */ - execv (argv [0], argv); + execv (result->argv [0], result->argv); fprintf (error_file, "%s (%s): execv (\"%s\", ...) error: %s\n", - exe_name, target_name, argv [0], strerror (errno)); + exe_name, target_name, result->argv [0], strerror (errno)); exit (1); } @@ -787,13 +846,15 @@ if (-1 == child_pid) { /* Fake a failue to execute status return structure */ struct exec_attrs state = {127, -1}; - warn ("Unable to create child process for %s: %s\n", argv [0], + warn ("Unable to create child process for %s: %s\n", result->argv [0], strerror (errno)); return state; + } else { + /* parent */ + struct exec_attrs state = wait_for_child (child_pid); + calculate_usage (result); + return state; } - - /* parent */ - return wait_for_child (child_pid); } #else /* _WIN{32,64} */ /** @@ -950,7 +1011,7 @@ @see wait_for_child () */ struct exec_attrs -exec_file (char** argv) +exec_file (struct target_status* result) { char* merged; PROCESS_INFORMATION child; @@ -962,7 +1023,9 @@ const DWORD real_timeout = (timeout > 0) ? timeout * 1000 : INFINITE; DWORD wait_code; - assert (0 != argv); + assert (0 != result); + assert (0 != result->argv); + assert (0 != result->argv [0]); memset (&status, 0, sizeof status); @@ -979,7 +1042,7 @@ /* Create I/O handles */ { /* Output redirection */ - char* const tmp_name = output_name (argv [0]); + char* const tmp_name = output_name (result->argv [0]); context.hStdOutput = CreateFile (tmp_name, GENERIC_WRITE, FILE_SHARE_WRITE, &child_sa, CREATE_ALWAYS, @@ -1003,7 +1066,7 @@ } } - merged = merge_argv (argv); + merged = merge_argv (result->argv); /* set appropriate error mode (the child process inherits this error mode) to disable displaying the critical-error-handler @@ -1011,7 +1074,7 @@ UINT old_mode = SetErrorMode (SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX); /* Create the child process */ - if (0 == CreateProcess (argv [0], merged, 0, 0, 1, + if (0 == CreateProcess (result->argv [0], merged, 0, 0, 1, CREATE_NEW_PROCESS_GROUP, 0, 0, &context, &child)) { /* record the status if we failed to create the process */ status.status = -1; Modified: incubator/stdcxx/trunk/util/exec.h URL: http://svn.apache.org/viewvc/incubator/stdcxx/trunk/util/exec.h?view=diff&rev=446689&r1=446688&r2=446689 ============================================================================== --- incubator/stdcxx/trunk/util/exec.h (original) +++ incubator/stdcxx/trunk/util/exec.h Fri Sep 15 12:02:55 2006 @@ -42,6 +42,6 @@ const char* get_signame (int signo); -struct exec_attrs exec_file (char** argv); +struct exec_attrs exec_file (struct target_status* result); #endif // RW_EXEC_H Modified: incubator/stdcxx/trunk/util/runall.cpp URL: http://svn.apache.org/viewvc/incubator/stdcxx/trunk/util/runall.cpp?view=diff&rev=446689&r1=446688&r2=446689 ============================================================================== --- incubator/stdcxx/trunk/util/runall.cpp (original) +++ incubator/stdcxx/trunk/util/runall.cpp Fri Sep 15 12:02:55 2006 @@ -415,7 +415,7 @@ print_target (&results); if (check_target_ok (&results)) { - struct exec_attrs status = exec_file (results.argv); + struct exec_attrs status = exec_file (&results); process_results (&status, &results); }