Logo Search packages:      
Sourcecode: u++ version File versions

uStaticPriorityQ.cc

//                              -*- Mode: C++ -*- 
// 
// uC++ Version 5.0.1, Copyright (C) Ashif S. Harji 2000
// 
// uStaticPriorityQ.cc -- 
// 
// Author           : Ashif S. Harji
// Created On       : Mon Feb  1 15:06:12 1999
// Last Modified By : Peter A. Buhr
// Last Modified On : Sat Jun 26 19:20:25 2004
// Update Count     : 126
//
// This  library is free  software; you  can redistribute  it and/or  modify it
// under the terms of the GNU Lesser General Public License as published by the
// Free Software  Foundation; either  version 2.1 of  the License, or  (at your
// option) any later version.
// 
// This library is distributed in the  hope that it will be useful, but WITHOUT
// ANY  WARRANTY;  without even  the  implied  warranty  of MERCHANTABILITY  or
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
// for more details.
// 
// You should  have received a  copy of the  GNU Lesser General  Public License
// along  with this library.
// 

#define __U_KERNEL__
#include <uC++.h>
#include <uStaticPriorityQ.h>
#include <uStaticPIQ.h>
//#include <uDebug.h>

#define uLockAcquired  0
#define uLockReleased  1


uStaticPriorityQ::uStaticPriorityQ() {                      
    uMask = 0;
    uExecuteHooks = true;
    uCurrPriority = -1;
} // uStaticPriorityQ::uStaticPriorityQ

bool uStaticPriorityQ::uEmpty() const {               
    return uMask == 0;
} // uStaticPriorityQ::uEmpty

uBaseTaskDL *uStaticPriorityQ::uHead() const {              
    int highestPriority = ffs( uMask ) - 1;

    if ( highestPriority >= 0 ) {
      uBaseTaskDL *node = uObjects[highestPriority].uHead();
      return node;
    } else {
      return NULL;
    } // if
} // uStaticPriorityQ::uHead

int uStaticPriorityQ::uAdd( uBaseTaskDL *node, uBaseTask *uOwner ) {
    // Dynamic check to verify that the task being added to entry queue is
    // compliant with PIHeap type.
    uStaticPIQ *PIQptr = dynamic_cast<uStaticPIQ *>(node->uGet().uPIQ);
    if ( PIQptr == NULL ) {
    //return uLockAcquired; // TEMPORARY
      uAbort("(uStaticPriorityQ &)0x%p.uAdd: Task 0x%p has incorrect uPIQ type for mutex object", this, &node->uGet());
    } //if
    
    // check if your priority needs to be updated
    if ( PIQptr->uGetHighestPriority() < uGetActivePriorityValue( node->uGet() )  ) {
      uThisCluster().uTaskSetPriority( node->uGet(), node->uGet() );
    } // if

    // As uCurrentSerial is updated, the calling task's priority can no longer
    // change because the tasks uPIQ is fixed as the entry lock is acquired.
    // So subsequent updates will only reaffirm the task's current priority.

    int priority = uGetActivePriorityValue( node->uGet() );

    uAssert( 0 <= priority && priority <= __U_MAX_NUMBER_PRIORITIES__ - 1 );
    uObjects[priority].uAdd( node );
    uMask |= 1ul << priority;

    // only perform inheritance for entry list
    if ( /* this == &(s->uEntryList) */ uIsEntryBlocked( node->uGet() ) && uCheckHookConditions( *uOwner, node->uGet() ) ) {  // TEMP: entry queue??
      return( uAfterEntry( uOwner ) );          // perform any priority inheritance
    } else {
      return uLockAcquired;
    } // if

} // uStaticPriorityQ::uAdd

uBaseTaskDL *uStaticPriorityQ::uDrop() {                    
    int highestPriority = ffs( uMask ) - 1;

    if ( highestPriority >= 0 ) {
      uBaseTaskDL *node = uObjects[highestPriority].uDrop();
      if ( uObjects[highestPriority].uEmpty() ) {
          uMask &= ~ ( 1ul << highestPriority );
      } // if
      return node;
    } else {
      return NULL;
    } // if
} // uStaticPriorityQ::uDrop

void uStaticPriorityQ::uRemove( uBaseTaskDL *node ) {       
    // use stored priority value because this task has entry lock, so its uPIQ may
    // be updated, but not its position on the entry queue.
    int priority = uGetActivePriorityValue( node->uGet() );

    uObjects[priority].uRemove( node );
    if ( uObjects[priority].uEmpty() ) {
      uMask &= ~ ( 1ul << priority );
    } // if
} // uStaticPriorityQ::uRemove


int uStaticPriorityQ::uAfterEntry(uBaseTask *uOwner ) { // use pointer to owner as it could be Null
    // static_cast to uStaticPIQ are valid here as uAdd and uOnAcquire already
    // verify that the associated tasks use type uStaticPIQ.

    // assume entry lock acquired
    int uRelPrevLock = uLockAcquired;

    // if entry queue empty (called by owner) or no owner, then no inheritance
    if ( uEmpty() || uOwner == NULL /* || uCurrPriority == -1 */ ) {
      return uRelPrevLock;
    } // if

    uBaseTask &uCalling = uHead()->uGet();            // can't be NULL as not empty 

    // does node need to be updated?
    if ( uCalling.uGetActivePriorityValue() < uCurrPriority ) { 
        // only task with entry lock can be modifying this mutex's node
      // remove node
      (static_cast<uStaticPIQ *>(uOwner->uPIQ))->uRemove( uCurrPriority );
      
      // reset priority value for monitor
      uCurrPriority = uCalling.uGetActivePriorityValue();

        // update mutex owner's uPIQ for new priority
      (static_cast<uStaticPIQ *>(uOwner->uPIQ))->uAdd( uCurrPriority ) ;  
    
      // does inheritance occur ?
      if ( uCurrPriority < uOwner->uGetActivePriorityValue() ) {
          
          uRepositionEntry rep(*uOwner, uCalling);
          //uSerial *uRememberSerial = &(uOwner->uGetSerial());
            // if task is blocked on entry list, adjust and perform transitivity
          if ( uIsEntryBlocked( *uOwner ) ) {

            uRelPrevLock = rep.uReposition(true);
            //uRepositionWrapper( uOwner, uRememberSerial, s );
            //uRememberSerial->lock.uAcquire();
            
            // if owner's current mutex object changes, then owner fixes
            // its own active priority. Recheck if inheritance is necessary
            // as only owner can lower its priority => updated
            //if ( uRememberSerial != &(uOwner->uGetSerial()) || ! uIsEntryBlocked( *uOwner ) ||
            //    (static_cast<uStaticPIQ *>(uOwner->uPIQ))->uGetHighestPriority() >= uOwner->uGetActivePriorityValue() ) {
            // As owner restarted, the end of the blocking chain has been reached.
            //uRememberSerial->lock.uRelease();
            //return uRelPrevLock;
            //} // if

            //s->lock.uRelease();  // release the old lock as correct current lock is acquired
            //uRelPrevLock = uLockReleased;
            
            //if ( uReposition( uOwner, uRememberSerial ) == uLockAcquired ) {
            // only last call does not release lock, so reacquire first entry lock
            //uThisTask().uGetSerial().lock.uAcquire();
            //uRememberSerial->lock.uRelease();
            //} // if
            
                // proceed with transitivity
            // remove from entry queue
            //uRememberSerial->uEntryList.uRemove( &(uOwner->uEntryRef) ); 
            // remove from mutex queue
            //uOwner->uCalledEntryMem->uRemove( &(uOwner->uMutexRef) );
            
            // call cluster routine to adjust ready queue and active
            // priority as owner is not on entry queue, it can be updated
            // based on its uPIQ
            //uThisCluster().uTaskSetPriority( *uOwner, *uOwner );
            
            // add to mutex queue
            //uOwner->uCalledEntryMem->uAdd( &(uOwner->uMutexRef), uRememberSerial->uMutexOwner, uRememberSerial );
            
            // add to entry queue, automatically does transitivity
            //if ( uRememberSerial->uEntryList.uAdd( &(uOwner->uEntryRef), uRememberSerial->uMutexOwner, uRememberSerial ) == uLockAcquired ) {
                    // only last call does not release lock, so reacquire first entry lock
            //uThisTask().uCurrentSerial->lock.uAcquire();
            //uRememberSerial->lock.uRelease();
            //} // if
            
          } else {
                // call cluster routine to adjust ready queue and active
                // priority Note: can only raise priority to at most uCalling,
                // otherwise updating uOwner's priority can conflit with the
                // uOwner blocking on an entry queue at a particular priority
                // level.  Furthermore, uCalling's priority is fixed while the
                // entry lock of where it is blocked (s->lock) is acquired, but
                // uThisTask()'s priority can change as entry lock's are
                // released along inheritance chain.
            uThisCluster().uTaskSetPriority( *uOwner, uCalling );
          } // if
      } // if
    } // if

    return uRelPrevLock;
} // uStaticPriorityQ::uAfterEntry


void uStaticPriorityQ::uOnAcquire(uBaseTask &uOwner ) {
    // Dynamic check to verify that the task acquiring the serial is compliant
    // with PIHeap type.
    uStaticPIQ *PIQptr = dynamic_cast<uStaticPIQ *>(uOwner.uPIQ);
    if ( PIQptr == NULL ) {
      uAbort("(uStaticPriorityQ &)0x%p.uOnAcquire : Task 0x%p has incorrect uPIQ type for mutex object", this, &uOwner);
    } //if

    // check if mutex owner's priority needs to be updated
    if ( PIQptr->uGetHighestPriority() < uGetActivePriorityValue( uOwner ) ) {
      uThisCluster().uTaskSetPriority( uOwner, uOwner );
    } // if

    // remember current priority value, update task's uPIQ
    uCurrPriority = uOwner.uGetBasePriority();

    PIQptr->uAdd( uCurrPriority );

    // perform priority inheritance
    uAfterEntry( &uOwner );
} // uStaticPriorityQ::uOnAcquire


void uStaticPriorityQ::uOnRelease(uBaseTask &uOldOwner ) {
    // static_cast to PIHeap are valid here as uAdd and uOnAcquire already
    // verify that the associated tasks use type uStaticPIQ.

    // update task's uPIQ, reset stored values
    (static_cast<uStaticPIQ *>(uOldOwner.uPIQ))->uRemove( uCurrPriority ); 
    uCurrPriority = -1;

    // reset active priority if necessary
    // only case where priority can decrease
    if ( (static_cast<uStaticPIQ *>(uOldOwner.uPIQ))->uEmpty() || (static_cast<uStaticPIQ *>(uOldOwner.uPIQ))->uGetHighestPriority() > uGetActivePriorityValue( uOldOwner ) ) {
      uThisCluster().uTaskSetPriority( uOldOwner, uOldOwner );
    } // if
} // uStaticPriorityQ::uOnRelease

// Local Variables: //
// compile-command: "gmake install" //
// End: //

Generated by  Doxygen 1.6.0   Back to index