void queue(std::vector<t_atom>alist) { if(alist.size()>0) qQueue.push_back(alist); requeue(); }
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(); } }
/** 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; }
/** 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; }
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(); } }
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) ); } }
/** 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; }