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.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     /* Check inputs, */
00086     if( CORBA::is_nil(task) )
00087     {
00088         throw CORBA::BAD_PARAM();
00089     }
00090 
00091     /* ... make sure our task list is sane, and */
00092     this->RepairTaskList();
00093     
00094     /* ... try to add the new task. */
00095     /** @todo Handle other types of tasks. */
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             /* Initialize the node and */
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             /* ... cache some values. */
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             /* Finally, add it to list, ordered by tp_Link.ln_Pri. */
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     /* Find the task, */
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     /** @todo implement */
00197 }
00198 
00199 void StrictPolicyImpl::Deactivate(void)
00200     throw (CORBA::SystemException)
00201 {
00202     /** @todo implement */
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     /* Remove from the list */
00242     lnRemove((struct lnMinNode *)&tp->tp_Link);
00243     /* ... set the new priority */
00244     tp->tp_Link.ln_Pri = (char)priority;
00245     /* ... and reinsert to get the new ordering. */
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             /* no change... */
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 }

Generated on Fri Oct 22 07:50:25 2004 for CPU Broker by  doxygen 1.3.9.1