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

StrictPolicyImpl.cc

Go to the documentation of this file.
00001 /*
00002  * StrictPolicyImpl.cc
00003  *
00004  * Copyright (c) 2003 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 <assert_pp.h>
00021 
00022 #include "StubRealTimeTask.hh"
00023 #include "StrictPolicyImpl.hh"
00024 
00025 StrictPolicyImpl::StrictPolicyImpl(const char *name) :
00026     sp_Name(name)
00027 {
00028     StubRealTimeTask *srtt;
00029     
00030     require(name != NULL);
00031     
00032     this->sp_MaxUsedCPU = DEFAULT_MAX_USED_CPU;
00033     this->sp_MinTaskCPU = DEFAULT_MIN_TASK_CPU;
00034     lnNewList((struct lnMinList *)&this->sp_List);
00035     memset(&this->sp_FauxTask, 0, sizeof(struct TaskPriority));
00036     this->sp_FauxTask.tp_Link.ln_Pri = 127;
00037     srtt = new StubRealTimeTask("_faux_");
00038     this->sp_FauxTask.tp_Task = srtt->_this();
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     if( !lnEmptyList(&this->sp_List) )
00073     {
00074         if( value > this->sp_MaxUsedCPU )
00075         {
00076             CORBA::ULong amount;
00077             
00078             amount = (CORBA::ULong)
00079                 ((value - this->sp_MaxUsedCPU) *
00080                  this->sp_FauxTask.tp_Schedule.rts_Deadline);
00081             this->GiveCPU(this->SubList(this->sp_FauxTask.tp_Schedule, NULL),
00082                           amount,
00083                           &this->sp_FauxTask);
00084         }
00085         else if( value < this->sp_MaxUsedCPU )
00086         {
00087             CORBA::ULong amount;
00088             
00089             amount = (CORBA::ULong)
00090                 ((this->sp_MaxUsedCPU - value) *
00091                  this->sp_FauxTask.tp_Schedule.rts_Deadline);
00092             this->TakeCPU(this->SubList(this->sp_FauxTask.tp_Schedule, NULL),
00093                           amount,
00094                           &this->sp_FauxTask);
00095         }
00096     }
00097     this->sp_MaxUsedCPU = value;
00098 }
00099 
00100 void StrictPolicyImpl::AddTask(Broker::Task_ptr task,
00101                                const Broker::ScheduleParameters &sp)
00102     throw (CORBA::SystemException)
00103 {
00104     Broker::RealTimeTask_ptr rtt;
00105     
00106     /* Check inputs. */
00107     if( CORBA::is_nil(task) )
00108     {
00109         throw CORBA::BAD_PARAM();
00110     }
00111 
00112     this->RepairTaskList();
00113     
00114     /* XXX We can only handle RealTimeTasks at the moment. */
00115     rtt = Broker::RealTimeTask::_narrow(task);
00116     if( !CORBA::is_nil(rtt) )
00117     {
00118         if( (rtt->Period() == 0) || (rtt->Deadline() == 0) )
00119         {
00120             throw CORBA::BAD_PARAM();
00121         }
00122 
00123         struct TaskPriority *tp = new TaskPriority();
00124         struct TaskPriority *sub_list;
00125         CORBA::ULong ct;
00126         
00127         /* Initialize the node and */
00128         tp->tp_Link.ln_Pred = NULL;
00129         tp->tp_Link.ln_Succ = NULL;
00130         tp->tp_Link.ln_Pri = 0;
00131         tp->tp_Task = rtt;
00132         /* ... cache some values. */
00133         tp->tp_Schedule.rts_Period = rtt->Period();
00134         tp->tp_Schedule.rts_Deadline = rtt->Deadline();
00135         
00136         /* XXX fix this, use task->GetComputeTime() */
00137         ct = (CORBA::ULong)(this->sp_MinTaskCPU *
00138                             (float)tp->tp_Schedule.rts_Deadline);
00139         sub_list = this->SubList(tp->tp_Schedule, tp);
00140         ct = this->TakeCPU(sub_list, ct, tp);
00141         try
00142         {
00143             rtt->SetComputeTime(ct);
00144             tp->tp_ComputeTime = ct;
00145         }
00146         catch(const CORBA::Exception &e)
00147         {
00148             cerr << e << endl;
00149         }
00150         catch(...)
00151         {
00152             cerr << "Gah error in SetComputeTime!\n"; // XXX
00153         }
00154         
00155         /* Finally, add it to list, ordered by tp_Link.ln_Pri. */
00156         lnEnqueue(&this->sp_List, &tp->tp_Link);
00157     }
00158 }
00159 
00160 void StrictPolicyImpl::RemoveTask(Broker::Task_ptr task)
00161     throw (CORBA::SystemException)
00162 {
00163     Broker::RealTimeTask_ptr rtt;
00164     struct TaskPriority *tp;
00165 
00166     /* Find the task and */
00167     rtt = Broker::RealTimeTask::_narrow(task);
00168     if( (tp = this->FindTaskPriority(rtt)) == NULL )
00169     {
00170         throw CORBA::BAD_PARAM();
00171     }
00172 
00173     /* ... give its compute time to the others. */
00174     this->GiveCPU(this->SubList(tp->tp_Schedule, tp),
00175                   tp->tp_ComputeTime,
00176                   tp);
00177     /* Finally, remove the node and */
00178     lnRemove((struct lnMinNode *)&tp->tp_Link);
00179     /* ... delete it. */
00180     delete tp;
00181 }
00182 
00183 void StrictPolicyImpl::Activate(const Broker::TaskList &tl)
00184     throw (CORBA::SystemException)
00185 {
00186     /* XXX */
00187 }
00188 
00189 void StrictPolicyImpl::Deactivate(void)
00190     throw (CORBA::SystemException)
00191 {
00192     /* XXX */
00193 }
00194 
00195 Broker::TaskList *StrictPolicyImpl::GetTaskList(void)
00196     throw (CORBA::SystemException)
00197 {
00198     Broker::TaskList_var retval;
00199     struct TaskPriority *tp;
00200     unsigned int lpc = 0;
00201     
00202     retval = new Broker::TaskList();
00203     retval->length(lnCountNodes((struct lnMinList *)&this->sp_List));
00204     tp = (struct TaskPriority *)this->sp_List.lh_Head;
00205     while( tp->tp_Link.ln_Succ != NULL )
00206     {
00207         (*retval)[lpc] = Broker::Task::_duplicate(tp->tp_Task.in());
00208         lpc += 1;
00209         tp = (struct TaskPriority *)tp->tp_Link.ln_Succ;
00210     }
00211     return( retval._retn() );
00212 }
00213 
00214 void StrictPolicyImpl::SetTaskPriority(Broker::Task_ptr task,
00215                                        CORBA::Short priority)
00216     throw (CORBA::SystemException)
00217 {
00218     Broker::RealTimeTask_var rtt;
00219     struct TaskPriority *tp;
00220 
00221     rtt = Broker::RealTimeTask::_narrow(task);
00222     if( CORBA::is_nil(rtt.in()) )
00223     {
00224         throw CORBA::BAD_PARAM();
00225     }
00226     if( (tp = this->FindTaskPriority(rtt.in())) == NULL )
00227     {
00228         throw CORBA::BAD_PARAM();
00229     }
00230 
00231     /* Remove from the list */
00232     lnRemove((struct lnMinNode *)&tp->tp_Link);
00233     /* ... set the new priority */
00234     tp->tp_Link.ln_Pri = (char)priority;
00235     /* ... and reinsert to get the new ordering. */
00236     lnEnqueue(&this->sp_List, &tp->tp_Link);
00237 }
00238 
00239 CORBA::Short StrictPolicyImpl::GetTaskPriority(Broker::Task_ptr task)
00240     throw (CORBA::SystemException)
00241 {
00242     Broker::RealTimeTask_var rtt;
00243     struct TaskPriority *tp;
00244     CORBA::Short retval;
00245 
00246     rtt = Broker::RealTimeTask::_narrow(task);
00247     if( CORBA::is_nil(rtt.in()) )
00248     {
00249         throw CORBA::BAD_PARAM();
00250     }
00251     if( (tp = this->FindTaskPriority(rtt.in())) == NULL )
00252     {
00253         throw CORBA::BAD_PARAM();
00254     }
00255 
00256     retval = tp->tp_Link.ln_Pri;
00257     return( retval );
00258 }
00259 
00260 struct StrictPolicyImpl::TaskPriority *
00261 StrictPolicyImpl::SubList(const RealTimeSchedule &rts,
00262                           struct TaskPriority *ignore)
00263 {
00264     CORBA::ULong start, stop, max_deadline = 0;
00265     struct TaskPriority *curr, *retval = NULL;
00266 
00267     start = rts.rts_Start;
00268     stop = rts.rts_Start + rts.rts_Deadline;
00269     retval = NULL;
00270 
00271     if( ignore != NULL )
00272     {
00273         max_deadline = ignore->tp_Schedule.rts_Deadline;
00274     }
00275     
00276     /* Walk the list to */
00277     curr = (struct TaskPriority *)this->sp_List.lh_Head;
00278     while( curr->tp_Link.ln_Succ != NULL )
00279     {
00280         /* ... see if they intersect and by how much */
00281         if( (curr != ignore) &&
00282             (curr->tp_SubTime = curr->tp_Schedule.intersect(start, stop)) > 0 )
00283         {
00284             curr->tp_SubLink = retval;
00285             retval = curr;
00286         }
00287         if( curr->tp_Schedule.rts_Deadline > max_deadline )
00288         {
00289             max_deadline = curr->tp_Schedule.rts_Deadline;
00290         }
00291         curr = (struct TaskPriority *)curr->tp_Link.ln_Succ;
00292     }
00293 
00294     {
00295         CORBA::ULong ct;
00296 
00297         ct = (CORBA::ULong)(this->sp_MaxUsedCPU * max_deadline);
00298         this->sp_FauxTask.tp_Schedule.rts_Period = max_deadline;
00299         this->sp_FauxTask.tp_Schedule.rts_Deadline = max_deadline;
00300         this->sp_FauxTask.tp_SubTime = ct;
00301         this->sp_FauxTask.tp_Task->SetComputeTime(ct);
00302         this->sp_FauxTask.tp_ComputeTime = ct;
00303     }
00304     
00305     return( retval );
00306 }
00307 
00308 CORBA::ULong StrictPolicyImpl::TakeCPU(struct TaskPriority *sub_list,
00309                                        CORBA::ULong amount,
00310                                        struct TaskPriority *for_tp)
00311 {
00312     float percent_cpu, percent_req_cpu, percent_total_cpu = 0.0;
00313     CORBA::ULong ct, new_ct, window_ct, new_window_ct;
00314     CORBA::ULong retval = 0;
00315     struct TaskPriority *tp;
00316 
00317     require(for_tp != NULL);
00318 
00319 #if defined(DEBUG)
00320     cout << "TakeCPU amount="
00321          << amount
00322          << "; for="
00323          << for_tp->tp_Task->Name()
00324          << "; start="
00325          << for_tp->tp_Schedule.rts_Start
00326          << "; period="
00327          << for_tp->tp_Schedule.rts_Period
00328          << "; deadline="
00329          << for_tp->tp_Schedule.rts_Deadline
00330          << endl;
00331 #endif
00332 
00333     /* Figure out the total percentage of CPU currently in use. */
00334 #if defined(DEBUG)
00335     cout << "\tName\tPri\tCPU\n";
00336 #endif
00337     for( tp = sub_list; tp != NULL; tp = tp->tp_SubLink )
00338     {
00339         CORBA::ULong sub_us;
00340         
00341         ct = tp->tp_ComputeTime;
00342         percent_cpu = (float)ct / (float)tp->tp_Schedule.rts_Deadline;
00343         sub_us = (CORBA::ULong)((float)tp->tp_SubTime * percent_cpu);
00344         percent_cpu = (float)sub_us / (float)for_tp->tp_Schedule.rts_Deadline;
00345         percent_total_cpu += percent_cpu;
00346 #if defined(DEBUG)
00347         cout << "\t"
00348              << tp->tp_Task->Name()
00349              << "\t"
00350              << tp->tp_Link.ln_Pri
00351              << "\t"
00352              << (percent_cpu * 100.0)
00353              << "%"
00354              << endl;
00355 #endif
00356     }
00357     percent_req_cpu = (float)amount / (float)for_tp->tp_Schedule.rts_Deadline;
00358 #if defined(DEBUG)
00359     cout << "\tSubtotal\t" << (percent_total_cpu * 100.0) << "%" << endl;
00360     cout << "\t" << for_tp->tp_Task->Name()
00361          << "\t" << for_tp->tp_Link.ln_Pri
00362          << "\t" << (percent_req_cpu * 100.0) << "%"
00363          << endl
00364          << "\tTotal\t\t"
00365          << ((percent_total_cpu + percent_req_cpu) * 100.0)
00366          << "%"
00367          << endl;
00368 #endif
00369     if( (percent_total_cpu + percent_req_cpu) <= this->sp_MaxUsedCPU )
00370     {
00371         /* There is still some free CPU, give it to the requester. */
00372         retval = amount;
00373     }
00374     else
00375     {
00376         float percent_free_cpu;
00377         CORBA::ULong free_ct;
00378 
00379         /* There is contention */
00380         percent_free_cpu = this->sp_MaxUsedCPU - percent_total_cpu -
00381             ((float)for_tp->tp_ComputeTime /
00382              (float)for_tp->tp_Schedule.rts_Deadline);
00383         if( percent_free_cpu < 0.0 )
00384         {
00385             /* Adjust for any rounding errors/etc... */
00386             percent_free_cpu = 0.0;
00387         }
00388         free_ct = (CORBA::ULong)(percent_free_cpu *
00389                                  (float)for_tp->tp_Schedule.rts_Deadline);
00390 #if defined(DEBUG)
00391         cout << "cpu free " << (percent_free_cpu * 100.0) << "%\n";
00392         cout << "already have " << for_tp->tp_ComputeTime << "..." << endl;
00393 #endif
00394         /*
00395          * The task already has some compute time, subtract that from what they
00396          * need.
00397          */
00398         amount -= for_tp->tp_ComputeTime;
00399         retval += for_tp->tp_ComputeTime;
00400         if( amount > free_ct )
00401         {
00402             /* The amount needed is greater than the available CPU */
00403             amount -= free_ct;
00404             retval += free_ct;
00405         }
00406         else
00407         {
00408             retval += amount;
00409             amount = 0;
00410         }
00411 #if defined(DEBUG)
00412         cout << "revoking " << amount << "..." << endl;
00413 #endif
00414         percent_total_cpu = 0.0;
00415         /*
00416          * Walk the list as long as more CPU is needed and the task has
00417          * priority over the others.
00418          */
00419         for( tp = sub_list;
00420              tp &&
00421                  (for_tp->tp_Link.ln_Pri > tp->tp_Link.ln_Pri) &&
00422                  (amount > 0);
00423              tp = tp->tp_SubLink )
00424         {
00425             float percent_orig_cpu;
00426 
00427             /* Convert their CPU usage to our time frame by */
00428             ct = tp->tp_ComputeTime;
00429             /* ... figuring out their total allocated percentage and */
00430             percent_orig_cpu = (float)ct / (float)tp->tp_Schedule.rts_Deadline;
00431             /*
00432              * ... multiplying that by the amount of time that both tasks
00433              * interesect
00434              */
00435             window_ct = (CORBA::ULong)(percent_orig_cpu *
00436                                        (float)tp->tp_SubTime);
00437             if( amount > window_ct )
00438             {
00439                 /*
00440                  * They don't have enough to satisfy the request, so take
00441                  * some of it away and look for more.
00442                  */
00443                 new_window_ct = 0;
00444             }
00445             else
00446             {
00447                 /* They have more than enough to satisfy the request. */
00448                 new_window_ct = window_ct - amount;
00449             }
00450             /* Convert the CPU percentage back to the tasks time frame. */
00451             percent_cpu = (float)new_window_ct / (float)tp->tp_SubTime;
00452             if( percent_cpu < this->sp_MinTaskCPU )
00453             {
00454                 percent_cpu = this->sp_MinTaskCPU;
00455                 new_window_ct = (CORBA::ULong)
00456                     (percent_cpu * (float)tp->tp_SubTime);
00457             }
00458             amount -= (window_ct - new_window_ct);
00459             retval += (window_ct - new_window_ct);
00460             percent_total_cpu += percent_cpu;
00461 #if defined(DEBUG)
00462             cout << "\t"
00463                  << tp->tp_Task->Name()
00464                  << "\t"
00465                  << (percent_orig_cpu * 100.0)
00466                  << "% -> "
00467                  << (percent_cpu * 100.0)
00468                  << "%"
00469                  << endl;
00470 #endif
00471             new_ct = (CORBA::ULong)((float)tp->tp_Schedule.rts_Deadline *
00472                                     percent_cpu);
00473             try
00474             {
00475                 tp->tp_Task->SetComputeTime(new_ct);
00476                 tp->tp_ComputeTime = new_ct;
00477             }
00478             catch(...)
00479             {
00480                 // assert(0);
00481             }
00482         }
00483         percent_req_cpu = (float)retval /
00484             (float)for_tp->tp_Schedule.rts_Deadline;
00485 #if defined(DEBUG)
00486         cout << "\tSubtotal\t" << (percent_total_cpu * 100.0) << "%" << endl;
00487         cout << "\tTotal\t"
00488              << ((percent_total_cpu + percent_req_cpu) * 100.0)
00489              << "%"
00490              << endl;
00491 #endif
00492     }
00493 
00494     if( retval < amount )
00495     {
00496         for_tp->tp_Flags |= TPF_STARVED;
00497     }
00498     else
00499     {
00500         for_tp->tp_Flags &= ~TPF_STARVED;
00501     }
00502 
00503 #if defined(DEBUG)
00504     cout << "end TakeCPU retval="
00505          << retval
00506          << endl;
00507 #endif
00508     
00509     return( retval );
00510 }
00511 
00512 CORBA::ULong StrictPolicyImpl::GiveCPU(struct TaskPriority *sub_list,
00513                                        CORBA::ULong amount,
00514                                        struct TaskPriority *for_tp)
00515 {
00516     float percent_cpu, percent_ret_cpu, percent_total_cpu = 0.0;
00517     CORBA::ULong ct, new_ct, window_ct, new_window_ct;
00518     CORBA::ULong retval = 0;
00519     struct TaskPriority *tp;
00520 
00521     require(for_tp != NULL);
00522 
00523     /* Very similar to TakeCPU */
00524 
00525 #if defined(DEBUG)
00526     try
00527     {
00528         cout << "GiveCPU amount="
00529              << amount
00530              << "; for="
00531              << for_tp->tp_Task->Name()
00532              << "; start="
00533              << for_tp->tp_Schedule.rts_Start
00534              << "; period="
00535              << for_tp->tp_Schedule.rts_Period
00536              << "; deadline="
00537              << for_tp->tp_Schedule.rts_Deadline
00538              << endl;
00539     }
00540     catch(const CORBA::SystemException &e)
00541     {
00542         cerr << e << endl;
00543     }
00544 #endif
00545 
00546 #if defined(DEBUG)
00547     cout << "\tName\tPri\tCPU\n";
00548 #endif
00549     for( tp = sub_list; tp != NULL; tp = tp->tp_SubLink )
00550     {
00551         CORBA::ULong sub_us;
00552         
00553         ct = tp->tp_ComputeTime;
00554         percent_cpu = (float)ct / (float)tp->tp_Schedule.rts_Deadline;
00555         sub_us = (CORBA::ULong)((float)tp->tp_SubTime * percent_cpu);
00556         percent_cpu = (float)sub_us / (float)for_tp->tp_Schedule.rts_Deadline;
00557 #if defined(DEBUG)
00558         try
00559         {
00560             cout << "\t"
00561                  << tp->tp_Task->Name()
00562                  << "\t"
00563                  << tp->tp_Link.ln_Pri
00564                  << "\t"
00565                  << (percent_cpu * 100.0)
00566                  << "%"
00567                  << endl;
00568         }
00569         catch(const CORBA::SystemException &e)
00570         {
00571             cerr << e << endl;
00572         }
00573 #endif
00574         percent_total_cpu += percent_cpu;
00575     }
00576     percent_ret_cpu = (float)amount / (float)for_tp->tp_Schedule.rts_Deadline;
00577 #if defined(DEBUG)
00578     cout << "\tSubtotal\t" << (percent_total_cpu * 100.0) << "%" << endl;
00579     try
00580     {
00581         cout << "\t" << for_tp->tp_Task->Name()
00582              << "\t" << for_tp->tp_Link.ln_Pri
00583              << "\t" << (percent_ret_cpu * 100.0) << "%"
00584              << endl
00585              << "\tTotal\t\t"
00586              << ((percent_total_cpu + percent_ret_cpu) * 100.0)
00587              << "%"
00588              << endl;
00589     }
00590     catch(const CORBA::SystemException &e)
00591     {
00592         cerr << e << endl;
00593     }
00594 #endif
00595     {
00596 #if defined(DEBUG)
00597         cout << "returning " << amount << "..." << endl;
00598 #endif
00599         for( tp = sub_list; tp && (amount > 0); tp = tp->tp_SubLink )
00600         {
00601             float percent_orig_cpu;
00602 
00603             /*
00604              * Only give CPU to those tasks that are actually starved and need
00605              * it.
00606              */
00607             if( !(tp->tp_Flags & TPF_STARVED) )
00608             {
00609                 continue;
00610             }
00611             ct = tp->tp_ComputeTime;
00612             percent_orig_cpu = (float)ct / (float)tp->tp_Schedule.rts_Deadline;
00613             window_ct = (CORBA::ULong)(percent_orig_cpu *
00614                                        (float)tp->tp_SubTime);
00615             if( (window_ct + amount) < tp->tp_Schedule.rts_Deadline )
00616             {
00617                 new_window_ct = window_ct + amount;
00618                 amount = 0;
00619             }
00620             else
00621             {
00622                 CORBA::ULong diff;
00623 
00624                 diff = tp->tp_Schedule.rts_Deadline - window_ct;
00625                 new_window_ct = window_ct + (diff / 2);
00626                 amount -= diff / 2;
00627             }
00628             percent_cpu = (float)new_window_ct / (float)tp->tp_SubTime;
00629 #if defined(DEBUG)
00630             try
00631             {
00632                 cout << "\t"
00633                      << tp->tp_Task->Name()
00634                      << "\t"
00635                      << (percent_orig_cpu * 100.0)
00636                      << "% -> "
00637                      << (percent_cpu * 100.0)
00638                      << "%"
00639                      << endl;
00640             }
00641             catch(const CORBA::SystemException &e)
00642             {
00643                 cerr << e << endl;
00644             }
00645 #endif
00646             new_ct = (CORBA::ULong)((float)tp->tp_Schedule.rts_Deadline *
00647                                     percent_cpu);
00648             try
00649             {
00650                 tp->tp_Task->SetComputeTime(new_ct);
00651                 tp->tp_ComputeTime = new_ct;
00652             }
00653             catch(const CORBA::Exception &e)
00654             {
00655                 cerr << "SetComputeTime failed: " << e << endl;
00656             }
00657             catch(...)
00658             {
00659                 cerr << "** Give failed: " << new_ct << endl;
00660             }
00661         }
00662     }
00663 
00664 #if defined(DEBUG)
00665     cout << "end GiveCPU retval="
00666          << retval
00667          << endl;
00668 #endif
00669 
00670     return( retval );
00671 }
00672 
00673 void StrictPolicyImpl::RepairTaskList(void)
00674 {
00675     struct TaskPriority *curr, *succ;
00676 
00677     curr = (struct TaskPriority *)this->sp_List.lh_Head;
00678     while( curr->tp_Link.ln_Succ != NULL )
00679     {
00680         succ = (struct TaskPriority *)curr->tp_Link.ln_Succ;
00681         try
00682         {
00683             curr->tp_Task->GetComputeTime();
00684         }
00685         catch(const CORBA::TRANSIENT &e)
00686         {
00687             this->GiveCPU(this->SubList(curr->tp_Schedule, curr),
00688                           curr->tp_ComputeTime,
00689                           curr);
00690             lnRemove((struct lnMinNode *)&curr->tp_Link);
00691             delete curr;
00692         }
00693         curr = succ;
00694     }
00695 
00696 }
00697 
00698 struct StrictPolicyImpl::TaskPriority *
00699 StrictPolicyImpl::FindTaskPriority(Broker::RealTimeTask_ptr task)
00700 {
00701     struct TaskPriority *curr, *retval = NULL;
00702 
00703     require(task != NULL);
00704     
00705     curr = (struct TaskPriority *)this->sp_List.lh_Head;
00706     while( (retval == NULL) && (curr->tp_Link.ln_Succ != NULL) )
00707     {
00708         if( task->_is_equivalent(curr->tp_Task.in()) )
00709         {
00710             retval = curr;
00711         }
00712         curr = (struct TaskPriority *)curr->tp_Link.ln_Succ;
00713     }
00714 
00715     if( retval == NULL )
00716     {
00717         cerr << "Unknown task" << endl;
00718         throw Broker::Internal("FindTaskPriority failed to find task");
00719     }
00720     
00721     return( retval );
00722 }
00723 
00724 void StrictPolicyImpl::ChangeTaskCPU(Broker::RealTimeTask_ptr task,
00725                                      CORBA::ULong ct,
00726                                      CORBA::ULong status,
00727                                      CORBA::ULong advice)
00728     throw (CORBA::SystemException, Broker::InvalidState)
00729 {
00730     struct TaskPriority *tp;
00731 
00732     require(task != NULL);
00733 
00734 #if defined(DEBUG)
00735     cout << "policy: ct="
00736          << ct
00737          << "; status="
00738          << status
00739          << "; advice="
00740          << advice
00741          << endl;
00742 #endif
00743     if( (tp = this->FindTaskPriority(task)) != NULL )
00744     {
00745         struct TaskPriority *sub_list;
00746         CORBA::ULong compute_us;
00747 
00748         /* Find the list of tasks that this one competes with and */
00749         sub_list = this->SubList(tp->tp_Schedule, tp);
00750         compute_us = tp->tp_ComputeTime;
00751         if( advice >= compute_us )
00752         {
00753             /* ... try to take CPU away from them for the task. */
00754             advice = this->TakeCPU(sub_list, advice, tp);
00755         }
00756         /* Finally, set their new compute time. */
00757         try
00758         {
00759             task->SetComputeTime(advice);
00760             tp->tp_ComputeTime = advice;
00761         }
00762         catch(const CORBA::Exception &e)
00763         {
00764             cerr << "SetComputeTime failed: " << e << endl;
00765         }
00766         catch(...)
00767         {
00768             cerr << "** Change failed: " << advice << endl;
00769         }
00770         if( advice < compute_us )
00771         {
00772             /* ... give back CPU that was taken away from them. */
00773             this->GiveCPU(sub_list, compute_us - advice, tp);
00774         }
00775     }
00776     else
00777     {
00778         throw Broker::InvalidState("AddTask must be called first");
00779     }
00780 }

Generated on Mon Dec 1 16:29:07 2003 for CPU Broker by doxygen 1.3.4