00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "config.h"
00019
00020 #include <limits.h>
00021 #include <stdio.h>
00022 #include <stdlib.h>
00023 #include <string.h>
00024 #include <errno.h>
00025 #include <math.h>
00026 #include <ctype.h>
00027
00028 #include "rk.h"
00029 #include "rk_stub.h"
00030
00031 #include "assert_pp.h"
00032 #include "time_util.h"
00033
00034
00035
00036 #if !defined(max)
00037
00038 #define max(x, y) \
00039 ((x) > (y) ? (x) : (y))
00040 #endif
00041
00042 #if !defined(min)
00043
00044 #define min(x, y) \
00045 ((x) < (y) ? (x) : (y))
00046 #endif
00047
00048
00049
00050
00051 struct rk_stub_data rk_stub_data;
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064 static
00065 void rk_cpu_reserve_tick(rk_resource_set_t rs,
00066 cpu_reserve_t cr,
00067 struct timespec *curr,
00068 struct timespec *next,
00069 struct timespec *new_compute);
00070
00071
00072 static char *rk_cpu_trace_names[RK_CPU_TRACE_MAX] = {
00073 "period",
00074 "deadline",
00075 "complete",
00076 "drop",
00077 "realtime",
00078 "success",
00079 "fail"
00080 };
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091 static int rk_name_valid(const char *name)
00092 {
00093 int lpc, retval = 1;
00094
00095 require(name != NULL);
00096
00097 for( lpc = 0; name[lpc] && retval; lpc++ )
00098 {
00099 retval = isprint(name[lpc]);
00100 }
00101 return( retval );
00102 }
00103
00104
00105
00106
00107
00108
00109
00110
00111 static int rk_reserve_mode_valid(rk_reserve_mode_t rm)
00112 {
00113 int retval = 0;
00114
00115 switch( rm )
00116 {
00117 case RSV_HARD:
00118 case RSV_FIRM:
00119 case RSV_SOFT:
00120 retval = 1;
00121 break;
00122 default:
00123 retval = 0;
00124 break;
00125 }
00126 return( retval );
00127 }
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140 static int rk_reserve_param_valid(rk_reserve_param_t rp)
00141 {
00142 int retval = 1;
00143
00144 if( !rk_reserve_mode_valid(rp->sch_mode) ||
00145 !rk_reserve_mode_valid(rp->enf_mode) ||
00146 !rk_reserve_mode_valid(rp->rep_mode) )
00147 {
00148 retval = 0;
00149 }
00150 return( retval );
00151 }
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166 static int rk_cpu_reserve_attr_valid(cpu_reserve_attr_t ra_in)
00167 {
00168 static struct timespec zero = { 0, 0 };
00169 static struct timespec min_period = RT_MIN_PERIOD;
00170
00171 int retval = 1;
00172
00173 require(ra_in != NULL);
00174
00175 if( tscmp(&ra_in->period, &min_period, <) ||
00176 tscmp(&ra_in->compute_time, &ra_in->deadline, >) ||
00177 tscmp(&ra_in->deadline, &zero, ==) ||
00178 tscmp(&ra_in->deadline, &ra_in->period, >) ||
00179 !rk_reserve_param_valid(&ra_in->reserve_type) )
00180 {
00181 retval = 0;
00182 }
00183 return( retval );
00184 }
00185
00186
00187
00188
00189
00190
00191
00192
00193 static int cpu_reserve_valid(cpu_reserve_t cr)
00194 {
00195 rk_resource_set_t curr;
00196 int retval = 0;
00197
00198 require(cr != NULL);
00199
00200 curr = (rk_resource_set_t)rk_stub_data.sd_ResourceSets.lh_Head;
00201 while( curr->rs_Link.ln_Succ && !retval )
00202 {
00203 if( curr->rs_CPU == cr )
00204 {
00205 retval = 1;
00206 }
00207 curr = (rk_resource_set_t)curr->rs_Link.ln_Succ;
00208 }
00209 return( retval );
00210 }
00211
00212
00213
00214
00215
00216
00217
00218
00219 static int rk_resource_set_valid(rk_resource_set_t rs)
00220 {
00221 rk_resource_set_t curr;
00222 int retval = 0;
00223
00224 require(rs != NULL);
00225
00226 curr = (rk_resource_set_t)rk_stub_data.sd_ResourceSets.lh_Head;
00227 while( curr->rs_Link.ln_Succ && !retval )
00228 {
00229 if( curr == rs )
00230 {
00231 retval = 1;
00232 }
00233 curr = (rk_resource_set_t)curr->rs_Link.ln_Succ;
00234 }
00235 return( retval );
00236 }
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248 static char *rk_reserve_mode_string(rk_reserve_mode_t rm)
00249 {
00250 char *retval;
00251
00252 switch( rm )
00253 {
00254 case RSV_HARD:
00255 retval = "HARD";
00256 break;
00257 case RSV_FIRM:
00258 retval = "FIRM";
00259 break;
00260 case RSV_SOFT:
00261 retval = "SOFT";
00262 break;
00263 default:
00264 retval = "invalid";
00265 break;
00266 }
00267 return( retval );
00268 }
00269
00270
00271
00272
00273
00274
00275
00276
00277 static char *rk_reserve_param_string(rk_reserve_param_t rp)
00278 {
00279 static char retval[128];
00280
00281 if( rp != NULL )
00282 {
00283 sprintf(retval,
00284 "[sch_mode=%s; enf_mode=%s; rep_mode=%s]",
00285 rk_reserve_mode_string(rp->sch_mode),
00286 rk_reserve_mode_string(rp->enf_mode),
00287 rk_reserve_mode_string(rp->rep_mode));
00288 }
00289 else
00290 {
00291 sprintf(retval, "(null)");
00292 }
00293
00294 return( retval );
00295 }
00296
00297
00298
00299
00300
00301
00302
00303
00304 static char *cpu_reserve_attr_string(cpu_reserve_attr_t ra)
00305 {
00306 static char retval[1024];
00307
00308 if( ra != NULL )
00309 {
00310 sprintf(retval,
00311 "[compute_time=%d.%ld"
00312 "; period=%d.%ld"
00313 "; deadline=%d.%ld"
00314 "; blocking_time=%d.%ld"
00315 "; start_time=%d.%ld"
00316 "; reserve_type=%s"
00317 "; processor=%d]",
00318 (int)ra->compute_time.tv_sec,
00319 ra->compute_time.tv_nsec,
00320 (int)ra->period.tv_sec,
00321 ra->period.tv_nsec,
00322 (int)ra->deadline.tv_sec,
00323 ra->deadline.tv_nsec,
00324 (int)ra->blocking_time.tv_sec,
00325 ra->blocking_time.tv_nsec,
00326 (int)ra->start_time.tv_sec,
00327 ra->start_time.tv_nsec,
00328 rk_reserve_param_string(&ra->reserve_type),
00329 ra->processor);
00330 }
00331 else
00332 {
00333 sprintf(retval, "(null)");
00334 }
00335
00336 return( retval );
00337 }
00338
00339
00340
00341
00342
00343
00344
00345
00346 static char *cpu_reserve_string(cpu_reserve_t cr)
00347 {
00348 static char retval[1024];
00349
00350 if( cr != NULL )
00351 {
00352 sprintf(retval,
00353 "[cr_Attributes=%s"
00354 "; cr_Flags=%lx"
00355 "; cr_Times=%p"
00356 "; cr_Length=%d"
00357 "; cr_DataIndex=%d"
00358 "; cr_TimeIndex=%d"
00359 "; cr_DataPeriodStart=%d.%ld"
00360 "; cr_DataPeriodEnd=%d.%ld"
00361 "; cr_DataPeriodNext=%d.%ld"
00362 "; cr_TimePeriodStart=%d.%ld"
00363 "; cr_TimePeriodEnd=%d.%ld"
00364 "; cr_TimePeriodNext=%d.%ld]",
00365 cpu_reserve_attr_string(&cr->cr_Attributes),
00366 cr->cr_Flags,
00367 cr->cr_Compute.cr_Times,
00368 cr->cr_Compute.cr_Length,
00369 cr->cr_Compute.cr_DataIndex,
00370 cr->cr_Compute.cr_TimeIndex,
00371 (int)cr->cr_Compute.cr_DataPeriodStart.tv_sec,
00372 cr->cr_Compute.cr_DataPeriodStart.tv_nsec,
00373 (int)cr->cr_Compute.cr_DataPeriodEnd.tv_sec,
00374 cr->cr_Compute.cr_DataPeriodEnd.tv_nsec,
00375 (int)cr->cr_Compute.cr_DataPeriodNext.tv_sec,
00376 cr->cr_Compute.cr_DataPeriodNext.tv_nsec,
00377 (int)cr->cr_Compute.cr_TimePeriodStart.tv_sec,
00378 cr->cr_Compute.cr_TimePeriodStart.tv_nsec,
00379 (int)cr->cr_Compute.cr_TimePeriodEnd.tv_sec,
00380 cr->cr_Compute.cr_TimePeriodEnd.tv_nsec,
00381 (int)cr->cr_Compute.cr_TimePeriodNext.tv_sec,
00382 cr->cr_Compute.cr_TimePeriodNext.tv_nsec);
00383 }
00384 else
00385 {
00386 sprintf(retval, "(null)");
00387 }
00388
00389 return( retval );
00390 }
00391
00392
00393
00394
00395
00396
00397
00398
00399 static char *rk_resource_set_string(rk_resource_set_t rs)
00400 {
00401 static char retval[1024];
00402
00403 if( (rs != NULL) && rk_resource_set_valid(rs) )
00404 {
00405 sprintf(retval,
00406 "[rs_Name=%s"
00407 "; rs_ProcessID=%d"
00408 "; rs_CPU=%s]",
00409 rs->rs_Name,
00410 rs->rs_ProcessID,
00411 cpu_reserve_string(rs->rs_CPU));
00412 }
00413 else
00414 {
00415 sprintf(retval, "(null)");
00416 }
00417
00418 return( retval );
00419 }
00420
00421
00422
00423
00424
00425
00426
00427
00428 static char *rk_stub_pcb_string(pid_t pid)
00429 {
00430 static char retval[1024];
00431
00432 if( (pid >= 0) && (pid <= MAX_PCB) )
00433 {
00434 if( rk_stub_data.sd_PCBs[pid].p_Flags & PCBF_IN_USE )
00435 {
00436 struct rk_stub_pcb *sp = &rk_stub_data.sd_PCBs[pid];
00437
00438 sprintf(retval,
00439 "[p_Name=%s"
00440 "; p_Flags=%lx"
00441 "; p_Data=%p"
00442 "; p_Precall=%p"
00443 "; p_Postcall=%p]",
00444 sp->p_Name,
00445 sp->p_Flags,
00446 sp->p_Data,
00447 sp->p_Precall,
00448 sp->p_Postcall);
00449 }
00450 else
00451 {
00452 sprintf(retval, "(stale:%d)", pid);
00453 }
00454 }
00455 else
00456 {
00457 sprintf(retval, "(invalid:%d)", pid);
00458 }
00459
00460 return( retval );
00461 }
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476 void rk_inherit_mode(int dummy)
00477 {
00478 require(rk_stub_data.sd_Mode > RK_STUB_MIN);
00479 require(rk_stub_data.sd_Mode < RK_STUB_MAX);
00480
00481 fprintf(rk_stub_data.sd_LogFile, "BEGIN %s(%d)\n", __PRETTY_FUNCTION__, dummy);
00482
00483 fprintf(rk_stub_data.sd_LogFile, "END %s\n", __PRETTY_FUNCTION__);
00484 }
00485
00486 int rk_resource_sets_get_list(rk_resource_set_t *rs_inout, int count)
00487 {
00488 int retval = 0;
00489
00490 require(rk_stub_data.sd_Mode > RK_STUB_MIN);
00491 require(rk_stub_data.sd_Mode < RK_STUB_MAX);
00492
00493 fprintf(rk_stub_data.sd_LogFile, "BEGIN %s(%p, %d)\n", __PRETTY_FUNCTION__, rs_inout, count);
00494
00495 if( (rs_inout == NULL) || (count < 0) )
00496 {
00497 errno = EINVAL;
00498 }
00499 else if( count == 0 )
00500 {
00501 }
00502 else
00503 {
00504 struct rk_resource_set *rs;
00505 int lpc;
00506
00507 rs = (struct rk_resource_set *)rk_stub_data.sd_ResourceSets.lh_Head;
00508 for( retval = 0;
00509 (rs->rs_Link.ln_Succ != NULL) && (retval < count);
00510 retval++, rs = (struct rk_resource_set *)rs->rs_Link.ln_Succ)
00511 {
00512 rs_inout[retval] = rs;
00513 }
00514 for( lpc = retval; lpc < count; lpc++ )
00515 {
00516 rs_inout[retval] = NULL;
00517 }
00518 }
00519
00520 fprintf(rk_stub_data.sd_LogFile, "END %d = %s\n", retval, __PRETTY_FUNCTION__);
00521
00522 return( retval );
00523 }
00524
00525 int rk_resource_sets_get_num(void)
00526 {
00527 struct rk_resource_set *rs;
00528 int retval = 0;
00529
00530 require(rk_stub_data.sd_Mode > RK_STUB_MIN);
00531 require(rk_stub_data.sd_Mode < RK_STUB_MAX);
00532
00533 fprintf(rk_stub_data.sd_LogFile, "BEGIN %s()\n", __PRETTY_FUNCTION__);
00534
00535 rs = (struct rk_resource_set *)rk_stub_data.sd_ResourceSets.lh_Head;
00536 for( retval = 0;
00537 (rs->rs_Link.ln_Succ != NULL);
00538 retval++, rs = (struct rk_resource_set *)rs->rs_Link.ln_Succ)
00539 {
00540
00541 }
00542
00543 fprintf(rk_stub_data.sd_LogFile, "END %d = %s\n", retval, __PRETTY_FUNCTION__);
00544
00545 return( retval );
00546 }
00547
00548 rk_resource_set_t rk_resource_set_create(const char *name)
00549 {
00550 rk_resource_set_t retval = NULL_RESOURCE_SET;
00551
00552 require(rk_stub_data.sd_Mode > RK_STUB_MIN);
00553 require(rk_stub_data.sd_Mode < RK_STUB_MAX);
00554
00555 fprintf(rk_stub_data.sd_LogFile, "BEGIN %s(%s)\n", __PRETTY_FUNCTION__, name);
00556
00557 if( name == NULL )
00558 {
00559 errno = EINVAL;
00560 }
00561 else if( strlen(name) == 0 )
00562 {
00563 errno = EINVAL;
00564 }
00565 else if( strlen(name) >= RSET_NAME_LEN )
00566 {
00567 errno = ENAMETOOLONG;
00568 }
00569 else if( !rk_name_valid(name) )
00570 {
00571 errno = EINVAL;
00572 }
00573 else if( (retval = calloc(1, sizeof(struct rk_resource_set))) != NULL )
00574 {
00575 lnAddTail(&rk_stub_data.sd_ResourceSets, &retval->rs_Link);
00576 strncpy(retval->rs_Name, name, RSET_NAME_LEN);
00577 retval->rs_ProcessID = -1;
00578
00579 ensure(strlen(retval->rs_Name) > 0);
00580 ensure(strlen(retval->rs_Name) < RSET_NAME_LEN);
00581 ensure(strcmp(retval->rs_Name, name) == 0);
00582 ensure(rk_resource_set_valid(retval));
00583 }
00584 else
00585 {
00586 errno = ENOMEM;
00587 }
00588
00589 fprintf(rk_stub_data.sd_LogFile, "END %p = %s\n", retval, __PRETTY_FUNCTION__);
00590
00591 return( retval );
00592 }
00593
00594 int rk_resource_set_destroy(rk_resource_set_t rs)
00595 {
00596 int retval = -1;
00597
00598 require(rk_stub_data.sd_Mode > RK_STUB_MIN);
00599 require(rk_stub_data.sd_Mode < RK_STUB_MAX);
00600
00601 fprintf(rk_stub_data.sd_LogFile, "BEGIN %s(%p%s)\n", __PRETTY_FUNCTION__, rs, rk_resource_set_string(rs));
00602
00603 if( rs == NULL )
00604 {
00605 errno = EINVAL;
00606 }
00607 else if( rk_resource_set_valid(rs) )
00608 {
00609 rk_cpu_reserve_delete(rs);
00610
00611 if( rs->rs_ProcessID != -1 )
00612 {
00613 rk_stub_data.sd_PCBs[rs->rs_ProcessID].p_Resources = NULL;
00614 rs->rs_ProcessID = -1;
00615 }
00616 lnRemove(&rs->rs_Link);
00617 free(rs);
00618 retval = 0;
00619
00620 ensure(!rk_resource_set_valid(rs));
00621 }
00622
00623 fprintf(rk_stub_data.sd_LogFile, "%d END %s\n", retval, __PRETTY_FUNCTION__);
00624
00625 return( retval );
00626 }
00627
00628 int rk_resource_set_set_name(rk_resource_set_t rs, const char *name)
00629 {
00630 int retval = -1;
00631
00632 require(rk_stub_data.sd_Mode > RK_STUB_MIN);
00633 require(rk_stub_data.sd_Mode < RK_STUB_MAX);
00634
00635 fprintf(rk_stub_data.sd_LogFile, "BEGIN %s(%p%s, %s)\n", __PRETTY_FUNCTION__, rs, rk_resource_set_string(rs), name);
00636
00637 if( (rs == NULL) || (name == NULL) )
00638 {
00639 errno = EINVAL;
00640 }
00641 else if( !rk_resource_set_valid(rs) )
00642 {
00643 errno = EINVAL;
00644 }
00645 else if( strlen(name) == 0 )
00646 {
00647 errno = EINVAL;
00648 }
00649 else if( strlen(name) >= RSET_NAME_LEN )
00650 {
00651 errno = ENAMETOOLONG;
00652 }
00653 else if( !rk_name_valid(name) )
00654 {
00655 errno = EINVAL;
00656 }
00657 else
00658 {
00659 strncpy(rs->rs_Name, name, RSET_NAME_LEN);
00660 retval = 0;
00661
00662 ensure(strlen(rs->rs_Name) > 0);
00663 ensure(strlen(rs->rs_Name) < RSET_NAME_LEN);
00664 ensure(strcmp(rs->rs_Name, name) == 0);
00665 }
00666
00667 fprintf(rk_stub_data.sd_LogFile, "END %d = %s\n", retval, __PRETTY_FUNCTION__);
00668
00669 return( retval );
00670 }
00671
00672 int rk_resource_set_get_name(rk_resource_set_t rs, char *name_out)
00673 {
00674 int retval = -1;
00675
00676 require(rk_stub_data.sd_Mode > RK_STUB_MIN);
00677 require(rk_stub_data.sd_Mode < RK_STUB_MAX);
00678
00679 fprintf(rk_stub_data.sd_LogFile, "BEGIN %s(%p%s, %p)\n", __PRETTY_FUNCTION__, rs, rk_resource_set_string(rs), name_out);
00680
00681 if( (rs == NULL) || (name_out == NULL) )
00682 {
00683 errno = EINVAL;
00684 }
00685 else if( !rk_resource_set_valid(rs) )
00686 {
00687 name_out[0] = '\0';
00688 errno = EINVAL;
00689 }
00690 else
00691 {
00692 strcpy(name_out, rs->rs_Name);
00693 retval = 0;
00694
00695 ensure(strlen(name_out) > 0);
00696 ensure(strlen(name_out) < RSET_NAME_LEN);
00697 ensure(strcmp(rs->rs_Name, name_out) == 0);
00698 }
00699
00700 fprintf(rk_stub_data.sd_LogFile, "END %d = %s name_out=%s\n", retval, __PRETTY_FUNCTION__, name_out);
00701
00702 return( retval );
00703 }
00704
00705 rk_reserve_t rk_resource_set_get_cpu_rsv(rk_resource_set_t rs)
00706 {
00707 rk_reserve_t retval = NULL_RESERVE;
00708
00709 require(rk_stub_data.sd_Mode > RK_STUB_MIN);
00710 require(rk_stub_data.sd_Mode < RK_STUB_MAX);
00711
00712 fprintf(rk_stub_data.sd_LogFile, "BEGIN %s(%p%s)\n", __PRETTY_FUNCTION__, rs, rk_resource_set_string(rs));
00713
00714 if( rs == NULL )
00715 {
00716 errno = EINVAL;
00717 }
00718 else if( !rk_resource_set_valid(rs) )
00719 {
00720 errno = EINVAL;
00721 }
00722 else if( rs->rs_CPU == NULL )
00723 {
00724 errno = ENOTCONN;
00725 }
00726 else
00727 {
00728 retval = (rk_reserve_t)rs->rs_CPU;
00729
00730 ensure(cpu_reserve_valid(retval));
00731 }
00732
00733 fprintf(rk_stub_data.sd_LogFile, "END %p = %s\n", retval, __PRETTY_FUNCTION__);
00734
00735 return( retval );
00736 }
00737
00738 int rk_resource_set_attach_process(rk_resource_set_t rs, pid_t pid)
00739 {
00740 int retval = -1;
00741
00742 require(rk_stub_data.sd_Mode > RK_STUB_MIN);
00743 require(rk_stub_data.sd_Mode < RK_STUB_MAX);
00744
00745 fprintf(rk_stub_data.sd_LogFile, "BEGIN %s(%p%s, %d%s)\n", __PRETTY_FUNCTION__, rs, rk_resource_set_string(rs), pid, rk_stub_pcb_string(pid));
00746
00747 if( (rs == NULL) || (pid < 0) )
00748 {
00749 errno = EINVAL;
00750 }
00751 else if( !rk_resource_set_valid(rs) )
00752 {
00753 errno = EINVAL;
00754 }
00755 else if( (rk_stub_data.sd_Mode >= RK_STUB_SIM) &&
00756 ((pid >= MAX_PCB) ||
00757 !(rk_stub_data.sd_PCBs[pid].p_Flags & PCBF_IN_USE)) )
00758 {
00759 errno = ESRCH;
00760 }
00761 else if( rs->rs_ProcessID == -1 )
00762 {
00763 rs->rs_ProcessID = pid;
00764 if( rk_stub_data.sd_Mode >= RK_STUB_SIM )
00765 {
00766 rk_stub_data.sd_PCBs[pid].p_Resources = rs;
00767
00768 ensure(rk_proc_get_rset(pid) == rs);
00769 }
00770 retval = 0;
00771 }
00772 else
00773 {
00774 errno = ENOSYS;
00775 }
00776
00777 fprintf(rk_stub_data.sd_LogFile, "END %d = %s\n", retval, __PRETTY_FUNCTION__);
00778
00779 return( retval );
00780 }
00781
00782 int rk_resource_set_detach_process(rk_resource_set_t rs, pid_t pid)
00783 {
00784 int retval = -1;
00785
00786 require(rk_stub_data.sd_Mode > RK_STUB_MIN);
00787 require(rk_stub_data.sd_Mode < RK_STUB_MAX);
00788
00789 fprintf(rk_stub_data.sd_LogFile, "BEGIN %s(%p%s, %d%s)\n", __PRETTY_FUNCTION__, rs, rk_resource_set_string(rs), pid, rk_stub_pcb_string(pid));
00790
00791 if( (rs == NULL) || (pid < 0) || (pid >= MAX_PCB) )
00792 {
00793 errno = EINVAL;
00794 }
00795 else if( !rk_resource_set_valid(rs) )
00796 {
00797 errno = EINVAL;
00798 }
00799 else if( !(rk_stub_data.sd_PCBs[pid].p_Flags & PCBF_IN_USE) )
00800 {
00801 errno = ESRCH;
00802 }
00803 else if( rs->rs_ProcessID == pid )
00804 {
00805 rk_stub_data.sd_PCBs[pid].p_Resources = NULL;
00806 rs->rs_ProcessID = -1;
00807 retval = 0;
00808
00809 ensure(rk_proc_get_rset(pid) == NULL);
00810 }
00811 else
00812 {
00813 errno = EINVAL;
00814 }
00815
00816 fprintf(rk_stub_data.sd_LogFile, "END %d = %s\n", retval, __PRETTY_FUNCTION__);
00817
00818 return( retval );
00819 }
00820
00821 int rk_resource_set_get_num_procs(rk_resource_set_t rs)
00822 {
00823 int retval = -1;
00824
00825 require(rk_stub_data.sd_Mode > RK_STUB_MIN);
00826 require(rk_stub_data.sd_Mode < RK_STUB_MAX);
00827
00828 fprintf(rk_stub_data.sd_LogFile, "BEGIN %s(%p%s)\n", __PRETTY_FUNCTION__, rs, rk_resource_set_string(rs));
00829
00830 if( rs == NULL_RESOURCE_SET )
00831 {
00832 errno = EINVAL;
00833 }
00834 else
00835 {
00836 if( rs->rs_ProcessID != -1 )
00837 {
00838 retval = 1;
00839 }
00840 else
00841 {
00842 retval = 0;
00843 }
00844 }
00845
00846 fprintf(rk_stub_data.sd_LogFile, "END %d = %s\n", retval, __PRETTY_FUNCTION__);
00847
00848 return( retval );
00849 }
00850
00851 int rk_resource_set_get_proclist(rk_resource_set_t rs,
00852 pid_t *procs_inout,
00853 int count)
00854 {
00855 int retval = -1;
00856
00857 require(rk_stub_data.sd_Mode > RK_STUB_MIN);
00858 require(rk_stub_data.sd_Mode < RK_STUB_MAX);
00859
00860 fprintf(rk_stub_data.sd_LogFile, "BEGIN %s(%p%s, %p, %d)\n", __PRETTY_FUNCTION__, rs, rk_resource_set_string(rs), procs_inout, count);
00861
00862 if( (rs == NULL_RESOURCE_SET) || (procs_inout == NULL) || (count < 0) )
00863 {
00864 errno = EINVAL;
00865 }
00866 else if( count == 0 )
00867 {
00868 retval = 0;
00869 }
00870 else
00871 {
00872 int lpc;
00873
00874 if( rs->rs_ProcessID != -1 )
00875 {
00876 retval = 0;
00877 }
00878 procs_inout[0] = rs->rs_ProcessID;
00879 for( lpc = 1; lpc < count; lpc++ )
00880 {
00881 procs_inout[lpc] = -1;
00882 }
00883 }
00884
00885 fprintf(rk_stub_data.sd_LogFile, "END %d = %s\n", retval, __PRETTY_FUNCTION__);
00886
00887 return( retval );
00888 }
00889
00890 rk_resource_set_t rk_proc_get_rset(pid_t pid)
00891 {
00892 rk_resource_set_t retval = NULL_RESOURCE_SET;
00893
00894 require(rk_stub_data.sd_Mode > RK_STUB_MIN);
00895 require(rk_stub_data.sd_Mode < RK_STUB_MAX);
00896
00897 fprintf(rk_stub_data.sd_LogFile, "BEGIN %s(%d%s)\n", __PRETTY_FUNCTION__, pid, rk_stub_pcb_string(pid));
00898
00899 if( (pid < 0) || (pid >= MAX_PCB) )
00900 {
00901 errno = EINVAL;
00902 }
00903 else if( !(rk_stub_data.sd_PCBs[pid].p_Flags & PCBF_IN_USE) )
00904 {
00905 errno = ESRCH;
00906 }
00907 else if( rk_stub_data.sd_PCBs[pid].p_Resources == NULL )
00908 {
00909 errno = ENOTCONN;
00910 }
00911 else
00912 {
00913 retval = rk_stub_data.sd_PCBs[pid].p_Resources;
00914
00915 ensure(rk_resource_set_valid(retval));
00916 }
00917
00918 fprintf(rk_stub_data.sd_LogFile, "END %p%s = %s\n", retval, rk_resource_set_string(retval), __PRETTY_FUNCTION__);
00919
00920 return( retval );
00921 }
00922
00923 int rk_cpu_reserve_create(rk_resource_set_t rs,
00924 rk_reserve_t *r_out,
00925 cpu_reserve_attr_t ra_in)
00926 {
00927 cpu_reserve_t cr;
00928 int retval = -1;
00929
00930 require(rk_stub_data.sd_Mode > RK_STUB_MIN);
00931 require(rk_stub_data.sd_Mode < RK_STUB_MAX);
00932
00933 fprintf(rk_stub_data.sd_LogFile, "BEGIN %s(%p%s, %p, %p%s)\n", __PRETTY_FUNCTION__, rs, rk_resource_set_string(rs), r_out, ra_in, cpu_reserve_attr_string(ra_in));
00934
00935 if( (rs == NULL) || (r_out == NULL) || (ra_in == NULL) )
00936 {
00937 errno = EINVAL;
00938 }
00939 else if( !rk_resource_set_valid(rs) )
00940 {
00941 errno = EINVAL;
00942 }
00943 else if( !rk_cpu_reserve_attr_valid(ra_in) )
00944 {
00945 errno = EINVAL;
00946 }
00947 else if( (rs->rs_CPU != NULL) )
00948 {
00949 errno = EISCONN;
00950 }
00951 else if( (cr = calloc(1, sizeof(struct cpu_reserve))) != NULL )
00952 {
00953 int lpc;
00954
00955 *r_out = NULL;
00956 rs->rs_CPU = cr;
00957 cr->cr_Attributes = *((cpu_reserve_attr_t)ra_in);
00958 switch( rk_stub_data.sd_Mode )
00959 {
00960 case RK_STUB_LOG:
00961 retval = 0;
00962 break;
00963 case RK_STUB_SIM:
00964 cr->cr_Compute.cr_DataPeriodStart = rk_stub_data.sd_CurrentTime;
00965 cr->cr_Compute.cr_DataPeriodEnd = rk_stub_data.sd_CurrentTime;
00966 cr->cr_Compute.cr_DataPeriodNext = rk_stub_data.sd_CurrentTime;
00967 cr->cr_Compute.cr_TimePeriodStart = rk_stub_data.sd_CurrentTime;
00968 cr->cr_Compute.cr_TimePeriodEnd = rk_stub_data.sd_CurrentTime;
00969 cr->cr_Compute.cr_TimePeriodNext = rk_stub_data.sd_CurrentTime;
00970
00971 retval = 0;
00972 for( lpc = 0; (lpc < RK_CPU_TRACE_MAX) && (retval == 0); lpc++ )
00973 {
00974 char trace_name[RSET_NAME_LEN + 64];
00975
00976 snprintf(trace_name, sizeof(trace_name),
00977 "%s_cpu_%s",
00978 rs->rs_Name,
00979 rk_cpu_trace_names[lpc]);
00980 if( (cr->cr_Trace[lpc] = fopen(trace_name, "w")) != NULL )
00981 {
00982 fprintf(cr->cr_Trace[lpc], "0 0.0\n");
00983 }
00984 else
00985 {
00986 retval = -1;
00987 }
00988
00989 ensure(strlen(trace_name) < sizeof(trace_name));
00990 }
00991 if( retval == 0 )
00992 {
00993 char times_name[RSET_NAME_LEN + 64];
00994 FILE *times_file;
00995
00996
00997 snprintf(times_name, sizeof(times_name),
00998 "%s_cpu_times",
00999 rs->rs_Name);
01000 if( (times_file = fopen(times_name, "r")) != NULL )
01001 {
01002 long long deadline_us;
01003 int done = 0;
01004
01005 deadline_us = timespec_to_microsec(&ra_in->deadline);
01006 cr->cr_Compute.cr_Length = 1;
01007 while( !done && (retval == 0) )
01008 {
01009 struct timespec *ts;
01010
01011 if( (ts = realloc(cr->cr_Compute.cr_Times,
01012 cr->cr_Compute.cr_Length *
01013 sizeof(struct timespec)))
01014 != NULL )
01015 {
01016 float percent;
01017
01018 cr->cr_Compute.cr_Times = ts;
01019 if( (fscanf(times_file, "%f", &percent) == 1) &&
01020 (percent >= 0.0) && (percent <= 120.0) )
01021 {
01022 long long compute_us;
01023
01024
01025
01026
01027
01028
01029
01030 compute_us = (long long)
01031 (((double)deadline_us) *
01032 (percent / 100.0));
01033 cr->cr_Compute.
01034 cr_Times[cr->cr_Compute.cr_TimeIndex] =
01035 microsec_to_timespec(compute_us);
01036 cr->cr_Compute.cr_TimeIndex += 1;
01037 cr->cr_Compute.cr_Length += 1;
01038 }
01039 else if( feof(times_file) )
01040 {
01041
01042 cr->cr_Compute.cr_DataPeriodRemaining =
01043 cr->cr_Compute.cr_Times[0];
01044 cr->cr_Compute.cr_Length -= 1;
01045 cr->cr_Compute.cr_TimeIndex = -1;
01046 done = 1;
01047 }
01048 else
01049 {
01050
01051 #if defined(EFTYPE)
01052 errno = EFTYPE;
01053 #else
01054 errno = EINVAL;
01055 #endif
01056 retval = -1;
01057 }
01058 }
01059 else
01060 {
01061 errno = ENOMEM;
01062 retval = -1;
01063 }
01064 }
01065 if( cr->cr_Compute.cr_Length != 0 )
01066 {
01067
01068 }
01069 else
01070 {
01071
01072 #if defined(EFTYPE)
01073 errno = EFTYPE;
01074 #else
01075 errno = EINVAL;
01076 #endif
01077 retval = -1;
01078 }
01079 fclose(times_file);
01080 }
01081 else
01082 {
01083 retval = -1;
01084 }
01085
01086 ensure(strlen(times_name) < sizeof(times_name));
01087 }
01088 break;
01089 default:
01090 break;
01091 }
01092 if( retval == 0 )
01093 {
01094 *r_out = cr;
01095 }
01096 else
01097 {
01098 rk_cpu_reserve_delete(rs);
01099 }
01100
01101 ensure((*r_out == NULL) || cpu_reserve_valid(*r_out));
01102 }
01103 else
01104 {
01105 errno = ENOMEM;
01106 }
01107
01108 fprintf(rk_stub_data.sd_LogFile, "END %d = %s r_out=%s\n", retval, __PRETTY_FUNCTION__, r_out == NULL ? "(null)" : cpu_reserve_string(*r_out));
01109
01110 return( retval );
01111 }
01112
01113 int rk_cpu_reserve_delete(rk_resource_set_t rs)
01114 {
01115 int retval = -1;
01116
01117 require(rk_stub_data.sd_Mode > RK_STUB_MIN);
01118 require(rk_stub_data.sd_Mode < RK_STUB_MAX);
01119
01120 fprintf(rk_stub_data.sd_LogFile, "BEGIN %s(%p%s)\n", __PRETTY_FUNCTION__, rs, rk_resource_set_string(rs));
01121
01122 if( rs == NULL )
01123 {
01124 errno = EINVAL;
01125 }
01126 else if( rs->rs_CPU == NULL )
01127 {
01128 errno = ENOTCONN;
01129 }
01130 else if( !rk_resource_set_valid(rs) )
01131 {
01132 errno = EINVAL;
01133 }
01134 else
01135 {
01136 cpu_reserve_t cr;
01137 int lpc;
01138
01139 cr = rs->rs_CPU;
01140 free(cr->cr_Compute.cr_Times);
01141 cr->cr_Compute.cr_Times = NULL;
01142
01143 for( lpc = 0; lpc < RK_CPU_TRACE_MAX; lpc++ )
01144 {
01145
01146
01147
01148
01149 if( cr->cr_Trace[lpc] != NULL )
01150 {
01151 fclose(cr->cr_Trace[lpc]);
01152 cr->cr_Trace[lpc] = NULL;
01153 }
01154 }
01155 free(rs->rs_CPU);
01156 rs->rs_CPU = NULL;
01157 retval = 0;
01158
01159 ensure(!cpu_reserve_valid(cr));
01160 }
01161
01162 fprintf(rk_stub_data.sd_LogFile, "%d END %s\n", retval, __PRETTY_FUNCTION__);
01163
01164 return( retval );
01165 }
01166
01167 int rk_cpu_reserve_get_attr(rk_reserve_t cr, cpu_reserve_attr_t ra_out)
01168 {
01169 int retval = -1;
01170
01171 require(rk_stub_data.sd_Mode > RK_STUB_MIN);
01172 require(rk_stub_data.sd_Mode < RK_STUB_MAX);
01173
01174 fprintf(rk_stub_data.sd_LogFile, "BEGIN %s(%p%s, %p)\n", __PRETTY_FUNCTION__, cr, cpu_reserve_string((cpu_reserve_t)cr), ra_out);
01175
01176 if( (cr == NULL) || (ra_out == NULL) )
01177 {
01178 errno = EINVAL;
01179 }
01180 else if( !cpu_reserve_valid(cr) )
01181 {
01182 errno = EINVAL;
01183 }
01184 else
01185 {
01186 *ra_out = ((cpu_reserve_t)cr)->cr_Attributes;
01187 retval = 0;
01188
01189 ensure(rk_cpu_reserve_attr_valid(ra_out));
01190 }
01191
01192 fprintf(rk_stub_data.sd_LogFile, "END %d = %s ra_out=%p%s\n", retval, __PRETTY_FUNCTION__, ra_out, cpu_reserve_attr_string(ra_out));
01193
01194 return( retval );
01195 }
01196
01197 int rk_cpu_reserve_ctl(rk_resource_set_t rs, cpu_reserve_attr_t ra_in)
01198 {
01199 int retval = -1;
01200
01201 require(rk_stub_data.sd_Mode > RK_STUB_MIN);
01202 require(rk_stub_data.sd_Mode < RK_STUB_MAX);
01203
01204 fprintf(rk_stub_data.sd_LogFile, "BEGIN %s(%p%s, %p%s)\n", __PRETTY_FUNCTION__, rs, rk_resource_set_string(rs), ra_in, cpu_reserve_attr_string(ra_in));
01205
01206 if( (rs == NULL) || (ra_in == NULL) )
01207 {
01208 errno = EINVAL;
01209 }
01210 else if( !rk_resource_set_valid(rs) )
01211 {
01212 errno = EINVAL;
01213 }
01214 else if( !rk_cpu_reserve_attr_valid(ra_in) )
01215 {
01216 errno = ENOSPC;
01217 }
01218 else if( rs->rs_CPU == NULL )
01219 {
01220 errno = ENOTCONN;
01221 }
01222 else
01223 {
01224 cpu_reserve_t cr;
01225
01226 cr = rs->rs_CPU;
01227
01228 if( (cr->cr_Flags & CRF_RUNNING) &&
01229 tscmp(&cr->cr_Compute.cr_TimePeriodEnd,
01230 &rk_stub_data.sd_CurrentTime,
01231 !=) &&
01232 tscmp(&cr->cr_Compute.cr_DataPeriodEnd,
01233 &rk_stub_data.sd_CurrentTime,
01234 !=) )
01235 {
01236 rk_cpu_reserve_tick(rs,
01237 cr,
01238 &rk_stub_data.sd_CurrentTime,
01239 &rk_stub_data.sd_NextTime,
01240 &ra_in->compute_time);
01241 if( !(rk_stub_data.sd_Flags & SDF_IN_TICK) )
01242 {
01243 rk_stub_data.sd_CurrentTime = rk_stub_data.sd_NextTime;
01244 }
01245 }
01246 cr->cr_Attributes = *ra_in;
01247 retval = 0;
01248 }
01249
01250 fprintf(rk_stub_data.sd_LogFile, "END %d = %s\n", retval, __PRETTY_FUNCTION__);
01251
01252 return( retval );
01253 }
01254
01255 int rk_clock_gettime(clockid_t clock_id, struct timespec *ts)
01256 {
01257 int retval = -1;
01258
01259 if( clock_id != CLOCK_REALTIME )
01260 {
01261 errno = EINVAL;
01262 }
01263 else if( ts == NULL )
01264 {
01265 errno = EINVAL;
01266 }
01267 else
01268 {
01269 *ts = rk_stub_data.sd_CurrentTime;
01270 retval = 0;
01271 }
01272 return( retval );
01273 }
01274
01275 int rk_clock_settime(clockid_t clock_id, struct timespec *ts)
01276 {
01277 int retval = -1;
01278
01279 if( clock_id != CLOCK_REALTIME )
01280 {
01281 errno = EINVAL;
01282 }
01283 else if( ts == NULL )
01284 {
01285 errno = EINVAL;
01286 }
01287 else
01288 {
01289 rk_stub_data.sd_CurrentTime = *ts;
01290 retval = 0;
01291 }
01292 return( retval );
01293 }
01294
01295 int rk_clock_getres(clockid_t clock_id, struct timespec *ts)
01296 {
01297 int retval = -1;
01298
01299 if( clock_id != CLOCK_REALTIME )
01300 {
01301 errno = EINVAL;
01302 }
01303 else if( ts == NULL )
01304 {
01305 errno = EINVAL;
01306 }
01307 else
01308 {
01309 ts->tv_sec = 0;
01310 ts->tv_nsec = NANOS_PER_MICRO;
01311 retval = 0;
01312 }
01313 return( retval );
01314 }
01315
01316
01317
01318
01319
01320 void rk_stub_set_mode(rk_stub_mode_t mode)
01321 {
01322 require(mode > RK_STUB_MIN);
01323 require(mode < RK_STUB_MAX);
01324
01325 require(rk_stub_data.sd_Mode == RK_STUB_MIN);
01326
01327 rk_stub_data.sd_Mode = mode;
01328
01329 lnNewList(&rk_stub_data.sd_ResourceSets);
01330 if( (rk_stub_data.sd_LogFile = fopen("rk.log", "w")) == NULL )
01331 {
01332 perror("Cannot open log file.");
01333 exit(EXIT_FAILURE);
01334 }
01335 setvbuf(rk_stub_data.sd_LogFile, NULL, _IONBF, 0);
01336 }
01337
01338
01339
01340
01341
01342
01343
01344
01345
01346 static
01347 void rk_next_tick(struct timespec *next,
01348 struct timespec *curr,
01349 struct timespec *new_next)
01350 {
01351 require(next != NULL);
01352 require(curr != NULL);
01353 require(new_next != NULL);
01354
01355 if( ((int)new_next->tv_nsec) < 0 )
01356 {
01357 require(0);
01358 }
01359 if( tscmp(curr, new_next, ==) )
01360 {
01361
01362 }
01363 else if( tscmp(new_next, next, <) )
01364 {
01365 *next = *new_next;
01366 }
01367 }
01368
01369 static
01370 void rk_cpu_reserve_tick(rk_resource_set_t rs,
01371 cpu_reserve_t cr,
01372 struct timespec *curr,
01373 struct timespec *next,
01374 struct timespec *new_compute)
01375 {
01376 long long time_period_start_us, time_period_end_us, time_period_next_us;
01377 long long data_period_start_us, data_period_end_us, data_period_next_us;
01378 long long curr_us, given_compute_us, given_period_us, given_deadline_us;
01379 long long needed_compute_us, data_period_remaining_us;
01380 float given_cpu_percent, needed_cpu_percent;
01381 struct rk_stub_pcb *proc;
01382
01383 require(rs != NULL);
01384 require(cr != NULL);
01385 require(curr != NULL);
01386 require(next != NULL);
01387
01388 proc = &rk_stub_data.sd_PCBs[rs->rs_ProcessID];
01389
01390 fprintf(cr->cr_Trace[RK_CPU_TRACE_COMPUTE_FAIL],
01391 "# tick %p %d.%ld rem %d.%ld\n",
01392 rs,
01393 (int)curr->tv_sec,
01394 curr->tv_nsec,
01395 (int)cr->cr_Compute.cr_DataPeriodRemaining.tv_sec,
01396 cr->cr_Compute.cr_DataPeriodRemaining.tv_nsec);
01397
01398 curr_us = timespec_to_microsec(curr);
01399
01400 given_compute_us = timespec_to_microsec(&cr->cr_Attributes.compute_time);
01401 given_period_us = timespec_to_microsec(&cr->cr_Attributes.period);
01402 given_deadline_us = timespec_to_microsec(&cr->cr_Attributes.deadline);
01403
01404 given_cpu_percent = (((float)given_compute_us) /
01405 ((float)given_deadline_us));
01406
01407 needed_compute_us = timespec_to_microsec(
01408 &cr->cr_Compute.cr_Times[(cr->cr_Compute.cr_DataIndex) %
01409 (cr->cr_Compute.cr_Length)]);
01410
01411 time_period_start_us =
01412 timespec_to_microsec(&cr->cr_Compute.cr_TimePeriodStart);
01413 time_period_end_us =
01414 timespec_to_microsec(&cr->cr_Compute.cr_TimePeriodEnd);
01415 time_period_next_us =
01416 timespec_to_microsec(&cr->cr_Compute.cr_TimePeriodNext);
01417 data_period_start_us =
01418 timespec_to_microsec(&cr->cr_Compute.cr_DataPeriodStart);
01419 data_period_end_us =
01420 timespec_to_microsec(&cr->cr_Compute.cr_DataPeriodEnd);
01421 data_period_next_us =
01422 timespec_to_microsec(&cr->cr_Compute.cr_DataPeriodNext);
01423 data_period_remaining_us =
01424 timespec_to_microsec(&cr->cr_Compute.cr_DataPeriodRemaining);
01425
01426 needed_cpu_percent = (((float)data_period_remaining_us) /
01427 ((float)given_deadline_us));
01428
01429 if( cr->cr_Flags & CRF_RUNNING )
01430 {
01431 if( curr_us == data_period_end_us )
01432 {
01433 struct timeval tv;
01434
01435 if( cr->cr_Compute.cr_DataIndex == cr->cr_Compute.cr_TimeIndex )
01436 {
01437 cr->cr_Flags &= ~CRF_RUNNING;
01438
01439 fprintf(cr->cr_Trace[RK_CPU_TRACE_COMPUTE_SUCCESS],
01440 "# line %d\n"
01441 "%qd 0\n",
01442 __LINE__,
01443 curr_us / 1000);
01444 fprintf(cr->cr_Trace[RK_CPU_TRACE_COMPUTE_FAIL],
01445 "# line %d\n"
01446 "%qd 0\n",
01447 __LINE__,
01448 curr_us / 1000);
01449 }
01450 else
01451 {
01452 fprintf(cr->cr_Trace[RK_CPU_TRACE_COMPUTE_FAIL],
01453 "# line %d next %d.%ld ind %d %d\n"
01454 "%qd %f\n"
01455 "%qd 0\n",
01456 __LINE__,
01457 (int)cr->cr_Compute.cr_DataPeriodNext.tv_sec,
01458 cr->cr_Compute.cr_DataPeriodNext.tv_nsec,
01459 cr->cr_Compute.cr_DataIndex + 1,
01460 cr->cr_Compute.cr_TimeIndex,
01461 (curr_us / 1000) - 1,
01462 given_cpu_percent * 100.0,
01463 curr_us / 1000);
01464 fprintf(cr->cr_Trace[RK_CPU_TRACE_COMPUTE_SUCCESS],
01465 "# line %d\n"
01466 "%qd 0\n",
01467 __LINE__,
01468 curr_us / 1000);
01469 }
01470
01471 tv.tv_sec = timespec_to_microsec(
01472 &cr->cr_Compute.cr_Times[(cr->cr_Compute.cr_DataIndex) %
01473 (cr->cr_Compute.cr_Length)]) / 1000000;
01474 tv.tv_usec = timespec_to_microsec(
01475 &cr->cr_Compute.cr_Times[(cr->cr_Compute.cr_DataIndex) %
01476 (cr->cr_Compute.cr_Length)]) % 1000000;
01477 timeradd(&proc->p_Usage.ru_utime, &tv, &proc->p_Usage.ru_utime);
01478 proc->p_Postcall(rk_stub_data.sd_PCBs[rs->rs_ProcessID].p_Data);
01479 fprintf(cr->cr_Trace[RK_CPU_TRACE_COMPLETE],
01480 "# %d\n"
01481 "%qd -5\n",
01482 cr->cr_Compute.cr_DataIndex,
01483 curr_us / 1000);
01484 cr->cr_Compute.cr_DataIndex += 1;
01485
01486 cr->cr_Compute.cr_DataPeriodRemaining =
01487 cr->cr_Compute.cr_Times[(cr->cr_Compute.cr_DataIndex) %
01488 (cr->cr_Compute.cr_Length)];
01489
01490 if( cr->cr_Flags & CRF_RUNNING )
01491 {
01492
01493 needed_compute_us = timespec_to_microsec(
01494 &cr->cr_Compute.
01495 cr_Times[(cr->cr_Compute.cr_DataIndex) %
01496 (cr->cr_Compute.cr_Length)]);
01497
01498 needed_cpu_percent = (((float)needed_compute_us) /
01499 ((float)given_deadline_us));
01500 }
01501 }
01502 if( curr_us == time_period_end_us )
01503 {
01504 if( cr->cr_Compute.cr_DataIndex == cr->cr_Compute.cr_TimeIndex )
01505 {
01506 fprintf(cr->cr_Trace[RK_CPU_TRACE_COMPUTE_FAIL],
01507 "# line %d\n"
01508 "%qd 0\n",
01509 __LINE__,
01510 curr_us / 1000);
01511 fprintf(cr->cr_Trace[RK_CPU_TRACE_COMPUTE_SUCCESS],
01512 "# line %d\n"
01513 "%qd 0\n",
01514 __LINE__,
01515 curr_us / 1000);
01516 }
01517 }
01518 }
01519 if( curr_us == time_period_end_us )
01520 {
01521 fprintf(cr->cr_Trace[RK_CPU_TRACE_DEADLINE],
01522 "# line %d\n"
01523 "%qd 120\n",
01524 __LINE__,
01525 curr_us / 1000);
01526 if( (cr->cr_Flags & CRF_RUNNING) &&
01527 (cr->cr_Compute.cr_DataIndex < cr->cr_Compute.cr_TimeIndex) )
01528 {
01529 fprintf(cr->cr_Trace[RK_CPU_TRACE_COMPUTE_FAIL],
01530 "# line %d\n"
01531 "%qd 0\n",
01532 __LINE__,
01533 curr_us / 1000);
01534 fprintf(cr->cr_Trace[RK_CPU_TRACE_COMPUTE_SUCCESS],
01535 "# line %d\n"
01536 "%qd 0\n",
01537 __LINE__,
01538 curr_us / 1000);
01539 }
01540 if( (cr->cr_Flags & CRF_RUNNING) && (curr_us != data_period_end_us) )
01541 {
01542 fprintf(cr->cr_Trace[RK_CPU_TRACE_COMPUTE_FAIL],
01543 "# line %d %qd -= %qd max(%qd, %qd) * %f\n",
01544 __LINE__,
01545 data_period_remaining_us,
01546 curr_us,
01547 time_period_start_us,
01548 data_period_start_us,
01549 given_cpu_percent);
01550 data_period_remaining_us -=
01551 (curr_us - max(time_period_start_us, data_period_start_us)) *
01552 given_cpu_percent;
01553 if( data_period_remaining_us < 0 )
01554 {
01555 data_period_remaining_us = 0;
01556 }
01557 cr->cr_Compute.cr_DataPeriodRemaining =
01558 microsec_to_timespec(data_period_remaining_us);
01559 fprintf(cr->cr_Trace[RK_CPU_TRACE_COMPUTE_FAIL],
01560 "# sub line %d %d.%ld\n",
01561 __LINE__,
01562 (int)cr->cr_Compute.cr_DataPeriodRemaining.tv_sec,
01563 cr->cr_Compute.cr_DataPeriodRemaining.tv_nsec);
01564 }
01565
01566 cr->cr_Flags &= ~CRF_RUNNING;
01567
01568 cr->cr_Compute.cr_TimeIndex += 1;
01569 }
01570
01571 if( curr_us == time_period_next_us )
01572 {
01573 long long realtime_compute_us;
01574 float realtime_cpu_percent;
01575
01576 cr->cr_Flags |= CRF_RUNNING;
01577
01578 realtime_compute_us = timespec_to_microsec(
01579 &cr->cr_Compute.cr_Times[(cr->cr_Compute.cr_TimeIndex) %
01580 (cr->cr_Compute.cr_Length)]);
01581
01582 realtime_cpu_percent = (((float)realtime_compute_us) /
01583 ((float)given_deadline_us));
01584
01585 fprintf(cr->cr_Trace[RK_CPU_TRACE_PERIOD],
01586 "# line %d\n"
01587 "%qd 120\n",
01588 __LINE__,
01589 curr_us / 1000);
01590 fprintf(cr->cr_Trace[RK_CPU_TRACE_REALTIME],
01591 "# line %d\n"
01592 "%qd %f\n"
01593 "%qd 0\n",
01594 __LINE__,
01595 curr_us / 1000,
01596 realtime_cpu_percent * 100.0,
01597 (curr_us + given_deadline_us) / 1000);
01598 if( cr->cr_Compute.cr_DataIndex < cr->cr_Compute.cr_TimeIndex )
01599 {
01600 fprintf(cr->cr_Trace[RK_CPU_TRACE_COMPUTE_FAIL],
01601 "# line %d\n"
01602 "%qd %f\n",
01603 __LINE__,
01604 curr_us / 1000,
01605 given_cpu_percent * 100.0);
01606 fprintf(cr->cr_Trace[RK_CPU_TRACE_COMPUTE_SUCCESS],
01607 "# line %d\n"
01608 "%qd 0\n",
01609 __LINE__,
01610 curr_us / 1000);
01611 }
01612
01613 cr->cr_Compute.cr_TimePeriodStart = *curr;
01614 cr->cr_Compute.cr_TimePeriodEnd = microsec_to_timespec(
01615 curr_us + given_deadline_us);
01616 cr->cr_Compute.cr_TimePeriodNext =
01617 microsec_to_timespec(time_period_next_us + given_period_us);
01618 }
01619
01620 if( (curr_us == data_period_next_us) || (new_compute != NULL) )
01621 {
01622 float period_used, needed_periods, floored_periods;
01623
01624 if( new_compute == NULL )
01625 {
01626 rk_stub_precall_t precall;
01627
01628 precall = rk_stub_data.sd_PCBs[rs->rs_ProcessID].p_Precall;
01629 if( precall != NULL )
01630 {
01631 void *proc_data;
01632
01633 proc_data = rk_stub_data.sd_PCBs[rs->rs_ProcessID].p_Data;
01634 while( (cr->cr_Compute.cr_DataIndex <=
01635 cr->cr_Compute.cr_TimeIndex) &&
01636 (precall(proc_data) == RKSP_DROP) )
01637 {
01638 fprintf(cr->cr_Trace[RK_CPU_TRACE_DROP],
01639 "# line %d\n"
01640 "%qd -2\n",
01641 __LINE__,
01642 curr_us / 1000);
01643 cr->cr_Compute.cr_DataIndex += 1;
01644 }
01645 if( cr->cr_Compute.cr_DataIndex <=
01646 cr->cr_Compute.cr_TimeIndex )
01647 {
01648 cr->cr_Compute.cr_DataPeriodRemaining =
01649 cr->cr_Compute.cr_Times[(cr->cr_Compute.cr_DataIndex) %
01650 (cr->cr_Compute.cr_Length)];
01651
01652 needed_compute_us = timespec_to_microsec(
01653 &cr->cr_Compute.
01654 cr_Times[(cr->cr_Compute.cr_DataIndex) %
01655 (cr->cr_Compute.cr_Length)]);
01656 needed_cpu_percent = (((float)needed_compute_us) /
01657 ((float)given_deadline_us));
01658 }
01659 else
01660 {
01661 cr->cr_Flags &= ~CRF_RUNNING;
01662
01663 cr->cr_Compute.cr_DataPeriodNext =
01664 cr->cr_Compute.cr_TimePeriodNext;
01665 goto reeval;
01666 }
01667 }
01668 }
01669 else
01670 {
01671 data_period_remaining_us =
01672 timespec_to_microsec(&cr->cr_Compute.cr_DataPeriodRemaining);
01673 fprintf(cr->cr_Trace[RK_CPU_TRACE_COMPUTE_FAIL],
01674 "# line %d %qd -= %qd - max(%qd, %qd) * %f\n",
01675 __LINE__,
01676 data_period_remaining_us,
01677 curr_us,
01678 time_period_start_us,
01679 data_period_start_us,
01680 given_cpu_percent);
01681 data_period_remaining_us -=
01682 (curr_us - max(time_period_start_us, data_period_start_us)) *
01683 given_cpu_percent;
01684 cr->cr_Compute.cr_DataPeriodRemaining =
01685 microsec_to_timespec(data_period_remaining_us);
01686 needed_cpu_percent = (((float)data_period_remaining_us) /
01687 ((float)given_deadline_us));
01688 }
01689
01690 if( new_compute == NULL )
01691 {
01692 given_compute_us =
01693 timespec_to_microsec(&cr->cr_Attributes.compute_time);
01694 }
01695 else
01696 {
01697 given_compute_us = timespec_to_microsec(new_compute);
01698 }
01699 given_period_us = timespec_to_microsec(&cr->cr_Attributes.period);
01700 given_deadline_us = timespec_to_microsec(&cr->cr_Attributes.deadline);
01701
01702 given_cpu_percent = (((float)given_compute_us) /
01703 ((float)given_deadline_us));
01704
01705 if( given_cpu_percent == 0.0 )
01706 {
01707 cr->cr_Compute.cr_DataPeriodEnd = (struct timespec){
01708 LONG_MAX,
01709 LONG_MAX
01710 };
01711 cr->cr_Compute.cr_DataPeriodNext = (struct timespec){
01712 LONG_MAX,
01713 LONG_MAX
01714 };
01715 fprintf(cr->cr_Trace[RK_CPU_TRACE_COMPUTE_SUCCESS],
01716 "# line %d\n"
01717 "%qd 0\n",
01718 __LINE__,
01719 curr_us / 1000);
01720 fprintf(cr->cr_Trace[RK_CPU_TRACE_COMPUTE_FAIL],
01721 "# line %d\n"
01722 "%qd 0\n",
01723 __LINE__,
01724 curr_us / 1000);
01725 return;
01726 }
01727
01728 time_period_start_us =
01729 timespec_to_microsec(&cr->cr_Compute.cr_TimePeriodStart);
01730 period_used = (((float)(curr_us - time_period_start_us)) /
01731 ((float)given_deadline_us));
01732 fprintf(cr->cr_Trace[RK_CPU_TRACE_COMPUTE_FAIL],
01733 "# line %d %f + %f / %f\n",
01734 __LINE__,
01735 period_used,
01736 needed_cpu_percent,
01737 given_cpu_percent);
01738 if( needed_cpu_percent == 0.0 )
01739 {
01740 needed_periods = 0.0;
01741 floored_periods = 0.0;
01742 cr->cr_Compute.cr_DataPeriodEnd = *curr;
01743 cr->cr_Compute.cr_DataPeriodEnd.tv_nsec += NANOS_PER_MICRO;
01744 }
01745 else
01746 {
01747 needed_periods = period_used +
01748 (needed_cpu_percent / given_cpu_percent);
01749 floored_periods = floorf(needed_periods);
01750 if( needed_periods == floored_periods )
01751 {
01752 floored_periods -= 1.0;
01753 }
01754 cr->cr_Compute.cr_DataPeriodStart = *curr;
01755 fprintf(cr->cr_Trace[RK_CPU_TRACE_COMPUTE_FAIL],
01756 "# line %d %d.%ld\n",
01757 __LINE__,
01758 (int)cr->cr_Compute.cr_DataPeriodStart.tv_sec,
01759 cr->cr_Compute.cr_DataPeriodStart.tv_nsec);
01760 fprintf(cr->cr_Trace[RK_CPU_TRACE_COMPUTE_FAIL],
01761 "# line %d %qd + (%qd * %f) + (%qd * (%f - %f))\n",
01762 __LINE__,
01763 time_period_start_us,
01764 given_period_us,
01765 floored_periods,
01766 given_deadline_us,
01767 needed_periods,
01768 floored_periods);
01769 cr->cr_Compute.cr_DataPeriodEnd = microsec_to_timespec(
01770 time_period_start_us +
01771 (given_period_us * floored_periods) +
01772 (given_deadline_us * (needed_periods - floored_periods)));
01773 }
01774
01775 if( needed_periods <= 1.0 )
01776 {
01777 if( needed_periods == 1.0 )
01778 {
01779
01780 cr->cr_Compute.cr_DataPeriodEnd =
01781 cr->cr_Compute.cr_TimePeriodEnd;
01782 }
01783 if( cr->cr_Compute.cr_DataIndex == cr->cr_Compute.cr_TimeIndex )
01784 {
01785 cr->cr_Compute.cr_DataPeriodNext =
01786 cr->cr_Compute.cr_TimePeriodNext;
01787 fprintf(cr->cr_Trace[RK_CPU_TRACE_COMPUTE_SUCCESS],
01788 "# line %d end %d.%ld\n"
01789 "%qd %f\n",
01790 __LINE__,
01791 (int)cr->cr_Compute.cr_DataPeriodEnd.tv_sec,
01792 cr->cr_Compute.cr_DataPeriodEnd.tv_nsec,
01793 curr_us / 1000,
01794 given_cpu_percent * 100.0);
01795 fprintf(cr->cr_Trace[RK_CPU_TRACE_COMPUTE_FAIL],
01796 "# line %d\n"
01797 "%qd 0\n",
01798 __LINE__,
01799 curr_us / 1000);
01800 }
01801 else
01802 {
01803 cr->cr_Compute.cr_DataPeriodNext =
01804 cr->cr_Compute.cr_DataPeriodEnd;
01805 fprintf(cr->cr_Trace[RK_CPU_TRACE_COMPUTE_FAIL],
01806 "# line %d end %d.%ld\n"
01807 "%qd %f\n",
01808 __LINE__,
01809 (int)cr->cr_Compute.cr_DataPeriodEnd.tv_sec,
01810 cr->cr_Compute.cr_DataPeriodEnd.tv_nsec,
01811 curr_us / 1000,
01812 given_cpu_percent * 100.0);
01813 fprintf(cr->cr_Trace[RK_CPU_TRACE_COMPUTE_SUCCESS],
01814 "# line %d\n"
01815 "%qd 0\n",
01816 __LINE__,
01817 curr_us / 1000);
01818 }
01819 }
01820 else if( !(cr->cr_Flags & CRF_RUNNING) )
01821 {
01822 cr->cr_Compute.cr_DataPeriodNext =
01823 cr->cr_Compute.cr_TimePeriodNext;
01824 }
01825 else
01826 {
01827 cr->cr_Compute.cr_DataPeriodNext = cr->cr_Compute.cr_DataPeriodEnd;
01828
01829 fprintf(cr->cr_Trace[RK_CPU_TRACE_COMPUTE_FAIL],
01830 "# line %d\n"
01831 "%qd %f\n",
01832 __LINE__,
01833 curr_us / 1000,
01834 given_cpu_percent * 100.0);
01835 fprintf(cr->cr_Trace[RK_CPU_TRACE_COMPUTE_SUCCESS],
01836 "# line %d\n"
01837 "%qd 0\n",
01838 __LINE__,
01839 curr_us / 1000);
01840 }
01841
01842 }
01843
01844 reeval:
01845
01846 fprintf(cr->cr_Trace[RK_CPU_TRACE_COMPUTE_FAIL],
01847 "# line %d\n"
01848 "# data end %d.%ld next %d.%ld\n"
01849 "# time end %d.%ld next %d.%ld\n",
01850 __LINE__,
01851 (int)cr->cr_Compute.cr_DataPeriodEnd.tv_sec,
01852 cr->cr_Compute.cr_DataPeriodEnd.tv_nsec,
01853 (int)cr->cr_Compute.cr_DataPeriodNext.tv_sec,
01854 cr->cr_Compute.cr_DataPeriodNext.tv_nsec,
01855 (int)cr->cr_Compute.cr_TimePeriodEnd.tv_sec,
01856 cr->cr_Compute.cr_TimePeriodEnd.tv_nsec,
01857 (int)cr->cr_Compute.cr_TimePeriodNext.tv_sec,
01858 cr->cr_Compute.cr_TimePeriodNext.tv_nsec);
01859
01860 rk_next_tick(next, curr, &cr->cr_Compute.cr_TimePeriodEnd);
01861 rk_next_tick(next, curr, &cr->cr_Compute.cr_TimePeriodNext);
01862 if( cr->cr_Flags & CRF_RUNNING )
01863 {
01864 rk_next_tick(next, curr, &cr->cr_Compute.cr_DataPeriodEnd);
01865 }
01866 rk_next_tick(next, curr, &cr->cr_Compute.cr_DataPeriodNext);
01867
01868 fprintf(cr->cr_Trace[RK_CPU_TRACE_COMPUTE_FAIL],
01869 "# line %d next %d.%ld\n",
01870 __LINE__,
01871 (int)next->tv_sec,
01872 next->tv_nsec);
01873
01874 ensure(timespec_to_microsec(curr) < timespec_to_microsec(next));
01875 }
01876
01877 void rk_stub_next_tick(void)
01878 {
01879 rk_resource_set_t rs;
01880
01881 require(rk_stub_data.sd_Mode > RK_STUB_MIN);
01882 require(rk_stub_data.sd_Mode < RK_STUB_MAX);
01883
01884 rk_stub_data.sd_Flags |= SDF_IN_TICK;
01885 rk_stub_data.sd_CurrentTime = rk_stub_data.sd_NextTime;
01886 rk_stub_data.sd_NextTime.tv_sec = LONG_MAX;
01887 rk_stub_data.sd_NextTime.tv_nsec = LONG_MAX;
01888
01889 rs = (rk_resource_set_t)rk_stub_data.sd_ResourceSets.lh_Head;
01890 while( rs->rs_Link.ln_Succ != NULL )
01891 {
01892 if( (rs->rs_CPU != NULL) && (rs->rs_ProcessID != -1) )
01893 {
01894 rk_cpu_reserve_tick(rs,
01895 rs->rs_CPU,
01896 &rk_stub_data.sd_CurrentTime,
01897 &rk_stub_data.sd_NextTime,
01898 NULL);
01899 }
01900 rs = (rk_resource_set_t)rs->rs_Link.ln_Succ;
01901 }
01902 rk_stub_data.sd_Flags &= ~SDF_IN_TICK;
01903
01904 ensure(timespec_to_microsec(&rk_stub_data.sd_CurrentTime) <
01905 timespec_to_microsec(&rk_stub_data.sd_NextTime));
01906 }
01907
01908 pid_t rk_stub_mk_pid(const char *name,
01909 void *data,
01910 rk_stub_precall_t precall,
01911 rk_stub_postcall_t postcall)
01912 {
01913 pid_t retval = -1;
01914 int lpc;
01915
01916 require(rk_stub_data.sd_Mode > RK_STUB_MIN);
01917 require(rk_stub_data.sd_Mode < RK_STUB_MAX);
01918
01919 require(name != NULL);
01920
01921
01922 for( lpc = 0; (lpc < MAX_PCB) && (retval == -1); lpc++ )
01923 {
01924 if( !(rk_stub_data.sd_PCBs[lpc].p_Flags & PCBF_IN_USE) )
01925 {
01926 rk_stub_data.sd_PCBs[lpc].p_Name = name;
01927 rk_stub_data.sd_PCBs[lpc].p_Flags |= PCBF_IN_USE;
01928 rk_stub_data.sd_PCBs[lpc].p_Data = data;
01929 rk_stub_data.sd_PCBs[lpc].p_Precall = precall;
01930 rk_stub_data.sd_PCBs[lpc].p_Postcall = postcall;
01931 retval = lpc;
01932 }
01933 }
01934 if( retval == -1 )
01935 {
01936 errno = ENOMEM;
01937 }
01938 return( retval );
01939 }
01940
01941 void rk_stub_getrusage(pid_t pid, struct rusage *ru)
01942 {
01943 require(pid >= 0);
01944 require(pid < MAX_PCB);
01945 require(rk_stub_data.sd_PCBs[pid].p_Flags & PCBF_IN_USE);
01946 require(ru != NULL);
01947
01948 *ru = rk_stub_data.sd_PCBs[pid].p_Usage;
01949 }
01950
01951