Main Page | Namespace List | Class Hierarchy | Class List | File List | Namespace Members | Class Members | File Members

rk_stub.c

Go to the documentation of this file.
00001 /*
00002  * rk_stub.c
00003  *
00004  * Copyright (c) 2003 The University of Utah and the Flux Group.
00005  * All rights reserved.
00006  *
00007  * This file is licensed under the terms of the GNU Public License.  
00008  * See the file "license.terms" for restrictions on redistribution 
00009  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
00010  */
00011 
00012 /**
00013  * @file rk_stub.c
00014  *
00015  * The implementation of the resource kernel (rk) simulator.
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 /* Macros */
00035 
00036 #if !defined(max)
00037 /** Return the maximum of two values. */
00038 #define max(x, y) \
00039         ((x) > (y) ? (x) : (y))
00040 #endif
00041 
00042 #if !defined(min)
00043 /** Return the minimum of two values. */
00044 #define min(x, y) \
00045         ((x) < (y) ? (x) : (y))
00046 #endif
00047 
00048 /* Static data */
00049 
00050 /** Global data for the rk_stub functions. */
00051 struct rk_stub_data rk_stub_data;
00052 
00053 /* Static function protos */
00054 
00055 /**
00056  * Function used to advance simulated time.
00057  *
00058  * @param rs The resource set that has processes that will consume resources.
00059  * @param cr The cpu_reserve_t of the resource set.
00060  * @param curr The current time.
00061  * @param next The next time a simulated event will occur.
00062  * @param new_compute NULL or the resource set's new computation time.
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 /** The string forms of the trace file enumeration. */
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 /* BEGIN validation functions **/
00083 
00084 /**
00085  * Validate a user provided name value.  Currently, the only test is whether or
00086  * not the name is printable.
00087  *
00088  * @param name The name to validate.
00089  * @return True if the parameter is valid, false otherwise.
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  * Validate a user provided rk_reserve_mode_t value.  The only valid values
00106  * are listed in the enumeration.
00107  *
00108  * @param rm The rk_reserve_mode_t to validate.
00109  * @return True if the parameter is valid, false otherwise.
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  * Validate a user provided rk_reserve_param_t value.  A valid
00131  * rk_reserve_param_t must have the following attributes:
00132  *
00133  * @li rk_reserve_mode_valid(sch_mode) == 1
00134  * @li rk_reserve_mode_valid(enf_mode) == 1
00135  * @li rk_reserve_mode_valid(rep_mode) == 1
00136  *
00137  * @param rp The rk_reserve_param_t to validate.
00138  * @return True if the parameter is valid, false otherwise.
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  * Validate a user provided cpu_reserve_attr_t value.  A valid reserve must
00155  * have the following attributes:
00156  *
00157  * @li period >= RT_MIN_PERIOD
00158  * @li compute_time <= deadline
00159  * @li deadline > 0
00160  * @li deadline <= period
00161  * @li rk_reserve_param_valid(reserve_type) == 1
00162  *
00163  * @param ra_in The cpu_reserve_attr_t to validate.
00164  * @return True if the parameter is valid, false otherwise.
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  * Validate a user provided cpu_reserve_t value.  Validation is done by
00188  * checking the pointer against the internal list of resource sets.
00189  *
00190  * @param cr The cpu_reserve_t to validate.
00191  * @return True if the parameter is valid, false otherwise.
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  * Validate a user provided rk_resource_set_t value.  Validation is done by
00214  * checking the pointer against the internal list of resource sets.
00215  *
00216  * @param rs The rk_resource_set_t to validate.
00217  * @return True if the parameter is valid, false otherwise.
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 /* END validation functions **/
00239 
00240 /* BEGIN object -> string functions **/
00241 
00242 /**
00243  * Get the string version of an rk_reserve_mode_t value.
00244  *
00245  * @param rm The rk_reserve_mode_t to stringify.
00246  * @return A statically allocated string that corresponds to the parameter.
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  * Get the string version of an rk_reserve_param_t value.
00272  *
00273  * @param rp The rk_reserve_param_t to stringify or NULL.
00274  * @return A statically allocated string formatted with the values in the
00275  *         parameter.
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  * Get the string version of a cpu_reserve_attr_t value.
00299  *
00300  * @param ra The cpu_reserve_attr_t to stringify or NULL.
00301  * @return A statically allocated string formatted with the values in the
00302  *         parameter.
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  * Get the string version of a cpu_reserve_t value.
00341  *
00342  * @param cr The cpu_reserve_t to stringify or NULL.
00343  * @return A statically allocated string formatted with the values in the
00344  *         parameter.
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" // XXX
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  * Get the string version of a rk_resource_set_t value.
00394  *
00395  * @param rs The rk_resource_set_t to stringify or NULL.
00396  * @return A statically allocated string formatted with the values in the
00397  *         parameter.
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  * Get the string version of a simulated pid_t value.
00423  *
00424  * @param pid The simulated pid_t to stringify.
00425  * @return A statically allocated string formatted with the values in the
00426  *         parameter.
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 /* END object -> string functions **/
00464 
00465 /* BEGIN rk functions **/
00466 
00467 /*
00468  * The majority of these functions are pretty straightforward.  They follow the
00469  * general form of:
00470  *
00471  *   - Validate inputs
00472  *   - Perform function
00473  *   - Handle resulting errors, if any
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         /* empty... */
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     /* XXX Is the name exclusive? */
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; // XXX only one attach allowed at the moment.
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             /* Open the trace files... */
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; /* errno is set by fopen. */
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                 /* Parse the input file... */
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                                  * Compute the needed compute time from the
01027                                  * percentage required as specified by the
01028                                  * file and the deadline as specified by
01029                                  * ra_in.
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                                 /* No more inputs. */
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                                 /* Bad data. */
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                         /* Found some valid data. */
01069                     }
01070                     else
01071                     {
01072                         /* No inputs... */
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; /* errno is set by fopen. */
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         /* Cleanup the trace files... */
01144         for( lpc = 0; lpc < RK_CPU_TRACE_MAX; lpc++ )
01145         {
01146             /*
01147              * Check for NULLs since this function will be called if
01148              * rk_cpu_reserve_create() fails to open a trace file.
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         /* XXX ick */
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 /* END rk functions **/
01318 
01319 /* BEGIN rk_stub functions **/
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  * Verify time values and update the next time value if an earlier time is
01341  * seen.
01342  *
01343  * @param next The next simulated time value.
01344  * @param curr The current time.
01345  * @param new_next An event time.
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         /* Ignore */
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                 /* Recompute */
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                     /* Recompute */
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                 /* XXX ick */
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     /* Process all the resource sets. */
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     /* Scan all PCBs looking for one that is not in use. */
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 /* END rk_stub functions **/

Generated on Mon Dec 1 16:29:07 2003 for CPU Broker by doxygen 1.3.4