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