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

rk_stub.c

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

Generated on Tue Jun 22 14:50:10 2004 for CPU Broker by doxygen 1.3.6