Main Page | Namespace List | Class Hierarchy | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

StrictPolicyImpl.cc

Go to the documentation of this file.
00001 /*
00002  * StrictPolicyImpl.cc
00003  *
00004  * Copyright (c) 2003, 2004 The University of Utah and the Flux Group.
00005  * All rights reserved.
00006  *
00007  * This file is licensed under the terms of the GNU Public License.  
00008  * See the file "license.terms" for restrictions on redistribution 
00009  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
00010  */
00011 
00012 /**
00013  * @file StrictPolicyImpl.cc
00014  *
00015  * Implementation of the StrictPolicyImpl class.
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     /* Check inputs, */
00085     if( CORBA::is_nil(task) )
00086     {
00087         throw CORBA::BAD_PARAM();
00088     }
00089 
00090     /* ... make sure our task list is sane, and */
00091     this->RepairTaskList();
00092     
00093     /* ... try to add the new task. */
00094     /** @todo Handle other types of tasks. */
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             /* Initialize the node and */
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             /* ... cache some values. */
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             /* Finally, add it to list, ordered by tp_Link.ln_Pri. */
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     /* Find the task, */
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     /** @todo implement */
00196 }
00197 
00198 void StrictPolicyImpl::Deactivate(void)
00199     throw (CORBA::SystemException)
00200 {
00201     /** @todo implement */
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     /* Remove from the list */
00241     lnRemove((struct lnMinNode *)&tp->tp_Link);
00242     /* ... set the new priority */
00243     tp->tp_Link.ln_Pri = (char)priority;
00244     /* ... and reinsert to get the new ordering. */
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             /* no change... */
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 }

Generated on Tue Jun 22 14:50:11 2004 for CPU Broker by doxygen 1.3.6