00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "config.h"
00023
00024 #include <errno.h>
00025 #include <stdio.h>
00026 #include <string.h>
00027 #include <stdlib.h>
00028 #include <signal.h>
00029 #include <unistd.h>
00030 #include <fcntl.h>
00031
00032 #include <sys/time.h>
00033 #include <sys/types.h>
00034 #include <sys/times.h>
00035 #include <sys/wait.h>
00036 #include <sys/socket.h>
00037 #include <sys/resource.h>
00038
00039 #include <netinet/in.h>
00040
00041 #include <assert_pp.h>
00042 #include <time_util.h>
00043
00044 #include "gkemu.h"
00045 #include "childProcess.h"
00046
00047 #include <rk/rk.h>
00048 #include <rk/rk_error.h>
00049
00050 #include "rk_util.h"
00051
00052
00053
00054
00055 #define SAMPLES_PER_SECOND 1
00056
00057
00058
00059
00060 #define MAX_CLIENTS 8
00061
00062
00063
00064
00065 #define CLIENT_BUFFER_MAX 4096
00066
00067 #if !defined(__XSTRING)
00068
00069
00070
00071
00072
00073 #define __XSTRING(x) __STRING(x)
00074 #endif
00075
00076
00077
00078
00079
00080
00081 #define my_perror(x) perror(x ", file " __FILE__ ", line " __XSTRING(__LINE__))
00082
00083 enum {
00084 RKTB_DONE,
00085 RKTB_CREATED_RESOURCE_SET,
00086 };
00087
00088
00089
00090
00091
00092
00093
00094 enum {
00095 RKTF_DONE = (1L << RKTB_DONE),
00096 RKTF_CREATED_RESOURCE_SET = (1L << RKTB_CREATED_RESOURCE_SET),
00097 };
00098
00099 enum {
00100 RKTB_CLIENT_INITIALIZED,
00101 };
00102
00103
00104
00105
00106
00107
00108
00109 enum {
00110 RKTF_CLIENT_INITIALIZED = (1L << RKTB_CLIENT_INITIALIZED),
00111 };
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132 static struct {
00133 unsigned long rkt_Flags;
00134 const char *rkt_UtilityName;
00135 struct timeval rkt_StartTime;
00136 const char *rkt_OutputBase;
00137 const char *rkt_Name;
00138 unsigned int rkt_ChildPeriod;
00139 unsigned int rkt_ChildCompute;
00140 rk_resource_set_t rkt_ResourceSet;
00141 pid_t rkt_ChildPID;
00142
00143 int rkt_ServerSocket;
00144 char rkt_ClientBuffer[CLIENT_BUFFER_MAX];
00145 int rkt_ClientSockets[MAX_CLIENTS];
00146 unsigned long rkt_ClientFlags[MAX_CLIENTS];
00147 } rktimes_data;
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158 static void rktClientWrite(unsigned int index, const char *buffer, size_t len)
00159 {
00160 int fd;
00161
00162 require(rktimes_data.rkt_ServerSocket != -1);
00163 require(index < MAX_CLIENTS);
00164 require(buffer != NULL);
00165
00166 if( (fd = rktimes_data.rkt_ClientSockets[index]) >= 0 )
00167 {
00168 int rc;
00169
00170 rc = write(fd, buffer, len);
00171 if( rc != len )
00172 {
00173 require((rc != -1) || (errno == EPIPE) || (errno == EWOULDBLOCK));
00174
00175
00176 close(fd);
00177 rktimes_data.rkt_ClientSockets[index] = -1;
00178 rktimes_data.rkt_ClientFlags[index] = 0;
00179 }
00180 }
00181 }
00182
00183
00184
00185
00186
00187
00188 static void sigpass(int sig)
00189 {
00190 require((sig == SIGINT) || (sig == SIGTERM));
00191 require(rktimes_data.rkt_ChildPID != 0);
00192
00193 if( kill(rktimes_data.rkt_ChildPID, sig) == -1 )
00194 {
00195 my_perror("kill");
00196 }
00197 }
00198
00199
00200 #define MAX_PROC_LIST 128
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212 static void sigalrm(int sig)
00213 {
00214 static unsigned long long total_compute, total_nice, total_deadline;
00215 static unsigned long long total_usage;
00216 static pid_t procs[MAX_PROC_LIST];
00217
00218 unsigned long long inc_usage = 0, total_run, total_idle;
00219 struct cpu_reserve_attr cra;
00220 struct timeval curr, run;
00221 int lpc, len, count;
00222 rk_reserve_t cr;
00223
00224 require(sig == SIGALRM);
00225
00226
00227 gettimeofday(&curr, NULL);
00228 timersub(&curr, &rktimes_data.rkt_StartTime, &run);
00229 total_run = (run.tv_sec * 1000000) + run.tv_usec;
00230
00231
00232 if( (count = rk_resource_set_get_proclist(rktimes_data.rkt_ResourceSet,
00233 procs,
00234 MAX_PROC_LIST)) == -1 )
00235 {
00236 my_perror("rk_resource_set_get_proclist");
00237
00238 rktimes_data.rkt_Flags |= RKTF_DONE;
00239 }
00240
00241
00242 for( lpc = 0; lpc < count; lpc++ )
00243 {
00244 struct cpChildProcess *cp;
00245
00246 if( (cp = cpFindChildProcess(procs[lpc])) == NULL )
00247 {
00248
00249 if( (cp = cpCreateChildProcess(procs[lpc])) != NULL )
00250 {
00251 cpOpenOutput(cp,
00252 rktimes_data.rkt_OutputBase,
00253 &rktimes_data.rkt_StartTime);
00254 }
00255 }
00256 if( cp != NULL )
00257 {
00258 inc_usage += cpSampleUsage(cp, &run);
00259 }
00260 }
00261
00262
00263 total_usage += inc_usage;
00264
00265
00266 if( (cr = rk_resource_set_get_cpu_rsv(rktimes_data.rkt_ResourceSet)) !=
00267 NULL_RESERVE)
00268 {
00269 if( rk_cpu_reserve_get_attr(cr, &cra) != RK_ERROR )
00270 {
00271 unsigned long long rsv_period, rsv_compute, rsv_nice, rsv_deadline;
00272 double multiplier;
00273
00274
00275 rsv_period = (cra.period.tv_sec * 1000000) +
00276 (cra.period.tv_nsec / 1000);
00277 multiplier = (1000000.0 / rsv_period) /
00278 (double)SAMPLES_PER_SECOND;
00279 rsv_compute = ((cra.compute_time.tv_sec * 1000000) +
00280 (cra.compute_time.tv_nsec / 1000)) * multiplier;
00281 if( inc_usage > rsv_compute )
00282 {
00283 rsv_nice = 0;
00284 }
00285 else
00286 {
00287 rsv_nice = rsv_compute - inc_usage;
00288 rsv_compute = inc_usage;
00289 }
00290 rsv_deadline = ((cra.deadline.tv_sec * 1000000) +
00291 (cra.deadline.tv_nsec / 1000)) * multiplier;
00292
00293 total_deadline += rsv_deadline - (rsv_compute + rsv_nice);
00294 total_compute += rsv_compute;
00295 total_nice += rsv_nice;
00296 }
00297 else
00298 {
00299 my_perror("rk_cpu_reserve_get_attr");
00300 }
00301 }
00302
00303 total_idle = total_run - total_usage;
00304
00305
00306 len = gkFormatUpdate(rktimes_data.rkt_ClientBuffer, CLIENT_BUFFER_MAX,
00307 GKA_CPUUser, total_usage,
00308 GKA_CPUIdle, total_idle,
00309 GKA_CPUReserveUser, total_compute,
00310 GKA_CPUReserveNice, total_nice,
00311 GKA_CPUReserveIdle, total_deadline,
00312 GKA_Processes, count,
00313 GKA_ProcessesRunning, 0,
00314 GKA_UpTime, &run,
00315 GKA_TAG_DONE);
00316
00317
00318 for( lpc = 0; lpc < MAX_CLIENTS; lpc++ )
00319 {
00320 if( rktimes_data.rkt_ClientSockets[lpc] != -1 )
00321 {
00322 if( !(rktimes_data.rkt_ClientFlags[lpc] &
00323 RKTF_CLIENT_INITIALIZED) )
00324 {
00325 rktClientWrite(lpc,
00326 gkInitialUpdateOpen,
00327 strlen(gkInitialUpdateOpen));
00328 }
00329 rktClientWrite(lpc, rktimes_data.rkt_ClientBuffer, len);
00330 if( !(rktimes_data.rkt_ClientFlags[lpc] &
00331 RKTF_CLIENT_INITIALIZED) )
00332 {
00333 rktClientWrite(lpc,
00334 gkInitialUpdateClose,
00335 strlen(gkInitialUpdateClose));
00336 rktimes_data.rkt_ClientFlags[lpc] |= RKTF_CLIENT_INITIALIZED;
00337 }
00338 }
00339 }
00340 }
00341
00342
00343
00344
00345
00346
00347 static void sigchld(int sig)
00348 {
00349 require(sig == SIGCHLD);
00350 require(rktimes_data.rkt_ChildPID != 0);
00351
00352 rktimes_data.rkt_Flags |= RKTF_DONE;
00353 }
00354
00355
00356
00357
00358
00359
00360 static void sigexit(int sig)
00361 {
00362 require((sig == SIGINT) || (sig == SIGTERM));
00363
00364 rktimes_data.rkt_Flags |= RKTF_DONE;
00365 }
00366
00367
00368
00369
00370
00371
00372
00373 static void sigio(int sig)
00374 {
00375 struct sockaddr saddr;
00376 socklen_t saddrlen;
00377 int fd;
00378
00379 require(sig == SIGIO);
00380 require(rktimes_data.rkt_ServerSocket != -1);
00381
00382 saddrlen = sizeof(saddr);
00383
00384 while( (fd = accept(rktimes_data.rkt_ServerSocket,
00385 &saddr,
00386 &saddrlen)) >= 0 )
00387 {
00388 int fl, lpc;
00389
00390
00391
00392
00393
00394 fl = fcntl(fd, F_GETFL, 0);
00395 fcntl(fd, F_SETFL, fl | O_NONBLOCK);
00396
00397 for( lpc = 0;
00398 (lpc < MAX_CLIENTS) &&
00399 (rktimes_data.rkt_ClientSockets[lpc] != -1);
00400 lpc++ );
00401 if( lpc < MAX_CLIENTS )
00402 {
00403 int len;
00404
00405 rktimes_data.rkt_ClientSockets[lpc] = fd;
00406
00407
00408 len = gkFormatPreamble(
00409 rktimes_data.rkt_ClientBuffer,
00410 CLIENT_BUFFER_MAX,
00411 GKA_HostName, rktimes_data.rkt_Name,
00412 GKA_SystemName, rktimes_data.rkt_UtilityName,
00413 GKA_TAG_DONE);
00414 rktClientWrite(lpc, rktimes_data.rkt_ClientBuffer, len);
00415 }
00416 else
00417 {
00418
00419 close(fd);
00420 }
00421 }
00422 }
00423
00424
00425
00426
00427
00428
00429
00430
00431 static rk_resource_set_t rktCreateSelfResourceSet(char *name)
00432 {
00433 rk_resource_set_t rs, retval = NULL_RESOURCE_SET;
00434
00435 require(name != NULL);
00436 require(strlen(name) > 0);
00437 require(strlen(name) < RK_NAME_LEN);
00438
00439 if( (rs = rk_resource_set_create(name)) != NULL_RESOURCE_SET )
00440 {
00441 struct cpu_reserve_attr cra;
00442 rk_reserve_t cr;
00443
00444 memset(&cra, 0, sizeof(cra));
00445
00446 cra.compute_time.tv_sec = 0;
00447 cra.compute_time.tv_nsec = 5000000;
00448 cra.period.tv_sec = 0;
00449 cra.period.tv_nsec = 1000000000;
00450 cra.deadline = cra.period;
00451 cra.blocking_time = cra.start_time = (struct timespec){ 0, 0 };
00452 cra.reserve_type.sch_mode = RSV_SOFT;
00453 cra.reserve_type.enf_mode = RSV_SOFT;
00454 cra.reserve_type.rep_mode = RSV_SOFT;
00455 cra.processor = RK_ANY_CPU;
00456 if( rk_cpu_reserve_create(rs, &cr, &cra) != RK_ERROR )
00457 {
00458
00459
00460
00461
00462 retval = rs;
00463 }
00464 else
00465 {
00466 my_perror("rk_cpu_reserve_create");
00467 rk_resource_set_destroy(rs);
00468 }
00469 }
00470 else
00471 {
00472 my_perror("rk_resource_set_create");
00473 }
00474 return( retval );
00475 }
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494 static rk_resource_set_t rktGetChildResourceSet(rk_resource_set_t rs,
00495 const char *requested_name,
00496 const char *default_name,
00497 unsigned int child_period,
00498 unsigned int child_compute)
00499 {
00500 rk_resource_set_t retval = rs;
00501
00502 require((requested_name == NULL) ||
00503 ((strlen(requested_name) > 0) &&
00504 (strlen(requested_name) <= RK_NAME_LEN)));
00505 require(default_name != NULL);
00506 require(strlen(default_name) > 0);
00507 require(strlen(default_name) <= RK_NAME_LEN);
00508 require(((child_period == 0) && (child_compute == 0)) ||
00509 (child_compute < child_period));
00510
00511
00512 if( retval == NULL_RESOURCE_SET )
00513 {
00514 const char *actual_name;
00515
00516 if( requested_name != NULL )
00517 {
00518 actual_name = requested_name;
00519 }
00520 else
00521 {
00522 actual_name = default_name;
00523 }
00524 if( (retval = rk_resource_set_create((char *)actual_name)) !=
00525 NULL_RESOURCE_SET )
00526 {
00527 rktimes_data.rkt_Flags |= RKTF_CREATED_RESOURCE_SET;
00528 }
00529 else
00530 {
00531 my_perror("rk_resource_set_create");
00532 }
00533 }
00534
00535 if( retval != NULL_RESOURCE_SET )
00536 {
00537 rk_reserve_t cr = NULL_RESERVE;
00538
00539 if( (cr = rk_resource_set_get_cpu_rsv(retval)) != NULL_RESERVE )
00540 {
00541
00542
00543
00544
00545 if( rk_resource_set_get_num_procs(retval) > 0 )
00546 {
00547
00548 }
00549 else
00550 {
00551
00552 if( rk_cpu_reserve_delete(retval) == 0 )
00553 {
00554 cr = NULL_RESERVE;
00555
00556 rktimes_data.rkt_Flags |= RKTF_CREATED_RESOURCE_SET;
00557 }
00558 else
00559 {
00560 my_perror("rk_cpu_reserve_delete");
00561 }
00562 }
00563 }
00564
00565 if( (cr == NULL_RESERVE) && (child_period > 0) )
00566 {
00567 struct cpu_reserve_attr cra;
00568
00569 cra.compute_time.tv_sec = 0;
00570 cra.compute_time.tv_nsec = child_compute * 1000;
00571 cra.period.tv_sec = 0;
00572 cra.period.tv_nsec = child_period * 1000;
00573 cra.deadline = cra.period;
00574 cra.blocking_time = cra.start_time = (struct timespec){ 0, 0 };
00575 cra.reserve_type.sch_mode = RSV_SOFT;
00576 cra.reserve_type.enf_mode = RSV_SOFT;
00577 cra.reserve_type.rep_mode = RSV_SOFT;
00578 cra.processor = RK_ANY_CPU;
00579 if( rk_cpu_reserve_create(retval, &cr, &cra) < 0 )
00580 {
00581 my_perror("rk_cpu_reserve_create");
00582 }
00583 }
00584 }
00585 return( retval );
00586 }
00587
00588
00589
00590
00591
00592
00593
00594 static void rktUsage(FILE *file, char *prog_name)
00595 {
00596 require(file != NULL);
00597 require(prog_name != NULL);
00598 require(strlen(prog_name) > 0);
00599
00600 fprintf(file,
00601 "Usage: %s [options] -- <command> [argument ...]\n",
00602 prog_name);
00603 fprintf(file,
00604 "\n"
00605 "Create a resource set and periodically record the CPU\n"
00606 "usage of the attached process and its children.\n"
00607 "\n"
00608 "Options:\n"
00609 "\t-h\t\tThis help message.\n"
00610 "\t-V\t\tShow the version number.\n"
00611
00612 "\t-o <file>\tBase name for the output files. (Default: rktimes)\n"
00613
00614 "\t-n <name>\tName of the RK resource set. If a resource set\n"
00615 "\t\t\twith that name already exists, that will be used.\n"
00616 "\t\t\tOtherwise, a new one with that name will be created.\n"
00617 "\t\t\t(Default: rktimes)\n"
00618
00619 "\t-p <port>\tServer port for GKrellmd emulation.\n"
00620
00621 "\t-P <time>\tThe period for the CPU reservation.\n"
00622 "\t\t\tThe -C option must also be given.\n"
00623
00624 "\t-C <time>\tThe compute time for the CPU reservation.\n"
00625 "\t\t\tThe -P option must also be given.\n"
00626
00627 "\n"
00628
00629 "Package: " PACKAGE_STRING "\n"
00630 "Contact: " PACKAGE_BUGREPORT "\n");
00631 }
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644 static int rktProcessOptions(int *argc_inout, char **argv_inout[])
00645 {
00646 unsigned long long us_time;
00647 int ch, retval = 0;
00648 char *prog_name;
00649 char **argv;
00650 int argc;
00651
00652 require(argc_inout != NULL);
00653 require(argv_inout != NULL);
00654
00655 argc = *argc_inout;
00656 argv = *argv_inout;
00657 prog_name = argv[0];
00658 while( ((ch = getopt(argc, argv, "hVo:n:p:P:C:")) != -1) && (retval == 0) )
00659 {
00660 switch( ch )
00661 {
00662 case 'o':
00663
00664 if( strlen(optarg) == 0 )
00665 {
00666 fprintf(stderr,
00667 "%s: -o value is empty\n",
00668 prog_name);
00669 }
00670 else
00671 {
00672 rktimes_data.rkt_OutputBase = optarg;
00673 }
00674 break;
00675 case 'n':
00676
00677 if( strlen(optarg) == 0 )
00678 {
00679 fprintf(stderr,
00680 "%s: -n value is empty\n",
00681 prog_name);
00682 }
00683 else if( strlen(optarg) > RK_NAME_LEN )
00684 {
00685 fprintf(stderr,
00686 "%s: -n value too long (only %d characters allowed)\n",
00687 prog_name,
00688 RK_NAME_LEN);
00689 retval = 1;
00690 }
00691 else
00692 {
00693 rktimes_data.rkt_Name = optarg;
00694 }
00695 break;
00696 case 'P':
00697
00698 if( string_to_microsec(&us_time, optarg) )
00699 {
00700 rktimes_data.rkt_ChildPeriod = us_time;
00701 }
00702 else
00703 {
00704 fprintf(stderr,
00705 "%s: -P option requires a time value\n",
00706 prog_name);
00707 }
00708 break;
00709 case 'C':
00710
00711 if( string_to_microsec(&us_time, optarg) )
00712 {
00713 rktimes_data.rkt_ChildCompute = us_time;
00714 }
00715 else
00716 {
00717 fprintf(stderr,
00718 "%s: -C option requires a time value\n",
00719 prog_name);
00720 }
00721 break;
00722 case 'p':
00723
00724 {
00725 int port;
00726
00727 if( (sscanf(optarg, "%d", &port) == 1) &&
00728 (port > 0) && (port < 65536) )
00729 {
00730 int fd;
00731
00732 if( (fd = socket(PF_INET, SOCK_STREAM, 0)) >= 0 )
00733 {
00734 struct sockaddr_in sin;
00735 int on = 1;
00736
00737 (void)setsockopt(fd,
00738 SOL_SOCKET,
00739 SO_REUSEADDR,
00740 (char *)&on,
00741 sizeof(on));
00742 #if defined(BSD44)
00743 sin.sin_len = sizeof(sin);
00744 #endif
00745 sin.sin_family = AF_INET;
00746 sin.sin_port = htons(port);
00747 sin.sin_addr.s_addr = INADDR_ANY;
00748 if( bind(fd,
00749 (struct sockaddr *)&sin,
00750 sizeof(sin)) == 0 )
00751 {
00752 if( listen(fd, 5) == 0 )
00753 {
00754 int fl;
00755
00756 fl = fcntl(fd, F_GETFL, 0);
00757 fl |= O_NONBLOCK |
00758 #if defined(O_ASYNC)
00759 O_ASYNC
00760 #elif defined(FASYNC)
00761 FASYNC
00762 #endif
00763 ;
00764 fcntl(fd, F_SETFL, fl);
00765 fcntl(fd, F_SETOWN, getpid());
00766
00767
00768
00769
00770 }
00771 else
00772 {
00773 my_perror("listen");
00774 retval = -1;
00775 }
00776 }
00777 else
00778 {
00779 my_perror("bind");
00780 retval = -1;
00781 }
00782 }
00783 else
00784 {
00785 my_perror("socket");
00786 retval = -1;
00787 }
00788 if( retval == 0 )
00789 {
00790 rktimes_data.rkt_ServerSocket = fd;
00791 }
00792 else
00793 {
00794 close(fd);
00795 }
00796 }
00797 else
00798 {
00799 fprintf(stderr,
00800 "%s: Invalid -p value: %s\n",
00801 prog_name,
00802 optarg);
00803 retval = 1;
00804 }
00805 }
00806 break;
00807 case 'V':
00808 fprintf(stderr, "%s\n", PACKAGE_VERSION);
00809 retval = -1;
00810 break;
00811 case 'h':
00812 case '?':
00813 default:
00814 retval = 1;
00815 break;
00816 }
00817 }
00818 if( (rktimes_data.rkt_ChildCompute == 0) &&
00819 (rktimes_data.rkt_ChildPeriod == 0) )
00820 {
00821 }
00822 else if( rktimes_data.rkt_ChildCompute == 0 )
00823 {
00824 fprintf(stderr,
00825 "%s: Compute time _must_ be specified with period\n",
00826 prog_name);
00827 retval = 1;
00828 }
00829 else if( rktimes_data.rkt_ChildPeriod == 0 )
00830 {
00831 fprintf(stderr,
00832 "%s: Period time _must_ be specified with compute time\n",
00833 prog_name);
00834 retval = 1;
00835 }
00836 else if( rktimes_data.rkt_ChildCompute >= rktimes_data.rkt_ChildPeriod )
00837 {
00838 fprintf(stderr,
00839 "%s: Compute time _must_ be less than period\n",
00840 prog_name);
00841 retval = 1;
00842 }
00843 *argc_inout -= optind;
00844 *argv_inout += optind;
00845
00846 if( (*argc_inout > 0) && (strcmp(*argv_inout[0], "--") == 0) )
00847 {
00848 *argc_inout -= 1;
00849 *argv_inout += 1;
00850 }
00851 if( (retval == 0) && (*argc_inout == 0) )
00852 {
00853
00854 if( rktimes_data.rkt_Name == NULL )
00855 {
00856 fprintf(stderr, "%s: Missing utility to monitor\n", prog_name);
00857 retval = 1;
00858 }
00859
00860 else if( (rktimes_data.rkt_ResourceSet =
00861 rk_resource_set_get_by_name(rktimes_data.rkt_Name)) ==
00862 NULL_RESOURCE_SET )
00863 {
00864 fprintf(stderr,
00865 "%s: No such resource set: %s\n",
00866 prog_name,
00867 rktimes_data.rkt_Name);
00868 retval = 1;
00869 }
00870 }
00871 return( retval );
00872 }
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885 static int rktParentPart(rk_resource_set_t rs)
00886 {
00887 int retval = EXIT_FAILURE;
00888 struct itimerval itv;
00889 struct sigaction sa;
00890 sigset_t sigmask;
00891
00892 require(rs != NULL_RESOURCE_SET);
00893
00894
00895 if( rk_resource_set_attach_process(rs, getpid()) < 0 )
00896 {
00897 my_perror("rk_resource_set_attach_process");
00898 }
00899
00900
00901
00902
00903
00904
00905
00906 sigemptyset(&sigmask);
00907 sigaddset(&sigmask, SIGALRM);
00908 sigaddset(&sigmask, SIGCHLD);
00909 sigaddset(&sigmask, SIGIO);
00910 sigaddset(&sigmask, SIGINT);
00911 sigaddset(&sigmask, SIGTERM);
00912 if( sigprocmask(SIG_BLOCK, &sigmask, NULL) < 0 )
00913 {
00914 my_perror("sigprocmask");
00915
00916 ensure(0);
00917 }
00918
00919
00920 sa.sa_mask = sigmask;
00921 sa.sa_flags = 0;
00922 #if defined(SA_RESTART)
00923 sa.sa_flags |= SA_RESTART;
00924 #endif
00925
00926 signal(SIGPIPE, SIG_IGN);
00927
00928 sa.sa_handler = sigalrm;
00929 sigaction(SIGALRM, &sa, NULL);
00930
00931 if( rktimes_data.rkt_ServerSocket != -1 )
00932 {
00933 sa.sa_handler = sigio;
00934 sigaction(SIGIO, &sa, NULL);
00935 }
00936
00937 if( rktimes_data.rkt_ChildPID == 0 )
00938 {
00939
00940
00941
00942
00943
00944 sa.sa_handler = sigexit;
00945 sigaction(SIGINT, &sa, NULL);
00946 sigaction(SIGTERM, &sa, NULL);
00947 }
00948 else
00949 {
00950
00951 sa.sa_handler = sigchld;
00952 sigaction(SIGCHLD, &sa, NULL);
00953
00954
00955
00956
00957
00958
00959 sa.sa_handler = sigpass;
00960 sigaction(SIGINT, &sa, NULL);
00961 sigaction(SIGTERM, &sa, NULL);
00962 }
00963
00964 itv.it_interval.tv_sec = 0;
00965 itv.it_interval.tv_usec = 1000000 / SAMPLES_PER_SECOND;
00966 itv.it_value.tv_sec = 0;
00967 itv.it_value.tv_usec = 1000000 / SAMPLES_PER_SECOND;
00968
00969 if( setitimer(ITIMER_REAL, &itv, NULL) == 0 )
00970 {
00971 sigset_t empty_sigmask;
00972 int status;
00973
00974 sigemptyset(&empty_sigmask);
00975
00976
00977 while( !(rktimes_data.rkt_Flags & RKTF_DONE) )
00978 {
00979 sigsuspend(&empty_sigmask);
00980 }
00981
00982
00983 if( rktimes_data.rkt_ChildPID == 0 )
00984 {
00985
00986
00987
00988 }
00989 else if( wait(&status) >= 0 )
00990 {
00991 if( WIFEXITED(status) )
00992 {
00993 retval = WEXITSTATUS(status);
00994 }
00995 else if( WIFSIGNALED(status) )
00996 {
00997 retval = EXIT_SUCCESS;
00998 }
00999 else
01000 {
01001 retval = EXIT_FAILURE;
01002 }
01003 }
01004 else
01005 {
01006 my_perror("wait");
01007 retval = EXIT_FAILURE;
01008 }
01009
01010
01011 memset(&itv, 0, sizeof(itv));
01012 if( setitimer(ITIMER_REAL, &itv, NULL) < 0 )
01013 {
01014 my_perror("setitimer");
01015
01016 ensure(0);
01017 }
01018 }
01019 else
01020 {
01021 my_perror("setitimer");
01022 retval = EXIT_FAILURE;
01023 }
01024
01025
01026 signal(SIGALRM, SIG_IGN);
01027 signal(SIGCHLD, SIG_IGN);
01028 signal(SIGINT, SIG_IGN);
01029 signal(SIGTERM, SIG_IGN);
01030 signal(SIGIO, SIG_IGN);
01031
01032
01033 if( sigprocmask(SIG_UNBLOCK, &sigmask, NULL) < 0 )
01034 {
01035 my_perror("sigprocmask");
01036
01037 ensure(0);
01038 }
01039
01040 return( retval );
01041 }
01042
01043
01044
01045
01046
01047
01048
01049
01050
01051
01052
01053
01054
01055 static int rktChildPart(rk_resource_set_t rs, char *argv[])
01056 {
01057 int retval = EXIT_SUCCESS;
01058 sigset_t sigmask;
01059
01060 require(rs != NULL_RESOURCE_SET);
01061 require(argv != NULL);
01062
01063
01064
01065
01066
01067 rk_inherit_mode(1);
01068 if( rk_resource_set_attach_process(rs, getpid()) == 0 )
01069 {
01070 }
01071 else
01072 {
01073 my_perror("rk_resource_set_attach_process");
01074 retval = EXIT_FAILURE;
01075 }
01076
01077
01078 sigfillset(&sigmask);
01079 if( sigprocmask(SIG_UNBLOCK, &sigmask, NULL) < 0 )
01080 {
01081 my_perror("sigprocmask");
01082
01083 ensure(0);
01084 }
01085
01086 if( retval == EXIT_SUCCESS )
01087 {
01088 execvp(argv[0], argv);
01089
01090
01091 perror(argv[0]);
01092 switch( errno )
01093 {
01094 case ENOENT:
01095 case EPERM:
01096 retval = 127;
01097 break;
01098 default:
01099 retval = EXIT_FAILURE;
01100 break;
01101 }
01102 }
01103 return( retval );
01104 }
01105
01106 int main(int argc, char *argv[])
01107 {
01108 int lpc, retval = EXIT_FAILURE;
01109
01110
01111 rktimes_data.rkt_OutputBase = "rktimes";
01112 rktimes_data.rkt_ServerSocket = -1;
01113 for( lpc = 0; lpc < MAX_CLIENTS; lpc++ )
01114 {
01115 rktimes_data.rkt_ClientSockets[lpc] = -1;
01116 }
01117
01118
01119 if( cpInitChildProcessData() )
01120 {
01121 char *prog_name = argv[0];
01122 int rc;
01123
01124 rc = rktProcessOptions(&argc, &argv);
01125 if( (rc == 0) && ((argc > 0) || (rktimes_data.rkt_Name != NULL)) )
01126 {
01127 char self_rs_name[RK_NAME_LEN + 1];
01128 rk_resource_set_t rs;
01129
01130 if( argc > 0 )
01131 {
01132 rktimes_data.rkt_UtilityName = argv[0];
01133 }
01134 else
01135 {
01136 rktimes_data.rkt_UtilityName = "<none>";
01137 }
01138 snprintf(self_rs_name, RK_NAME_LEN + 1, "rktimes.%d", getpid());
01139
01140
01141
01142
01143
01144 {
01145 sigset_t sigmask;
01146
01147 sigaddset(&sigmask, SIGINT);
01148 sigaddset(&sigmask, SIGTERM);
01149 if( sigprocmask(SIG_BLOCK, &sigmask, NULL) < 0 )
01150 {
01151 my_perror("sigprocmask");
01152
01153 ensure(0);
01154 }
01155 }
01156
01157 rs = rktCreateSelfResourceSet(self_rs_name);
01158 rktimes_data.rkt_ResourceSet =
01159 rktGetChildResourceSet(rktimes_data.rkt_ResourceSet,
01160 rktimes_data.rkt_Name,
01161 "rktimes",
01162 rktimes_data.rkt_ChildPeriod,
01163 rktimes_data.rkt_ChildCompute);
01164 if( (rs != NULL_RESOURCE_SET) &&
01165 (rktimes_data.rkt_ResourceSet != NULL_RESOURCE_SET) )
01166 {
01167 gettimeofday(&rktimes_data.rkt_StartTime, NULL);
01168 if( argc == 0 )
01169 {
01170 retval = rktParentPart(rs);
01171 }
01172 else if( (rktimes_data.rkt_ChildPID = fork()) > 0 )
01173 {
01174 retval = rktParentPart(rs);
01175 }
01176 else if( rktimes_data.rkt_ChildPID == 0 )
01177 {
01178 return( rktChildPart(rktimes_data.rkt_ResourceSet, argv) );
01179 }
01180 else
01181 {
01182 my_perror("fork");
01183 retval = EXIT_FAILURE;
01184 }
01185 }
01186 if( rktimes_data.rkt_Flags & RKTF_CREATED_RESOURCE_SET )
01187 {
01188 rk_resource_set_destroy(rktimes_data.rkt_ResourceSet);
01189 rktimes_data.rkt_ResourceSet = NULL_RESOURCE_SET;
01190 }
01191 rk_resource_set_destroy(rs);
01192 }
01193 else if( rc >= 0 )
01194 {
01195 rktUsage(stderr, prog_name);
01196 }
01197 if( rktimes_data.rkt_ServerSocket != -1 )
01198 {
01199 close(rktimes_data.rkt_ServerSocket);
01200 rktimes_data.rkt_ServerSocket = -1;
01201 }
01202 cpKillChildProcessData();
01203 }
01204
01205 return( retval );
01206 }