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