TEST(libbacktrace, thread_multiple_dump) { // Dump NUM_THREADS simultaneously. std::vector<thread_t> runners(NUM_THREADS); std::vector<dump_thread_t> dumpers(NUM_THREADS); pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); for (size_t i = 0; i < NUM_THREADS; i++) { // Launch the runners, they will spin in hard loops doing nothing. runners[i].tid = 0; runners[i].state = 0; ASSERT_TRUE(pthread_create(&runners[i].threadId, &attr, ThreadMaxRun, &runners[i]) == 0); } // Wait for tids to be set. for (std::vector<thread_t>::iterator it = runners.begin(); it != runners.end(); ++it) { ASSERT_TRUE(WaitForNonZero(&it->state, 10)); } // Start all of the dumpers at once, they will spin until they are signalled // to begin their dump run. int32_t dump_now = 0; for (size_t i = 0; i < NUM_THREADS; i++) { dumpers[i].thread.tid = runners[i].tid; dumpers[i].thread.state = 0; dumpers[i].done = 0; dumpers[i].now = &dump_now; ASSERT_TRUE(pthread_create(&dumpers[i].thread.threadId, &attr, ThreadDump, &dumpers[i]) == 0); } // Start all of the dumpers going at once. android_atomic_acquire_store(1, &dump_now); for (size_t i = 0; i < NUM_THREADS; i++) { ASSERT_TRUE(WaitForNonZero(&dumpers[i].done, 10)); // Tell the runner thread to exit its infinite loop. android_atomic_acquire_store(0, &runners[i].state); ASSERT_TRUE(dumpers[i].backtrace != NULL); VerifyMaxDump(dumpers[i].backtrace); delete dumpers[i].backtrace; dumpers[i].backtrace = NULL; } }
TEST(libbacktrace, thread_ignore_frames) { pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); thread_t thread_data = { 0, 0, 0 }; pthread_t thread; ASSERT_TRUE(pthread_create(&thread, &attr, ThreadLevelRun, &thread_data) == 0); // Wait up to 2 seconds for the tid to be set. ASSERT_TRUE(WaitForNonZero(&thread_data.state, 2)); UniquePtr<Backtrace> all(Backtrace::Create(getpid(), thread_data.tid)); ASSERT_TRUE(all.get() != NULL); ASSERT_TRUE(all->Unwind(0)); UniquePtr<Backtrace> ign1(Backtrace::Create(getpid(), thread_data.tid)); ASSERT_TRUE(ign1.get() != NULL); ASSERT_TRUE(ign1->Unwind(1)); UniquePtr<Backtrace> ign2(Backtrace::Create(getpid(), thread_data.tid)); ASSERT_TRUE(ign2.get() != NULL); ASSERT_TRUE(ign2->Unwind(2)); VerifyIgnoreFrames(all.get(), ign1.get(), ign2.get(), NULL); // Tell the thread to exit its infinite loop. android_atomic_acquire_store(0, &thread_data.state); }
TEST(libbacktrace, thread_ignore_frames) { pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); thread_t thread_data = { 0, 0, 0 }; pthread_t thread; ASSERT_TRUE(pthread_create(&thread, &attr, ThreadLevelRun, &thread_data) == 0); // Wait up to 2 seconds for the tid to be set. ASSERT_TRUE(WaitForNonZero(&thread_data.state, 2)); backtrace_context_t all; ASSERT_TRUE(backtrace_create_context(&all, getpid(), thread_data.tid, 0)); backtrace_context_t ign1; ASSERT_TRUE(backtrace_create_context(&ign1, getpid(), thread_data.tid, 1)); backtrace_context_t ign2; ASSERT_TRUE(backtrace_create_context(&ign2, getpid(), thread_data.tid, 2)); VerifyIgnoreFrames(all.backtrace, ign1.backtrace, ign2.backtrace, NULL); backtrace_destroy_context(&all); backtrace_destroy_context(&ign1); backtrace_destroy_context(&ign2); // Tell the thread to exit its infinite loop. android_atomic_acquire_store(0, &thread_data.state); }
TEST(libbacktrace, thread_level_trace) { pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); thread_t thread_data = { 0, 0, 0 }; pthread_t thread; ASSERT_TRUE(pthread_create(&thread, &attr, ThreadLevelRun, &thread_data) == 0); // Wait up to 2 seconds for the tid to be set. ASSERT_TRUE(WaitForNonZero(&thread_data.state, 2)); // Save the current signal action and make sure it is restored afterwards. struct sigaction cur_action; ASSERT_TRUE(sigaction(SIGURG, NULL, &cur_action) == 0); UniquePtr<Backtrace> backtrace(Backtrace::Create(getpid(), thread_data.tid)); ASSERT_TRUE(backtrace.get() != NULL); ASSERT_TRUE(backtrace->Unwind(0)); VerifyLevelDump(backtrace.get()); // Tell the thread to exit its infinite loop. android_atomic_acquire_store(0, &thread_data.state); // Verify that the old action was restored. struct sigaction new_action; ASSERT_TRUE(sigaction(SIGURG, NULL, &new_action) == 0); EXPECT_EQ(cur_action.sa_sigaction, new_action.sa_sigaction); EXPECT_EQ(cur_action.sa_flags, new_action.sa_flags); }
void ThreadSetState(void* data) { thread_t* thread = reinterpret_cast<thread_t*>(data); android_atomic_acquire_store(1, &thread->state); volatile int i = 0; while (thread->state) { i++; } }
status_t V4L2VideoNode::open() { status_t status(NO_ERROR); status = V4L2DeviceBase::open(); if (status == NO_ERROR) mState = DEVICE_OPEN; android_atomic_acquire_store(0,&mBuffersInDevice); return status; }
void* ThreadDump(void* data) { dump_thread_t* dump = reinterpret_cast<dump_thread_t*>(data); while (true) { if (android_atomic_acquire_load(dump->now)) { break; } } // The status of the actual unwind will be checked elsewhere. dump->backtrace = Backtrace::Create(getpid(), dump->thread.tid); dump->backtrace->Unwind(0); android_atomic_acquire_store(1, &dump->done); return NULL; }
/* * this is called by our "fake" BpGraphicBufferProducer. We package the * data and reply Parcel and forward them to the calling thread. */ virtual status_t transact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { this->code = code; this->data = &data; this->reply = reply; android_atomic_acquire_store(0, &memoryBarrier); if (exitPending) { // if we've exited, we run the message synchronously right here handleMessage(Message(MSG_API_CALL)); } else { barrier.close(); looper->sendMessage(this, Message(MSG_API_CALL)); barrier.wait(); } return NO_ERROR; }
status_t V4L2VideoNode::close() { status_t status(NO_ERROR); if (mState == DEVICE_STARTED) { stop(); } if (!mBufferPool.isEmpty()) { destroyBufferPool(); } status = V4L2DeviceBase::close(); if (status == NO_ERROR) mState = DEVICE_CLOSED; android_atomic_acquire_store(0,&mBuffersInDevice); return status; }
void* ThreadDump(void* data) { dump_thread_t* dump = reinterpret_cast<dump_thread_t*>(data); while (true) { if (android_atomic_acquire_load(dump->now)) { break; } } dump->context.data = NULL; dump->context.backtrace = NULL; // The status of the actual unwind will be checked elsewhere. backtrace_create_context(&dump->context, getpid(), dump->thread.tid, 0); android_atomic_acquire_store(1, &dump->done); return NULL; }
TEST(libbacktrace, thread_max_trace) { pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); thread_t thread_data = { 0, 0, 0 }; pthread_t thread; ASSERT_TRUE(pthread_create(&thread, &attr, ThreadMaxRun, &thread_data) == 0); // Wait for the tid to be set. ASSERT_TRUE(WaitForNonZero(&thread_data.state, 2)); UniquePtr<Backtrace> backtrace(Backtrace::Create(getpid(), thread_data.tid)); ASSERT_TRUE(backtrace.get() != NULL); ASSERT_TRUE(backtrace->Unwind(0)); VerifyMaxDump(backtrace.get()); // Tell the thread to exit its infinite loop. android_atomic_acquire_store(0, &thread_data.state); }
void MonoPipe::updateFrontAndNRPTS(int32_t newFront, int64_t newNextRdPTS) { // Set the MSB of the update sequence number to indicate that there is a // multi-variable update in progress. Use an atomic store with an "acquire" // barrier to make sure that the next operations cannot be re-ordered and // take place before the change to mUpdateSeq is commited.. int32_t tmp = mUpdateSeq | 0x80000000; android_atomic_acquire_store(tmp, &mUpdateSeq); // Update mFront and mNextRdPTS mFront = newFront; mNextRdPTS = newNextRdPTS; // We are finished with the update. Compute the next sequnce number (which // should be the old sequence number, plus one, and with the MSB cleared) // and then store it in mUpdateSeq using an atomic store with a "release" // barrier so our update operations cannot be re-ordered past the update of // the sequence number. tmp = (tmp + 1) & 0x7FFFFFFF; android_atomic_release_store(tmp, &mUpdateSeq); }
TEST(libbacktrace, thread_max_trace) { pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); thread_t thread_data = { 0, 0, 0 }; pthread_t thread; ASSERT_TRUE(pthread_create(&thread, &attr, ThreadMaxRun, &thread_data) == 0); // Wait for the tid to be set. ASSERT_TRUE(WaitForNonZero(&thread_data.state, 2)); backtrace_context_t context; ASSERT_TRUE(backtrace_create_context(&context, getpid(), thread_data.tid, 0)); VerifyMaxDump(context.backtrace); backtrace_destroy_context(&context); // Tell the thread to exit its infinite loop. android_atomic_acquire_store(0, &thread_data.state); }