00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
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
00035 RSRF_OWNER = (1L << RSRB_OWNER),
00036 };
00037
00038
00039
00040
00041
00042
00043
00044
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
00054
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
00112 rts_repair_resource_sets();
00113
00114
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";
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
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
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
00163 retval = errno;
00164 }
00165 else
00166 {
00167
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
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
00256 if( rsr->rsr_CPUReserve == NULL_RESERVE )
00257 {
00258
00259 if( rk_resource_set_get_cpu_rsv(rsr->rsr_ResourceSet) !=
00260 NULL_RESERVE )
00261 {
00262 retval = EBUSY;
00263 }
00264
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
00307 if( rk_cpu_reserve_get_attr(rsr->rsr_CPUReserve, &cra) == -1 )
00308 {
00309 retval = errno;
00310 }
00311
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 }