示例#1
0
  void queue(std::vector<t_atom>alist) {
    if(alist.size()>0)
      qQueue.push_back(alist);

    requeue();
  }
示例#2
0
文件: atropos.c 项目: berkus/nemesis
void ksched_scheduler(addr_t             stp,
		      dcb_ro_t 	        *cur_dcb,
		      context_t 	*cur_ctxt )
{
    kernel_st   *st = (kernel_st *)stp;
    SDom_t	*cur_sdom;              /* Current sdom		*/
    Time_ns 	 time;			/* Current time? 		*/
    Time_ns	 itime;			/* Time on interval timer	*/
    Time_ns	 newtime;		/* What to set the itimer to	*/
    Time_ns      ranfor;	        /* How long the domain ran      */
    dcb_ro_t	*dcb;			/* tmp. domain control block	*/
    dcb_rw_t	*dcbrw;
    SDom_t	*sdom;			/* tmp. scheduling domain	*/
    bool_t       blocking;	        /* does the domain wish to block? */
    Activation_Reason   reason;
    

    /* Increment the heartbeat counter in the PIP.  This allows 
       benchmark code, etc. to see how many passes through the scheduler 
       happened as a result of certain tests - useful for spotting bugs! */
    INFO_PAGE.sheartbeat++;

    /* Squash timer and read the time */
    time = Timer$Clear(st->t, &itime);

    /* Give the Measure boys a change to do their stuff */
    MEASURE(ac_measure(st, time)); 

    /* If we were spinning in the idle loop, there is no current
     * domain to deschedule. */
    if (cur_dcb == NULL) {
	goto deschedule_done;
    }

    /*****************************
     * 
     * Deschedule the current scheduling domain
     *
     ****************************/
    
    dcbrw = DCB_RO2RW(cur_dcb);

#ifndef __IX86__
    /* We enable activations here for an RFABlock to avoid trashing
       the actctx on the way into the scheduler.  Turn on activations
       and then treat just like a block */
    if (cur_dcb->schst == DCBST_K_RFABLOCK) {
	dcbrw->mode = 0;
	cur_dcb->schst = DCBST_K_BLOCK;
    }
#endif    

#if defined(INTEL) || defined(__ARM__)
    /* Send any delayed events */
    while(cur_dcb->outevs_processed < dcbrw->outevs_pushed) {
	word_t next_event = cur_dcb->outevs_processed + 1;
	dcb_event *ev = &dcbrw->outevs[next_event % NUM_DCB_EVENTS];
#ifdef INTEL
	k_dsc_send(ev->ep, ev->val);
#else
	k_sc_send(ev->ep, ev->val);
#endif
	cur_dcb->outevs_processed++;
    }
#endif

    /* Record the time the domain was preempted and for how long it
       ran.  Work out if the domain is going to be blocked to save
       some pointless queue shuffling */
    cur_sdom = st->cur_sdom;
    cur_sdom->lastdsch = time;
    ranfor = (time - cur_sdom->lastschd);
    blocking = (cur_dcb->schst == DCBST_K_BLOCK) && EP_FIFO_EMPTY (dcbrw);

    if ((cur_sdom->state == sdom_run) ||
	(cur_sdom->state == sdom_unblocked)) {

	/* In this block, we are doing accounting for an sdom which has 
	   been running in contracted time.  Note that this could now happen
	   even if the domain is on the wait queue (i.e. if it blocked) */

	/* Deduct guaranteed time from the domain */
	cur_sdom->remain  -= ranfor;
	cur_sdom->ac_time += ranfor;
	MEASURE(cur_sdom->ac_m_tm += ranfor); 

	/* If guaranteed time has run out... */
	if (!blocking && (cur_sdom->remain <= 0)) {
	    /* Move domain to correct position in WAIT queue */
            /* XXX sdom_unblocked doesn't need this since it is 
	     already in the correct place. */
	    dequeue(st, cur_sdom);
	    cur_sdom->state = sdom_wait;
	    requeue(st, cur_sdom);
	} 

    } else {
      
	/*
	 * In this block, the sdom was running optimistically - so no
	 * accounting is necessary. The sdom is not the head of the 
	 * run queue, but st->next_optm gives its position 
	 * in the wait queue 
	 */
	cur_sdom->ac_x += ranfor;
	MEASURE(cur_sdom->ac_m_tm += ranfor);
    }

    /******************
     * 
     * If the domain wishes to block, then block it.
     *
     * We only block a domain if it has no events in the fifo - this 
     * is to avoid the "wake-up-waiting" race 
     *
     *******************/
    if (blocking) { 
	/* Remove the domain from whichever queue and block it */
	dequeue(st, cur_sdom);
	block(st, cur_sdom);
    }
    
  deschedule_done:
    
    /*****************************
     * 
     * We have now successfully descheduled the current sdom.
     * The next task is the allocate CPU time to any sdom it is due to.
     *
     ****************************/
    cur_dcb =  (dcb_ro_t *)0;
    cur_sdom = (SDom_t *)0;
    
    /*****************************
     * 
     * Allocate CPU to any waiting domains who have passed their
     * period deadline.  If necessary, move them to run queue.
     *
     ****************************/
    while(PQ_SIZE(st->wait) && 
	  (sdom = PQ_HEAD(st->wait))->deadline <= time ) {
	
	/* Remove from HEAD of wait queue */
	PQ_REMOVE(st->wait);

	/* Domain begins a new period and receives a slice of CPU 
	 * If this domain has been blocking then throw away the
	 * rest of it's remain - it can't be trusted */
	if (sdom->remain > 0) 
	    sdom->remain = sdom->slice;
    	else 
	    sdom->remain += sdom->slice;
	sdom->prevddln = sdom->deadline;
	sdom->deadline += sdom->period;
	sdom->state = (sdom->remain > 0) ? sdom_run : sdom_wait;

	/* Place on the appropriate queue */
	requeue(st, sdom);

	/* Update the accounts */
	endofperiod(sdom, time);
    }
    
    /*****************************
     * 
     * Next we must handle all domains to which new events have been
     * delivered.  These domains will have been placed in a fifo by
     * the event send code.
     *
     ****************************/
    
    while (st->domq.tail != st->domq.head)  {
	/* Let the event delivery mechanism know we've seen this one. */
	st->domq.tail = (st->domq.tail + 1) % CFG_UNBLOCK_QUEUE_SIZE;
	dcb   = st->domq.q[st->domq.tail];
	sdom  = dcb->sdomptr;

	/*
	 * Do not reschedule stopped or dying domains.
	 * They are not on ANY queue, but other domains may still
	 * send them events.
	 */
	if (dcb->schst == DCBST_K_STOPPED ||
	    dcb->schst == DCBST_K_DYING) continue;

	/* Unblock the domain if necessary */
	if(sdom->state == sdom_block) {

	    /* Remove from the MIDDLE of the blocked queue */
	    dequeue(st, sdom);

	    /* Unblock and move to the appropriate queue */
	    unblock(st, sdom, time);
	    requeue(st, sdom);
	}
    }
    
    /*****************************
     * 
     * Next we must handle all domains whose block timeouts have expired.
     * Currently we treat a timeout as though an event had arrived.  
     *
     ****************************/
    
    /* Wake up any blocked domains whose timeout has expired */
    while(PQ_SIZE(st->blocked) && 
	  (sdom = PQ_HEAD(st->blocked))->deadline <= time ) {
	
	/* Remove from HEAD of blocked queue */
	PQ_REMOVE(st->blocked);
	
	/* Unblock and move to the appropriate queue */
	unblock(st, sdom, time);
	requeue(st, sdom);
    }
    
    /*****************************
     * 
     * Next we need to pick an sdom to run.
     * If anything is actually 'runnable', we run that. 
     * If nothing is, we pick a waiting sdom to run optimistically.
     * If there aren't even any of those, we have to spin waiting for an
     * event or a suitable time condition to happen.
     *
     ****************************/
    
    newtime = FOREVER;
    reason = 0;

    /* If we have an sdom on the RUN queue, then run it. */
    if (PQ_SIZE(st->run)) {
	
	cur_sdom = PQ_HEAD(st->run);
	cur_dcb = cur_sdom->dcb;
	newtime = time + cur_sdom->remain;
	reason  = (cur_sdom->prevddln > cur_sdom->lastschd) ?
	    Activation_Reason_Allocated : Activation_Reason_Preempted;
	
    } else if (PQ_SIZE(st->wait)) {

	int i;

	/* Try running a domain on the WAIT queue - this part of the
	   scheduler isn't particularly efficient but then again, we
	   don't have any guaranteed domains to worry about. */
	
	/* See if there are any unblocked domains on the WAIT
	   queue who we can give preferential treatment to. */
	for (i = 1; i <= PQ_SIZE(st->wait); i++) {
	    sdom = PQ_NTH(st->wait, i);
	    if (sdom->state == sdom_unblocked) {
		cur_sdom = sdom;
		cur_dcb  = sdom->dcb;
		newtime  = time + sdom->remain;
		reason   = Activation_Reason_Preempted;
		goto found;
	    }
	}

	/* Last chance: pick a domain on the wait queue with the XTRA
	   flag set.  The NEXT_OPTM field is used to cheaply achieve
	   an approximation of round-robin order */
	for (i = 0; i < PQ_SIZE(st->wait); i++) {
	    /* Pick (roughly) the next domain on the wait q. */
	    if (++(st->next_optm) > PQ_SIZE(st->wait)) 
		st->next_optm = 1;
	    
	    sdom = PQ_NTH(st->wait, st->next_optm);
	    if (sdom->xtratime) {	
		cur_sdom = sdom;
		cur_dcb  = sdom->dcb;
		newtime = time + BESTEFFORT_QUANTUM;
		reason  = Activation_Reason_Extra;
		goto found;
	    }
	}

    }
    
    found:

    /**********************
     * 
     * We now have to work out the time when we next need to
     * make a scheduling decision.  We set the alarm timer
     * to cause an interrupt at that time.
     *
     **********************/
     
    /* If we might be able to run a waiting domain before this one has */
    /* exhausted its time, cut short the time allocation */
    if (PQ_SIZE(st->wait))
	newtime = MIN(newtime, PQ_HEAD(st->wait)->deadline);
    
    /* If necessary reenter the scheduler to wake up blocked domains */ 
    if (PQ_SIZE(st->blocked))
	newtime = MIN(newtime, PQ_HEAD(st->blocked)->deadline);

    MEASURE(newtime = MIN(newtime, ac_next));

    /* Set timer for newtime */
    Timer$Set(st->t, newtime);  
    
    MEASURE_TRACE(Trace$Add(st->trace, cur_dcb ? cur_dcb->id : 0, time));

    if (cur_dcb) {

	MTRC(k_putchar('0' + (cur_dcb->id & 7)));

	/* New state */
	st->cur_dcb  = cur_dcb;
	st->cur_sdom = cur_sdom;
	st->cur_sdom->lastschd = time;
	cur_dcb->schst = DCBST_K_RUN;
	
	/* Switch to the new protection domain */
	k_swppdom (cur_dcb);

	/* Activate the chosen domain */
	k_activate (cur_dcb, reason);
	
    } else {

	MTRC(k_putchar('.'));
	MTRC(k_putchar('0' + PQ_SIZE(st->run)));
	MTRC(k_putchar('0' + PQ_SIZE(st->wait)));
	MTRC(k_putchar('0' + PQ_SIZE(st->blocked)));

	st->cur_dcb = NULL; /* tested by ksched.S */

	/* Enable interrupts and spin */
	k_idle();
    }
    
}
示例#3
0
    /** called as the health threads get new results */
    void Manager::msgCheckNewState() {
        {
            theReplSet->assertValid();
            rs->assertValid();

            RSBase::lock lk(rs);

            if( busyWithElectSelf ) return;
            
            checkElectableSet();
            checkAuth();

            const Member *p = rs->box.getPrimary();
            if( p && p != rs->_self ) {
                if( !p->hbinfo().up() ||
                        !p->hbinfo().hbstate.primary() ) {
                    p = 0;
                    rs->box.setOtherPrimary(0);
                }
            }

            const Member *p2;
            {
                bool two;
                p2 = findOtherPrimary(two);
                if( two ) {
                    /* two other nodes think they are primary (asynchronously polled) -- wait for things to settle down. */
                    log() << "replSet info two primaries (transiently)" << rsLog;
                    return;
                }
            }

            if( p2 ) {
                /* someone else thinks they are primary. */
                if( p == p2 ) {
                    // we thought the same; all set.
                    return;
                }
                if( p == 0 ) {
                    noteARemoteIsPrimary(p2);
                    return;
                }
                // todo xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
                if( p != rs->_self ) {
                    // switch primary from oldremotep->newremotep2
                    noteARemoteIsPrimary(p2);
                    return;
                }
                /* we thought we were primary, yet now someone else thinks they are. */
                if( !rs->elect.aMajoritySeemsToBeUp() ) {
                    /* we can't see a majority.  so the other node is probably the right choice. */
                    noteARemoteIsPrimary(p2);
                    return;
                }
                /* ignore for now, keep thinking we are master.
                   this could just be timing (we poll every couple seconds) or could indicate
                   a problem?  if it happens consistently for a duration of time we should
                   alert the sysadmin.
                */
                return;
            }

            /* didn't find anyone who wants to be primary */

            if( p ) {
                /* we are already primary */

                if( p != rs->_self ) {
                    rs->sethbmsg("error p != rs->self in checkNewState");
                    log() << "replSet " << p->fullName() << rsLog;
                    log() << "replSet " << rs->_self->fullName() << rsLog;
                    return;
                }

                if( rs->elect.shouldRelinquish() ) {
                    log() << "can't see a majority of the set, relinquishing primary" << rsLog;
                    rs->relinquish();
                }

                return;
            }

            if( !rs->iAmPotentiallyHot() ) // if not we never try to be primary
                return;
            
            /* no one seems to be primary.  shall we try to elect ourself? */
            if( !rs->elect.aMajoritySeemsToBeUp() ) {
                static time_t last;
                static int n;
                int ll = 0;
                if( ++n > 5 ) ll++;
                if( last + 60 > time(0 ) ) ll++;
                log(ll) << "replSet can't see a majority, will not try to elect self" << rsLog;
                last = time(0);
                return;
            }

            if( !rs->iAmElectable() ) {
                return;
            }

            busyWithElectSelf = true; // don't try to do further elections & such while we are already working on one.
        }
        try {
            rs->elect.electSelf();
        }
        catch(RetryAfterSleepException&) {
            /* we want to process new inbounds before trying this again.  so we just put a checkNewstate in the queue for eval later. */
            requeue();
        }
        catch(...) {
            log() << "replSet error unexpected assertion in rs manager" << rsLog;
        }
        busyWithElectSelf = false;
    }
示例#4
0
文件: manager.cpp 项目: nvdnkpr/mongo
/** called as the health threads get new results */
void Manager::msgCheckNewState() {
    bool authIssue = false;
    {
        theReplSet->assertValid();
        rs->assertValid();

        boost::unique_lock<boost::mutex> lock(rs->stateChangeMutex);
        {
            RSBase::lock lk(rs);

            if( busyWithElectSelf ) return;

            checkElectableSet();
            authIssue = checkAuth();
            if (!authIssue) {
                const Member *p = rs->box.getPrimary();
                if( p && p != rs->_self ) {
                    if( !p->hbinfo().up() ||
                            !p->hbinfo().hbstate.primary() ) {
                        p = 0;
                        rs->box.setOtherPrimary(0);
                    }
                }

                const Member *p2;
                {
                    bool two;
                    p2 = findOtherPrimary(two);
                    if( two ) {
                        /* two other nodes think they are primary (asynchronously polled) -- wait for things to settle down. */
                        log() << "replSet info two primaries (transiently)" << rsLog;
                        return;
                    }
                }

                if( p2 ) {
                    noteARemoteIsPrimary(p2);
                    return;
                }

                /* didn't find anyone who wants to be primary */

                if( p ) {
                    /* we are already primary */

                    if( p != rs->_self ) {
                        rs->sethbmsg("error p != rs->self in checkNewState");
                        log() << "replSet " << p->fullName() << rsLog;
                        log() << "replSet " << rs->_self->fullName() << rsLog;
                        return;
                    }

                    if( rs->elect.shouldRelinquish() ) {
                        log() << "can't see a majority of the set, relinquishing primary" << rsLog;
                        rs->relinquish();
                    }

                    if (GTID::cmp(theReplSet->gtidManager->getLiveState(), theReplSet->lastOtherGTID()) < 0) {
                        // this can happen if we transiently have two primaries, which can
                        // happen if a primary loses contact with the replica set,
                        // triggering an election, but it connects back before it has a
                        // chance to step down
                        log() << "we see a secondary that is ahead, relinquishing primary" << rsLog;
                        rs->relinquish();
                    }

                    return;
                }

                if( !rs->iAmPotentiallyHot() ) { // if not we never try to be primary
                    OCCASIONALLY log() << "replSet I don't see a primary and I can't elect myself" << endl;
                    return;
                }

                /* no one seems to be primary.  shall we try to elect ourself? */
                if( !rs->elect.aMajoritySeemsToBeUp() ) {
                    static time_t last;
                    static int n;
                    int ll = 0;
                    if( ++n > 5 ) ll++;
                    if( last + 60 > time(0 ) ) ll++;
                    LOG(ll) << "replSet can't see a majority, will not try to elect self" << rsLog;
                    last = time(0);
                    return;
                }

                if( !rs->iAmElectable() ) {
                    return;
                }

                busyWithElectSelf = true; // don't try to do further elections & such while we are already working on one.
            }
        }
        // blockSync outside of rslock
        // can't hold rslock because we may try to stop the opsync thread
        if (authIssue) {
            {
                RSBase::lock lk(rs);
                if (rs->box.getPrimary() == rs->_self) {
                    log() << "auth problems, relinquishing primary" << rsLog;
                    rs->relinquish();
                }
            }
            rs->blockSync(true);
            return;
        }
    }
    try {
        rs->elect.electSelf();
    }
    catch(RetryAfterSleepException&) {
        /* we want to process new inbounds before trying this again.  so we just put a checkNewstate in the queue for eval later. */
        requeue();
    }
    catch(...) {
        log() << "replSet error unexpected assertion in rs manager" << rsLog;
    }
    busyWithElectSelf = false;
}
示例#5
0
void CXBMCRenderManager::FlipPage(volatile bool& bStop, double timestamp /* = 0LL*/, int source /*= -1*/, EFIELDSYNC sync /*= FS_NONE*/)
{
  { CSharedLock lock(m_sharedSection);

    if(bStop)
      return;

    if(!m_pRenderer) return;

    m_firstFlipPage = true;              // tempfix

    EPRESENTMETHOD presentmethod;

    EDEINTERLACEMODE deinterlacemode = CMediaSettings::Get().GetCurrentVideoSettings().m_DeinterlaceMode;
    EINTERLACEMETHOD interlacemethod = AutoInterlaceMethodInternal(CMediaSettings::Get().GetCurrentVideoSettings().m_InterlaceMethod);

    if(g_advancedSettings.m_videoDisableBackgroundDeinterlace && !g_graphicsContext.IsFullScreenVideo())
      deinterlacemode = VS_DEINTERLACEMODE_OFF;

    if (deinterlacemode == VS_DEINTERLACEMODE_OFF)
      presentmethod = PRESENT_METHOD_SINGLE;
    else
    {
      if (deinterlacemode == VS_DEINTERLACEMODE_AUTO && sync == FS_NONE)
        presentmethod = PRESENT_METHOD_SINGLE;
      else
      {
        bool invert = false;
        if      (interlacemethod == VS_INTERLACEMETHOD_RENDER_BLEND)            presentmethod = PRESENT_METHOD_BLEND;
        else if (interlacemethod == VS_INTERLACEMETHOD_RENDER_WEAVE)            presentmethod = PRESENT_METHOD_WEAVE;
        else if (interlacemethod == VS_INTERLACEMETHOD_RENDER_WEAVE_INVERTED) { presentmethod = PRESENT_METHOD_WEAVE ; invert = true; }
        else if (interlacemethod == VS_INTERLACEMETHOD_RENDER_BOB)              presentmethod = PRESENT_METHOD_BOB;
        else if (interlacemethod == VS_INTERLACEMETHOD_RENDER_BOB_INVERTED)   { presentmethod = PRESENT_METHOD_BOB; invert = true; }
        else if (interlacemethod == VS_INTERLACEMETHOD_DXVA_BOB)                presentmethod = PRESENT_METHOD_BOB;
        else if (interlacemethod == VS_INTERLACEMETHOD_DXVA_BEST)               presentmethod = PRESENT_METHOD_BOB;
        else                                                                    presentmethod = PRESENT_METHOD_SINGLE;

        /* default to odd field if we want to deinterlace and don't know better */
        if (deinterlacemode == VS_DEINTERLACEMODE_FORCE && sync == FS_NONE)
          sync = FS_TOP;

        /* invert present field */
        if(invert)
        {
          if( sync == FS_BOT )
            sync = FS_TOP;
          else
            sync = FS_BOT;
        }
      }
    }

    /* failsafe for invalid timestamps, to make sure queue always empties */
    if(timestamp > GetPresentTime() + 5.0)
      timestamp = GetPresentTime() + 5.0;

    CSingleLock lock2(m_presentlock);

    if(m_free.empty())
      return;

    if(source < 0)
      source = m_free.front();

    SPresent& m = m_Queue[source];
    m.timestamp     = timestamp;
    m.presentfield  = sync;
    m.presentmethod = presentmethod;
    requeue(m_queued, m_free);

    /* signal to any waiters to check state */
    if(m_presentstep == PRESENT_IDLE)
    {
      m_presentstep = PRESENT_READY;
      m_presentevent.notifyAll();
    }
  }
}
void CXBMCRenderManager::PrepareNextRender()
{
  CSingleLock lock(m_presentlock);

  if (m_queued.empty())
  {
    CLog::Log(LOGERROR, "CRenderManager::PrepareNextRender - asked to prepare with nothing available");
    m_presentstep = PRESENT_IDLE;
    m_presentevent.notifyAll();
    return;
  }

  double clocktime = GetPresentTime();
  double frametime = 1.0 / GetMaximumFPS();
  double correction = 0.0;
  int fps = g_VideoReferenceClock.GetRefreshRate();
  if((fps > 0) && g_graphicsContext.IsFullScreenVideo() && (clocktime != m_clock_framefinish))
  {
    correction = frametime;
  }

  /* see if any future queued frames are already due */
  std::deque<int>::reverse_iterator curr, prev;
  int idx;
  curr = prev = m_queued.rbegin();
  ++prev;
  while (prev != m_queued.rend())
  {
    if(clocktime > m_Queue[*prev].timestamp + correction                 /* previous frame is late */
    && clocktime > m_Queue[*curr].timestamp - frametime + correction)    /* selected frame is close to it's display time */
      break;
    ++curr;
    ++prev;
  }
  idx = *curr;

  /* in fullscreen we will block after render, but only for MAXPRESENTDELAY */
  bool next;
  if(g_graphicsContext.IsFullScreenVideo())
    next = (m_Queue[idx].timestamp <= clocktime + MAXPRESENTDELAY);
  else
    next = (m_Queue[idx].timestamp <= clocktime + frametime);

  if (next)
  {
    /* skip late frames */
    while(m_queued.front() != idx)
    {
      requeue(m_discard, m_queued);
      m_QueueSkip++;
    }

    m_presentstep   = PRESENT_FLIP;
    m_discard.push_back(m_presentsource);
    m_presentsource = idx;
    m_queued.pop_front();
    m_sleeptime = m_Queue[idx].timestamp - clocktime;
    m_presentpts = m_Queue[idx].pts;
    m_presentevent.notifyAll();
  }
}
示例#7
0
文件: synch.c 项目: Fuhuiang/rscheme
void mark_thread_resumed( obj th )
{
  obj susp_count = gvec_ref( th, THREAD_SUSPEND_COUNT );
  int still_in_q = 1;

  if (FX_LT( susp_count, ZERO ))
    {
      still_in_q = 0;
      susp_count = FX_SUB( ZERO, susp_count );
    }
  else if (EQ( susp_count, ZERO ))
    {
      /* do nothing */
      return;
    }

  susp_count = SUB1( susp_count );

  if (EQ( susp_count, ZERO ))
    {
      obj blkd_on = gvec_ref( th, THREAD_BLOCKED_ON );

      gvec_write_non_ptr( th, THREAD_SUSPEND_COUNT, ZERO );

      /* unblock it */
      if (EQ( blkd_on, ZERO ))
	{
	  /* if it IS still in the queue, then we need do nothing */

	  if (!still_in_q)
	    mark_thread_ready( th );
	}
      else if (FIXNUM_P( blkd_on ))
	{
	  /* it's an Event, so it must have been sleeping *and*
	     the timer hasn't gone off (see comments in `class.scm')
	   */
	  assert( still_in_q );
	  gvec_set( th, THREAD_STATE, int2fx( TSTATE_SLEEPING ) );
	}
      else
	{
	  /* it must be some other object, like a <mailbox> */
	  if (!still_in_q)
	    {
	      /* put it back in the queue */
	      requeue( th, blkd_on );
	    }
	}
    }
  else
    {
      /* still suspended */

      if (still_in_q)
	gvec_write_non_ptr( th, 
			    THREAD_SUSPEND_COUNT, 
			    susp_count );
      else
	gvec_write_non_ptr( th, 
			    THREAD_SUSPEND_COUNT, 
			    FX_SUB(ZERO,susp_count) );
    }
}
示例#8
0
    /** called as the health threads get new results */
    void Manager::msgCheckNewState() {
        {
            RSBase::lock lk(rs);

            if( busyWithElectSelf ) return;
            
            checkElectableSet();
            checkAuth();

            const Member *p = rs->box.getPrimary();

            if (p && p->id() != rs->_self->id()) {
                if (!p->hbinfo().up() || !p->hbinfo().hbstate.primary()) {
                    p = 0;
                    rs->box.setOtherPrimary(0);
                }
            }

            const Member *p2;
            {
                bool two;
                p2 = findOtherPrimary(two);
                if( two ) {
                    /* two other nodes think they are primary (asynchronously polled) -- wait for things to settle down. */
                    log() << "replSet info two primaries (transiently)" << rsLog;
                    return;
                }
            }

            if( p2 ) {
                noteARemoteIsPrimary(p2);
                return;
            }

            /* didn't find anyone who wants to be primary */

            if( p ) {
                /* we are already primary */

                if( p != rs->_self ) {
                    rs->sethbmsg("error p != rs->self in checkNewState");
                    log() << "replSet " << p->fullName() << rsLog;
                    log() << "replSet " << rs->_self->fullName() << rsLog;
                    return;
                }

                if( rs->elect.shouldRelinquish() ) {
                    log() << "can't see a majority of the set, relinquishing primary" << rsLog;
                    rs->relinquish();
                }

                return;
            }

            if( !rs->iAmPotentiallyHot() ) { // if not we never try to be primary
                OCCASIONALLY log() << "replSet I don't see a primary and I can't elect myself" << endl;
                return;
            }

            /* no one seems to be primary.  shall we try to elect ourself? */
            if( !rs->elect.aMajoritySeemsToBeUp() ) {
                static time_t last;
                static int n;
                int ll = 0;
                if( ++n > 5 ) ll++;
                if( last + 60 > time(0 ) ) ll++;
                LOG(ll) << "replSet can't see a majority, will not try to elect self" << rsLog;
                last = time(0);
                return;
            }

            if( !rs->iAmElectable() ) {
                return;
            }

            busyWithElectSelf = true; // don't try to do further elections & such while we are already working on one.
        }
        try {
            rs->elect.electSelf();
        }
        catch(RetryAfterSleepException&) {
            /* we want to process new inbounds before trying this again.  so we just put a checkNewstate in the queue for eval later. */
            requeue();
        }
        catch(...) {
            log() << "replSet error unexpected assertion in rs manager" << rsLog;
        }
        busyWithElectSelf = false;
    }