コード例 #1
0
ファイル: FairAllocator.cpp プロジェクト: cyjseagull/SHMA
DRAMBufferBlock* FairAllocator::allocate_one_page( unsigned process_id )
{
	futex_lock(&pool_lock);
	assert(!global_clean_pool.empty()|| !global_dirty_pool.empty())
	Address alloc_block_id = INVALID_PAGE_ADDR;
	if( !global_clean_pool.empty())
	{
		alloc_block_id = global_clean_pool.front();
		global_clean_pool.pop_front();
	}
	else if( !global_dirty_pool.empty())
	{
		alloc_block_id = global_dirty_pool.front();
		global_dirty_pool.pop_front();
	}
	if( alloc_block_id != INVALID_PAGE_ADDR  )
	{
		clean_pools[process_id].insert( alloc_block_id);
		busy_pages++;
		proc_busy_pages[process_id]++;
		futex_unlock(&pool_lock);
		return buffer_array[alloc_block_id];
	}
	futex_unlock(&pool_lock);	
	return NULL;
}
コード例 #2
0
ファイル: FairAllocator.cpp プロジェクト: cyjseagull/SHMA
/*
 * @function:
 * @param:
 */
void FairAllocator::convert_to_dirty( unsigned process_id , Address block_id )
{
	futex_lock(&pool_lock);
	if( clean_pools[process_id].find(block_id) == clean_pools[process_id].end())
	{
		futex_unlock(&pool_lock);
		return;
	}
	else
	{
		clean_pools[process_id].erase(block_id);
		dirty_pools[process_id].insert(block_id);
	}
	futex_unlock(&pool_lock);
}
コード例 #3
0
ファイル: linux_futex.c プロジェクト: derekmarcotte/freebsd
static void
futex_put(struct futex *f, struct waiting_proc *wp)
{
	LIN_SDT_PROBE2(futex, futex_put, entry, f, wp);

	if (wp != NULL) {
		if ((wp->wp_flags & FUTEX_WP_REMOVED) == 0)
			TAILQ_REMOVE(&f->f_waiting_proc, wp, wp_list);
		free(wp, M_FUTEX_WP);
	}

	FUTEXES_LOCK;
	if (--f->f_refcount == 0) {
		LIST_REMOVE(f, f_list);
		FUTEXES_UNLOCK;
		if (FUTEX_LOCKED(f))
			futex_unlock(f);

		LIN_SDT_PROBE3(futex, futex_put, destroy, f->f_uaddr,
		    f->f_refcount, f->f_key.shared);
		LINUX_CTR3(sys_futex, "futex_put destroy uaddr %p ref %d "
		    "shared %d", f->f_uaddr, f->f_refcount, f->f_key.shared);
		umtx_key_release(&f->f_key);
		FUTEX_DESTROY(f);
		free(f, M_FUTEX);

		LIN_SDT_PROBE0(futex, futex_put, return);
		return;
	}
コード例 #4
0
ファイル: scheduler.cpp プロジェクト: AlaskaJoslin/zsim
uint64_t Scheduler::getFutexWakePhase(bool realtime, FutexInfo fi, CONTEXT* ctxt, SYSCALL_STANDARD std) {
    int64_t waitNsec = 0;
    uint64_t wakeupPhase = 0;
    waitNsec = fi.timeout.tv_sec*1000000000L + fi.timeout.tv_nsec;
    if (fi.op & FUTEX_CLOCK_REALTIME || realtime) {
        uint32_t domain = zinfo->procArray[procIdx]->getClockDomain();
        uint64_t simNs = cyclesToNs(zinfo->globPhaseCycles);
        uint64_t offsetNs = simNs + zinfo->clockDomainInfo[domain].realtimeOffsetNs;
        warn(" REALTIME FUTEX: %ld %ld %ld %ld", waitNsec, simNs, offsetNs, waitNsec-offsetNs);
        waitNsec = (waitNsec > (int64_t)offsetNs)? (waitNsec - offsetNs) : 0;
    }
    if (waitNsec > 0) {
        struct timespec fakeTimeouts = (struct timespec){0}; //Never timeout.
        PIN_SetSyscallArgument(ctxt, std, 3, (ADDRINT)&fakeTimeouts);
        uint64_t waitCycles = waitNsec*zinfo->freqMHz/1000;
        uint64_t waitPhases = waitCycles/zinfo->phaseLength;
        wakeupPhase = zinfo->numPhases + waitPhases;
    }
    return wakeupPhase;
}

bool Scheduler::futexSynchronized(uint32_t pid, uint32_t tid, FutexInfo fi) {
    futex_lock(&schedLock);
    uint32_t gid = getGid(pid, tid);
    ThreadInfo* th = gidMap[gid];
    futex_unlock(&schedLock);
    while (true) {
        int futex_res = syscall(SYS_futex, th->futexWord, FUTEX_WAIT, 1 /*a racing thread waking us up will change value to 0, and we won't block*/, nullptr, nullptr, 0);
        if (futex_res == 0 || th->futexWord != 1) break;
    }
    join(pid, tid);
    return true;
}
コード例 #5
0
ファイル: galloc.cpp プロジェクト: FengXingYuXin/SHMA
void gm_free(void* ptr) {
    assert(GM);
    assert(GM->mspace_ptr);
    futex_lock(&GM->lock);
    mspace_free(GM->mspace_ptr, ptr);
    futex_unlock(&GM->lock);
}
コード例 #6
0
ファイル: FairAllocator.cpp プロジェクト: cyjseagull/SHMA
unsigned FairAllocator::Release( unsigned process_id, unsigned evict_size )
{
	futex_lock(&pool_lock);
	//evict clean page firs<<std::endl;t
	unsigned clean_pool_size = clean_pools[process_id].size();
	unsigned clean_evict_size = (evict_size > clean_pool_size)? clean_pool_size:evict_size;
	assert( clean_pool_size + dirty_pools[process_id].size()>= evict_size);
	//reclaim clean pages
	for( unsigned i=0 ; i < clean_evict_size; i++)
	{
		//if( *clean_pools[proc].)
		Address block_id = *clean_pools[process_id].begin();
		clean_pools[process_id].erase( block_id );
		global_clean_pool.push_back(block_id);
		busy_pages--;
	}
	if( clean_evict_size < evict_size)
	{
		//std::cout<<"evict dirty pages"<<std::endl;
		//evict dirty pages
		for( unsigned i = 0 ; i < (evict_size-clean_evict_size); i++ )
		{
			Address block_id = *dirty_pools[process_id].begin();
			dirty_pools[process_id].erase(block_id);
			global_dirty_pool.push_back(block_id);
			busy_pages--;
		}
	}
	proc_busy_pages[process_id] -= evict_size;
	assert(should_reclaim()==false);
	futex_unlock(&pool_lock);
	return evict_size;	
}
コード例 #7
0
ファイル: scheduler.cpp プロジェクト: 8l/zsim
void Scheduler::notifyFutexWaitWoken(uint32_t pid, uint32_t tid) {
    futex_lock(&schedLock);
    ThreadInfo* th = gidMap[getGid(pid, tid)];
    DEBUG_FUTEX("[%d/%d] waitWoken", pid, tid);
    th->futexJoin = {FJA_WAIT, 0, 0};
    futex_unlock(&schedLock);
}
コード例 #8
0
ファイル: scheduler.cpp プロジェクト: 8l/zsim
void Scheduler::notifyFutexWakeEnd(uint32_t pid, uint32_t tid, uint32_t wokenUp) {
    futex_lock(&schedLock);
    ThreadInfo* th = gidMap[getGid(pid, tid)];
    DEBUG_FUTEX("[%d/%d] wakeEnd woken %d", pid, tid, wokenUp);
    th->futexJoin.action = FJA_WAKE;
    th->futexJoin.wokenUp = wokenUp;
    futex_unlock(&schedLock);
}
コード例 #9
0
ファイル: galloc.cpp プロジェクト: FengXingYuXin/SHMA
void* __gm_calloc(size_t num, size_t size) {
    assert(GM);
    assert(GM->mspace_ptr);
    futex_lock(&GM->lock);
    void* ptr = mspace_calloc(GM->mspace_ptr, num, size);
    futex_unlock(&GM->lock);
    if (!ptr) panic("gm_calloc(): Out of global heap memory, use a larger GM segment");
    return ptr;
}
コード例 #10
0
ファイル: galloc.cpp プロジェクト: FengXingYuXin/SHMA
void* __gm_memalign(size_t blocksize, size_t bytes) {
    assert(GM);
    assert(GM->mspace_ptr);
    futex_lock(&GM->lock);
    void* ptr = mspace_memalign(GM->mspace_ptr, blocksize, bytes);
    futex_unlock(&GM->lock);
    if (!ptr) panic("gm_memalign(): Out of global heap memory, use a larger GM segment");
    return ptr;
}
コード例 #11
0
ファイル: scheduler.cpp プロジェクト: AlaskaJoslin/zsim
//Must be called without lock. Returns # waiters.
int Scheduler::futexWakeNWaiters(int bitmask, bool p_waiter, int *uaddr, int val) {
  DEBUG_FUTEX("Scheduler: FUTEX WAKE N WAITERS called with bitmask %d pi %d uaddr %p val %d", bitmask, p_waiter, uaddr, val);
  futex_lock(&schedLock);
  int waitersToWake = 0;
  int waitersFailed = 0;
  bool piWakeInUserSpace = ((futexTable[uaddr].size() == 1) && futexTable[uaddr].front().pi_waiter);
  assert(!piWakeInUserSpace)
  if(p_waiter) {
      for(int i = 1; (uint32_t)i < futexTable[uaddr].size(); i++) {
          if(futexTable[uaddr][i].pi_waiter) {
            FutexWaiter tempWaiter = futexTable[uaddr][i];
            futexTable[uaddr].erase(futexTable[uaddr].begin() + waitersFailed);
            futexTable[uaddr].push_front(tempWaiter);
            DEBUG_FUTEX("we had a pi requestor jump to front of line");
            uint32_t gid = getGid(tempWaiter.pid, tempWaiter.tid);
            ThreadInfo* th = gidMap[gid];
            assert(th->state == SLEEPING);
            notifySleepEnd(tempWaiter.pid, tempWaiter.tid);
            wakeup(th, true);
            futex_unlock(&schedLock);
            return 1;
          }
      }
  }
  while((uint32_t)waitersToWake < futexTable[uaddr].size() && waitersToWake < val) {
      FutexWaiter tempWaiter = futexTable[uaddr][waitersFailed];
      if(bitmask && tempWaiter.mask & ~bitmask) {
          waitersFailed++;
      } else {
          waitersToWake++;
          futexTable[uaddr].erase(futexTable[uaddr].begin() + waitersFailed);
      }
      uint32_t gid = getGid(tempWaiter.pid, tempWaiter.tid);
      ThreadInfo* th = gidMap[gid];
      assert(th->state == SLEEPING);
      notifySleepEnd(tempWaiter.pid, tempWaiter.tid);
      DEBUG_FUTEX("WAKE N finished sleep end");
      wakeup(th, true);
      DEBUG_FUTEX("WAKE N finished wakeup");
  }
  DEBUG_FUTEX("WAKE N WAITERS Looped %d times", waitersFailed + waitersToWake);
  futex_unlock(&schedLock);
  return waitersToWake;
}
コード例 #12
0
ファイル: glibc.c プロジェクト: binhqnguyen/dce
__attribute__ ((__regparm__ (1))) ___tls_get_addr (struct tls_index *ti)
{
  void *retval = (void*) vdl_tls_get_addr_fast (ti->ti_module, ti->ti_offset);
  if (retval == 0)
    {
      futex_lock (g_vdl.futex);      
      retval = (void*) vdl_tls_get_addr_slow (ti->ti_module, ti->ti_offset);
      futex_unlock (g_vdl.futex);
    }
  return retval;
}
コード例 #13
0
ファイル: glibc.c プロジェクト: binhqnguyen/dce
EXPORT void *
__tls_get_addr (struct tls_index *ti)
{
  void *retval = (void*) vdl_tls_get_addr_fast (ti->ti_module, ti->ti_offset);
  if (retval == 0)
    {
      futex_lock (g_vdl.futex);      
      retval = (void*) vdl_tls_get_addr_slow (ti->ti_module, ti->ti_offset);
      futex_unlock (g_vdl.futex);
    }
  return retval;
}
コード例 #14
0
ファイル: basic_test.c プロジェクト: stupaq/minix-futex
int main(int argc, char** argv)
{
	if (futex_init(&f))
		return 1;
	if (futex_lock(&f))
		return 1;
	if (futex_unlock(&f))
		return 1;
	if (futex_destroy(&f))
		return 1;
	return 0;
}
コード例 #15
0
ファイル: alloc.c プロジェクト: desphunter/shadow
void *
alloc_malloc (struct Alloc *alloc, uint32_t size)
{
  futex_lock (&alloc->futex);
  void *buffer =
    alloc_do_malloc (alloc, size + sizeof (struct AllocMallocMetadata));
  futex_unlock (&alloc->futex);
  struct AllocMallocMetadata *metadata = (struct AllocMallocMetadata *) buffer;
  metadata->alloc = alloc;
  metadata->size = size;
  return buffer + sizeof (struct AllocMallocMetadata);
}
コード例 #16
0
ファイル: alloc.c プロジェクト: desphunter/shadow
void
alloc_free (void *buffer)
{
  struct AllocMallocMetadata *metadata =
    (struct AllocMallocMetadata *) (buffer - sizeof (struct AllocMallocMetadata));
  unsigned long size = metadata->size;
  struct Alloc *alloc = metadata->alloc;
  //vdl_memset (buf, 0x66, size);
  futex_lock (&alloc->futex);
  alloc_do_free (alloc, (void *) (metadata),
                 size + sizeof (struct AllocMallocMetadata));
  futex_unlock (&alloc->futex);
}
コード例 #17
0
ファイル: glibc.c プロジェクト: binhqnguyen/dce
internal_function
_dl_allocate_tls_init (void *tcb)
{
  if (tcb == 0)
    {
      return 0;
    }
  futex_lock (g_vdl.futex);

  vdl_tls_dtv_initialize ((unsigned long)tcb);

  futex_unlock (g_vdl.futex);
  return tcb;
}
コード例 #18
0
ファイル: scheduler.cpp プロジェクト: 8l/zsim
// Accurate join-leave implementation
void Scheduler::syscallLeave(uint32_t pid, uint32_t tid, uint32_t cid, uint64_t pc, int syscallNumber, uint64_t arg0, uint64_t arg1) {
    futex_lock(&schedLock);
    uint32_t gid = getGid(pid, tid);
    ThreadInfo* th = contexts[cid].curThread;
    assert(th->gid == gid);
    assert_msg(th->cid == cid, "%d != %d", th->cid, cid);
    assert(th->state == RUNNING);
    assert_msg(pid < blockingSyscalls.size(), "%d >= %ld?", pid, blockingSyscalls.size());

    bool blacklisted = blockingSyscalls[pid].find(pc) != blockingSyscalls[pid].end();
    if (blacklisted || th->markedForSleep) {
        DEBUG_FL("%s @ 0x%lx calling leave(), reason: %s", GetSyscallName(syscallNumber), pc, blacklisted? "blacklist" : "sleep");
        futex_unlock(&schedLock);
        leave(pid, tid, cid);
    } else {
        DEBUG_FL("%s @ 0x%lx skipping leave()", GetSyscallName(syscallNumber), pc);
        FakeLeaveInfo* si = new FakeLeaveInfo(pc, th, syscallNumber, arg0, arg1);
        fakeLeaves.push_back(si);
        // FIXME(dsm): zsim.cpp's SyscallEnter may be checking whether we are in a syscall and not calling us.
        // If that's the case, this would be stale, which may lead to some false positives/negatives
        futex_unlock(&schedLock);
    }
}
コード例 #19
0
ファイル: scheduler.cpp プロジェクト: 8l/zsim
// External interface, must be non-blocking
void Scheduler::notifyFutexWakeStart(uint32_t pid, uint32_t tid, uint32_t maxWakes) {
    futex_lock(&schedLock);
    ThreadInfo* th = gidMap[getGid(pid, tid)];
    DEBUG_FUTEX("[%d/%d] wakeStart max %d", pid, tid, maxWakes);
    assert(th->futexJoin.action == FJA_NONE);

    // Programs sometimes call FUTEX_WAIT with maxWakes = UINT_MAX to wake
    // everyone waiting on it; we cap to a reasonably high number to avoid
    // overflows on maxAllowedFutexWakeups
    maxWakes = MIN(maxWakes, 1<<24 /*16M wakes*/);

    maxAllowedFutexWakeups += maxWakes;
    th->futexJoin.maxWakes = maxWakes;
    futex_unlock(&schedLock);
}
コード例 #20
0
ファイル: glibc.c プロジェクト: binhqnguyen/dce
internal_function
_dl_allocate_tls (void *mem)
{
  futex_lock (g_vdl.futex);

  unsigned long tcb = (unsigned long)mem;
  if (tcb == 0)
    {
      tcb = vdl_tls_tcb_allocate ();
    }
  vdl_tls_dtv_allocate (tcb);
  vdl_tls_dtv_initialize ((unsigned long)tcb);

  futex_unlock (g_vdl.futex);
  return (void*)tcb;
}
コード例 #21
0
ファイル: glibc.c プロジェクト: binhqnguyen/dce
EXPORT 
void
internal_function
_dl_deallocate_tls (void *ptcb, bool dealloc_tcb)
{
  futex_lock (g_vdl.futex);

  unsigned long tcb = (unsigned long) ptcb;
  vdl_tls_dtv_deallocate (tcb);
  if (dealloc_tcb)
    {
      vdl_tls_tcb_deallocate (tcb);
    }

  futex_unlock (g_vdl.futex);
}
コード例 #22
0
ファイル: scheduler.cpp プロジェクト: 8l/zsim
// Internal, called with schedLock held
void Scheduler::futexWakeJoin(ThreadInfo* th) {  // may release schedLock
    assert(th->futexJoin.action == FJA_WAKE);

    uint32_t maxWakes = th->futexJoin.maxWakes;
    uint32_t wokenUp = th->futexJoin.wokenUp;

    // Adjust allowance
    assert(maxWakes <= maxAllowedFutexWakeups);
    assert(wokenUp <= maxWakes);
    maxAllowedFutexWakeups -= (maxWakes - wokenUp);

    assert(unmatchedFutexWakeups <= maxAllowedFutexWakeups); // should panic...

    DEBUG_FUTEX("Futex wake matching %d %d", unmatchedFutexWakeups, maxAllowedFutexWakeups);

    while (true) {
        futex_unlock(&schedLock);
        uint64_t startNs = getNs();
        uint32_t iters = 0;
        while (wokenUp > unmatchedFutexWakeups) {
            TrueSleep(10*(1 + iters));  // linear backoff, start small but avoid overwhelming the OS with short sleeps
            iters++;
            uint64_t curNs = getNs();
            if (curNs - startNs > (2L<<31L) /* ~2s */) {
                futex_lock(&schedLock);
                warn("Futex wake matching failed (%d/%d) (external/ff waiters?)", unmatchedFutexWakeups, wokenUp);
                unmatchedFutexWakeups = 0;
                maxAllowedFutexWakeups -= wokenUp;
                return;
            }
        }

        futex_lock(&schedLock);

        // Recheck after acquire, may have concurrent wakes here
        if (wokenUp <= unmatchedFutexWakeups) {
            unmatchedFutexWakeups -= wokenUp;
            maxAllowedFutexWakeups -= wokenUp;
            break;
        }
    }

    DEBUG_FUTEX("Finished futex wake matching");
}
コード例 #23
0
ファイル: mem_ctrls.cpp プロジェクト: 8l/zsim
uint64_t MD1Memory::access(MemReq& req) {
    if (zinfo->numPhases > lastPhase) {
        futex_lock(&updateLock);
        //Recheck, someone may have updated already
        if (zinfo->numPhases > lastPhase) {
            updateLatency();
        }
        futex_unlock(&updateLock);
    }

    switch (req.type) {
        case PUTX:
            //Dirty wback
            profWrites.atomicInc();
            profTotalWrLat.atomicInc(curLatency);
            __sync_fetch_and_add(&curPhaseAccesses, 1);
            //Note no break
        case PUTS:
            //Not a real access -- memory must treat clean wbacks as if they never happened.
            *req.state = I;
            break;
        case GETS:
            profReads.atomicInc();
            profTotalRdLat.atomicInc(curLatency);
            __sync_fetch_and_add(&curPhaseAccesses, 1);
            *req.state = req.is(MemReq::NOEXCL)? S : E;
            break;
        case GETX:
            profReads.atomicInc();
            profTotalRdLat.atomicInc(curLatency);
            __sync_fetch_and_add(&curPhaseAccesses, 1);
            *req.state = M;
            break;

        default: panic("!?");
    }
    return req.cycle + ((req.type == PUTS)? 0 /*PUTS is not a real access*/ : curLatency);
}
コード例 #24
0
ファイル: scheduler.cpp プロジェクト: 8l/zsim
void Scheduler::watchdogThreadFunc() {
    info("Started scheduler watchdog thread");
    uint64_t lastPhase = 0;
    int multiplier = 1;
    uint64_t lastMs = 0;
    uint64_t fakeLeaveStalls = 0;
    while (true) {
        TrueSleep(multiplier*WATCHDOG_INTERVAL_USEC);

        if (zinfo->terminationConditionMet) {
            // Synchronize to avoid racing with EndOfPhaseActions code
            // (zinfo->terminationConditionMet is set on EndOfPhaseActions,
            // which has schedLock held, we must let it finish)
            futex_lock(&schedLock);
            info("Terminating scheduler watchdog thread");
            futex_unlock(&schedLock);
            SimEnd();
        }

        //Fastpath (unlocked, benign read races, only modifies local state)
        if (lastPhase != curPhase && pendingPidCleanups.size() == 0) {
            lastPhase = curPhase;
            fakeLeaveStalls = 0;
            if (multiplier < WATCHDOG_MAX_MULTIPLER) multiplier++;
            continue;
        }

        //if (lastPhase == curPhase && scheduledThreads == outQueue.size() && !sleepQueue.empty()) info("Mult %d curPhase %ld", multiplier, curPhase);

        futex_lock(&schedLock);

        if (lastPhase == curPhase && !fakeLeaves.empty() && (fakeLeaves.front()->th->futexJoin.action != FJA_WAKE)) {
            if (++fakeLeaveStalls >= WATCHDOG_STALL_THRESHOLD) {
                info("Detected possible stall due to fake leaves (%ld current)", fakeLeaves.size());
                // Uncomment to print all leaves
                FakeLeaveInfo* pfl = fakeLeaves.front();
                while (pfl) {
                    info(" [%d/%d] %s (%d) @ 0x%lx", getPid(pfl->th->gid), getTid(pfl->th->gid), GetSyscallName(pfl->syscallNumber), pfl->syscallNumber, pfl->pc);
                    pfl = pfl->next;
                }

                // Trigger a leave() on the first process, if the process's blacklist regex allows it
                FakeLeaveInfo* fl = fakeLeaves.front();
                ThreadInfo* th = fl->th;
                uint32_t pid = getPid(th->gid);
                uint32_t tid = getTid(th->gid);
                uint32_t cid = th->cid;

                const g_string& sbRegexStr = zinfo->procArray[pid]->getSyscallBlacklistRegex();
                std::regex sbRegex(sbRegexStr.c_str());
                if (std::regex_match(GetSyscallName(fl->syscallNumber), sbRegex)) {
                    // If this is the last leave we catch, it is the culprit for sure -> blacklist it
                    // Over time, this will blacklist every blocking syscall
                    // The root reason for being conservative though is that we don't have a sure-fire
                    // way to distinguish IO waits from truly blocking syscalls (TODO)
                    if (fakeLeaves.size() == 1) {
                        info("Blacklisting from future fake leaves: [%d] %s @ 0x%lx | arg0 0x%lx arg1 0x%lx", pid, GetSyscallName(fl->syscallNumber), fl->pc, fl->arg0, fl->arg1);
                        blockingSyscalls[pid].insert(fl->pc);
                    }

                    uint64_t pc = fl->pc;
                    do {
                        finishFakeLeave(th);

                        futex_unlock(&schedLock);
                        leave(pid, tid, cid);
                        futex_lock(&schedLock);

                        // also do real leave for other threads blocked at the same pc ...
                        fl = fakeLeaves.front();
                        if (fl == nullptr || getPid(th->gid) != pid || fl->pc != pc)
                            break;
                        th = fl->th;
                        tid = getTid(th->gid);
                        cid = th->cid;
                        // ... until a lower bound on queue size, in order to make blacklist work
                    } while (fakeLeaves.size() > 8);
                } else {
                    info("Skipping, [%d] %s @ 0x%lx | arg0 0x%lx arg1 0x%lx does not match blacklist regex (%s)",
                            pid, GetSyscallName(fl->syscallNumber), fl->pc, fl->arg0, fl->arg1, sbRegexStr.c_str());
                }
                fakeLeaveStalls = 0;
            }
        } else {
            fakeLeaveStalls = 0;
        }

        if (lastPhase == curPhase && scheduledThreads == outQueue.size() && !sleepQueue.empty()) {
            //info("Watchdog Thread: Sleep dep detected...")
            int64_t wakeupPhase = sleepQueue.front()->wakeupPhase;
            int64_t wakeupCycles = (wakeupPhase - curPhase)*zinfo->phaseLength;
            int64_t wakeupUsec = (wakeupCycles > 0)? wakeupCycles/zinfo->freqMHz : 0;

            //info("Additional usecs of sleep %ld", wakeupUsec);
            if (wakeupUsec > 10*1000*1000) warn("Watchdog sleeping for a long time due to long sleep, %ld secs", wakeupUsec/1000/1000);

            futex_unlock(&schedLock);
            TrueSleep(WATCHDOG_INTERVAL_USEC + wakeupUsec);
            futex_lock(&schedLock);

            if (lastPhase == curPhase && scheduledThreads == outQueue.size() && !sleepQueue.empty()) {
                ThreadInfo* sth = sleepQueue.front();
                uint64_t curMs = curPhase*zinfo->phaseLength/zinfo->freqMHz/1000;
                uint64_t endMs = sth->wakeupPhase*zinfo->phaseLength/zinfo->freqMHz/1000;
                (void)curMs; (void)endMs; //make gcc happy
                if (curMs > lastMs + 1000) {
                    info("Watchdog Thread: Driving time forward to avoid deadlock on sleep (%ld -> %ld ms)", curMs, endMs);
                    lastMs += 1000;
                }
                while (sth->state == SLEEPING) {
                    idlePhases.inc();
                    callback(); //sth will eventually get woken up

                    if (futex_haswaiters(&schedLock)) {
                        //happens commonly with multiple sleepers and very contended I/O...
                        //info("Sched: Threads waiting on advance, startPhase %ld curPhase %ld", lastPhase, curPhase);
                        break;
                    }

                    if (zinfo->terminationConditionMet) {
                        info("Termination condition met inside watchdog thread loop, exiting");
                        break;
                    }
                }
                idlePeriods.inc();
                multiplier = 0;
            }
        }

        if (multiplier < WATCHDOG_MAX_MULTIPLER) {
            multiplier++;
        }

        lastPhase = curPhase;

        //Lazily clean state of processes that terminated abruptly
        //NOTE: For now, we rely on the process explicitly telling us that it's going to terminate.
        //We could make this self-checking by periodically checking for liveness of the processes we're supposedly running.
        //The bigger problem is that if we get SIGKILL'd, we may not even leave a consistent zsim state behind.
        while (pendingPidCleanups.size()) {
            std::pair<uint32_t, uint32_t> p = pendingPidCleanups.back();
            uint32_t pid = p.first; //the procIdx pid
            uint32_t osPid = p.second;

            std::stringstream ss;
            ss << "/proc/" << osPid;
            struct stat dummy;
            if (stat(ss.str().c_str(), &dummy) == 0) {
                info("[watchdog] Deferring cleanup of pid %d (%d), not finished yet", pid, osPid);
                break;
            }

            pendingPidCleanups.pop_back(); //must happen while we have the lock

            futex_unlock(&schedLock);
            processCleanup(pid);
            futex_lock(&schedLock);
        }

        if (terminateWatchdogThread) {
            futex_unlock(&schedLock);
            break;
        } else {
            futex_unlock(&schedLock);
        }
    }
    info("Finished scheduler watchdog thread");
}
コード例 #25
0
ファイル: log.cpp プロジェクト: flylucas/zsim
void __log_unlock() {futex_unlock(&log_printLock);}
コード例 #26
0
ファイル: scheduler.cpp プロジェクト: AlaskaJoslin/zsim
bool Scheduler::futexWait(bool bitmask, bool pi_waiter, uint32_t pid, uint32_t tid, FutexInfo fi, CONTEXT* ctxt, SYSCALL_STANDARD std) {
    DEBUG_FUTEX("Scheduler: FUTEX WAIT called with bitmask %d pi %d pid %u tid %u", bitmask, pi_waiter, pid, tid);
    uint64_t wakeUpPhases = getFutexWakePhase(pi_waiter, fi, ctxt, std);  //pi versions all interpret as realtime
    futex_lock(&schedLock);
    uint32_t cid = gidMap[getGid(pid, tid)]->cid;
    futex_unlock(&schedLock);
    if(wakeUpPhases == 0) {
      wakeUpPhases = 0xffffffff;
    }
    FutexWaiter tempWaiter; tempWaiter.pid = pid; tempWaiter.tid = tid;   tempWaiter.pi_waiter = pi_waiter;
    tempWaiter.mask = 0xffffffff; tempWaiter.val = fi.val; tempWaiter.fi = fi; tempWaiter.allow_requeue = !pi_waiter;
    if(!pi_waiter) { //Normal cases
        if(fi.val != *fi.uaddr) {
            DEBUG_FUTEX("Cur val didn't match val in futex wait");
            return false;
        }
        DEBUG_FUTEX("WAIT took normal path");
        if(bitmask) {
            tempWaiter.mask = fi.val3;
        }
        futexTable[fi.uaddr].push_back(tempWaiter);
        markForSleep(pid, tid, wakeUpPhases);
        leave(pid, tid, cid);
    } else {    //if pi_waiter
        switch (fi.op & FUTEX_CMD_MASK) {
            case FUTEX_LOCK_PI:
                DEBUG_FUTEX("WAIT took lock path");
                if(futexTable[fi.uaddr].size() == 0) // Check that no one else is in line.
                {
                    DEBUG_FUTEX("FUTEX_LOCK_PI successfully locked");
                    futexTable[fi.uaddr].push_back(tempWaiter); //Notice we don't deschedule
                    return true;
                } else {
                  DEBUG_FUTEX("LOCK delayed");
                  if(bitmask) {
                      tempWaiter.mask = fi.val3;
                  }
                  futexTable[fi.uaddr].push_back(tempWaiter);
                  markForSleep(pid, tid, wakeUpPhases);
                  leave(pid, tid, cid);
                }
                break;
            case FUTEX_WAIT_REQUEUE_PI:
                DEBUG_FUTEX("WAIT took reque pi path");
                if(fi.val != *fi.uaddr) {
                    DEBUG_FUTEX("Cur val didn't match val in futex wait");
                    return false;
                }
                tempWaiter.allow_requeue = true;
                if(bitmask) {
                    tempWaiter.mask = fi.val3;
                }
                markForSleep(pid, tid, wakeUpPhases);
                leave(pid, tid, cid);
                futexTable[fi.uaddr].push_back(tempWaiter);
                break;
            case FUTEX_TRYLOCK_PI:
                DEBUG_FUTEX("WAIT took trylock path");
                if(futexTable[fi.uaddr].size() == 0) {
                    DEBUG_FUTEX("FUTEX_LOCK_PI successfully locked");
                    futexTable[fi.uaddr].push_back(tempWaiter); //Notice we don't deschedule
                    return true;
                } else {
                    return false;
                }
                break;
            default:
                panic("We missed something in futex wait.");
        }
    }
    return true;
}