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

rt_scheduler_rk.c

Go to the documentation of this file.
00001 /*
00002  * rt_scheduler_rk.c
00003  *
00004  * Copyright (c) 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 rt_scheduler_rk.c
00014  *
00015  * TimeSys Linux implementation of the rt_scheduler interface.
00016  */
00017 
00018 #include "config.h"
00019 
00020 #include <errno.h>
00021 #include <string.h>
00022 #include <stdlib.h>
00023 
00024 #include <rk.h>
00025 #include <rk_util.h>
00026 #include <rt_scheduler.h>
00027 #include <assert_pp.h>
00028 
00029 enum {
00030     RSRB_OWNER,
00031 };
00032 
00033 enum {
00034     /** The schedulable owns the resource set, it was not discovered. */
00035     RSRF_OWNER = (1L << RSRB_OWNER),
00036 };
00037 
00038 /**
00039  * The TimeSys implementation of a schedulable.
00040  *
00041  * rsr_ResourceSet - The resource set this schedulable maps to.
00042  * rsr_CPUReserve - The CPU reserve connected to the resource set or NULL if
00043  * one has not yet been attached.
00044  * rsr_Flags - Field used to store any RSRF_ flags.
00045  */
00046 typedef struct rts_schedulable_rk {
00047     rk_resource_set_t rsr_ResourceSet;
00048     rk_reserve_t rsr_CPUReserve;
00049     unsigned long rsr_Flags;
00050 } *rts_schedulable_rk_t;
00051 
00052 /**
00053  * "Repair" the system by deleting any resource sets that have a CPU reserve
00054  * but no processes.
00055  */
00056 static void rts_repair_resource_sets(void)
00057 {
00058 #define MAX_RK_SETS 128
00059     static rk_resource_set_t rk_sets[MAX_RK_SETS];
00060     
00061     unsigned int lpc, actual;
00062 
00063     actual = rk_resource_sets_get_list(rk_sets, MAX_RK_SETS);
00064     for( lpc = 0; lpc < actual; lpc++ )
00065     {
00066         int proc_count = rk_resource_set_get_num_procs(rk_sets[lpc]);
00067         rk_reserve_t cr = rk_resource_set_get_cpu_rsv(rk_sets[lpc]);
00068         
00069         if( (proc_count == 0) && (cr != NULL_RESERVE) )
00070         {
00071             rk_resource_set_destroy(rk_sets[lpc]);
00072             rk_sets[lpc] = NULL_RESOURCE_SET;
00073         }
00074     }
00075 #undef MAX_RK_SETS
00076 }
00077 
00078 int rts_query_scheduler(rts_scheduler_data_t rsd)
00079 {
00080     int retval = 0;
00081 
00082     if( rsd == NULL )
00083     {
00084         retval = EINVAL;
00085     }
00086     else
00087     {
00088         rsd->rsd_Flags = RSDF_RESERVATIONS;
00089         rsd->rsd_MaxReservable = 0.90;
00090     }
00091     return( retval );
00092 }
00093 
00094 int rts_grab_schedulable(rts_schedulable_t *rs, pid_t member, const char *name)
00095 {
00096     rts_schedulable_rk_t rsr;
00097     int retval = 0;
00098 
00099     if( (rs == NULL) || ((member == -1) && (name == NULL)) )
00100     {
00101         retval = EINVAL;
00102     }
00103     else if( (rsr = calloc(1, sizeof(struct rts_schedulable_rk))) == NULL )
00104     {
00105         retval = ENOMEM;
00106     }
00107     else
00108     {
00109         rk_reserve_t old_reserve;
00110         
00111         /* Make sure the world is sane. */
00112         rts_repair_resource_sets();
00113 
00114         /* Try to get a resource set, */
00115         if( (rsr->rsr_ResourceSet = rk_proc_get_rset(member)) ==
00116             NULL_RESOURCE_SET )
00117         {
00118             if( (name == NULL) ||
00119                 (rsr->rsr_ResourceSet = rk_resource_set_get_by_name(name)) ==
00120                 NULL_RESOURCE_SET )
00121             {
00122                 if( name == NULL )
00123                 {
00124                     name = "rt_schedulable"; // XXX Generate one?
00125                 }
00126                 if( (rsr->rsr_ResourceSet = rk_resource_set_create(name)) ==
00127                     NULL_RESOURCE_SET )
00128                 {
00129                     retval = errno;
00130                 }
00131                 else
00132                 {
00133                     rsr->rsr_Flags |= RSRF_OWNER;
00134                 }
00135             }
00136         }
00137 
00138         /* ... make sure it is sane, and then */
00139         if( (old_reserve =
00140              rk_resource_set_get_cpu_rsv(rsr->rsr_ResourceSet)) !=
00141             NULL_RESERVE )
00142         {
00143             if( rk_resource_set_get_num_procs(rsr->rsr_ResourceSet) != 0 )
00144             {
00145                 retval = EBUSY;
00146             }
00147             else
00148             {
00149                 rk_cpu_reserve_delete(rsr->rsr_ResourceSet);
00150                 old_reserve = NULL_RESERVE;
00151             }
00152         }
00153         
00154         /* ... try to attach our process. */
00155         if( (retval == 0) && (rsr->rsr_ResourceSet != NULL_RESOURCE_SET) )
00156         {
00157             if( (member != -1) &&
00158                 (rk_resource_set_attach_process(rsr->rsr_ResourceSet,
00159                                                 member) == -1) &&
00160                 (errno != EBUSY) )
00161             {
00162                 /* No joy, something went wrong. */
00163                 retval = errno;
00164             }
00165             else
00166             {
00167                 /* This process is already attached. */
00168                 *rs = rsr;
00169                 rsr = NULL;
00170             }
00171         }
00172 
00173         if( rsr != NULL )
00174         {
00175             rts_release_schedulable(rsr);
00176             rsr = NULL;
00177         }
00178     }
00179     return( retval );
00180 }
00181 
00182 int rts_release_schedulable(rts_schedulable_t rs)
00183 {
00184     int retval = 0;
00185 
00186     if( rs == NULL )
00187     {
00188         retval = EINVAL;
00189     }
00190     else
00191     {
00192         {
00193             rts_schedulable_rk_t rsr = (rts_schedulable_rk_t)rs;
00194             
00195             if( rsr->rsr_CPUReserve != NULL_RESERVE )
00196             {
00197                 rk_cpu_reserve_delete(rsr->rsr_ResourceSet);
00198             }
00199             if( rsr->rsr_Flags & RSRF_OWNER )
00200             {
00201                 rk_resource_set_destroy(rsr->rsr_ResourceSet);
00202             }
00203             rsr->rsr_ResourceSet = NULL_RESOURCE_SET;
00204         }
00205         free(rs);
00206         rs = NULL;
00207     }
00208     return( retval );
00209 }
00210 
00211 int rts_set_schedule(rts_schedulable_t rsa, rts_schedule_t rs)
00212 {
00213     rts_schedulable_rk_t rsr = (rts_schedulable_rk_t)rsa;
00214     int retval = 0;
00215 
00216     if( (rsa == NULL) || (rs == NULL) )
00217     {
00218         retval = EINVAL;
00219     }
00220     else if( rsr->rsr_ResourceSet == NULL_RESOURCE_SET )
00221     {
00222         retval = EINVAL;
00223     }
00224     else if( (rs->rs_ReserveMode <= RTS_RSV_MIN) ||
00225              (rs->rs_ReserveMode >= RTS_RSV_MAX) )
00226     {
00227         retval = EINVAL;
00228     }
00229     else
00230     {
00231         struct cpu_reserve_attr cra;
00232 
00233         /* Convert from rt_scheduler to TimeSys and then */
00234         memset(&cra, 0, sizeof(cra));
00235         cra.compute_time = rs->rs_ComputeTime;
00236         cra.period = cra.deadline = rs->rs_Period;
00237         switch( rs->rs_ReserveMode )
00238         {
00239         case RTS_RSV_SOFT:
00240             cra.reserve_type.sch_mode = RSV_SOFT;
00241             cra.reserve_type.enf_mode = RSV_SOFT;
00242             cra.reserve_type.rep_mode = RSV_SOFT;
00243             break;
00244         case RTS_RSV_HARD:
00245             cra.reserve_type.sch_mode = RSV_HARD;
00246             cra.reserve_type.enf_mode = RSV_HARD;
00247             cra.reserve_type.rep_mode = RSV_HARD;
00248             break;
00249         default:
00250             ensure(0);
00251             break;
00252         }
00253         cra.processor = RK_ANY_CPU;
00254 
00255         /* ... change the reserve. */
00256         if( rsr->rsr_CPUReserve == NULL_RESERVE )
00257         {
00258             /* No reserve yet, make sure the set is consistent and then */
00259             if( rk_resource_set_get_cpu_rsv(rsr->rsr_ResourceSet) !=
00260                 NULL_RESERVE )
00261             {
00262                 retval = EBUSY;
00263             }
00264             /* ... create one. */
00265             else if( rk_cpu_reserve_create(rsr->rsr_ResourceSet,
00266                                            &rsr->rsr_CPUReserve,
00267                                            &cra) == -1 )
00268             {
00269                 retval = errno;
00270             }
00271         }
00272         else
00273         {
00274             if( rk_cpu_reserve_ctl(rsr->rsr_ResourceSet, &cra) == -1 )
00275             {
00276                 retval = errno;
00277             }
00278         }
00279     }
00280     return( retval );
00281 }
00282 
00283 int rts_get_schedule(rts_schedulable_t rsa, rts_schedule_t rs_out)
00284 {
00285     rts_schedulable_rk_t rsr = (rts_schedulable_rk_t)rsa;
00286     int retval = 0;
00287 
00288     if( (rsa == NULL) || (rs_out == NULL) )
00289     {
00290         retval = EINVAL;
00291     }
00292     else if( rsr->rsr_ResourceSet == NULL_RESOURCE_SET )
00293     {
00294         retval = EINVAL;
00295     }
00296     else
00297     {
00298         if( rsr->rsr_CPUReserve == NULL_RESERVE )
00299         {
00300             memset(rs_out, 0, sizeof(struct rts_schedule));
00301         }
00302         else
00303         {
00304             struct cpu_reserve_attr cra;
00305 
00306             /* Try to get the TimeSys schedule and then */
00307             if( rk_cpu_reserve_get_attr(rsr->rsr_CPUReserve, &cra) == -1 )
00308             {
00309                 retval = errno;
00310             }
00311             /* ... convert it to rt_scheduler format. */
00312             else
00313             {
00314                 rs_out->rs_Period = cra.period;
00315                 rs_out->rs_ComputeTime = cra.compute_time;
00316                 switch( cra.reserve_type.sch_mode )
00317                 {
00318                 case RSV_SOFT:
00319                     rs_out->rs_ReserveMode = RTS_RSV_SOFT;
00320                     break;
00321                 case RSV_HARD:
00322                     rs_out->rs_ReserveMode = RTS_RSV_HARD;
00323                     break;
00324                 default:
00325                     ensure(0);
00326                     break;
00327                 }
00328             }
00329         }
00330     }
00331     return( retval );
00332 }
00333 
00334 int rts_clear_schedule(rts_schedulable_t rsa)
00335 {
00336     rts_schedulable_rk_t rsr = (rts_schedulable_rk_t)rsa;
00337     int retval = 0;
00338 
00339     if( rsa == NULL )
00340     {
00341         retval = EINVAL;
00342     }
00343     else if( rsr->rsr_ResourceSet == NULL )
00344     {
00345         retval = EINVAL;
00346     }
00347     else
00348     {
00349         if( rsr->rsr_CPUReserve != NULL_RESERVE )
00350         {
00351             rk_cpu_reserve_delete(rsr->rsr_ResourceSet);
00352             rsr->rsr_CPUReserve = NULL_RESERVE;
00353         }
00354     }
00355     return( retval );
00356 }

Generated on Fri Oct 22 07:50:24 2004 for CPU Broker by  doxygen 1.3.9.1