Esempio n. 1
0
NABoolean ex_queue::allocateAtps(CollHeap * space,
				 atp_struct * atps,
				 queue_index numNewAtps,
				 Int32 atpSize,
				 NABoolean failureIsFatal)
{
  queue_index      i;

  // remember that we need ATPs for this queue
  needsAtps_ = TRUE;

  // if the number of needed ATPs is not passed in, assume that all
  // queue entries need an ATP
  if (atps == NULL)
    {
      // initially try to get a whole array of ATP's rather than one
      // at a time We are sent back the size of the atp struct since
      // it also allocates space for number of tuples per criDesc.
      numNewAtps = size_;
#pragma nowarn(1506)   // warning elimination 
      atps = allocateAtpArray( criDesc_, numNewAtps, &atpSize, space, failureIsFatal);
#pragma warn(1506)  // warning elimination 
    }

  // check whether the caller provided the ATPs or whether we were
  // successful in allocating them as an array
  if (atps)
    {
      ex_assert(atpSize >= sizeof(atp_struct),
		"Invalid ATP size passed to ex_queue::allocateAtps()");
      for(i = 0; i < size_; i++)
	{
	  if (queue_[i].atp_ == NULL)
	    {
	      ex_assert(numNewAtps != 0,
			"There are more empty queue entries than new ATPs");
	      numNewAtps--;
	      queue_[i].atp_ = atps;
	      atps = (atp_struct *) ((char *)atps + atpSize);
	    }
	}
    }
  else 
    // Didn't get enough space to get all of them at one shot so do
    // it one at a time.
  // Allocate space for the tuples in each atp
  // Allocate the atp if it has not been allocated yet
  for(i = 0; i<size_; i++)
  {
	if (queue_[i].atp_ == NULL)
	  {
	    queue_[i].atp_ = allocateAtpArray(criDesc_, 1, &atpSize, space, failureIsFatal);
	    if (!failureIsFatal && queue_[i].atp_ == NULL)
	      return FALSE; // let user handle the failure
	    ex_assert(queue_[i].atp_,"Memory Allocation Fatal Failure Expected but Jump Buffer does not seem to be set!");
	  }
  }
  atpsAllocated_ = TRUE;
  return TRUE;
}
Esempio n. 2
0
queue_index ex_queue::resize(ex_tcb *    tcb,
			     queue_index newSize)
{
  queue_index          sizeDelta;
  Space                *space = tcb->getSpace();
  ex_queue_entry       *newQueue;
  queue_index          newMask;
  Int32                  queueWasFull = isFull();
  NABoolean            needAtps = needsAtps();
  Int32                  atpSize = 0;
  atp_struct           *atps = NULL;
  queue_index          numAllocatedAtps = 0;
  ex_tcb_private_state *pstates = NULL;
  Lng32                 numAllocatedPstates = 0;
  Lng32                 pstateLength = 0;
  queue_index          qi;
  queue_index          lastEntryToCopy;
  ex_queue_entry       *oldQueue = queue_;
  const queue_index    oldSize = size_;
  const queue_index    oldMask = mask_;
  
  // the new size must be a power of 2, round up to the next power of 2
  queue_index p2 = size_;
  while (p2 < newSize && p2 != 0)
    p2 = p2 << 1;
  // p2 is now a power of 2 that is >= newSize, except that
  // it is 0 in some unsupported cases, like size_ being 0 or newSize
  // being too large to be rounded up to a power of 2
  newSize = p2;

  // can't resize to a smaller size
  if (newSize <= size_)
    return size_;

  sizeDelta = newSize - size_;
  newMask   = newSize - 1;

  // try to allocate the needed memory first and give up if that's not
  // possible

  // allocate new array of ex_queue_entry structs
  newQueue = (ex_queue_entry *) (space->allocateMemory(
       newSize * sizeof(ex_queue_entry),FALSE));
  if (newQueue == NULL)
    return size_; // out of memory

  // allocate array of ATPs if needed
  if (needAtps)
    {
      atps = allocateAtpArray(criDesc_, sizeDelta, &atpSize, space, FALSE);

      // for now, give up if it wasn't possible to allocate the ATPs in
      // one piece (one could try to allocate them one by one)
      if (atps == NULL)
	return size_; 

      numAllocatedAtps = sizeDelta;
    }

  // allocate an array of pstate objects if needed
  if (needsPstates_)
    {
      numAllocatedPstates = sizeDelta;
      pstates = tcb->allocatePstates(numAllocatedPstates,pstateLength);
      if (pstates == NULL)
	{
	  // either the TCB doesn't support the allocatePstates()
	  // method yet (it would be a dumb thing for a TCB not to
	  // support this AND to call the resize method) or we don't
	  // have enough memory. Give up without changing the size.
	  return size_;
	}
    }

  // at this point we have allocated everything we need, so we
  // should be in good shape from now on

  // initialize the new queue
  for(qi = 0; qi < newSize; qi++)
    {
      // Initialize private state pointer
      newQueue[qi].pstate = NULL;
      
      // initialize the public state
      newQueue[qi].initializeState(upDown_);
      
      // Initialize the pointer to the atp_struct
      newQueue[qi].atp_ = NULL;
    }

  // calculate last entry to copy (the addition here may wrap around
  // such that <lastEntryToCopy> is actually smaller than <head_>)
  lastEntryToCopy = head_ + size_;

  // Copy all queue entries (whether they are in use or not) over to
  // the new queue. Do this in such a way that the used entries move
  // to the new queue entry that corresponds to their index. Note
  // that we will start copying the used entries (if any) first, and
  // that those are the first entries until (but not including) the
  // entry where qi is equal to <tail_>.
  for (qi = head_; qi != lastEntryToCopy; qi++)
    {
      newQueue[qi & newMask] = queue_[qi & mask_];
    }

  // At this point, <size_> elements of the new queue are initialized
  // with actual queue entries, while <sizeDelta> entries may still
  // need ATPs and/or pstates (if applicable). These sizeDelta entries
  // will be taken care of next by using the regular allocation methods
  // for new queues. Note that the ATPs and PSTATEs of the remaining
  // entries may or may not be contiguous.

  // reset counter that counts empty/full transitions
  resizePoints_ = 0;
  needsResize_ = FALSE;

  // set the data member to point to the newly allocated structures
  queue_ = newQueue;
  size_  = newSize;
  mask_  = newMask;

  NABoolean finalAllocSucceeded = TRUE;

  // initialize the uninitialized ATPs if required to do so
  if (needAtps)
    finalAllocSucceeded = allocateAtps(space,
				       atps,
				       numAllocatedAtps,
				       atpSize,
				       FALSE);

  // allocate PSTATEs for the uninitialized queue entries if this
  // queue needs PSTATEs
  if (needsPstates_ && finalAllocSucceeded)
    {
      finalAllocSucceeded = allocatePstate(tcb,
					   pstates,
					   numAllocatedPstates,
					   pstateLength,
					   FALSE);
    }

  if (finalAllocSucceeded)
    {
      // schedule the unblock subtask of the queue if the queue was full
      // before the resize and now is no longer full (a deadlock could
      // occur if we wouldn't schedule the unblock task for a full to
      // not full transition of a queue)
      if (queueWasFull)
	unblockSubtask_->schedule();
    }
  else
    {
      // We failed during allocation of ATPs or PStates. Undo the switch
      // to the new, resized queue and restore the queue to its old state.
      queue_ = oldQueue;
      size_  = oldSize;
      mask_  = oldMask;
    }

  return size_;
}