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