void Fpc1020Sensor::FingerprintThread::handleShutdown()
{
    ALOGV("Shutting down thread %d", getTid());
    mSensor->deactivate();
    mSensor->stopWatchdogThread();

    android::Mutex::Autolock l(mSensor->mThreadStateLock);
    mSensor->mWaitingForWakeup = false;
    mSensor->mThread.clear();

    ALOGV("Thread %d now shut down", getTid());
}
Esempio n. 2
0
EXP_OPTION int getLastError()
{
  THREAD_ID Tid = getTid();

  ThreadErrors *threadErrors = findThreadErrorsByTid(Tid);
  if (threadErrors == NULL)
    return 0;
  return  (threadErrors->readErrorIdx >= 0 ?
	   threadErrors->ddocLastErrors[threadErrors->readErrorIdx].code : ERR_OK);
}
Esempio n. 3
0
EXP_OPTION void clearErrors()
{
  THREAD_ID Tid = getTid();
  ThreadErrors *threadErrors = findThreadErrorsByTid(Tid);
  if (threadErrors == NULL)
    return;
  memset(threadErrors->ddocLastErrors, 0, sizeof(ErrorInfo) * ERROR_BUF_LENGTH);
  threadErrors->readErrorIdx = -1;
  threadErrors->currentErrorIdx = -1;
}
Esempio n. 4
0
void Scheduler::waitUntilQueued(ThreadInfo* th) {
    uint64_t startNs = getNs();
    uint32_t sleepUs = 1;
    while(!IsSleepingInFutex(th->linuxPid, th->linuxTid, (uintptr_t)&schedLock)) {
        TrueSleep(sleepUs++); // linear backoff, start small but avoid overwhelming the OS with short sleeps
        uint64_t curNs = getNs();
        if (curNs - startNs > (2L<<31L) /* ~2s */) {
            warn("waitUntilQueued for pid %d tid %d timed out", getPid(th->gid), getTid(th->gid));
            return;
        }
    }
}
virtual void run(void)
{
    ULong                   sAllocSize;
    SInt                    i;
    iduMemoryClientIndex    sTestIndex = (iduMemoryClientIndex)0;
    
    for (i = 0; i < TEST_ALLOC_COUNT / 2; i++)
    {
        sAllocSize = gAllocSize[i];

        ACT_CHECK_DESC(iduMemMgr::malloc(sTestIndex,
                                         sAllocSize,
                                         (void **)&mBufPtrMalloc[i])
                       == IDE_SUCCESS,
                       ("malloc() failed at %p", (void*)getTid()));
        ACT_CHECK(mBufPtrMalloc[i] != NULL);
    }

    for (i = 0; i < TEST_ALLOC_COUNT / 2; i++)
    {
        sAllocSize = gAllocSize[i];

        ACT_CHECK_DESC(iduMemMgr::malloc(sTestIndex,
                                         sAllocSize,
                                         (void **)&mBufPtrMalloc[i + TEST_ALLOC_COUNT / 2])
                       == IDE_SUCCESS,
                       ("malloc() failed at %p", (void*)getTid()));
        ACT_CHECK(mBufPtrMalloc[i] != NULL);
        ACT_CHECK(iduMemMgr::free(mBufPtrMalloc[i]) == IDE_SUCCESS);
    }
    
    for (i = 0; i < TEST_ALLOC_COUNT / 2; i++)
    {
        ACT_CHECK(iduMemMgr::free(mBufPtrMalloc[i + TEST_ALLOC_COUNT / 2]) == IDE_SUCCESS);
    }
}
Esempio n. 6
0
EXP_OPTION void addError(int code, char *fileName, int line, char *assertion)
{
  //no errors found yet. Set a trace-back mark to the end of array.
  //printf("Error : %d at %s line %d, assertion %s\n", code, fileName, line, assertion);

  ThreadErrors	*threadErrors;
  THREAD_ID Tid = getTid();		//Find our identity

  threadErrors = findThreadErrorsByTid(Tid);
  //	printf("addError init: tid=%ld, threadErrors=%p\n", Tid, threadErrors);
  if (threadErrors == NULL) {	//This Tid has no entry in ThreadErrors table
    threadErrors = addThreadErrorsByTid(Tid);  // MEMLEAK:  ???
    if (threadErrors == NULL)
      return;				// What else can we do?
  }
	
  // printf("addError step 1 : tid=%ld, threadErrors=%p\n", Tid, threadErrors);
  if(threadErrors->currentErrorIdx < 0)
    resetError(&(threadErrors->ddocLastErrors[ERROR_BUF_LENGTH - 1]));

  threadErrors->currentErrorIdx++;

  //index at the end -> roll it over to the beginning
  if(threadErrors->currentErrorIdx == ERROR_BUF_LENGTH)
    threadErrors->currentErrorIdx = 0;

  //set the information
  ddocDebug(4, "addError", "Index: %d Error : %d at %s line %d, assertion %s", threadErrors->currentErrorIdx, code, fileName, line, assertion);
  threadErrors->ddocLastErrors[threadErrors->currentErrorIdx].code = code;
  threadErrors->ddocLastErrors[threadErrors->currentErrorIdx].fileName = fileName;
  threadErrors->ddocLastErrors[threadErrors->currentErrorIdx].line = line;
  threadErrors->ddocLastErrors[threadErrors->currentErrorIdx].assertion = assertion;

  //index at the end? Set the traceback mark to the beginning
  if(threadErrors->currentErrorIdx == ERROR_BUF_LENGTH - 1)
    resetError(&(threadErrors->ddocLastErrors[0]));
  else //set the traceback mark to the next position
    resetError(&(threadErrors->ddocLastErrors[threadErrors->currentErrorIdx + 1]));

  threadErrors->readErrorIdx = threadErrors->currentErrorIdx;
}
Esempio n. 7
0
//returns the last
EXP_OPTION ErrorInfo* getErrorInfo()
{
  ErrorInfo *pErrInfo = 0;
  THREAD_ID Tid = getTid();

  ThreadErrors *threadErrors = findThreadErrorsByTid(Tid);
  if (threadErrors == NULL)
    return 0;

  if(threadErrors->readErrorIdx >= 0 && 
     threadErrors->ddocLastErrors[threadErrors->readErrorIdx].code != ERR_OK) {
    pErrInfo = &(threadErrors->ddocLastErrors[threadErrors->readErrorIdx]);
    threadErrors->readErrorIdx--;
    if(threadErrors->readErrorIdx < 0) //roll over
      threadErrors->readErrorIdx = ERROR_BUF_LENGTH - 1;
  }
  else
    pErrInfo = 0;

  return pErrInfo;
}
// . ***** CHECKOFF LOOP *****
// . loop over the checkoff requests TO SEND
// . send checkoff requests out that we need to send and have not yet got
//   a reply for. when we get a reply for them the "need to send checkoff 
//   request" key is immediately deleted
// . make a big list then call msg1 with an rdbId of RDB_SYNCDB
// . do not include dead hosts
void Syncdb::loop5 ( ) {
	// make the start key
	key128_t k = m_nextk;
	// end key
	key128_t ek;
	ek = makeKey(1,0,0,0,0xffffffff,0xffffffff,0xffffffffffffffffLL,1);
	// reset
	m_nk = 0;
	// get it
	long nn = m_qt.getNextNode ( 0 , (char *)&k );
	// do one tid at a time
	uint32_t startTid = getTid ( &k );
	// do the loop
	for ( ; nn >= 0 ; nn = m_qt.getNextNode ( nn ) ) {
		// breathe
		QUICKPOLL ( MAX_NICENESS );
		// get key
		key128_t k = *(key128_t *)m_qt.getKey ( nn );
		// save it
		m_nextk = k;
		// add one
		m_nextk += 1;
		// stop when we hit the end
		if ( k > ek ) break;
		// get twin id
		uint32_t tid = getTid ( &k );
		// stop if tid changed
		if ( tid != startTid && m_nk >= 0 ) break;
		// skip if tid is dead
		if ( g_hostdb.isDead ( tid ) ) {
			// skip to next tid!
			tid++;
			// . find the key of the FIRST meta list we need to add
			//   for this new senderId, "sid"
			// . mdw: i reset sid to 0
			key128_t nk = makeKey ( 1,0,0,0,tid,0,0,0 );
			// undo the m_qt.getNextNode(nn) we call in for loop
			nn = m_qt.getPrevNode ( 0 , (char *)&nk );
			// bail if no good
			if ( nn < 0 ) break;
			// get next key from this new sid
			continue;
		}
		// get zid
		uint64_t zid = getZid ( &k );
		// get sid
		uint32_t sid = getSid ( &k );
		// note it
		log("sync: storing key for meta request list sid=%lu zid=%llu "
		    "from twin hostid #%li",(unsigned long)sid,
		    (unsigned long long)zid,(long)tid);
		// make the key. make NEGATIVE "b" keys.
		m_keys [ m_nk++ ] = makeKey ( 0,1,0,0,0,sid,zid,0 );
		// stop if full
		if ( m_nk >= MAX_CHECKOFF_KEYS ) break;
	}
	// all done?
	if ( k <= ek && m_nk <= 0 ) { m_calledLoop5 = true; return; }
	// . add the whole list at once
	// . make our own msg1 request to send to just one host
	if ( g_udpServer.sendRequest ( (char *)m_keys    ,
				       m_nk * 16         ,
				       0x5d              , // SYNCDB REQUEST
				       0                 , // ip
				       0                 , // port
				       startTid          , // hostId
				       NULL              , // retSlot
				       NULL              , // state
				       addedListWrapper5 , // wrapper
				       60                , // timeout
				       -1                , // backoff
				       -1                , // maxWait
				       NULL              , // replyBuf
				       0                 , // replyBufSize
				       MAX_NICENESS      ))
		// it blocked, return now
		return;
	// i guess we had an error...
	if ( ! addedList5() ) return;
}
// . ***** SYNC LOOP *****
// . loop over the checkoff requests we are waiting for. "b" keys.
// . send out msg0 requests for meta lists we need
// . if we got a 60+ sec old checkoff recvd but never got the meta list
//   ourselves, then request it!!
bool Syncdb::loop4 ( ) {
	// make the start key. a "b" key
	key128_t k = m_syncKey;
	// end key
	key128_t ek;
	ek = makeKey(0,1,0,0,0xffffffff,0xffffffff,0xffffffffffffffffLL,1);
	// get next node
	long nn = m_qt.getNode ( 0 , (char *)&k );
	// get group we are in
	//Host *group = g_hostdb.getMyShard();
	// use this for determining approximate age of meta lists
	long long nowms = gettimeofdayInMilliseconds();
	// do the loop
	for ( ; nn >= 0 ; nn = m_qt.getNextNode ( nn ) ) {
		// breathe
		QUICKPOLL ( MAX_NICENESS );
		// give other loops some time so we can digest these
		// meta lists we added
		if ( m_addCount >= 100 ) break;
		// get key
		key128_t k = *(key128_t *)m_qt.getKey ( nn );
		// stop when we hit the end
		if ( k > ek ) break;
		// update
		m_syncKey = k;
		// get twin id
		uint32_t tid = getTid ( &k );
		// skip if tid is dead
		if ( g_hostdb.isDead ( tid ) ) {
			// skip to next tid!
			tid++;
			// . find the key of the FIRST meta list we need to add
			//   for this new senderId, "sid"
			// . mdw: i reset sid to 0
			key128_t nk = makeKey ( 0,1,0,0,tid,0,0,0 );
			// undo the m_qt.getNextNode(nn) we call in for loop
			nn = m_qt.getPrevNode ( 0 , (char *)&nk );
			// sanity check
			if ( nn < 0 ) { char *xx=NULL;*xx=0; }
			// get next key from this new sid
			continue;
		}
		// . skip if delbit set
		// . the delbit set means we got the meta list and are 
		//   waiting to receive the checkoff request from twin #sid
		// . when it comes in it will annihilate with this key!
		// . right now we are only interested in *negative* keys, 
		//   those with their delbit cleared
		if ( (k.n0 & 0x01) == 0x01 ) continue;
		// . ok we got checkoff request from tid for this sid/zid
		// . and we have not got the meta list ourselves yet cuz
		//   we would have had k with the delbit set.
		// . get zid
		uint64_t zid = getZid ( &k );
		// get sid
		uint32_t sid = getSid ( &k );
		// get its approximate age
		long long age = nowms - zid;
		// go to next sid if not 60 seconds yet for this one
		if ( age < 60000 ) {
			// no use banging away at this sid any more since we
			// are missing another action for this one
			sid++;
			// find the key of the FIRST meta list we need to add
			// for this new senderId, "sid". make the "b" key.
			key128_t nk = makeKey ( 0,1,0,0,tid,sid,0,0 );
			// undo the m_qt.getNextNode(nn) we call in for loop
			nn = m_qt.getPrevNode ( 0 , (char *)&nk );
			// sanity check
			if ( nn < 0 ) { char *xx=NULL;*xx=0; }
			// get next key from this new sid
			continue;
		}
		// make the "d" key to see if we got the meta list just
		// to make sure! we do not want to re-add a meta list!
		key128_t dk = makeKey(0,0,0,1,0,sid,zid,1);
		if ( m_qt.getNode ( 0 , (char *)&dk ) >= 0 ) continue;
		// note it
		log("sync: requesting meta list sid=%lu zid=%llu age=%llu "
		    "from twin hostid #%li",
		    (unsigned long)sid,
		    (unsigned long long)zid,
		    (unsigned long long)age,
		    (long)tid);
		// i guess we are out of sync
		g_hostdb.m_myHost->m_inSync = false;
		// do not let sleep ticker call bigLoop
		m_outstanding = true;
		// record the sid
		m_requestedSid = sid;
		// make the c key range
		key128_t sk2 = makeKey(0,0,1,0,0,sid,zid,0);
		key128_t ek2 = makeKey(0,0,1,0,0,sid,zid,1);
		// ok, ask tid for this meta list
		if ( ! m_msg0.getList ( tid             , // hostId
					0               , // ip
					0               , // port
					0               , // maxCacheAge
					false           , // addToCache
					RDB_SYNCDB      ,
					0            , // collnum
					&m_list         ,
					(char *)&sk2    ,
					(char *)&ek2    ,
					999             , // minRecSizes
					NULL            ,
					gotListWrapper4 ,
					MAX_NICENESS    ,
					false           ))// err correction?
			return false;
		// stop on error. return true with g_errno set on error
		if ( ! gotList4() ) return true;
	}
	// we completed
	m_calledLoop4 = true;
	return true;
}
Esempio n. 10
0
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");
}
void EventThread::onFirstRef() {
    run("EventThread", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE);
    android_set_rt_ioprio(getTid(), 1);
}