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
00558 if( name == NULL )
00559 {
00560 errno = EINVAL;
00561 }
00562 else if( strlen(name) == 0 )
00563 {
00564 errno = EINVAL;
00565 }
00566 else if( strlen(name) >= RSET_NAME_LEN )
00567 {
00568 errno = ENAMETOOLONG;
00569 }
00570 else if( !rk_name_valid(name) )
00571 {
00572 errno = EINVAL;
00573 }
00574 else if( (retval = calloc(1, sizeof(struct rk_resource_set))) != NULL )
00575 {
00576 lnAddTail(&rk_stub_data.sd_ResourceSets, &retval->rs_Link);
00577 strncpy(retval->rs_Name, name, RSET_NAME_LEN);
00578 retval->rs_ProcessID = -1;
00579
00580 ensure(strlen(retval->rs_Name) > 0);
00581 ensure(strlen(retval->rs_Name) < RSET_NAME_LEN);
00582 ensure(strcmp(retval->rs_Name, name) == 0);
00583 ensure(rk_resource_set_valid(retval));
00584 }
00585 else
00586 {
00587 errno = ENOMEM;
00588 }
00589
00590 fprintf(rk_stub_data.sd_LogFile, "END %p = %s\n", retval, __PRETTY_FUNCTION__);
00591
00592 return( retval );
00593 }
00594
00595 int rk_resource_set_destroy(rk_resource_set_t rs)
00596 {
00597 int retval = -1;
00598
00599 require(rk_stub_data.sd_Mode > RK_STUB_MIN);
00600 require(rk_stub_data.sd_Mode < RK_STUB_MAX);
00601
00602 fprintf(rk_stub_data.sd_LogFile, "BEGIN %s(%p%s)\n", __PRETTY_FUNCTION__, rs, rk_resource_set_string(rs));
00603
00604 if( rs == NULL )
00605 {
00606 errno = EINVAL;
00607 }
00608 else if( rk_resource_set_valid(rs) )
00609 {
00610 rk_cpu_reserve_delete(rs);
00611
00612 if( rs->rs_ProcessID != -1 )
00613 {
00614 rk_stub_data.sd_PCBs[rs->rs_ProcessID].p_Resources = NULL;
00615 rs->rs_ProcessID = -1;
00616 }
00617 lnRemove(&rs->rs_Link);
00618 free(rs);
00619 retval = 0;
00620
00621 ensure(!rk_resource_set_valid(rs));
00622 }
00623
00624 fprintf(rk_stub_data.sd_LogFile, "%d END %s\n", retval, __PRETTY_FUNCTION__);
00625
00626 return( retval );
00627 }
00628
00629 int rk_resource_set_set_name(rk_resource_set_t rs, const char *name)
00630 {
00631 int retval = -1;
00632
00633 require(rk_stub_data.sd_Mode > RK_STUB_MIN);
00634 require(rk_stub_data.sd_Mode < RK_STUB_MAX);
00635
00636 fprintf(rk_stub_data.sd_LogFile, "BEGIN %s(%p%s, %s)\n", __PRETTY_FUNCTION__, rs, rk_resource_set_string(rs), name);
00637
00638 if( (rs == NULL) || (name == NULL) )
00639 {
00640 errno = EINVAL;
00641 }
00642 else if( !rk_resource_set_valid(rs) )
00643 {
00644 errno = EINVAL;
00645 }
00646 else if( strlen(name) == 0 )
00647 {
00648 errno = EINVAL;
00649 }
00650 else if( strlen(name) >= RSET_NAME_LEN )
00651 {
00652 errno = ENAMETOOLONG;
00653 }
00654 else if( !rk_name_valid(name) )
00655 {
00656 errno = EINVAL;
00657 }
00658 else
00659 {
00660 strncpy(rs->rs_Name, name, RSET_NAME_LEN);
00661 retval = 0;
00662
00663 ensure(strlen(rs->rs_Name) > 0);
00664 ensure(strlen(rs->rs_Name) < RSET_NAME_LEN);
00665 ensure(strcmp(rs->rs_Name, name) == 0);
00666 }
00667
00668 fprintf(rk_stub_data.sd_LogFile, "END %d = %s\n", retval, __PRETTY_FUNCTION__);
00669
00670 return( retval );
00671 }
00672
00673 int rk_resource_set_get_name(rk_resource_set_t rs, char *name_out)
00674 {
00675 int retval = -1;
00676
00677 require(rk_stub_data.sd_Mode > RK_STUB_MIN);
00678 require(rk_stub_data.sd_Mode < RK_STUB_MAX);
00679
00680 fprintf(rk_stub_data.sd_LogFile, "BEGIN %s(%p%s, %p)\n", __PRETTY_FUNCTION__, rs, rk_resource_set_string(rs), name_out);
00681
00682 if( (rs == NULL) || (name_out == NULL) )
00683 {
00684 errno = EINVAL;
00685 }
00686 else if( !rk_resource_set_valid(rs) )
00687 {
00688 name_out[0] = '\0';
00689 errno = EINVAL;
00690 }
00691 else
00692 {
00693 strcpy(name_out, rs->rs_Name);
00694 retval = 0;
00695
00696 ensure(strlen(name_out) > 0);
00697 ensure(strlen(name_out) < RSET_NAME_LEN);
00698 ensure(strcmp(rs->rs_Name, name_out) == 0);
00699 }
00700
00701 fprintf(rk_stub_data.sd_LogFile, "END %d = %s name_out=%s\n", retval, __PRETTY_FUNCTION__, name_out);
00702
00703 return( retval );
00704 }
00705
00706 rk_reserve_t rk_resource_set_get_cpu_rsv(rk_resource_set_t rs)
00707 {
00708 rk_reserve_t retval = NULL_RESERVE;
00709
00710 require(rk_stub_data.sd_Mode > RK_STUB_MIN);
00711 require(rk_stub_data.sd_Mode < RK_STUB_MAX);
00712
00713 fprintf(rk_stub_data.sd_LogFile, "BEGIN %s(%p%s)\n", __PRETTY_FUNCTION__, rs, rk_resource_set_string(rs));
00714
00715 if( rs == NULL )
00716 {
00717 errno = EINVAL;
00718 }
00719 else if( !rk_resource_set_valid(rs) )
00720 {
00721 errno = EINVAL;
00722 }
00723 else if( rs->rs_CPU == NULL )
00724 {
00725 errno = ENOTCONN;
00726 }
00727 else
00728 {
00729 retval = (rk_reserve_t)rs->rs_CPU;
00730
00731 ensure(cpu_reserve_valid(retval));
00732 }
00733
00734 fprintf(rk_stub_data.sd_LogFile, "END %p = %s\n", retval, __PRETTY_FUNCTION__);
00735
00736 return( retval );
00737 }
00738
00739 int rk_resource_set_attach_process(rk_resource_set_t rs, pid_t pid)
00740 {
00741 int retval = -1;
00742
00743 require(rk_stub_data.sd_Mode > RK_STUB_MIN);
00744 require(rk_stub_data.sd_Mode < RK_STUB_MAX);
00745
00746 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));
00747
00748 if( (rs == NULL) || (pid < 0) )
00749 {
00750 errno = EINVAL;
00751 }
00752 else if( !rk_resource_set_valid(rs) )
00753 {
00754 errno = EINVAL;
00755 }
00756 else if( (rk_stub_data.sd_Mode >= RK_STUB_SIM) &&
00757 ((pid >= MAX_PCB) ||
00758 !(rk_stub_data.sd_PCBs[pid].p_Flags & PCBF_IN_USE)) )
00759 {
00760 errno = ESRCH;
00761 }
00762 else if( rs->rs_ProcessID == -1 )
00763 {
00764 rs->rs_ProcessID = pid;
00765 if( rk_stub_data.sd_Mode >= RK_STUB_SIM )
00766 {
00767 rk_stub_data.sd_PCBs[pid].p_Resources = rs;
00768
00769 ensure(rk_proc_get_rset(pid) == rs);
00770 }
00771 retval = 0;
00772 }
00773 else
00774 {
00775 errno = ENOSYS;
00776 }
00777
00778 fprintf(rk_stub_data.sd_LogFile, "END %d = %s\n", retval, __PRETTY_FUNCTION__);
00779
00780 return( retval );
00781 }
00782
00783 int rk_resource_set_detach_process(rk_resource_set_t rs, pid_t pid)
00784 {
00785 int retval = -1;
00786
00787 require(rk_stub_data.sd_Mode > RK_STUB_MIN);
00788 require(rk_stub_data.sd_Mode < RK_STUB_MAX);
00789
00790 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));
00791
00792 if( (rs == NULL) || (pid < 0) || (pid >= MAX_PCB) )
00793 {
00794 errno = EINVAL;
00795 }
00796 else if( !rk_resource_set_valid(rs) )
00797 {
00798 errno = EINVAL;
00799 }
00800 else if( !(rk_stub_data.sd_PCBs[pid].p_Flags & PCBF_IN_USE) )
00801 {
00802 errno = ESRCH;
00803 }
00804 else if( rs->rs_ProcessID == pid )
00805 {
00806 rk_stub_data.sd_PCBs[pid].p_Resources = NULL;
00807 rs->rs_ProcessID = -1;
00808 retval = 0;
00809
00810 ensure(rk_proc_get_rset(pid) == NULL);
00811 }
00812 else
00813 {
00814 errno = EINVAL;
00815 }
00816
00817 fprintf(rk_stub_data.sd_LogFile, "END %d = %s\n", retval, __PRETTY_FUNCTION__);
00818
00819 return( retval );
00820 }
00821
00822 int rk_resource_set_get_num_procs(rk_resource_set_t rs)
00823 {
00824 int retval = -1;
00825
00826 require(rk_stub_data.sd_Mode > RK_STUB_MIN);
00827 require(rk_stub_data.sd_Mode < RK_STUB_MAX);
00828
00829 fprintf(rk_stub_data.sd_LogFile, "BEGIN %s(%p%s)\n", __PRETTY_FUNCTION__, rs, rk_resource_set_string(rs));
00830
00831 if( rs == NULL_RESOURCE_SET )
00832 {
00833 errno = EINVAL;
00834 }
00835 else
00836 {
00837 if( rs->rs_ProcessID != -1 )
00838 {
00839 retval = 1;
00840 }
00841 else
00842 {
00843 retval = 0;
00844 }
00845 }
00846
00847 fprintf(rk_stub_data.sd_LogFile, "END %d = %s\n", retval, __PRETTY_FUNCTION__);
00848
00849 return( retval );
00850 }
00851
00852 int rk_resource_set_get_proclist(rk_resource_set_t rs,
00853 pid_t *procs_inout,
00854 int count)
00855 {
00856 int retval = -1;
00857
00858 require(rk_stub_data.sd_Mode > RK_STUB_MIN);
00859 require(rk_stub_data.sd_Mode < RK_STUB_MAX);
00860
00861 fprintf(rk_stub_data.sd_LogFile, "BEGIN %s(%p%s, %p, %d)\n", __PRETTY_FUNCTION__, rs, rk_resource_set_string(rs), procs_inout, count);
00862
00863 if( (rs == NULL_RESOURCE_SET) || (procs_inout == NULL) || (count < 0) )
00864 {
00865 errno = EINVAL;
00866 }
00867 else if( count == 0 )
00868 {
00869 retval = 0;
00870 }
00871 else
00872 {
00873 int lpc;
00874
00875 if( rs->rs_ProcessID != -1 )
00876 {
00877 retval = 0;
00878 }
00879 procs_inout[0] = rs->rs_ProcessID;
00880 for( lpc = 1; lpc < count; lpc++ )
00881 {
00882 procs_inout[lpc] = -1;
00883 }
00884 }
00885
00886 fprintf(rk_stub_data.sd_LogFile, "END %d = %s\n", retval, __PRETTY_FUNCTION__);
00887
00888 return( retval );
00889 }
00890
00891 rk_resource_set_t rk_proc_get_rset(pid_t pid)
00892 {
00893 rk_resource_set_t retval = NULL_RESOURCE_SET;
00894
00895 require(rk_stub_data.sd_Mode > RK_STUB_MIN);
00896 require(rk_stub_data.sd_Mode < RK_STUB_MAX);
00897
00898 fprintf(rk_stub_data.sd_LogFile, "BEGIN %s(%d%s)\n", __PRETTY_FUNCTION__, pid, rk_stub_pcb_string(pid));
00899
00900 if( (pid < 0) || (pid >= MAX_PCB) )
00901 {
00902 errno = EINVAL;
00903 }
00904 else if( !(rk_stub_data.sd_PCBs[pid].p_Flags & PCBF_IN_USE) )
00905 {
00906 errno = ESRCH;
00907 }
00908 else if( rk_stub_data.sd_PCBs[pid].p_Resources == NULL )
00909 {
00910 errno = ENOTCONN;
00911 }
00912 else
00913 {
00914 retval = rk_stub_data.sd_PCBs[pid].p_Resources;
00915
00916 ensure(rk_resource_set_valid(retval));
00917 }
00918
00919 fprintf(rk_stub_data.sd_LogFile, "END %p%s = %s\n", retval, rk_resource_set_string(retval), __PRETTY_FUNCTION__);
00920
00921 return( retval );
00922 }
00923
00924 int rk_cpu_reserve_create(rk_resource_set_t rs,
00925 rk_reserve_t *r_out,
00926 cpu_reserve_attr_t ra_in)
00927 {
00928 cpu_reserve_t cr;
00929 int retval = -1;
00930
00931 require(rk_stub_data.sd_Mode > RK_STUB_MIN);
00932 require(rk_stub_data.sd_Mode < RK_STUB_MAX);
00933
00934 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));
00935
00936 if( (rs == NULL) || (r_out == NULL) || (ra_in == NULL) )
00937 {
00938 errno = EINVAL;
00939 }
00940 else if( !rk_resource_set_valid(rs) )
00941 {
00942 errno = EINVAL;
00943 }
00944 else if( !rk_cpu_reserve_attr_valid(ra_in) )
00945 {
00946 errno = EINVAL;
00947 }
00948 else if( (rs->rs_CPU != NULL) )
00949 {
00950 errno = EISCONN;
00951 }
00952 else if( (cr = calloc(1, sizeof(struct cpu_reserve))) != NULL )
00953 {
00954 int lpc;
00955
00956 *r_out = NULL;
00957 rs->rs_CPU = cr;
00958 cr->cr_Attributes = *((cpu_reserve_attr_t)ra_in);
00959 switch( rk_stub_data.sd_Mode )
00960 {
00961 case RK_STUB_LOG:
00962 retval = 0;
00963 break;
00964 case RK_STUB_SIM:
00965 cr->cr_Compute.cr_DataPeriodStart = rk_stub_data.sd_CurrentTime;
00966 cr->cr_Compute.cr_DataPeriodEnd = rk_stub_data.sd_CurrentTime;
00967 cr->cr_Compute.cr_DataPeriodNext = rk_stub_data.sd_CurrentTime;
00968 cr->cr_Compute.cr_TimePeriodStart = rk_stub_data.sd_CurrentTime;
00969 cr->cr_Compute.cr_TimePeriodEnd = rk_stub_data.sd_CurrentTime;
00970 cr->cr_Compute.cr_TimePeriodNext = rk_stub_data.sd_CurrentTime;
00971
00972 retval = 0;
00973 for( lpc = 0; (lpc < RK_CPU_TRACE_MAX) && (retval == 0); lpc++ )
00974 {
00975 char trace_name[RSET_NAME_LEN + 64];
00976
00977 snprintf(trace_name, sizeof(trace_name),
00978 "%s_cpu_%s",
00979 rs->rs_Name,
00980 rk_cpu_trace_names[lpc]);
00981 if( (cr->cr_Trace[lpc] = fopen(trace_name, "w")) != NULL )
00982 {
00983 fprintf(cr->cr_Trace[lpc], "0 0.0\n");
00984 }
00985 else
00986 {
00987 retval = -1;
00988 }
00989
00990 ensure(strlen(trace_name) < sizeof(trace_name));
00991 }
00992 if( retval == 0 )
00993 {
00994 char times_name[RSET_NAME_LEN + 64];
00995 FILE *times_file;
00996
00997
00998 snprintf(times_name, sizeof(times_name),
00999 "%s_cpu_times",
01000 rs->rs_Name);
01001 if( (times_file = fopen(times_name, "r")) != NULL )
01002 {
01003 long long deadline_us;
01004 int done = 0;
01005
01006 deadline_us = timespec_to_microsec(&ra_in->deadline);
01007 cr->cr_Compute.cr_Length = 1;
01008 while( !done && (retval == 0) )
01009 {
01010 struct timespec *ts;
01011
01012 if( (ts = realloc(cr->cr_Compute.cr_Times,
01013 cr->cr_Compute.cr_Length *
01014 sizeof(struct timespec)))
01015 != NULL )
01016 {
01017 float percent;
01018
01019 cr->cr_Compute.cr_Times = ts;
01020 if( (fscanf(times_file, "%f", &percent) == 1) &&
01021 (percent >= 0.0) && (percent <= 120.0) )
01022 {
01023 long long compute_us;
01024
01025
01026
01027
01028
01029
01030
01031 compute_us = (long long)
01032 (((double)deadline_us) *
01033 (percent / 100.0));
01034 cr->cr_Compute.
01035 cr_Times[cr->cr_Compute.cr_TimeIndex] =
01036 microsec_to_timespec(compute_us);
01037 cr->cr_Compute.cr_TimeIndex += 1;
01038 cr->cr_Compute.cr_Length += 1;
01039 }
01040 else if( feof(times_file) )
01041 {
01042
01043 cr->cr_Compute.cr_DataPeriodRemaining =
01044 cr->cr_Compute.cr_Times[0];
01045 cr->cr_Compute.cr_Length -= 1;
01046 cr->cr_Compute.cr_TimeIndex = -1;
01047 done = 1;
01048 }
01049 else
01050 {
01051
01052 #if defined(EFTYPE)
01053 errno = EFTYPE;
01054 #else
01055 errno = EINVAL;
01056 #endif
01057 retval = -1;
01058 }
01059 }
01060 else
01061 {
01062 errno = ENOMEM;
01063 retval = -1;
01064 }
01065 }
01066 if( cr->cr_Compute.cr_Length != 0 )
01067 {
01068
01069 }
01070 else
01071 {
01072
01073 #if defined(EFTYPE)
01074 errno = EFTYPE;
01075 #else
01076 errno = EINVAL;
01077 #endif
01078 retval = -1;
01079 }
01080 fclose(times_file);
01081 }
01082 else
01083 {
01084 retval = -1;
01085 }
01086
01087 ensure(strlen(times_name) < sizeof(times_name));
01088 }
01089 break;
01090 default:
01091 break;
01092 }
01093 if( retval == 0 )
01094 {
01095 *r_out = cr;
01096 }
01097 else
01098 {
01099 rk_cpu_reserve_delete(rs);
01100 }
01101
01102 ensure((*r_out == NULL) || cpu_reserve_valid(*r_out));
01103 }
01104 else
01105 {
01106 errno = ENOMEM;
01107 }
01108
01109 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));
01110
01111 return( retval );
01112 }
01113
01114 int rk_cpu_reserve_delete(rk_resource_set_t rs)
01115 {
01116 int retval = -1;
01117
01118 require(rk_stub_data.sd_Mode > RK_STUB_MIN);
01119 require(rk_stub_data.sd_Mode < RK_STUB_MAX);
01120
01121 fprintf(rk_stub_data.sd_LogFile, "BEGIN %s(%p%s)\n", __PRETTY_FUNCTION__, rs, rk_resource_set_string(rs));
01122
01123 if( rs == NULL )
01124 {
01125 errno = EINVAL;
01126 }
01127 else if( rs->rs_CPU == NULL )
01128 {
01129 errno = ENOTCONN;
01130 }
01131 else if( !rk_resource_set_valid(rs) )
01132 {
01133 errno = EINVAL;
01134 }
01135 else
01136 {
01137 cpu_reserve_t cr;
01138 int lpc;
01139
01140 cr = rs->rs_CPU;
01141 free(cr->cr_Compute.cr_Times);
01142 cr->cr_Compute.cr_Times = NULL;
01143
01144 for( lpc = 0; lpc < RK_CPU_TRACE_MAX; lpc++ )
01145 {
01146
01147
01148
01149
01150 if( cr->cr_Trace[lpc] != NULL )
01151 {
01152 fclose(cr->cr_Trace[lpc]);
01153 cr->cr_Trace[lpc] = NULL;
01154 }
01155 }
01156 free(rs->rs_CPU);
01157 rs->rs_CPU = NULL;
01158 retval = 0;
01159
01160 ensure(!cpu_reserve_valid(cr));
01161 }
01162
01163 fprintf(rk_stub_data.sd_LogFile, "%d END %s\n", retval, __PRETTY_FUNCTION__);
01164
01165 return( retval );
01166 }
01167
01168 int rk_cpu_reserve_get_attr(rk_reserve_t cr, cpu_reserve_attr_t ra_out)
01169 {
01170 int retval = -1;
01171
01172 require(rk_stub_data.sd_Mode > RK_STUB_MIN);
01173 require(rk_stub_data.sd_Mode < RK_STUB_MAX);
01174
01175 fprintf(rk_stub_data.sd_LogFile, "BEGIN %s(%p%s, %p)\n", __PRETTY_FUNCTION__, cr, cpu_reserve_string((cpu_reserve_t)cr), ra_out);
01176
01177 if( (cr == NULL) || (ra_out == NULL) )
01178 {
01179 errno = EINVAL;
01180 }
01181 else if( !cpu_reserve_valid(cr) )
01182 {
01183 errno = EINVAL;
01184 }
01185 else
01186 {
01187 *ra_out = ((cpu_reserve_t)cr)->cr_Attributes;
01188 retval = 0;
01189
01190 ensure(rk_cpu_reserve_attr_valid(ra_out));
01191 }
01192
01193 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));
01194
01195 return( retval );
01196 }
01197
01198 int rk_cpu_reserve_ctl(rk_resource_set_t rs, cpu_reserve_attr_t ra_in)
01199 {
01200 int retval = -1;
01201
01202 require(rk_stub_data.sd_Mode > RK_STUB_MIN);
01203 require(rk_stub_data.sd_Mode < RK_STUB_MAX);
01204
01205 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));
01206
01207 if( (rs == NULL) || (ra_in == NULL) )
01208 {
01209 errno = EINVAL;
01210 }
01211 else if( !rk_resource_set_valid(rs) )
01212 {
01213 errno = EINVAL;
01214 }
01215 else if( !rk_cpu_reserve_attr_valid(ra_in) )
01216 {
01217 errno = ENOSPC;
01218 }
01219 else if( rs->rs_CPU == NULL )
01220 {
01221 errno = ENOTCONN;
01222 }
01223 else
01224 {
01225 cpu_reserve_t cr;
01226
01227 cr = rs->rs_CPU;
01228
01229 if( (cr->cr_Flags & CRF_RUNNING) &&
01230 tscmp(&cr->cr_Compute.cr_TimePeriodEnd,
01231 &rk_stub_data.sd_CurrentTime,
01232 !=) &&
01233 tscmp(&cr->cr_Compute.cr_DataPeriodEnd,
01234 &rk_stub_data.sd_CurrentTime,
01235 !=) )
01236 {
01237 rk_cpu_reserve_tick(rs,
01238 cr,
01239 &rk_stub_data.sd_CurrentTime,
01240 &rk_stub_data.sd_NextTime,
01241 &ra_in->compute_time);
01242 if( !(rk_stub_data.sd_Flags & SDF_IN_TICK) )
01243 {
01244 rk_stub_data.sd_CurrentTime = rk_stub_data.sd_NextTime;
01245 }
01246 }
01247 cr->cr_Attributes = *ra_in;
01248 retval = 0;
01249 }
01250
01251 fprintf(rk_stub_data.sd_LogFile, "END %d = %s\n", retval, __PRETTY_FUNCTION__);
01252
01253 return( retval );
01254 }
01255
01256 int rk_clock_gettime(clockid_t clock_id, struct timespec *ts)
01257 {
01258 int retval = -1;
01259
01260 if( clock_id != CLOCK_REALTIME )
01261 {
01262 errno = EINVAL;
01263 }
01264 else if( ts == NULL )
01265 {
01266 errno = EINVAL;
01267 }
01268 else
01269 {
01270 *ts = rk_stub_data.sd_CurrentTime;
01271 retval = 0;
01272 }
01273 return( retval );
01274 }
01275
01276 int rk_clock_settime(clockid_t clock_id, struct timespec *ts)
01277 {
01278 int retval = -1;
01279
01280 if( clock_id != CLOCK_REALTIME )
01281 {
01282 errno = EINVAL;
01283 }
01284 else if( ts == NULL )
01285 {
01286 errno = EINVAL;
01287 }
01288 else
01289 {
01290 rk_stub_data.sd_CurrentTime = *ts;
01291 retval = 0;
01292 }
01293 return( retval );
01294 }
01295
01296 int rk_clock_getres(clockid_t clock_id, struct timespec *ts)
01297 {
01298 int retval = -1;
01299
01300 if( clock_id != CLOCK_REALTIME )
01301 {
01302 errno = EINVAL;
01303 }
01304 else if( ts == NULL )
01305 {
01306 errno = EINVAL;
01307 }
01308 else
01309 {
01310 ts->tv_sec = 0;
01311 ts->tv_nsec = NANOS_PER_MICRO;
01312 retval = 0;
01313 }
01314 return( retval );
01315 }
01316
01317
01318
01319
01320
01321 void rk_stub_set_mode(rk_stub_mode_t mode)
01322 {
01323 require(mode > RK_STUB_MIN);
01324 require(mode < RK_STUB_MAX);
01325
01326 require(rk_stub_data.sd_Mode == RK_STUB_MIN);
01327
01328 rk_stub_data.sd_Mode = mode;
01329
01330 lnNewList(&rk_stub_data.sd_ResourceSets);
01331 if( (rk_stub_data.sd_LogFile = fopen("rk.log", "w")) == NULL )
01332 {
01333 perror("Cannot open log file.");
01334 exit(EXIT_FAILURE);
01335 }
01336 setvbuf(rk_stub_data.sd_LogFile, NULL, _IONBF, 0);
01337 }
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347 static
01348 void rk_next_tick(struct timespec *next,
01349 struct timespec *curr,
01350 struct timespec *new_next)
01351 {
01352 require(next != NULL);
01353 require(curr != NULL);
01354 require(new_next != NULL);
01355
01356 if( ((int)new_next->tv_nsec) < 0 )
01357 {
01358 require(0);
01359 }
01360 if( tscmp(curr, new_next, ==) )
01361 {
01362
01363 }
01364 else if( tscmp(new_next, next, <) )
01365 {
01366 *next = *new_next;
01367 }
01368 }
01369
01370 static
01371 void rk_cpu_reserve_tick(rk_resource_set_t rs,
01372 cpu_reserve_t cr,
01373 struct timespec *curr,
01374 struct timespec *next,
01375 struct timespec *new_compute)
01376 {
01377 long long time_period_start_us, time_period_end_us, time_period_next_us;
01378 long long data_period_start_us, data_period_end_us, data_period_next_us;
01379 long long curr_us, given_compute_us, given_period_us, given_deadline_us;
01380 long long needed_compute_us, data_period_remaining_us;
01381 float given_cpu_percent, needed_cpu_percent;
01382 struct rk_stub_pcb *proc;
01383
01384 require(rs != NULL);
01385 require(cr != NULL);
01386 require(curr != NULL);
01387 require(next != NULL);
01388
01389 proc = &rk_stub_data.sd_PCBs[rs->rs_ProcessID];
01390
01391 fprintf(cr->cr_Trace[RK_CPU_TRACE_COMPUTE_FAIL],
01392 "# tick %p %d.%ld rem %d.%ld\n",
01393 rs,
01394 (int)curr->tv_sec,
01395 curr->tv_nsec,
01396 (int)cr->cr_Compute.cr_DataPeriodRemaining.tv_sec,
01397 cr->cr_Compute.cr_DataPeriodRemaining.tv_nsec);
01398
01399 curr_us = timespec_to_microsec(curr);
01400
01401 given_compute_us = timespec_to_microsec(&cr->cr_Attributes.compute_time);
01402 given_period_us = timespec_to_microsec(&cr->cr_Attributes.period);
01403 given_deadline_us = timespec_to_microsec(&cr->cr_Attributes.deadline);
01404
01405 given_cpu_percent = (((float)given_compute_us) /
01406 ((float)given_deadline_us));
01407
01408 needed_compute_us = timespec_to_microsec(
01409 &cr->cr_Compute.cr_Times[(cr->cr_Compute.cr_DataIndex) %
01410 (cr->cr_Compute.cr_Length)]);
01411
01412 time_period_start_us =
01413 timespec_to_microsec(&cr->cr_Compute.cr_TimePeriodStart);
01414 time_period_end_us =
01415 timespec_to_microsec(&cr->cr_Compute.cr_TimePeriodEnd);
01416 time_period_next_us =
01417 timespec_to_microsec(&cr->cr_Compute.cr_TimePeriodNext);
01418 data_period_start_us =
01419 timespec_to_microsec(&cr->cr_Compute.cr_DataPeriodStart);
01420 data_period_end_us =
01421 timespec_to_microsec(&cr->cr_Compute.cr_DataPeriodEnd);
01422 data_period_next_us =
01423 timespec_to_microsec(&cr->cr_Compute.cr_DataPeriodNext);
01424 data_period_remaining_us =
01425 timespec_to_microsec(&cr->cr_Compute.cr_DataPeriodRemaining);
01426
01427 needed_cpu_percent = (((float)data_period_remaining_us) /
01428 ((float)given_deadline_us));
01429
01430 if( cr->cr_Flags & CRF_RUNNING )
01431 {
01432 if( curr_us == data_period_end_us )
01433 {
01434 struct timeval tv;
01435
01436 if( cr->cr_Compute.cr_DataIndex == cr->cr_Compute.cr_TimeIndex )
01437 {
01438 cr->cr_Flags &= ~CRF_RUNNING;
01439
01440 fprintf(cr->cr_Trace[RK_CPU_TRACE_COMPUTE_SUCCESS],
01441 "# line %d\n"
01442 "%qd 0\n",
01443 __LINE__,
01444 curr_us / 1000);
01445 fprintf(cr->cr_Trace[RK_CPU_TRACE_COMPUTE_FAIL],
01446 "# line %d\n"
01447 "%qd 0\n",
01448 __LINE__,
01449 curr_us / 1000);
01450 }
01451 else
01452 {
01453 fprintf(cr->cr_Trace[RK_CPU_TRACE_COMPUTE_FAIL],
01454 "# line %d next %d.%ld ind %d %d\n"
01455 "%qd %f\n"
01456 "%qd 0\n",
01457 __LINE__,
01458 (int)cr->cr_Compute.cr_DataPeriodNext.tv_sec,
01459 cr->cr_Compute.cr_DataPeriodNext.tv_nsec,
01460 cr->cr_Compute.cr_DataIndex + 1,
01461 cr->cr_Compute.cr_TimeIndex,
01462 (curr_us / 1000) - 1,
01463 given_cpu_percent * 100.0,
01464 curr_us / 1000);
01465 fprintf(cr->cr_Trace[RK_CPU_TRACE_COMPUTE_SUCCESS],
01466 "# line %d\n"
01467 "%qd 0\n",
01468 __LINE__,
01469 curr_us / 1000);
01470 }
01471
01472 tv.tv_sec = timespec_to_microsec(
01473 &cr->cr_Compute.cr_Times[(cr->cr_Compute.cr_DataIndex) %
01474 (cr->cr_Compute.cr_Length)]) / 1000000;
01475 tv.tv_usec = timespec_to_microsec(
01476 &cr->cr_Compute.cr_Times[(cr->cr_Compute.cr_DataIndex) %
01477 (cr->cr_Compute.cr_Length)]) % 1000000;
01478 timeradd(&proc->p_Usage.ru_utime, &tv, &proc->p_Usage.ru_utime);
01479 proc->p_Postcall(rk_stub_data.sd_PCBs[rs->rs_ProcessID].p_Data);
01480 fprintf(cr->cr_Trace[RK_CPU_TRACE_COMPLETE],
01481 "# %d\n"
01482 "%qd -5\n",
01483 cr->cr_Compute.cr_DataIndex,
01484 curr_us / 1000);
01485 cr->cr_Compute.cr_DataIndex += 1;
01486
01487 cr->cr_Compute.cr_DataPeriodRemaining =
01488 cr->cr_Compute.cr_Times[(cr->cr_Compute.cr_DataIndex) %
01489 (cr->cr_Compute.cr_Length)];
01490
01491 if( cr->cr_Flags & CRF_RUNNING )
01492 {
01493
01494 needed_compute_us = timespec_to_microsec(
01495 &cr->cr_Compute.
01496 cr_Times[(cr->cr_Compute.cr_DataIndex) %
01497 (cr->cr_Compute.cr_Length)]);
01498
01499 needed_cpu_percent = (((float)needed_compute_us) /
01500 ((float)given_deadline_us));
01501 }
01502 }
01503 if( curr_us == time_period_end_us )
01504 {
01505 if( cr->cr_Compute.cr_DataIndex == cr->cr_Compute.cr_TimeIndex )
01506 {
01507 fprintf(cr->cr_Trace[RK_CPU_TRACE_COMPUTE_FAIL],
01508 "# line %d\n"
01509 "%qd 0\n",
01510 __LINE__,
01511 curr_us / 1000);
01512 fprintf(cr->cr_Trace[RK_CPU_TRACE_COMPUTE_SUCCESS],
01513 "# line %d\n"
01514 "%qd 0\n",
01515 __LINE__,
01516 curr_us / 1000);
01517 }
01518 }
01519 }
01520 if( curr_us == time_period_end_us )
01521 {
01522 fprintf(cr->cr_Trace[RK_CPU_TRACE_DEADLINE],
01523 "# line %d\n"
01524 "%qd 120\n",
01525 __LINE__,
01526 curr_us / 1000);
01527 if( (cr->cr_Flags & CRF_RUNNING) &&
01528 (cr->cr_Compute.cr_DataIndex < cr->cr_Compute.cr_TimeIndex) )
01529 {
01530 fprintf(cr->cr_Trace[RK_CPU_TRACE_COMPUTE_FAIL],
01531 "# line %d\n"
01532 "%qd 0\n",
01533 __LINE__,
01534 curr_us / 1000);
01535 fprintf(cr->cr_Trace[RK_CPU_TRACE_COMPUTE_SUCCESS],
01536 "# line %d\n"
01537 "%qd 0\n",
01538 __LINE__,
01539 curr_us / 1000);
01540 }
01541 if( (cr->cr_Flags & CRF_RUNNING) && (curr_us != data_period_end_us) )
01542 {
01543 fprintf(cr->cr_Trace[RK_CPU_TRACE_COMPUTE_FAIL],
01544 "# line %d %qd -= %qd max(%qd, %qd) * %f\n",
01545 __LINE__,
01546 data_period_remaining_us,
01547 curr_us,
01548 time_period_start_us,
01549 data_period_start_us,
01550 given_cpu_percent);
01551 data_period_remaining_us -=
01552 (curr_us - max(time_period_start_us, data_period_start_us)) *
01553 given_cpu_percent;
01554 if( data_period_remaining_us < 0 )
01555 {
01556 data_period_remaining_us = 0;
01557 }
01558 cr->cr_Compute.cr_DataPeriodRemaining =
01559 microsec_to_timespec(data_period_remaining_us);
01560 fprintf(cr->cr_Trace[RK_CPU_TRACE_COMPUTE_FAIL],
01561 "# sub line %d %d.%ld\n",
01562 __LINE__,
01563 (int)cr->cr_Compute.cr_DataPeriodRemaining.tv_sec,
01564 cr->cr_Compute.cr_DataPeriodRemaining.tv_nsec);
01565 }
01566
01567 cr->cr_Flags &= ~CRF_RUNNING;
01568
01569 cr->cr_Compute.cr_TimeIndex += 1;
01570 }
01571
01572 if( curr_us == time_period_next_us )
01573 {
01574 long long realtime_compute_us;
01575 float realtime_cpu_percent;
01576
01577 cr->cr_Flags |= CRF_RUNNING;
01578
01579 realtime_compute_us = timespec_to_microsec(
01580 &cr->cr_Compute.cr_Times[(cr->cr_Compute.cr_TimeIndex) %
01581 (cr->cr_Compute.cr_Length)]);
01582
01583 realtime_cpu_percent = (((float)realtime_compute_us) /
01584 ((float)given_deadline_us));
01585
01586 fprintf(cr->cr_Trace[RK_CPU_TRACE_PERIOD],
01587 "# line %d\n"
01588 "%qd 120\n",
01589 __LINE__,
01590 curr_us / 1000);
01591 fprintf(cr->cr_Trace[RK_CPU_TRACE_REALTIME],
01592 "# line %d\n"
01593 "%qd %f\n"
01594 "%qd 0\n",
01595 __LINE__,
01596 curr_us / 1000,
01597 realtime_cpu_percent * 100.0,
01598 (curr_us + given_deadline_us) / 1000);
01599 if( cr->cr_Compute.cr_DataIndex < cr->cr_Compute.cr_TimeIndex )
01600 {
01601 fprintf(cr->cr_Trace[RK_CPU_TRACE_COMPUTE_FAIL],
01602 "# line %d\n"
01603 "%qd %f\n",
01604 __LINE__,
01605 curr_us / 1000,
01606 given_cpu_percent * 100.0);
01607 fprintf(cr->cr_Trace[RK_CPU_TRACE_COMPUTE_SUCCESS],
01608 "# line %d\n"
01609 "%qd 0\n",
01610 __LINE__,
01611 curr_us / 1000);
01612 }
01613
01614 cr->cr_Compute.cr_TimePeriodStart = *curr;
01615 cr->cr_Compute.cr_TimePeriodEnd = microsec_to_timespec(
01616 curr_us + given_deadline_us);
01617 cr->cr_Compute.cr_TimePeriodNext =
01618 microsec_to_timespec(time_period_next_us + given_period_us);
01619 }
01620
01621 if( (curr_us == data_period_next_us) || (new_compute != NULL) )
01622 {
01623 float period_used, needed_periods, floored_periods;
01624
01625 if( new_compute == NULL )
01626 {
01627 rk_stub_precall_t precall;
01628
01629 precall = rk_stub_data.sd_PCBs[rs->rs_ProcessID].p_Precall;
01630 if( precall != NULL )
01631 {
01632 void *proc_data;
01633
01634 proc_data = rk_stub_data.sd_PCBs[rs->rs_ProcessID].p_Data;
01635 while( (cr->cr_Compute.cr_DataIndex <=
01636 cr->cr_Compute.cr_TimeIndex) &&
01637 (precall(proc_data) == RKSP_DROP) )
01638 {
01639 fprintf(cr->cr_Trace[RK_CPU_TRACE_DROP],
01640 "# line %d\n"
01641 "%qd -2\n",
01642 __LINE__,
01643 curr_us / 1000);
01644 cr->cr_Compute.cr_DataIndex += 1;
01645 }
01646 if( cr->cr_Compute.cr_DataIndex <=
01647 cr->cr_Compute.cr_TimeIndex )
01648 {
01649 cr->cr_Compute.cr_DataPeriodRemaining =
01650 cr->cr_Compute.cr_Times[(cr->cr_Compute.cr_DataIndex) %
01651 (cr->cr_Compute.cr_Length)];
01652
01653 needed_compute_us = timespec_to_microsec(
01654 &cr->cr_Compute.
01655 cr_Times[(cr->cr_Compute.cr_DataIndex) %
01656 (cr->cr_Compute.cr_Length)]);
01657 needed_cpu_percent = (((float)needed_compute_us) /
01658 ((float)given_deadline_us));
01659 }
01660 else
01661 {
01662 cr->cr_Flags &= ~CRF_RUNNING;
01663
01664 cr->cr_Compute.cr_DataPeriodNext =
01665 cr->cr_Compute.cr_TimePeriodNext;
01666 goto reeval;
01667 }
01668 }
01669 }
01670 else
01671 {
01672 data_period_remaining_us =
01673 timespec_to_microsec(&cr->cr_Compute.cr_DataPeriodRemaining);
01674 fprintf(cr->cr_Trace[RK_CPU_TRACE_COMPUTE_FAIL],
01675 "# line %d %qd -= %qd - max(%qd, %qd) * %f\n",
01676 __LINE__,
01677 data_period_remaining_us,
01678 curr_us,
01679 time_period_start_us,
01680 data_period_start_us,
01681 given_cpu_percent);
01682 data_period_remaining_us -=
01683 (curr_us - max(time_period_start_us, data_period_start_us)) *
01684 given_cpu_percent;
01685 cr->cr_Compute.cr_DataPeriodRemaining =
01686 microsec_to_timespec(data_period_remaining_us);
01687 needed_cpu_percent = (((float)data_period_remaining_us) /
01688 ((float)given_deadline_us));
01689 }
01690
01691 if( new_compute == NULL )
01692 {
01693 given_compute_us =
01694 timespec_to_microsec(&cr->cr_Attributes.compute_time);
01695 }
01696 else
01697 {
01698 given_compute_us = timespec_to_microsec(new_compute);
01699 }
01700 given_period_us = timespec_to_microsec(&cr->cr_Attributes.period);
01701 given_deadline_us = timespec_to_microsec(&cr->cr_Attributes.deadline);
01702
01703 given_cpu_percent = (((float)given_compute_us) /
01704 ((float)given_deadline_us));
01705
01706 if( given_cpu_percent == 0.0 )
01707 {
01708 cr->cr_Compute.cr_DataPeriodEnd = (struct timespec){
01709 LONG_MAX,
01710 LONG_MAX
01711 };
01712 cr->cr_Compute.cr_DataPeriodNext = (struct timespec){
01713 LONG_MAX,
01714 LONG_MAX
01715 };
01716 fprintf(cr->cr_Trace[RK_CPU_TRACE_COMPUTE_SUCCESS],
01717 "# line %d\n"
01718 "%qd 0\n",
01719 __LINE__,
01720 curr_us / 1000);
01721 fprintf(cr->cr_Trace[RK_CPU_TRACE_COMPUTE_FAIL],
01722 "# line %d\n"
01723 "%qd 0\n",
01724 __LINE__,
01725 curr_us / 1000);
01726 return;
01727 }
01728
01729 time_period_start_us =
01730 timespec_to_microsec(&cr->cr_Compute.cr_TimePeriodStart);
01731 period_used = (((float)(curr_us - time_period_start_us)) /
01732 ((float)given_deadline_us));
01733 fprintf(cr->cr_Trace[RK_CPU_TRACE_COMPUTE_FAIL],
01734 "# line %d %f + %f / %f\n",
01735 __LINE__,
01736 period_used,
01737 needed_cpu_percent,
01738 given_cpu_percent);
01739 if( needed_cpu_percent == 0.0 )
01740 {
01741 needed_periods = 0.0;
01742 floored_periods = 0.0;
01743 cr->cr_Compute.cr_DataPeriodEnd = *curr;
01744 cr->cr_Compute.cr_DataPeriodEnd.tv_nsec += NANOS_PER_MICRO;
01745 }
01746 else
01747 {
01748 needed_periods = period_used +
01749 (needed_cpu_percent / given_cpu_percent);
01750 floored_periods = floorf(needed_periods);
01751 if( needed_periods == floored_periods )
01752 {
01753 floored_periods -= 1.0;
01754 }
01755 cr->cr_Compute.cr_DataPeriodStart = *curr;
01756 fprintf(cr->cr_Trace[RK_CPU_TRACE_COMPUTE_FAIL],
01757 "# line %d %d.%ld\n",
01758 __LINE__,
01759 (int)cr->cr_Compute.cr_DataPeriodStart.tv_sec,
01760 cr->cr_Compute.cr_DataPeriodStart.tv_nsec);
01761 fprintf(cr->cr_Trace[RK_CPU_TRACE_COMPUTE_FAIL],
01762 "# line %d %qd + (%qd * %f) + (%qd * (%f - %f))\n",
01763 __LINE__,
01764 time_period_start_us,
01765 given_period_us,
01766 floored_periods,
01767 given_deadline_us,
01768 needed_periods,
01769 floored_periods);
01770 cr->cr_Compute.cr_DataPeriodEnd = microsec_to_timespec(
01771 time_period_start_us +
01772 (given_period_us * floored_periods) +
01773 (given_deadline_us * (needed_periods - floored_periods)));
01774 }
01775
01776 if( needed_periods <= 1.0 )
01777 {
01778 if( needed_periods == 1.0 )
01779 {
01780
01781 cr->cr_Compute.cr_DataPeriodEnd =
01782 cr->cr_Compute.cr_TimePeriodEnd;
01783 }
01784 if( cr->cr_Compute.cr_DataIndex == cr->cr_Compute.cr_TimeIndex )
01785 {
01786 cr->cr_Compute.cr_DataPeriodNext =
01787 cr->cr_Compute.cr_TimePeriodNext;
01788 fprintf(cr->cr_Trace[RK_CPU_TRACE_COMPUTE_SUCCESS],
01789 "# line %d end %d.%ld\n"
01790 "%qd %f\n",
01791 __LINE__,
01792 (int)cr->cr_Compute.cr_DataPeriodEnd.tv_sec,
01793 cr->cr_Compute.cr_DataPeriodEnd.tv_nsec,
01794 curr_us / 1000,
01795 given_cpu_percent * 100.0);
01796 fprintf(cr->cr_Trace[RK_CPU_TRACE_COMPUTE_FAIL],
01797 "# line %d\n"
01798 "%qd 0\n",
01799 __LINE__,
01800 curr_us / 1000);
01801 }
01802 else
01803 {
01804 cr->cr_Compute.cr_DataPeriodNext =
01805 cr->cr_Compute.cr_DataPeriodEnd;
01806 fprintf(cr->cr_Trace[RK_CPU_TRACE_COMPUTE_FAIL],
01807 "# line %d end %d.%ld\n"
01808 "%qd %f\n",
01809 __LINE__,
01810 (int)cr->cr_Compute.cr_DataPeriodEnd.tv_sec,
01811 cr->cr_Compute.cr_DataPeriodEnd.tv_nsec,
01812 curr_us / 1000,
01813 given_cpu_percent * 100.0);
01814 fprintf(cr->cr_Trace[RK_CPU_TRACE_COMPUTE_SUCCESS],
01815 "# line %d\n"
01816 "%qd 0\n",
01817 __LINE__,
01818 curr_us / 1000);
01819 }
01820 }
01821 else if( !(cr->cr_Flags & CRF_RUNNING) )
01822 {
01823 cr->cr_Compute.cr_DataPeriodNext =
01824 cr->cr_Compute.cr_TimePeriodNext;
01825 }
01826 else
01827 {
01828 cr->cr_Compute.cr_DataPeriodNext = cr->cr_Compute.cr_DataPeriodEnd;
01829
01830 fprintf(cr->cr_Trace[RK_CPU_TRACE_COMPUTE_FAIL],
01831 "# line %d\n"
01832 "%qd %f\n",
01833 __LINE__,
01834 curr_us / 1000,
01835 given_cpu_percent * 100.0);
01836 fprintf(cr->cr_Trace[RK_CPU_TRACE_COMPUTE_SUCCESS],
01837 "# line %d\n"
01838 "%qd 0\n",
01839 __LINE__,
01840 curr_us / 1000);
01841 }
01842
01843 }
01844
01845 reeval:
01846
01847 fprintf(cr->cr_Trace[RK_CPU_TRACE_COMPUTE_FAIL],
01848 "# line %d\n"
01849 "# data end %d.%ld next %d.%ld\n"
01850 "# time end %d.%ld next %d.%ld\n",
01851 __LINE__,
01852 (int)cr->cr_Compute.cr_DataPeriodEnd.tv_sec,
01853 cr->cr_Compute.cr_DataPeriodEnd.tv_nsec,
01854 (int)cr->cr_Compute.cr_DataPeriodNext.tv_sec,
01855 cr->cr_Compute.cr_DataPeriodNext.tv_nsec,
01856 (int)cr->cr_Compute.cr_TimePeriodEnd.tv_sec,
01857 cr->cr_Compute.cr_TimePeriodEnd.tv_nsec,
01858 (int)cr->cr_Compute.cr_TimePeriodNext.tv_sec,
01859 cr->cr_Compute.cr_TimePeriodNext.tv_nsec);
01860
01861 rk_next_tick(next, curr, &cr->cr_Compute.cr_TimePeriodEnd);
01862 rk_next_tick(next, curr, &cr->cr_Compute.cr_TimePeriodNext);
01863 if( cr->cr_Flags & CRF_RUNNING )
01864 {
01865 rk_next_tick(next, curr, &cr->cr_Compute.cr_DataPeriodEnd);
01866 }
01867 rk_next_tick(next, curr, &cr->cr_Compute.cr_DataPeriodNext);
01868
01869 fprintf(cr->cr_Trace[RK_CPU_TRACE_COMPUTE_FAIL],
01870 "# line %d next %d.%ld\n",
01871 __LINE__,
01872 (int)next->tv_sec,
01873 next->tv_nsec);
01874
01875 ensure(timespec_to_microsec(curr) < timespec_to_microsec(next));
01876 }
01877
01878 void rk_stub_next_tick(void)
01879 {
01880 rk_resource_set_t rs;
01881
01882 require(rk_stub_data.sd_Mode > RK_STUB_MIN);
01883 require(rk_stub_data.sd_Mode < RK_STUB_MAX);
01884
01885 rk_stub_data.sd_Flags |= SDF_IN_TICK;
01886 rk_stub_data.sd_CurrentTime = rk_stub_data.sd_NextTime;
01887 rk_stub_data.sd_NextTime.tv_sec = LONG_MAX;
01888 rk_stub_data.sd_NextTime.tv_nsec = LONG_MAX;
01889
01890 rs = (rk_resource_set_t)rk_stub_data.sd_ResourceSets.lh_Head;
01891 while( rs->rs_Link.ln_Succ != NULL )
01892 {
01893 if( (rs->rs_CPU != NULL) && (rs->rs_ProcessID != -1) )
01894 {
01895 rk_cpu_reserve_tick(rs,
01896 rs->rs_CPU,
01897 &rk_stub_data.sd_CurrentTime,
01898 &rk_stub_data.sd_NextTime,
01899 NULL);
01900 }
01901 rs = (rk_resource_set_t)rs->rs_Link.ln_Succ;
01902 }
01903 rk_stub_data.sd_Flags &= ~SDF_IN_TICK;
01904
01905 ensure(timespec_to_microsec(&rk_stub_data.sd_CurrentTime) <
01906 timespec_to_microsec(&rk_stub_data.sd_NextTime));
01907 }
01908
01909 pid_t rk_stub_mk_pid(const char *name,
01910 void *data,
01911 rk_stub_precall_t precall,
01912 rk_stub_postcall_t postcall)
01913 {
01914 pid_t retval = -1;
01915 int lpc;
01916
01917 require(rk_stub_data.sd_Mode > RK_STUB_MIN);
01918 require(rk_stub_data.sd_Mode < RK_STUB_MAX);
01919
01920 require(name != NULL);
01921
01922
01923 for( lpc = 0; (lpc < MAX_PCB) && (retval == -1); lpc++ )
01924 {
01925 if( !(rk_stub_data.sd_PCBs[lpc].p_Flags & PCBF_IN_USE) )
01926 {
01927 rk_stub_data.sd_PCBs[lpc].p_Name = name;
01928 rk_stub_data.sd_PCBs[lpc].p_Flags |= PCBF_IN_USE;
01929 rk_stub_data.sd_PCBs[lpc].p_Data = data;
01930 rk_stub_data.sd_PCBs[lpc].p_Precall = precall;
01931 rk_stub_data.sd_PCBs[lpc].p_Postcall = postcall;
01932 retval = lpc;
01933 }
01934 }
01935 if( retval == -1 )
01936 {
01937 errno = ENOMEM;
01938 }
01939 return( retval );
01940 }
01941
01942 void rk_stub_getrusage(pid_t pid, struct rusage *ru)
01943 {
01944 require(pid >= 0);
01945 require(pid < MAX_PCB);
01946 require(rk_stub_data.sd_PCBs[pid].p_Flags & PCBF_IN_USE);
01947 require(ru != NULL);
01948
01949 *ru = rk_stub_data.sd_PCBs[pid].p_Usage;
01950 }
01951
01952