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_pp.h>
00022 #include <instrumentation.h>
00023 
00024 #include "StubRealTimeTask.hh"
00025 #include "WeightedPolicyImpl.hh"
00026 
00027 using namespace std;
00028 
00029 WeightedPolicyImpl::WeightedPolicyImpl(const char *name) :
00030     wp_Name(name)
00031 {
00032     require(name != NULL);
00033     
00034     this->wp_MaxUsedCPU = DEFAULT_MAX_USED_CPU;
00035     this->wp_MinTaskCPU = DEFAULT_MIN_TASK_CPU;
00036     lnNewList((struct lnMinList *)&this->wp_List);
00037     this->wp_TotalWeightedComputeTime = 0;
00038 }
00039 
00040 WeightedPolicyImpl::~WeightedPolicyImpl()
00041 {
00042 }
00043 
00044 char *WeightedPolicyImpl::Name(void)
00045     throw (CORBA::SystemException)
00046 {
00047     CORBA::String_var retval;
00048 
00049     retval = this->wp_Name;
00050     return( retval._retn() );
00051 }
00052 
00053 CORBA::Float WeightedPolicyImpl::GetMaxCPUAllocation(void)
00054     throw (CORBA::SystemException)
00055 {
00056     CORBA::Float retval;
00057 
00058     retval = this->wp_MaxUsedCPU;
00059     return( retval );
00060 }
00061 
00062 void WeightedPolicyImpl::SetMaxCPUAllocation(CORBA::Float value)
00063     throw (CORBA::SystemException)
00064 {
00065     if( (value < BrokerPolicies::WeightedPolicy::CPU_ALLOCATION_MIN) ||
00066         (value > BrokerPolicies::WeightedPolicy::CPU_ALLOCATION_MAX) )
00067     {
00068         throw CORBA::BAD_PARAM();
00069     }
00070 
00071     this->wp_MaxUsedCPU = value;
00072     this->RedistributeCPU();
00073 }
00074 
00075 void WeightedPolicyImpl::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     // this->RepairTaskList();
00091     
00092     rtt = Broker::RealTimeTask::_narrow(task);
00093     if( !CORBA::is_nil(rtt) )
00094     {
00095         struct TaskData *td = NULL;
00096         CORBA::String_var name;
00097         int rc;
00098         
00099         name = rtt->Name();
00100 
00101         try
00102         {
00103             td = new TaskData();
00104             /* Initialize the node and */
00105             td->td_Link.ln_Pred = NULL;
00106             td->td_Link.ln_Succ = NULL;
00107             td->td_Task = Broker::RealTimeTask::_duplicate(rtt);
00108             td->td_Weight = 1;
00109             
00110             /* ... cache some values. */
00111             td->td_Schedule.setParameters(sp);
00112             td->td_ComputeTime = td->td_RequestedTime = 0;
00113         }
00114         catch(const Broker::DuplicateScheduleParameter &e)
00115         {
00116             delete td;
00117             throw e;
00118         }
00119         catch(const Broker::InvalidScheduleParameter &e)
00120         {
00121             delete td;
00122             throw e;
00123         }
00124         catch(const Broker::MissingScheduleParameter &e)
00125         {
00126             delete td;
00127             throw e;
00128         }
00129         
00130         if( (rc = rts_grab_schedulable(&td->td_Schedulable,
00131                                        td->td_Schedule.rts_PID,
00132                                        name.in())) == -1 )
00133         {
00134             cerr << "rts_grab_schedulable: " << strerror(rc) << endl;
00135         }
00136         else
00137         {
00138             /* Finally, add it to the tail of the list. */
00139             lnAddTail((struct lnMinList *)&this->wp_List, &td->td_Link);
00140             td = NULL;
00141         }
00142 
00143         if( td != NULL )
00144         {
00145             delete td;
00146             throw Broker::InvalidScheduleParameter();
00147         }
00148     }
00149 }
00150 
00151 void WeightedPolicyImpl::RemoveTask(Broker::Task_ptr task)
00152     throw (CORBA::SystemException)
00153 {
00154     Broker::RealTimeTask_var rtt;
00155     struct TaskData *td;
00156     int rc;
00157     
00158     /* Find the task, */
00159     rtt = Broker::RealTimeTask::_narrow(task);
00160     if( (td = this->FindTaskData(rtt.in())) == NULL )
00161     {
00162         throw CORBA::BAD_PARAM();
00163     }
00164     
00165     /* ... remove the node, */
00166     lnRemove((struct lnMinNode *)&td->td_Link);
00167     if( (rc = rts_clear_schedule(td->td_Schedulable)) == -1 )
00168     {
00169         cerr << "rts_clear_schedule: " << strerror(rc) << endl;
00170     }
00171     if( (rc = rts_release_schedulable(td->td_Schedulable)) == -1 )
00172     {
00173         cerr << "rts_release_schedulable: " << strerror(rc) << endl;
00174     }
00175     this->wp_TotalWeightedComputeTime -=
00176         (td->td_Weight * td->td_RequestedTime);
00177     /* ... give its compute time to the others, and */
00178     this->RedistributeCPU();
00179     /* ... delete it. */
00180     delete td;
00181 }
00182 
00183 void WeightedPolicyImpl::Activate(const Broker::TaskList &tl)
00184     throw (CORBA::SystemException)
00185 {
00186     /** @todo implement */
00187 }
00188 
00189 void WeightedPolicyImpl::Deactivate(void)
00190     throw (CORBA::SystemException)
00191 {
00192     /** @todo implement */
00193 }
00194 
00195 Broker::TaskList *WeightedPolicyImpl::GetTaskList(void)
00196     throw (CORBA::SystemException)
00197 {
00198     Broker::TaskList_var retval;
00199     struct TaskData *td;
00200     unsigned int lpc = 0;
00201     
00202     retval = new Broker::TaskList();
00203     retval->length(lnCountNodes((struct lnMinList *)&this->wp_List));
00204     td = (struct TaskData *)this->wp_List.lh_Head;
00205     while( td->td_Link.ln_Succ != NULL )
00206     {
00207         (*retval)[lpc] = Broker::Task::_duplicate(td->td_Task.in());
00208         lpc += 1;
00209         td = (struct TaskData *)td->td_Link.ln_Succ;
00210     }
00211     return( retval._retn() );
00212 }
00213 
00214 void WeightedPolicyImpl::SetTaskWeight(Broker::Task_ptr task,
00215                                        CORBA::UShort weight)
00216     throw (CORBA::SystemException)
00217 {
00218     Broker::RealTimeTask_var rtt;
00219     struct TaskData *td;
00220 
00221     rtt = Broker::RealTimeTask::_narrow(task);
00222     if( CORBA::is_nil(rtt.in()) )
00223     {
00224         throw CORBA::BAD_PARAM();
00225     }
00226     if( weight == 0 )
00227     {
00228         throw CORBA::BAD_PARAM();
00229     }
00230 
00231     /* Find the task, */
00232     if( (td = this->FindTaskData(rtt.in())) == NULL )
00233     {
00234         throw CORBA::BAD_PARAM();
00235     }
00236 
00237     this->wp_TotalWeightedComputeTime -=
00238         (td->td_Weight * td->td_RequestedTime);
00239     
00240     /* ... set the new weight, and */
00241     td->td_Weight = weight;
00242     
00243     this->wp_TotalWeightedComputeTime +=
00244         (td->td_Weight * td->td_RequestedTime);
00245     /* ... redistribute the reservations. */
00246     this->RedistributeCPU();
00247 }
00248 
00249 CORBA::UShort WeightedPolicyImpl::GetTaskWeight(Broker::Task_ptr task)
00250     throw (CORBA::SystemException)
00251 {
00252     Broker::RealTimeTask_var rtt;
00253     CORBA::UShort retval;
00254     struct TaskData *td;
00255 
00256     rtt = Broker::RealTimeTask::_narrow(task);
00257     if( CORBA::is_nil(rtt.in()) )
00258     {
00259         throw CORBA::BAD_PARAM();
00260     }
00261     if( (td = this->FindTaskData(rtt.in())) == NULL )
00262     {
00263         throw CORBA::BAD_PARAM();
00264     }
00265 
00266     retval = td->td_Weight;
00267     
00268     return( retval );
00269 }
00270 
00271 void WeightedPolicyImpl::RedistributeCPU(void)
00272 {
00273     struct lnMinList change_list;
00274     struct ChangeNode *cn;
00275     struct TaskData *curr;
00276 
00277     lnNewList(&change_list);
00278     /* Produce a change list that */
00279     curr = (struct TaskData *)this->wp_List.lh_Head;
00280     while( curr->td_Link.ln_Succ != NULL )
00281     {
00282         unsigned long long actual_cpu_time, max_cpu_time;
00283 
00284         /* Compute the weighted CPU time, */
00285         max_cpu_time = (unsigned long long)
00286             ((this->wp_MaxUsedCPU * (float)curr->td_Schedule.rts_Deadline));
00287         
00288         actual_cpu_time = (unsigned long long)
00289             (((curr->td_Weight * curr->td_RequestedTime) * max_cpu_time) /
00290              this->wp_TotalWeightedComputeTime);
00291         
00292         if( actual_cpu_time > curr->td_RequestedTime )
00293         {
00294             /* no overload, no need to compress... */
00295             actual_cpu_time = curr->td_RequestedTime;
00296         }
00297 
00298         /* ... update the change node, and */
00299         cn = &curr->td_ChangeLink;
00300         cn->cn_Parent = curr;
00301         cn->cn_NewTime = actual_cpu_time;
00302 
00303         /* add it to the change list depending on how it changes. */
00304         if( actual_cpu_time < curr->td_ComputeTime )
00305         {
00306             /*
00307              * Put decreases at the front of the change list so there will
00308              * CPU to give away later on.
00309              */
00310             lnAddHead(&change_list, &cn->cn_Link);
00311         }
00312         else if( actual_cpu_time == curr->td_ComputeTime )
00313         {
00314             /* no change... */
00315         }
00316         else if( actual_cpu_time > curr->td_ComputeTime )
00317         {
00318             /*
00319              * Put increases at the back of the change list so we do not try to
00320              * take CPU that is not yet available.
00321              */
00322             lnAddTail(&change_list, &cn->cn_Link);
00323         }
00324         else 
00325         {
00326             assert(0);
00327         }
00328         curr = (struct TaskData *)curr->td_Link.ln_Succ;
00329     }
00330     curr = NULL;
00331 
00332     /* ... takes away CPU before giving to the other tasks. */
00333     cn = (struct ChangeNode *)change_list.lh_Head;
00334     while( cn->cn_Link.ln_Succ != NULL )
00335     {
00336         struct TaskData *td;
00337 
00338         td = cn->cn_Parent;
00339         if( cn->cn_NewTime > 0 )
00340         {
00341             struct rts_schedule rs;
00342             int rc;
00343             
00344             rs.rs_Period = microsec_to_timespec(td->td_Schedule.rts_Period);
00345             rs.rs_ComputeTime = microsec_to_timespec(cn->cn_NewTime);
00346             rs.rs_ReserveMode = td->td_Schedule.rts_ReserveMode;
00347             if( (rc = rts_set_schedule(td->td_Schedulable, &rs)) == -1 )
00348             {
00349                 cerr << "rts_set_schedule: " << strerror(rc) << endl;
00350             }
00351             else
00352             {
00353                 cn->cn_Parent->td_ComputeTime = cn->cn_NewTime;
00354             }
00355         }
00356         else
00357         {
00358             int rc;
00359             
00360             if( (rc = rts_clear_schedule(td->td_Schedulable)) == -1 )
00361             {
00362                 cerr << "rts_set_schedule: " << strerror(rc) << endl;
00363             }
00364         }
00365         cn = (struct ChangeNode *)cn->cn_Link.ln_Succ;
00366     }
00367 }
00368 
00369 void WeightedPolicyImpl::RepairTaskList(void)
00370 {
00371     struct TaskData *curr, *succ;
00372     int do_redist = 0;
00373 
00374     /* Walk the task list to make sure it is sane and then */
00375     curr = (struct TaskData *)this->wp_List.lh_Head;
00376     while( curr->td_Link.ln_Succ != NULL )
00377     {
00378         succ = (struct TaskData *)curr->td_Link.ln_Succ;
00379 #if 0
00380         try
00381         {
00382             /* Force an RPC, to make sure the object is still alive. */
00383             curr->td_Task->GetComputeTime();
00384         }
00385         catch(const CORBA::TRANSIENT &e)
00386         {
00387             /* The object is dead, remove it, and */
00388             lnRemove((struct lnMinNode *)&curr->td_Link);
00389             /* ... delete it. */
00390             delete curr;
00391             do_redist = 1;
00392         }
00393 #endif
00394         curr = succ;
00395     }
00396     
00397     /* ... redistribute the CPU if there was a change. */
00398     if( do_redist )
00399     {
00400         this->RedistributeCPU();
00401     }
00402 }
00403 
00404 struct WeightedPolicyImpl::TaskData *
00405 WeightedPolicyImpl::FindTaskData(Broker::RealTimeTask_ptr task)
00406 {
00407     struct TaskData *curr, *retval = NULL;
00408 
00409     require(task != NULL);
00410     
00411     curr = (struct TaskData *)this->wp_List.lh_Head;
00412     while( (retval == NULL) && (curr->td_Link.ln_Succ != NULL) )
00413     {
00414         if( task->_is_equivalent(curr->td_Task.in()) )
00415         {
00416             retval = curr;
00417         }
00418         curr = (struct TaskData *)curr->td_Link.ln_Succ;
00419     }
00420 
00421     if( retval == NULL )
00422     {
00423         cerr << "Unknown task" << endl;
00424         throw Broker::Internal("FindTaskData failed to find task");
00425     }
00426     
00427     return( retval );
00428 }
00429 
00430 Broker::CPUReserve
00431 WeightedPolicyImpl::ChangeTaskCPU(Broker::RealTimeTask_ptr task,
00432                                   const Broker::CPUReserve &advice)
00433     throw (CORBA::SystemException, Broker::InvalidState)
00434 {
00435     Broker::CPUReserve retval = advice;
00436     struct TaskData *td;
00437 
00438     require(task != NULL);
00439     
00440     if( (td = this->FindTaskData(task)) != NULL )
00441     {
00442         td->td_Schedule.rts_Period = advice.Period;
00443         this->wp_TotalWeightedComputeTime -=
00444             (td->td_Weight * td->td_RequestedTime);
00445         td->td_RequestedTime = advice.Compute;
00446         this->wp_TotalWeightedComputeTime +=
00447             (td->td_Weight * td->td_RequestedTime);
00448         this->RedistributeCPU();
00449         retval.Compute = td->td_ComputeTime;
00450     }
00451     else
00452     {
00453         throw Broker::InvalidState("AddTask must be called first");
00454     }
00455     return retval;
00456 }

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