Esempio n. 1
0
SmpError SThread::run(const char* name, int priority, int stack)
{
	SMutex::Autolock _l(mLock);

	if (mRunning) {
		// thread already started
		return SMP_INVALID_REQ;
	}

	// reset status and exitPending to their default value, so we can
	// try again after an error happened (either below, or in readyToRun())
	mStatus = SMP_OK;
	mExitPending = false;
	mThread = thread_id_t(-1);
	mRunning = true;

	bool res;
	res = createRawThreadEtc(_threadLoop, this, name, priority, stack, &mThread);

	if (res == false) {
		mStatus = SMP_UNKNOWN;   // something happened!
		mRunning = false;
		mThread = thread_id_t(-1);

		return SMP_UNKNOWN;
	}

	// Do not refer to mStatus here: The thread is already running (may, in fact
	// already have exited with a valid mStatus result). The SMP_OK indication
	// here merely indicates successfully starting the thread and does not
	// imply successful termination/execution.
	return SMP_OK;

	// Exiting scope of mLock is a memory barrier and allows new thread to run
}
Esempio n. 2
0
SThread::SThread()
	:mThread(thread_id_t(-1)),
	mStatus(SMP_OK),
	mExitPending(false),
	mRunning(false)
{
}
status_t Thread::run(const char* name, int32_t priority, size_t stack)
{
    Mutex::Autolock _l(mLock);

    if (mRunning) {
        // thread already started
        return INVALID_OPERATION;
    }

    // reset status and exitPending to their default value, so we can
    // try again after an error happened (either below, or in readyToRun())
    mStatus = NO_ERROR;
    mExitPending = false;
    mThread = thread_id_t(-1);
    
    // hold a strong reference on ourself
    mHoldSelf = this;

    mRunning = true;

    bool res;
    if (mCanCallJava) {
        res = createThreadEtc(_threadLoop,
                this, name, priority, stack, &mThread);
    } else {
        res = androidCreateRawThreadEtc(_threadLoop,
                this, name, priority, stack, &mThread);
    }
    
    if (res == false) {
        mStatus = UNKNOWN_ERROR;   // something happened!
        mRunning = false;
        mThread = thread_id_t(-1);
        mHoldSelf.clear();  // "this" may have gone away after this.

        return UNKNOWN_ERROR;
    }
    
    // Do not refer to mStatus here: The thread is already running (may, in fact
    // already have exited with a valid mStatus result). The NO_ERROR indication
    // here merely indicates successfully starting the thread and does not
    // imply successful termination/execution.
    return NO_ERROR;

    // Exiting scope of mLock is a memory barrier and allows new thread to run
}
Thread::Thread(bool canCallJava)
    :   mCanCallJava(canCallJava),
        mThread(thread_id_t(-1)),
        mLock("Thread::mLock"),
        mStatus(NO_ERROR),
        mExitPending(false), mRunning(false)
{
}
int Thread::_threadLoop(void* user)
{
    Thread* const self = static_cast<Thread*>(user);
    sp<Thread> strong(self->mHoldSelf);
    wp<Thread> weak(strong);
    self->mHoldSelf.clear();

#if HAVE_ANDROID_OS
    // this is very useful for debugging with gdb
    self->mTid = gettid();
#endif

    bool first = true;

    do {
        bool result;
        if (first) {
            first = false;
            self->mStatus = self->readyToRun();
            result = (self->mStatus == NO_ERROR);

            if (result && !self->mExitPending) {
                // Binder threads (and maybe others) rely on threadLoop
                // running at least once after a successful ::readyToRun()
                // (unless, of course, the thread has already been asked to exit
                // at that point).
                // This is because threads are essentially used like this:
                //   (new ThreadSubclass())->run();
                // The caller therefore does not retain a strong reference to
                // the thread and the thread would simply disappear after the
                // successful ::readyToRun() call instead of entering the
                // threadLoop at least once.
                result = self->threadLoop();
            }
        } else {
            result = self->threadLoop();
        }

        if (result == false || self->mExitPending) {
            self->mExitPending = true;
            self->mLock.lock();
            self->mRunning = false;
            self->mThreadExitedCondition.broadcast();
			self->mThread = thread_id_t(-1); // thread id could be reused
            self->mLock.unlock();
            break;
        }
        
        // Release our strong reference, to let a chance to the thread
        // to die a peaceful death.
        strong.clear();
        // And immediately, re-acquire a strong reference for the next loop
        strong = weak.promote();
    } while(strong != 0);
    
    return 0;
}
Thread::Thread(bool canCallJava)
    :   mCanCallJava(canCallJava),
        mThread(thread_id_t(-1)),
        mLock("Thread::mLock"),
        mStatus(NO_ERROR),
        mExitPending(false), mRunning(false)
#ifdef HAVE_ANDROID_OS
        , mTid(-1)
#endif
{
}
Esempio n. 7
0
int SThread::_threadLoop(void* user)
{
	SThread* const self = static_cast<SThread*>(user);

	bool first = true;
	bool result;

	do {
		if (first) {
			first = false;
			self->mStatus = self->readyToRun();
			result = self->mStatus == SMP_OK;

			if (result && !self->exitPending()) {
				// Binder threads (and maybe others) rely on threadLoop
				// running at least once after a successful ::readyToRun()
				// (unless, of course, the thread has already been asked to exit
				// at that point).
				// This is because threads are essentially used like this:
				//   (new ThreadSubclass())->run();
				// The caller therefore does not retain a strong reference to
				// the thread and the thread would simply disappear after the
				// successful ::readyToRun() call instead of entering the
				// threadLoop at least once.
				result = self->threadLoop();
			}
		} else {
			result = self->threadLoop();
		}

		// establish a scope for mLock
		{
			SMutex::Autolock _l(self->mLock);
			if (result == false || self->mExitPending) {
				self->mExitPending = true;
				self->mRunning = false;
				// clear thread ID so that requestExitAndWait() does not exit if
				// called by a new thread using the same thread ID as this one.
				self->mThread = thread_id_t(-1);
				// note that interested observers blocked in requestExitAndWait are
				// awoken by broadcast, but blocked on mLock until break exits scope
				self->mThreadExitedCondition.broadcast();
				break;
			}
		}
	} while (true);

	return 0;
}