00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "config.h"
00019
00020 #include <stdlib.h>
00021 #include <string.h>
00022
00023 #include <sys/types.h>
00024 #include <sys/stat.h>
00025 #include <unistd.h>
00026
00027 #include <assert_pp.h>
00028 #include <time_util.h>
00029 #include <instrumentation.h>
00030
00031 #include <iostream>
00032
00033 #include <rk/rk.h>
00034 #include "rk_util.h"
00035
00036 #include "BrokerC.h"
00037 #include "RealTimeTaskImpl.hh"
00038 #include "MaxDecayTaskAdvocate.hh"
00039
00040 using namespace std;
00041
00042 #define INSTR_proc_len LRTIME_INSTR
00043 #define INSTR_proc_len_data "proc_len", "the wall clock time"
00044
00045 #if defined(INSTR_proc_len_data)
00046 static struct iPoint INSTR_proc_len_point = {
00047 INSTR_proc_len_data,
00048 };
00049 #endif
00050
00051 #if defined(INSTR_proc_advocate_periodic_data)
00052 static double periodic_history[1000];
00053 static struct iPoint INSTR_proc_advocate_periodic_point = {
00054 INSTR_proc_advocate_periodic_data,
00055 0,
00056 IPOINT_INIT_HISTORY(periodic_history),
00057 };
00058 #endif
00059
00060 #if defined(INSTR_proc_advocate_rpc_data)
00061 #undef INSTR_proc_advocate_rpc
00062 #define INSTR_proc_advocate_rpc LRTIME_INSTR
00063 static struct iPoint INSTR_proc_advocate_rpc_point = {
00064 INSTR_proc_advocate_rpc_data,
00065 };
00066 #endif
00067
00068 #if defined(INSTR_proc_advocate_periods_data)
00069 #undef INSTR_proc_advocate_periods
00070 #define INSTR_proc_advocate_periods LRTIME_INSTR
00071 static double periods_history[1000];
00072 static struct iPoint INSTR_proc_advocate_periods_point = {
00073 INSTR_proc_advocate_periods_data,
00074 0,
00075 IPOINT_INIT_HISTORY(periods_history),
00076 };
00077 #endif
00078
00079 enum {
00080 PAB_DONE,
00081 PAB_CREATED_RESOURCE_SET,
00082 PAB_NO_OBSERVE,
00083 };
00084
00085
00086
00087
00088
00089
00090 enum {
00091 PAF_DONE = (1L << PAB_DONE),
00092 PAF_CREATED_RESOURCE_SET = (1L << PAB_CREATED_RESOURCE_SET),
00093 PAF_NO_OBSERVE = (1L << PAB_NO_OBSERVE),
00094 };
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109 static struct {
00110 PortableServer::POA_var pa_POA;
00111 unsigned long pa_Flags;
00112 const char *pa_ManagerIOR;
00113 const char *pa_TaskIOR;
00114 const char *pa_TaskName;
00115 pid_t pa_ChildPID;
00116 CORBA::ULong pa_ChildPeriod;
00117 Broker::RealTimeTask_ptr pa_Advocate;
00118 rk_resource_set_t pa_ResourceSet;
00119 unsigned long long pa_LastUsage;
00120 Broker::KeyedReportParameters pa_KeyedReportParameters;
00121 } pa_data;
00122
00123
00124
00125
00126
00127
00128 static void sigchld(int sig)
00129 {
00130 require(sig == SIGCHLD);
00131
00132 pa_data.pa_Flags |= PAF_DONE;
00133 }
00134
00135
00136
00137
00138
00139
00140 static void sigpass(int sig)
00141 {
00142 require(pa_data.pa_ChildPID > 0);
00143 require((sig == SIGINT) || (sig == SIGTERM));
00144
00145 kill(pa_data.pa_ChildPID, sig);
00146 }
00147
00148
00149
00150
00151
00152
00153
00154 static void sigalrm(int sig)
00155 {
00156 struct rk_resource_set_usage rsu;
00157 int rc;
00158
00159 require(pa_data.pa_ResourceSet != NULL_RESOURCE_SET);
00160 require(!CORBA::is_nil(pa_data.pa_Advocate));
00161 require(sig == SIGALRM);
00162
00163 INSTR_proc_advocate_periods(&INSTR_proc_advocate_periods_point, {
00164 memset(&rsu, 0, sizeof(rsu));
00165 if( (rc = rk_resource_set_get_usage(pa_data.pa_ResourceSet,
00166 &rsu,
00167 NULL)) == 0 )
00168 {
00169 try
00170 {
00171 Broker::CPUReserve status;
00172
00173 status.Period = pa_data.pa_ChildPeriod;
00174 status.Compute = (CORBA::ULong)
00175 (rsu.active_cpu_usage - pa_data.pa_LastUsage);
00176 pa_data.pa_LastUsage = rsu.active_cpu_usage;
00177 pa_data.pa_Advocate->
00178 ReportCPU(status,
00179 status,
00180 pa_data.pa_KeyedReportParameters);
00181 }
00182 catch(const CORBA::SystemException &e)
00183 {
00184 cerr << "System exception: " << e << endl;
00185 pa_data.pa_Flags |= PAF_DONE;
00186 }
00187 catch(...)
00188 {
00189 cerr << "Caught unknown exception..." << endl;
00190 pa_data.pa_Flags |= PAF_DONE;
00191 }
00192 }
00193 else
00194 {
00195 cerr << "rk_resource_set_get_usage: "
00196 << strerror(rc)
00197 << endl;
00198 pa_data.pa_Flags |= PAF_DONE;
00199 }
00200 });
00201 }
00202
00203
00204
00205
00206
00207
00208 static void paUsage(const char *prog_name)
00209 {
00210 require(pa_data.pa_ManagerIOR != NULL);
00211 require(prog_name != NULL);
00212
00213 cerr << "CPU Broker wrapper for managing unmodified programs.\n"
00214 << "Usage: "
00215 << prog_name
00216 << " [options] -- <command> [argument ...]\n"
00217 << endl
00218 << "Options:\n"
00219 << "\t-h\t\tThis help message.\n"
00220 << "\t-V\t\tShow the version number.\n"
00221
00222 << "\t-o\t\tDo not observe the child process or make reports." << endl
00223
00224 << "\t-m <ior>\tThe Broker::Manager IOR."
00225 << " (Default: " << pa_data.pa_ManagerIOR << ")\n"
00226
00227 << "\t-t <ior>\tThe Broker::RealTimeTask IOR.\n"
00228
00229 << "\t-n <name>\tThe name for the task to create.\n"
00230
00231 << "\t-P <period>\tThe period as a time value."
00232 << " (Default: " << pa_data.pa_ChildPeriod << "us)\n"
00233
00234 << endl
00235
00236 << "Package: " << PACKAGE_STRING << endl
00237 << "Contact: " << PACKAGE_BUGREPORT << endl
00238
00239 ;
00240 }
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252 static int paProcessOptions(int &argc_inout, char **&argv_inout)
00253 {
00254 int ch, retval = 0;
00255 char *prog_name;
00256 char **argv;
00257 int argc;
00258
00259 argc = argc_inout;
00260 argv = argv_inout;
00261 prog_name = argv[0];
00262 while( ((ch = getopt(argc, argv, "hVn:m:t:P:o")) != -1) && (retval == 0) )
00263 {
00264 switch( ch )
00265 {
00266 case 'm':
00267 if( strlen(optarg) == 0 )
00268 {
00269 cerr << prog_name << ": Manager IOR is empty" << endl;
00270 retval = 1;
00271 }
00272 else
00273 {
00274 pa_data.pa_ManagerIOR = optarg;
00275 }
00276 break;
00277 case 't':
00278 if( strlen(optarg) == 0 )
00279 {
00280 cerr << prog_name << ": Task IOR is empty" << endl;
00281 retval = 1;
00282 }
00283 else if( pa_data.pa_TaskName != NULL )
00284 {
00285 cerr << prog_name
00286 << ": The -t and -n options are mutually exclusive"
00287 << endl;
00288 retval = 1;
00289 }
00290 else
00291 {
00292 pa_data.pa_TaskIOR = optarg;
00293 }
00294 break;
00295 case 'n':
00296 if( strlen(optarg) == 0 )
00297 {
00298 cerr << prog_name << ": Task name is empty" << endl;
00299 retval = 1;
00300 }
00301 else if( pa_data.pa_TaskIOR != NULL )
00302 {
00303 cerr << prog_name
00304 << ": The -t and -n options are mutually exclusive"
00305 << endl;
00306 retval = 1;
00307 }
00308 else
00309 {
00310 pa_data.pa_TaskName = optarg;
00311 }
00312 break;
00313 case 'o':
00314 pa_data.pa_Flags |= PAF_NO_OBSERVE;
00315 break;
00316 case 'P':
00317 {
00318 unsigned long long usecs;
00319
00320
00321 if( string_to_microsec(&usecs, optarg) )
00322 {
00323 pa_data.pa_ChildPeriod = usecs;
00324 }
00325 else
00326 {
00327 cerr << prog_name
00328 << ": -P options requires a time value\n";
00329 retval = 1;
00330 }
00331 }
00332 break;
00333 case 'V':
00334 cerr << PACKAGE_VERSION << endl;
00335 retval = -1;
00336 break;
00337 case 'h':
00338 case '?':
00339 default:
00340 retval = 1;
00341 break;
00342 }
00343 }
00344
00345 if( (pa_data.pa_TaskIOR == NULL) && (pa_data.pa_TaskName == NULL) )
00346 {
00347 cerr << prog_name
00348 << ": no task name or IOR specified\n";
00349 retval = 1;
00350 }
00351
00352 argc_inout -= optind;
00353 argv_inout += optind;
00354
00355 if( (argc_inout > 0) && (strcmp(argv_inout[0], "--") == 0) )
00356 {
00357 argc_inout -= 1;
00358 argv_inout += 1;
00359 }
00360 return( retval );
00361 }
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375 static Broker::RealTimeTask_ptr paGetAdvocate(CORBA::ORB_ptr orb,
00376 Broker::Manager_ptr manager,
00377 const char *task_ior,
00378 const char *task_name)
00379 {
00380 Broker::RealTimeTask_var retval;
00381 CORBA::Object_var obj;
00382
00383 require(!CORBA::is_nil(orb));
00384 require(!CORBA::is_nil(manager));
00385 require((task_ior != NULL) || (task_name != NULL));
00386
00387 if( task_ior != NULL )
00388 {
00389 obj = orb->string_to_object(task_ior);
00390 retval = Broker::RealTimeTask::_narrow(obj.in());
00391 if( CORBA::is_nil(retval.in()) )
00392 {
00393 cerr << "Invalid task factory IOR: "
00394 << task_ior
00395 << endl;
00396 throw CORBA::BAD_PARAM();
00397 }
00398 pa_data.pa_TaskName = retval->Name();
00399 }
00400 else if( task_name != NULL )
00401 {
00402 try
00403 {
00404 PortableServer::ObjectId_var oid;
00405 Broker::RealTimeTask_var rtt;
00406 MaxDecayTaskAdvocate *mdta;
00407 Broker::TaskParameters tp;
00408 RealTimeTaskImpl *rtti;
00409 CORBA::Any value;
00410
00411 tp.length(1);
00412 tp[0].name = "name";
00413 tp[0].value <<= task_name;
00414 rtti = new RealTimeTaskImpl(tp);
00415 oid = pa_data.pa_POA->activate_object(rtti);
00416 rtt = Broker::RealTimeTask::
00417 _narrow(pa_data.pa_POA->id_to_reference(oid.in()));
00418 mdta = new MaxDecayTaskAdvocate();
00419 value <<= rtt.in();
00420 mdta->SetDelegateAttribute("remote-object", value);
00421 oid = pa_data.pa_POA->activate_object(mdta);
00422 retval = Broker::RealTimeTask::
00423 _narrow(pa_data.pa_POA->id_to_reference(oid.in()));
00424 }
00425 catch(const Broker::DuplicateTaskParameter &e)
00426 {
00427 cerr << e << endl;
00428 ensure(0);
00429 }
00430 catch(const Broker::InvalidTaskParameter &e)
00431 {
00432 cerr << e << endl;
00433 ensure(0);
00434 }
00435 catch(const Broker::MissingTaskParameter &e)
00436 {
00437 cerr << e << endl;
00438 ensure(0);
00439 }
00440 }
00441 else
00442 {
00443 ensure(0);
00444 }
00445
00446 if( (pa_data.pa_ResourceSet = rk_proc_get_rset(getpid())) !=
00447 NULL_RESOURCE_SET )
00448 {
00449 }
00450 else if( (pa_data.pa_ResourceSet =
00451 rk_resource_set_get_by_name(pa_data.pa_TaskName)) !=
00452 NULL_RESOURCE_SET )
00453 {
00454 }
00455 else if( (pa_data.pa_ResourceSet =
00456 rk_resource_set_create((char *)pa_data.pa_TaskName)) ==
00457 NULL_RESOURCE_SET )
00458 {
00459 cerr << "rk_resource_set_create: " << strerror(errno) << endl;
00460 }
00461 else
00462 {
00463 pa_data.pa_Flags |= PAF_CREATED_RESOURCE_SET;
00464 }
00465
00466 try
00467 {
00468 struct rk_resource_set_usage rsu;
00469 Broker::ScheduleParameters sp;
00470
00471 memset(&rsu, 0, sizeof(rsu));
00472 sp.length(2);
00473 sp[0].name = "period";
00474 sp[0].value <<= pa_data.pa_ChildPeriod;
00475 sp[1].name = "pid";
00476 sp[1].value <<= (CORBA::Long)getpid();
00477 manager->AddTask(retval.in(), sp);
00478 if( rk_resource_set_get_usage(pa_data.pa_ResourceSet,
00479 &rsu,
00480 NULL) == 0 )
00481 {
00482 pa_data.pa_LastUsage = rsu.active_cpu_usage;
00483 }
00484 }
00485 catch(const Broker::DuplicateScheduleParameter &e)
00486 {
00487 cerr << e << endl;
00488 cerr << e.name << endl;
00489 throw CORBA::UNKNOWN();
00490 }
00491 catch(const Broker::InvalidScheduleParameter &e)
00492 {
00493 cerr << e << endl;
00494 cerr << e.message << endl;
00495 throw CORBA::UNKNOWN();
00496 }
00497 catch(const Broker::MissingScheduleParameter &e)
00498 {
00499 cerr << e << endl;
00500 cerr << e.name << endl;
00501 throw CORBA::UNKNOWN();
00502 }
00503
00504 return( retval._retn() );
00505 }
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518 static int paParentPart(Broker::RealTimeTask_ptr rtt)
00519 {
00520 int retval = EXIT_FAILURE;
00521 struct itimerval itv;
00522 struct sigaction sa;
00523 sigset_t sigmask;
00524
00525 require(pa_data.pa_ChildPID > 0);
00526 require(!CORBA::is_nil(rtt));
00527
00528
00529
00530
00531
00532
00533
00534 sigemptyset(&sigmask);
00535 sigaddset(&sigmask, SIGALRM);
00536 sigaddset(&sigmask, SIGCHLD);
00537 sigaddset(&sigmask, SIGINT);
00538 sigaddset(&sigmask, SIGTERM);
00539 if( sigprocmask(SIG_BLOCK, &sigmask, NULL) < 0 )
00540 {
00541 perror("sigprocmask");
00542
00543 ensure(0);
00544 }
00545
00546
00547 sa.sa_mask = sigmask;
00548 sa.sa_flags = 0;
00549 #if defined(SA_RESTART)
00550 sa.sa_flags |= SA_RESTART;
00551 #endif
00552
00553 if( !(pa_data.pa_Flags & PAF_NO_OBSERVE) )
00554 {
00555 sa.sa_handler = sigalrm;
00556 if( sigaction(SIGALRM, &sa, NULL) < 0 )
00557 {
00558 perror("sigprocmask");
00559
00560 ensure(0);
00561 }
00562 }
00563
00564
00565 sa.sa_handler = sigchld;
00566 if( sigaction(SIGCHLD, &sa, NULL) < 0 )
00567 {
00568 perror("sigprocmask");
00569
00570 ensure(0);
00571 }
00572
00573
00574
00575
00576
00577
00578 sa.sa_handler = sigpass;
00579 if( (sigaction(SIGINT, &sa, NULL) < 0) ||
00580 (sigaction(SIGTERM, &sa, NULL) < 0) )
00581 {
00582 perror("sigprocmask");
00583
00584 ensure(0);
00585 }
00586
00587 itv.it_interval.tv_sec = 0;
00588 itv.it_interval.tv_usec = pa_data.pa_ChildPeriod;
00589 itv.it_value.tv_sec = 0;
00590 itv.it_value.tv_usec = pa_data.pa_ChildPeriod;
00591
00592 if( !(pa_data.pa_Flags & PAF_NO_OBSERVE) &&
00593 (setitimer(ITIMER_REAL, &itv, NULL) == -1) )
00594 {
00595 perror("setitimer");
00596 retval = EXIT_FAILURE;
00597 }
00598 else
00599 {
00600 sigset_t empty_sigmask;
00601 int status;
00602
00603 sigemptyset(&empty_sigmask);
00604
00605 pa_data.pa_Advocate = rtt;
00606
00607
00608 while( !(pa_data.pa_Flags & PAF_DONE) )
00609 {
00610 INSTR_proc_len(&INSTR_proc_len_point, {
00611 INSTR_proc_advocate_periodic(&INSTR_proc_advocate_periodic_point, {
00612 sigsuspend(&empty_sigmask);
00613 });
00614 });
00615 }
00616
00617 pa_data.pa_Advocate = NULL;
00618
00619
00620 if( wait(&status) >= 0 )
00621 {
00622 if( WIFEXITED(status) )
00623 {
00624 retval = WEXITSTATUS(status);
00625 }
00626 else if( WIFSIGNALED(status) )
00627 {
00628 retval = EXIT_SUCCESS;
00629 }
00630 else
00631 {
00632 retval = EXIT_FAILURE;
00633 }
00634 }
00635 else
00636 {
00637 perror("wait");
00638 retval = EXIT_FAILURE;
00639 }
00640
00641
00642 memset(&itv, 0, sizeof(itv));
00643 if( setitimer(ITIMER_REAL, &itv, NULL) < 0 )
00644 {
00645 perror("setitimer");
00646 }
00647 }
00648
00649
00650 signal(SIGALRM, SIG_IGN);
00651 signal(SIGCHLD, SIG_IGN);
00652 signal(SIGINT, SIG_IGN);
00653 signal(SIGTERM, SIG_IGN);
00654
00655
00656 if( sigprocmask(SIG_UNBLOCK, &sigmask, NULL) < 0 )
00657 {
00658 perror("sigprocmask");
00659
00660 ensure(0);
00661 }
00662
00663 return( retval );
00664 }
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676 static int paChildPart(char *argv[])
00677 {
00678 int retval = EXIT_SUCCESS;
00679 sigset_t sigmask;
00680
00681
00682 sigfillset(&sigmask);
00683 if( sigprocmask(SIG_UNBLOCK, &sigmask, NULL) < 0 )
00684 {
00685 perror("sigprocmask");
00686
00687 ensure(0);
00688 }
00689
00690 execvp(argv[0], argv);
00691
00692
00693 perror(argv[0]);
00694 switch( errno )
00695 {
00696 case ENOENT:
00697 case EPERM:
00698 retval = 127;
00699 break;
00700 default:
00701 retval = EXIT_FAILURE;
00702 break;
00703 }
00704 return( retval );
00705 }
00706
00707 int main(int argc, char *argv[])
00708 {
00709 int lpc, old_argc = argc, retval = EXIT_FAILURE;
00710 const char *prog_name = argv[0];
00711
00712
00713 pa_data.pa_ManagerIOR = "file://manager.ior";
00714 pa_data.pa_ChildPeriod = 33333;
00715
00716 atexit(iPrintPointsAtExit);
00717
00718
00719
00720
00721
00722 for( lpc = 0; (lpc < argc) && (strcmp(argv[lpc], "--") != 0); lpc++ );
00723
00724 if( lpc < argc )
00725 {
00726 argc = lpc;
00727 }
00728
00729 try
00730 {
00731 CORBA::ORB_var orb = CORBA::ORB_init(argc, argv);
00732 int rc;
00733
00734 for( ; lpc < old_argc; argc++, lpc++ )
00735 {
00736 argv[argc] = argv[lpc];
00737 }
00738 argv[argc] = NULL;
00739
00740 rc = paProcessOptions(argc, argv);
00741
00742 if( pa_data.pa_TaskIOR == NULL )
00743 {
00744 CORBA::Object_var obj = orb->resolve_initial_references("RootPOA");
00745
00746 PortableServer::POA_var root_poa =
00747 PortableServer::POA::_narrow(obj.in());
00748 PortableServer::POAManager_var mgr = root_poa->the_POAManager();
00749
00750 PortableServer::ThreadPolicy_var thread = root_poa->
00751 create_thread_policy(PortableServer::SINGLE_THREAD_MODEL);
00752
00753 CORBA::PolicyList policy_list;
00754 policy_list.length(1);
00755 policy_list[0] =
00756 PortableServer::ThreadPolicy::_duplicate(thread.in());
00757
00758 pa_data.pa_POA = root_poa->
00759 create_POA("SingleThread", mgr.in(), policy_list);
00760
00761 thread->destroy();
00762 thread = PortableServer::ThreadPolicy::_nil();
00763
00764 mgr->activate();
00765 }
00766
00767 if( (rc == 0) && (argc > 0) )
00768 {
00769 Broker::RealTimeTask_var rtt;
00770 Broker::Manager_var manager;
00771 CORBA::Object_var obj;
00772
00773 obj = orb->string_to_object(pa_data.pa_ManagerIOR);
00774 manager = Broker::Manager::_narrow(obj.in());
00775 if( CORBA::is_nil(manager.in()) )
00776 {
00777 cerr << "Invalid manager IOR: "
00778 << pa_data.pa_ManagerIOR
00779 << endl;
00780 throw CORBA::BAD_PARAM();
00781 }
00782
00783
00784
00785
00786
00787 {
00788 sigset_t sigmask;
00789
00790 sigaddset(&sigmask, SIGINT);
00791 sigaddset(&sigmask, SIGTERM);
00792 if( sigprocmask(SIG_BLOCK, &sigmask, NULL) < 0 )
00793 {
00794 perror("sigprocmask");
00795
00796 ensure(0);
00797 }
00798 }
00799
00800 rtt = paGetAdvocate(orb.in(),
00801 manager.in(),
00802 pa_data.pa_TaskIOR,
00803 pa_data.pa_TaskName);
00804 if( (pa_data.pa_ChildPID = fork()) > 0 )
00805 {
00806 retval = paParentPart(rtt.in());
00807 }
00808 else if( pa_data.pa_ChildPID == 0 )
00809 {
00810 return( paChildPart(argv) );
00811 }
00812 else
00813 {
00814
00815 retval = EXIT_FAILURE;
00816 }
00817 manager->RemoveTask(rtt.in());
00818 }
00819 else
00820 {
00821 if( rc == 0 )
00822 {
00823 cerr << "No utility to execute\n";
00824 }
00825 if( rc >= 0 )
00826 {
00827 paUsage(prog_name);
00828 }
00829 }
00830 }
00831 catch(const CORBA::UNKNOWN &e)
00832 {
00833
00834 paUsage(prog_name);
00835 }
00836 catch(const CORBA::SystemException &e)
00837 {
00838 cerr << "Caught Exception: " << e << endl;
00839 }
00840 catch(...)
00841 {
00842 cerr << "Caught an unhandled exception" << endl;
00843 }
00844
00845 if( pa_data.pa_Flags & PAF_CREATED_RESOURCE_SET )
00846 {
00847 rk_resource_set_destroy(pa_data.pa_ResourceSet);
00848 pa_data.pa_ResourceSet = NULL_RESOURCE_SET;
00849 }
00850
00851 return( retval );
00852 }