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

WeightedPolicyImpl.cc

Go to the documentation of this file.
00001 /*
00002  * WeightedPolicyImpl.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 WeightedPolicyImpl.cc
00014  *
00015  * Implementation of the WeightedPolicyImpl class.
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     /* Check inputs. */
00086     if( CORBA::is_nil(task) )
00087     {
00088         throw CORBA::BAD_PARAM();
00089     }
00090 
00091     // this->RepairTaskList();
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             /* Initialize the node and */
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             /* ... cache some values. */
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             /* Finally, add it to the tail of the list. */
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     /* Find the task, */
00160     rtt = Broker::RealTimeTask::_narrow(task);
00161     if( (td = this->FindTaskData(rtt.in())) == NULL )
00162     {
00163         throw CORBA::BAD_PARAM();
00164     }
00165     
00166     /* ... remove the node, */
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     /* ... give its compute time to the others, and */
00179     this->RedistributeCPU();
00180     /* ... delete it. */
00181     delete td;
00182 }
00183 
00184 void WeightedPolicyImpl::Activate(const Broker::TaskList &tl)
00185     throw (CORBA::SystemException)
00186 {
00187     /** @todo implement */
00188 }
00189 
00190 void WeightedPolicyImpl::Deactivate(void)
00191     throw (CORBA::SystemException)
00192 {
00193     /** @todo implement */
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     /* Find the task, */
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     /* ... set the new weight, and */
00242     td->td_Weight = weight;
00243     
00244     this->wp_TotalWeightedComputeTime +=
00245         (td->td_Weight * td->td_RequestedTime);
00246     /* ... redistribute the reservations. */
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     /* Produce a change list that */
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         /* Compute the weighted CPU time, */
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             /* no overload, no need to compress... */
00296             actual_cpu_time = curr->td_RequestedTime;
00297         }
00298 
00299         /* ... update the change node, and */
00300         cn = &curr->td_ChangeLink;
00301         cn->cn_Parent = curr;
00302         cn->cn_NewTime = actual_cpu_time;
00303 
00304         /* add it to the change list depending on how it changes. */
00305         if( actual_cpu_time < curr->td_ComputeTime )
00306         {
00307             /*
00308              * Put decreases at the front of the change list so there will
00309              * CPU to give away later on.
00310              */
00311             lnAddHead(&change_list, &cn->cn_Link);
00312         }
00313         else if( actual_cpu_time == curr->td_ComputeTime )
00314         {
00315             /* no change... */
00316         }
00317         else if( actual_cpu_time > curr->td_ComputeTime )
00318         {
00319             /*
00320              * Put increases at the back of the change list so we do not try to
00321              * take CPU that is not yet available.
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     /* ... takes away CPU before giving to the other tasks. */
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     /* Walk the task list to make sure it is sane and then */
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             /* Force an RPC, to make sure the object is still alive. */
00384             curr->td_Task->GetComputeTime();
00385         }
00386         catch(const CORBA::TRANSIENT &e)
00387         {
00388             /* The object is dead, remove it, and */
00389             lnRemove((struct lnMinNode *)&curr->td_Link);
00390             /* ... delete it. */
00391             delete curr;
00392             do_redist = 1;
00393         }
00394 #endif
00395         curr = succ;
00396     }
00397     
00398     /* ... redistribute the CPU if there was a change. */
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 }

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