183ac345e264c1e22b7a2f1a110b2fe92473394ecJean-Michel Trivi/* 283ac345e264c1e22b7a2f1a110b2fe92473394ecJean-Michel Trivi * Copyright (C) 2011 The Android Open Source Project 383ac345e264c1e22b7a2f1a110b2fe92473394ecJean-Michel Trivi * 483ac345e264c1e22b7a2f1a110b2fe92473394ecJean-Michel Trivi * Licensed under the Apache License, Version 2.0 (the "License"); 583ac345e264c1e22b7a2f1a110b2fe92473394ecJean-Michel Trivi * you may not use this file except in compliance with the License. 683ac345e264c1e22b7a2f1a110b2fe92473394ecJean-Michel Trivi * You may obtain a copy of the License at 783ac345e264c1e22b7a2f1a110b2fe92473394ecJean-Michel Trivi * 883ac345e264c1e22b7a2f1a110b2fe92473394ecJean-Michel Trivi * http://www.apache.org/licenses/LICENSE-2.0 983ac345e264c1e22b7a2f1a110b2fe92473394ecJean-Michel Trivi * 1083ac345e264c1e22b7a2f1a110b2fe92473394ecJean-Michel Trivi * Unless required by applicable law or agreed to in writing, software 1183ac345e264c1e22b7a2f1a110b2fe92473394ecJean-Michel Trivi * distributed under the License is distributed on an "AS IS" BASIS, 1283ac345e264c1e22b7a2f1a110b2fe92473394ecJean-Michel Trivi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1383ac345e264c1e22b7a2f1a110b2fe92473394ecJean-Michel Trivi * See the License for the specific language governing permissions and 1483ac345e264c1e22b7a2f1a110b2fe92473394ecJean-Michel Trivi * limitations under the License. 1583ac345e264c1e22b7a2f1a110b2fe92473394ecJean-Michel Trivi */ 1683ac345e264c1e22b7a2f1a110b2fe92473394ecJean-Michel Trivi 176cce136651f6fd2c7aecd45bc553270152d75462Jean-Michel Trivi#include "CallbackProtector.h" 18f4b45a37248899ae2d27bb172f8387fbf1edff8eGlenn Kasten#include "sllog.h" 196cce136651f6fd2c7aecd45bc553270152d75462Jean-Michel Trivi 206cce136651f6fd2c7aecd45bc553270152d75462Jean-Michel Trivi#include <media/stagefright/foundation/ADebug.h> 2183ac345e264c1e22b7a2f1a110b2fe92473394ecJean-Michel Trivi 2283ac345e264c1e22b7a2f1a110b2fe92473394ecJean-Michel Trivi//-------------------------------------------------------------------------------------------------- 2383ac345e264c1e22b7a2f1a110b2fe92473394ecJean-Michel Trivinamespace android { 2483ac345e264c1e22b7a2f1a110b2fe92473394ecJean-Michel Trivi 2583ac345e264c1e22b7a2f1a110b2fe92473394ecJean-Michel Trivi 266cce136651f6fd2c7aecd45bc553270152d75462Jean-Michel TriviCallbackProtector::CallbackProtector() : RefBase(), 2783ac345e264c1e22b7a2f1a110b2fe92473394ecJean-Michel Trivi mSafeToEnterCb(true), 28f4b45a37248899ae2d27bb172f8387fbf1edff8eGlenn Kasten mCbCount(0) 29f4b45a37248899ae2d27bb172f8387fbf1edff8eGlenn Kasten#ifdef USE_DEBUG 303eaa329775fc522d8ea4acd4edc379eabf9ac332Glenn Kasten , mCallbackThread((pthread_t) NULL), 31f4b45a37248899ae2d27bb172f8387fbf1edff8eGlenn Kasten mCallbackTid(0), 323eaa329775fc522d8ea4acd4edc379eabf9ac332Glenn Kasten mRequesterThread((pthread_t) NULL), 33f4b45a37248899ae2d27bb172f8387fbf1edff8eGlenn Kasten mRequesterTid(0) 34f4b45a37248899ae2d27bb172f8387fbf1edff8eGlenn Kasten#endif 35f4b45a37248899ae2d27bb172f8387fbf1edff8eGlenn Kasten{ 3683ac345e264c1e22b7a2f1a110b2fe92473394ecJean-Michel Trivi} 3783ac345e264c1e22b7a2f1a110b2fe92473394ecJean-Michel Trivi 3883ac345e264c1e22b7a2f1a110b2fe92473394ecJean-Michel Trivi 396cce136651f6fd2c7aecd45bc553270152d75462Jean-Michel TriviCallbackProtector::~CallbackProtector() { 40f4b45a37248899ae2d27bb172f8387fbf1edff8eGlenn Kasten Mutex::Autolock _l(mLock); 41f4b45a37248899ae2d27bb172f8387fbf1edff8eGlenn Kasten if (mCbCount) { 42f4b45a37248899ae2d27bb172f8387fbf1edff8eGlenn Kasten SL_LOGE("Callback protector detected an active callback after destroy"); 43f4b45a37248899ae2d27bb172f8387fbf1edff8eGlenn Kasten } 446cce136651f6fd2c7aecd45bc553270152d75462Jean-Michel Trivi 456cce136651f6fd2c7aecd45bc553270152d75462Jean-Michel Trivi} 466cce136651f6fd2c7aecd45bc553270152d75462Jean-Michel Trivi 4783ac345e264c1e22b7a2f1a110b2fe92473394ecJean-Michel Trivi 48485a038f9f0f898227b8ab4218e94c5d56b6ed0bGlenn Kasten// static 496cce136651f6fd2c7aecd45bc553270152d75462Jean-Michel Trivibool CallbackProtector::enterCbIfOk(const sp<CallbackProtector> &protector) { 506cce136651f6fd2c7aecd45bc553270152d75462Jean-Michel Trivi if (protector != 0) { 516cce136651f6fd2c7aecd45bc553270152d75462Jean-Michel Trivi return protector->enterCb(); 526cce136651f6fd2c7aecd45bc553270152d75462Jean-Michel Trivi } else { 53f4b45a37248899ae2d27bb172f8387fbf1edff8eGlenn Kasten SL_LOGE("Callback protector is missing"); 546cce136651f6fd2c7aecd45bc553270152d75462Jean-Michel Trivi return false; 556cce136651f6fd2c7aecd45bc553270152d75462Jean-Michel Trivi } 5683ac345e264c1e22b7a2f1a110b2fe92473394ecJean-Michel Trivi} 5783ac345e264c1e22b7a2f1a110b2fe92473394ecJean-Michel Trivi 5883ac345e264c1e22b7a2f1a110b2fe92473394ecJean-Michel Trivi 596cce136651f6fd2c7aecd45bc553270152d75462Jean-Michel Trivibool CallbackProtector::enterCb() { 6083ac345e264c1e22b7a2f1a110b2fe92473394ecJean-Michel Trivi Mutex::Autolock _l(mLock); 6183ac345e264c1e22b7a2f1a110b2fe92473394ecJean-Michel Trivi if (mSafeToEnterCb) { 6283ac345e264c1e22b7a2f1a110b2fe92473394ecJean-Michel Trivi mCbCount++; 63f4b45a37248899ae2d27bb172f8387fbf1edff8eGlenn Kasten#ifdef USE_DEBUG 64f4b45a37248899ae2d27bb172f8387fbf1edff8eGlenn Kasten if (mCbCount > 1) { 6515c706b25a8b9993b5391de574ed52c1628060beGlenn Kasten SL_LOGV("Callback protector allowed multiple or nested callback entry: %u", mCbCount); 66f4b45a37248899ae2d27bb172f8387fbf1edff8eGlenn Kasten } else { 67f4b45a37248899ae2d27bb172f8387fbf1edff8eGlenn Kasten mCallbackThread = pthread_self(); 68f4b45a37248899ae2d27bb172f8387fbf1edff8eGlenn Kasten mCallbackTid = gettid(); 69f4b45a37248899ae2d27bb172f8387fbf1edff8eGlenn Kasten } 70f4b45a37248899ae2d27bb172f8387fbf1edff8eGlenn Kasten#endif 71f4b45a37248899ae2d27bb172f8387fbf1edff8eGlenn Kasten } else { 72f4b45a37248899ae2d27bb172f8387fbf1edff8eGlenn Kasten#ifdef USE_DEBUG 7315c706b25a8b9993b5391de574ed52c1628060beGlenn Kasten SL_LOGV("Callback protector denied callback entry by thread %p tid %d during destroy" 74f4b45a37248899ae2d27bb172f8387fbf1edff8eGlenn Kasten " requested by thread %p tid %d", 75f4b45a37248899ae2d27bb172f8387fbf1edff8eGlenn Kasten (void *) pthread_self(), gettid(), 76f4b45a37248899ae2d27bb172f8387fbf1edff8eGlenn Kasten (void *) mRequesterThread, mRequesterTid); 77f4b45a37248899ae2d27bb172f8387fbf1edff8eGlenn Kasten#else 7815c706b25a8b9993b5391de574ed52c1628060beGlenn Kasten SL_LOGV("Callback protector denied callback entry during destroy"); 79f4b45a37248899ae2d27bb172f8387fbf1edff8eGlenn Kasten#endif 8083ac345e264c1e22b7a2f1a110b2fe92473394ecJean-Michel Trivi } 8183ac345e264c1e22b7a2f1a110b2fe92473394ecJean-Michel Trivi return mSafeToEnterCb; 8283ac345e264c1e22b7a2f1a110b2fe92473394ecJean-Michel Trivi} 8383ac345e264c1e22b7a2f1a110b2fe92473394ecJean-Michel Trivi 8483ac345e264c1e22b7a2f1a110b2fe92473394ecJean-Michel Trivi 856cce136651f6fd2c7aecd45bc553270152d75462Jean-Michel Trivivoid CallbackProtector::exitCb() { 8683ac345e264c1e22b7a2f1a110b2fe92473394ecJean-Michel Trivi Mutex::Autolock _l(mLock); 876cce136651f6fd2c7aecd45bc553270152d75462Jean-Michel Trivi 886cce136651f6fd2c7aecd45bc553270152d75462Jean-Michel Trivi CHECK(mCbCount > 0); 896cce136651f6fd2c7aecd45bc553270152d75462Jean-Michel Trivi mCbCount--; 906cce136651f6fd2c7aecd45bc553270152d75462Jean-Michel Trivi 9183ac345e264c1e22b7a2f1a110b2fe92473394ecJean-Michel Trivi if (mCbCount == 0) { 92f4b45a37248899ae2d27bb172f8387fbf1edff8eGlenn Kasten if (!mSafeToEnterCb) { 93f4b45a37248899ae2d27bb172f8387fbf1edff8eGlenn Kasten#ifdef USE_DEBUG 9415c706b25a8b9993b5391de574ed52c1628060beGlenn Kasten SL_LOGV("Callback protector detected return from callback by thread %p tid %d during" 95f4b45a37248899ae2d27bb172f8387fbf1edff8eGlenn Kasten " destroy requested by thread %p tid %d", 96f4b45a37248899ae2d27bb172f8387fbf1edff8eGlenn Kasten (void *) mCallbackThread, mCallbackTid, 97f4b45a37248899ae2d27bb172f8387fbf1edff8eGlenn Kasten (void *) mRequesterThread, mRequesterTid); 98f4b45a37248899ae2d27bb172f8387fbf1edff8eGlenn Kasten#else 9915c706b25a8b9993b5391de574ed52c1628060beGlenn Kasten SL_LOGV("Callback protector detected return from callback during destroy"); 100f4b45a37248899ae2d27bb172f8387fbf1edff8eGlenn Kasten#endif 101f4b45a37248899ae2d27bb172f8387fbf1edff8eGlenn Kasten mCbExitedCondition.broadcast(); 102f4b45a37248899ae2d27bb172f8387fbf1edff8eGlenn Kasten } 103f4b45a37248899ae2d27bb172f8387fbf1edff8eGlenn Kasten#ifdef USE_DEBUG 1043eaa329775fc522d8ea4acd4edc379eabf9ac332Glenn Kasten mCallbackThread = (pthread_t) NULL; 105f4b45a37248899ae2d27bb172f8387fbf1edff8eGlenn Kasten mCallbackTid = 0; 106f4b45a37248899ae2d27bb172f8387fbf1edff8eGlenn Kasten#endif 10783ac345e264c1e22b7a2f1a110b2fe92473394ecJean-Michel Trivi } 10883ac345e264c1e22b7a2f1a110b2fe92473394ecJean-Michel Trivi} 10983ac345e264c1e22b7a2f1a110b2fe92473394ecJean-Michel Trivi 11083ac345e264c1e22b7a2f1a110b2fe92473394ecJean-Michel Trivi 1116cce136651f6fd2c7aecd45bc553270152d75462Jean-Michel Trivivoid CallbackProtector::requestCbExitAndWait() { 11283ac345e264c1e22b7a2f1a110b2fe92473394ecJean-Michel Trivi Mutex::Autolock _l(mLock); 11383ac345e264c1e22b7a2f1a110b2fe92473394ecJean-Michel Trivi mSafeToEnterCb = false; 114f4b45a37248899ae2d27bb172f8387fbf1edff8eGlenn Kasten#ifdef USE_DEBUG 115f4b45a37248899ae2d27bb172f8387fbf1edff8eGlenn Kasten mRequesterThread = pthread_self(); 116f4b45a37248899ae2d27bb172f8387fbf1edff8eGlenn Kasten mRequesterTid = gettid(); 117f4b45a37248899ae2d27bb172f8387fbf1edff8eGlenn Kasten#endif 11883ac345e264c1e22b7a2f1a110b2fe92473394ecJean-Michel Trivi while (mCbCount) { 119f4b45a37248899ae2d27bb172f8387fbf1edff8eGlenn Kasten#ifdef USE_DEBUG 12015c706b25a8b9993b5391de574ed52c1628060beGlenn Kasten SL_LOGV("Callback protector detected in-progress callback by thread %p tid %d during" 121f4b45a37248899ae2d27bb172f8387fbf1edff8eGlenn Kasten " blocking destroy requested by thread %p tid %d", 122f4b45a37248899ae2d27bb172f8387fbf1edff8eGlenn Kasten (void *) mCallbackThread, mCallbackTid, 123f4b45a37248899ae2d27bb172f8387fbf1edff8eGlenn Kasten (void *) pthread_self(), gettid()); 124f4b45a37248899ae2d27bb172f8387fbf1edff8eGlenn Kasten#else 12515c706b25a8b9993b5391de574ed52c1628060beGlenn Kasten SL_LOGV("Callback protector detected in-progress callback during blocking destroy"); 126f4b45a37248899ae2d27bb172f8387fbf1edff8eGlenn Kasten#endif 12783ac345e264c1e22b7a2f1a110b2fe92473394ecJean-Michel Trivi mCbExitedCondition.wait(mLock); 12883ac345e264c1e22b7a2f1a110b2fe92473394ecJean-Michel Trivi } 12983ac345e264c1e22b7a2f1a110b2fe92473394ecJean-Michel Trivi} 13083ac345e264c1e22b7a2f1a110b2fe92473394ecJean-Michel Trivi 13183ac345e264c1e22b7a2f1a110b2fe92473394ecJean-Michel Trivi 132f4b45a37248899ae2d27bb172f8387fbf1edff8eGlenn Kastenvoid CallbackProtector::requestCbExit() { 133f4b45a37248899ae2d27bb172f8387fbf1edff8eGlenn Kasten Mutex::Autolock _l(mLock); 134f4b45a37248899ae2d27bb172f8387fbf1edff8eGlenn Kasten mSafeToEnterCb = false; 135f4b45a37248899ae2d27bb172f8387fbf1edff8eGlenn Kasten#ifdef USE_DEBUG 136f4b45a37248899ae2d27bb172f8387fbf1edff8eGlenn Kasten mRequesterThread = pthread_self(); 137f4b45a37248899ae2d27bb172f8387fbf1edff8eGlenn Kasten mRequesterTid = gettid(); 138f4b45a37248899ae2d27bb172f8387fbf1edff8eGlenn Kasten#endif 139f4b45a37248899ae2d27bb172f8387fbf1edff8eGlenn Kasten if (mCbCount) { 140f4b45a37248899ae2d27bb172f8387fbf1edff8eGlenn Kasten#ifdef USE_DEBUG 14115c706b25a8b9993b5391de574ed52c1628060beGlenn Kasten SL_LOGV("Callback protector detected in-progress callback by thread %p tid %d during" 142f4b45a37248899ae2d27bb172f8387fbf1edff8eGlenn Kasten " non-blocking destroy requested by thread %p tid %d", 143f4b45a37248899ae2d27bb172f8387fbf1edff8eGlenn Kasten (void *) mCallbackThread, mCallbackTid, 144f4b45a37248899ae2d27bb172f8387fbf1edff8eGlenn Kasten (void *) pthread_self(), gettid()); 145f4b45a37248899ae2d27bb172f8387fbf1edff8eGlenn Kasten#else 14615c706b25a8b9993b5391de574ed52c1628060beGlenn Kasten SL_LOGV("Callback protector detected in-progress callback during non-blocking destroy"); 147f4b45a37248899ae2d27bb172f8387fbf1edff8eGlenn Kasten#endif 148f4b45a37248899ae2d27bb172f8387fbf1edff8eGlenn Kasten } 149f4b45a37248899ae2d27bb172f8387fbf1edff8eGlenn Kasten} 150f4b45a37248899ae2d27bb172f8387fbf1edff8eGlenn Kasten 15183ac345e264c1e22b7a2f1a110b2fe92473394ecJean-Michel Trivi} // namespace android 152