00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "config.h"
00019
00020 #include <iostream>
00021 #include <assert_pp.h>
00022 #include <instrumentation.h>
00023
00024 #include "StubRealTimeTask.hh"
00025 #include "WeightedPolicyImpl.hh"
00026
00027 using namespace std;
00028
00029 WeightedPolicyImpl::WeightedPolicyImpl(const char *name) :
00030 wp_Name(name)
00031 {
00032 require(name != NULL);
00033
00034 this->wp_MaxUsedCPU = DEFAULT_MAX_USED_CPU;
00035 this->wp_MinTaskCPU = DEFAULT_MIN_TASK_CPU;
00036 lnNewList((struct lnMinList *)&this->wp_List);
00037 this->wp_TotalWeightedComputeTime = 0;
00038 }
00039
00040 WeightedPolicyImpl::~WeightedPolicyImpl()
00041 {
00042 }
00043
00044 char *WeightedPolicyImpl::Name(void)
00045 throw (CORBA::SystemException)
00046 {
00047 CORBA::String_var retval;
00048
00049 retval = this->wp_Name;
00050 return( retval._retn() );
00051 }
00052
00053 CORBA::Float WeightedPolicyImpl::GetMaxCPUAllocation(void)
00054 throw (CORBA::SystemException)
00055 {
00056 CORBA::Float retval;
00057
00058 retval = this->wp_MaxUsedCPU;
00059 return( retval );
00060 }
00061
00062 void WeightedPolicyImpl::SetMaxCPUAllocation(CORBA::Float value)
00063 throw (CORBA::SystemException)
00064 {
00065 if( (value < BrokerPolicies::WeightedPolicy::CPU_ALLOCATION_MIN) ||
00066 (value > BrokerPolicies::WeightedPolicy::CPU_ALLOCATION_MAX) )
00067 {
00068 throw CORBA::BAD_PARAM();
00069 }
00070
00071 this->wp_MaxUsedCPU = value;
00072 this->RedistributeCPU();
00073 }
00074
00075 void WeightedPolicyImpl::AddTask(Broker::Task_ptr task,
00076 const Broker::ScheduleParameters &sp)
00077 throw (CORBA::SystemException,
00078 Broker::DuplicateScheduleParameter,
00079 Broker::InvalidScheduleParameter,
00080 Broker::MissingScheduleParameter)
00081 {
00082 Broker::RealTimeTask_ptr rtt;
00083
00084
00085 if( CORBA::is_nil(task) )
00086 {
00087 throw CORBA::BAD_PARAM();
00088 }
00089
00090
00091
00092 rtt = Broker::RealTimeTask::_narrow(task);
00093 if( !CORBA::is_nil(rtt) )
00094 {
00095 struct TaskData *td = NULL;
00096 CORBA::String_var name;
00097 int rc;
00098
00099 name = rtt->Name();
00100
00101 try
00102 {
00103 td = new TaskData();
00104
00105 td->td_Link.ln_Pred = NULL;
00106 td->td_Link.ln_Succ = NULL;
00107 td->td_Task = Broker::RealTimeTask::_duplicate(rtt);
00108 td->td_Weight = 1;
00109
00110
00111 td->td_Schedule.setParameters(sp);
00112 td->td_ComputeTime = td->td_RequestedTime = 0;
00113 }
00114 catch(const Broker::DuplicateScheduleParameter &e)
00115 {
00116 delete td;
00117 throw e;
00118 }
00119 catch(const Broker::InvalidScheduleParameter &e)
00120 {
00121 delete td;
00122 throw e;
00123 }
00124 catch(const Broker::MissingScheduleParameter &e)
00125 {
00126 delete td;
00127 throw e;
00128 }
00129
00130 if( (rc = rts_grab_schedulable(&td->td_Schedulable,
00131 td->td_Schedule.rts_PID,
00132 name.in())) == -1 )
00133 {
00134 cerr << "rts_grab_schedulable: " << strerror(rc) << endl;
00135 }
00136 else
00137 {
00138
00139 lnAddTail((struct lnMinList *)&this->wp_List, &td->td_Link);
00140 td = NULL;
00141 }
00142
00143 if( td != NULL )
00144 {
00145 delete td;
00146 throw Broker::InvalidScheduleParameter();
00147 }
00148 }
00149 }
00150
00151 void WeightedPolicyImpl::RemoveTask(Broker::Task_ptr task)
00152 throw (CORBA::SystemException)
00153 {
00154 Broker::RealTimeTask_var rtt;
00155 struct TaskData *td;
00156 int rc;
00157
00158
00159 rtt = Broker::RealTimeTask::_narrow(task);
00160 if( (td = this->FindTaskData(rtt.in())) == NULL )
00161 {
00162 throw CORBA::BAD_PARAM();
00163 }
00164
00165
00166 lnRemove((struct lnMinNode *)&td->td_Link);
00167 if( (rc = rts_clear_schedule(td->td_Schedulable)) == -1 )
00168 {
00169 cerr << "rts_clear_schedule: " << strerror(rc) << endl;
00170 }
00171 if( (rc = rts_release_schedulable(td->td_Schedulable)) == -1 )
00172 {
00173 cerr << "rts_release_schedulable: " << strerror(rc) << endl;
00174 }
00175 this->wp_TotalWeightedComputeTime -=
00176 (td->td_Weight * td->td_RequestedTime);
00177
00178 this->RedistributeCPU();
00179
00180 delete td;
00181 }
00182
00183 void WeightedPolicyImpl::Activate(const Broker::TaskList &tl)
00184 throw (CORBA::SystemException)
00185 {
00186
00187 }
00188
00189 void WeightedPolicyImpl::Deactivate(void)
00190 throw (CORBA::SystemException)
00191 {
00192
00193 }
00194
00195 Broker::TaskList *WeightedPolicyImpl::GetTaskList(void)
00196 throw (CORBA::SystemException)
00197 {
00198 Broker::TaskList_var retval;
00199 struct TaskData *td;
00200 unsigned int lpc = 0;
00201
00202 retval = new Broker::TaskList();
00203 retval->length(lnCountNodes((struct lnMinList *)&this->wp_List));
00204 td = (struct TaskData *)this->wp_List.lh_Head;
00205 while( td->td_Link.ln_Succ != NULL )
00206 {
00207 (*retval)[lpc] = Broker::Task::_duplicate(td->td_Task.in());
00208 lpc += 1;
00209 td = (struct TaskData *)td->td_Link.ln_Succ;
00210 }
00211 return( retval._retn() );
00212 }
00213
00214 void WeightedPolicyImpl::SetTaskWeight(Broker::Task_ptr task,
00215 CORBA::UShort weight)
00216 throw (CORBA::SystemException)
00217 {
00218 Broker::RealTimeTask_var rtt;
00219 struct TaskData *td;
00220
00221 rtt = Broker::RealTimeTask::_narrow(task);
00222 if( CORBA::is_nil(rtt.in()) )
00223 {
00224 throw CORBA::BAD_PARAM();
00225 }
00226 if( weight == 0 )
00227 {
00228 throw CORBA::BAD_PARAM();
00229 }
00230
00231
00232 if( (td = this->FindTaskData(rtt.in())) == NULL )
00233 {
00234 throw CORBA::BAD_PARAM();
00235 }
00236
00237 this->wp_TotalWeightedComputeTime -=
00238 (td->td_Weight * td->td_RequestedTime);
00239
00240
00241 td->td_Weight = weight;
00242
00243 this->wp_TotalWeightedComputeTime +=
00244 (td->td_Weight * td->td_RequestedTime);
00245
00246 this->RedistributeCPU();
00247 }
00248
00249 CORBA::UShort WeightedPolicyImpl::GetTaskWeight(Broker::Task_ptr task)
00250 throw (CORBA::SystemException)
00251 {
00252 Broker::RealTimeTask_var rtt;
00253 CORBA::UShort retval;
00254 struct TaskData *td;
00255
00256 rtt = Broker::RealTimeTask::_narrow(task);
00257 if( CORBA::is_nil(rtt.in()) )
00258 {
00259 throw CORBA::BAD_PARAM();
00260 }
00261 if( (td = this->FindTaskData(rtt.in())) == NULL )
00262 {
00263 throw CORBA::BAD_PARAM();
00264 }
00265
00266 retval = td->td_Weight;
00267
00268 return( retval );
00269 }
00270
00271 void WeightedPolicyImpl::RedistributeCPU(void)
00272 {
00273 struct lnMinList change_list;
00274 struct ChangeNode *cn;
00275 struct TaskData *curr;
00276
00277 lnNewList(&change_list);
00278
00279 curr = (struct TaskData *)this->wp_List.lh_Head;
00280 while( curr->td_Link.ln_Succ != NULL )
00281 {
00282 unsigned long long actual_cpu_time, max_cpu_time;
00283
00284
00285 max_cpu_time = (unsigned long long)
00286 ((this->wp_MaxUsedCPU * (float)curr->td_Schedule.rts_Deadline));
00287
00288 actual_cpu_time = (unsigned long long)
00289 (((curr->td_Weight * curr->td_RequestedTime) * max_cpu_time) /
00290 this->wp_TotalWeightedComputeTime);
00291
00292 if( actual_cpu_time > curr->td_RequestedTime )
00293 {
00294
00295 actual_cpu_time = curr->td_RequestedTime;
00296 }
00297
00298
00299 cn = &curr->td_ChangeLink;
00300 cn->cn_Parent = curr;
00301 cn->cn_NewTime = actual_cpu_time;
00302
00303
00304 if( actual_cpu_time < curr->td_ComputeTime )
00305 {
00306
00307
00308
00309
00310 lnAddHead(&change_list, &cn->cn_Link);
00311 }
00312 else if( actual_cpu_time == curr->td_ComputeTime )
00313 {
00314
00315 }
00316 else if( actual_cpu_time > curr->td_ComputeTime )
00317 {
00318
00319
00320
00321
00322 lnAddTail(&change_list, &cn->cn_Link);
00323 }
00324 else
00325 {
00326 assert(0);
00327 }
00328 curr = (struct TaskData *)curr->td_Link.ln_Succ;
00329 }
00330 curr = NULL;
00331
00332
00333 cn = (struct ChangeNode *)change_list.lh_Head;
00334 while( cn->cn_Link.ln_Succ != NULL )
00335 {
00336 struct TaskData *td;
00337
00338 td = cn->cn_Parent;
00339 if( cn->cn_NewTime > 0 )
00340 {
00341 struct rts_schedule rs;
00342 int rc;
00343
00344 rs.rs_Period = microsec_to_timespec(td->td_Schedule.rts_Period);
00345 rs.rs_ComputeTime = microsec_to_timespec(cn->cn_NewTime);
00346 rs.rs_ReserveMode = td->td_Schedule.rts_ReserveMode;
00347 if( (rc = rts_set_schedule(td->td_Schedulable, &rs)) == -1 )
00348 {
00349 cerr << "rts_set_schedule: " << strerror(rc) << endl;
00350 }
00351 else
00352 {
00353 cn->cn_Parent->td_ComputeTime = cn->cn_NewTime;
00354 }
00355 }
00356 else
00357 {
00358 int rc;
00359
00360 if( (rc = rts_clear_schedule(td->td_Schedulable)) == -1 )
00361 {
00362 cerr << "rts_set_schedule: " << strerror(rc) << endl;
00363 }
00364 }
00365 cn = (struct ChangeNode *)cn->cn_Link.ln_Succ;
00366 }
00367 }
00368
00369 void WeightedPolicyImpl::RepairTaskList(void)
00370 {
00371 struct TaskData *curr, *succ;
00372 int do_redist = 0;
00373
00374
00375 curr = (struct TaskData *)this->wp_List.lh_Head;
00376 while( curr->td_Link.ln_Succ != NULL )
00377 {
00378 succ = (struct TaskData *)curr->td_Link.ln_Succ;
00379 #if 0
00380 try
00381 {
00382
00383 curr->td_Task->GetComputeTime();
00384 }
00385 catch(const CORBA::TRANSIENT &e)
00386 {
00387
00388 lnRemove((struct lnMinNode *)&curr->td_Link);
00389
00390 delete curr;
00391 do_redist = 1;
00392 }
00393 #endif
00394 curr = succ;
00395 }
00396
00397
00398 if( do_redist )
00399 {
00400 this->RedistributeCPU();
00401 }
00402 }
00403
00404 struct WeightedPolicyImpl::TaskData *
00405 WeightedPolicyImpl::FindTaskData(Broker::RealTimeTask_ptr task)
00406 {
00407 struct TaskData *curr, *retval = NULL;
00408
00409 require(task != NULL);
00410
00411 curr = (struct TaskData *)this->wp_List.lh_Head;
00412 while( (retval == NULL) && (curr->td_Link.ln_Succ != NULL) )
00413 {
00414 if( task->_is_equivalent(curr->td_Task.in()) )
00415 {
00416 retval = curr;
00417 }
00418 curr = (struct TaskData *)curr->td_Link.ln_Succ;
00419 }
00420
00421 if( retval == NULL )
00422 {
00423 cerr << "Unknown task" << endl;
00424 throw Broker::Internal("FindTaskData failed to find task");
00425 }
00426
00427 return( retval );
00428 }
00429
00430 Broker::CPUReserve
00431 WeightedPolicyImpl::ChangeTaskCPU(Broker::RealTimeTask_ptr task,
00432 const Broker::CPUReserve &advice)
00433 throw (CORBA::SystemException, Broker::InvalidState)
00434 {
00435 Broker::CPUReserve retval = advice;
00436 struct TaskData *td;
00437
00438 require(task != NULL);
00439
00440 if( (td = this->FindTaskData(task)) != NULL )
00441 {
00442 td->td_Schedule.rts_Period = advice.Period;
00443 this->wp_TotalWeightedComputeTime -=
00444 (td->td_Weight * td->td_RequestedTime);
00445 td->td_RequestedTime = advice.Compute;
00446 this->wp_TotalWeightedComputeTime +=
00447 (td->td_Weight * td->td_RequestedTime);
00448 this->RedistributeCPU();
00449 retval.Compute = td->td_ComputeTime;
00450 }
00451 else
00452 {
00453 throw Broker::InvalidState("AddTask must be called first");
00454 }
00455 return retval;
00456 }