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