locks.c revision a60dbf554549d10780f473b6e1373aa07aec3a28
1a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten/*
2a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten * Copyright (C) 2010 The Android Open Source Project
3a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten *
4a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten * Licensed under the Apache License, Version 2.0 (the "License");
5a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten * you may not use this file except in compliance with the License.
6a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten * You may obtain a copy of the License at
7a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten *
8a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten *      http://www.apache.org/licenses/LICENSE-2.0
9a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten *
10a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten * Unless required by applicable law or agreed to in writing, software
11a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten * distributed under the License is distributed on an "AS IS" BASIS,
12a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten * See the License for the specific language governing permissions and
14a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten * limitations under the License.
15a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten */
16a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten
17a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten#include "sles_allinclusive.h"
18a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten
190b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
20928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten/** \brief Exclusively lock an object */
210b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
22fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten#ifdef USE_DEBUG
23bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kastenvoid object_lock_exclusive_(IObject *thiz, const char *file, int line)
24fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten{
25fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten    int ok;
26bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    ok = pthread_mutex_trylock(&thiz->mMutex);
27fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten    if (0 != ok) {
284f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten        // pthread_mutex_timedlock_np is not available, but wait up to 100 ms
294f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten        static const useconds_t backoffs[] = {1, 10000, 20000, 30000, 40000};
304f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten        unsigned i = 0;
314f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten        for (;;) {
324f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten            usleep(backoffs[i]);
33bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten            ok = pthread_mutex_trylock(&thiz->mMutex);
344f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten            if (0 == ok)
354f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten                break;
364f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten            if (++i >= (sizeof(backoffs) / sizeof(backoffs[0]))) {
37b52bc98b576a9b56e82eca435849bd55e54b6bc1Glenn Kasten                SL_LOGW("%s:%d: object %p was locked by %p at %s:%d\n",
38bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten                    file, line, thiz, *(void **)&thiz->mOwner, thiz->mFile, thiz->mLine);
394f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten                // attempt one more time; maybe this time we will be successful
40bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten                ok = pthread_mutex_lock(&thiz->mMutex);
414f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten                assert(0 == ok);
424f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten                break;
434f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten            }
444f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten        }
45fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten    }
46fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten    pthread_t zero;
47fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten    memset(&zero, 0, sizeof(pthread_t));
48bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    if (0 != memcmp(&zero, &thiz->mOwner, sizeof(pthread_t))) {
49bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        if (pthread_equal(pthread_self(), thiz->mOwner)) {
504f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten            SL_LOGE("%s:%d: object %p was recursively locked by %p at %s:%d\n",
51bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten                file, line, thiz, *(void **)&thiz->mOwner, thiz->mFile, thiz->mLine);
524f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten        } else {
534f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten            SL_LOGE("%s:%d: object %p was left unlocked in unexpected state by %p at %s:%d\n",
54bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten                file, line, thiz, *(void **)&thiz->mOwner, thiz->mFile, thiz->mLine);
554f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten        }
564f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten        assert(false);
574f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten    }
58bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    thiz->mOwner = pthread_self();
59bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    thiz->mFile = file;
60bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    thiz->mLine = line;
61fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten}
62fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten#else
63bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kastenvoid object_lock_exclusive(IObject *thiz)
64a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten{
65a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    int ok;
66bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    ok = pthread_mutex_lock(&thiz->mMutex);
67a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    assert(0 == ok);
68a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten}
69fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten#endif
70a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten
710b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
72928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten/** \brief Exclusively unlock an object and do not report any updates */
730b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
74fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten#ifdef USE_DEBUG
75bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kastenvoid object_unlock_exclusive_(IObject *thiz, const char *file, int line)
764597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten{
77bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    assert(pthread_equal(pthread_self(), thiz->mOwner));
78bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    assert(NULL != thiz->mFile);
79bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    assert(0 != thiz->mLine);
80bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    memset(&thiz->mOwner, 0, sizeof(pthread_t));
81bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    thiz->mFile = file;
82bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    thiz->mLine = line;
83a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    int ok;
84bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    ok = pthread_mutex_unlock(&thiz->mMutex);
85a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    assert(0 == ok);
86a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten}
874597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten#else
88bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kastenvoid object_unlock_exclusive(IObject *thiz)
894597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten{
904597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten    int ok;
91bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    ok = pthread_mutex_unlock(&thiz->mMutex);
924597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten    assert(0 == ok);
934597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten}
944597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten#endif
95a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten
960b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
97928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten/** \brief Exclusively unlock an object and report updates to the specified bit-mask of
98928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten *  attributes
99928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten */
1000b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
1014597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten#ifdef USE_DEBUG
102bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kastenvoid object_unlock_exclusive_attributes_(IObject *thiz, unsigned attributes,
1034597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten    const char *file, int line)
1044597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten#else
105bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kastenvoid object_unlock_exclusive_attributes(IObject *thiz, unsigned attributes)
1064597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten#endif
107e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten{
108fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten
109fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten#ifdef USE_DEBUG
110bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    assert(pthread_equal(pthread_self(), thiz->mOwner));
111bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    assert(NULL != thiz->mFile);
112bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    assert(0 != thiz->mLine);
113fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten#endif
114fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten
115e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten    int ok;
1163c170255cc71942f310b676d968cf73328aa5d70Jean-Michel Trivi
1177b726bdcd996f1cab3a584c04ce1afc07bc8fbe7Glenn Kasten    // make SL object IDs be contiguous with XA object IDs
1187b726bdcd996f1cab3a584c04ce1afc07bc8fbe7Glenn Kasten    SLuint32 objectID = IObjectToObjectID(thiz);
11947550bf6cf5cf08a402a54b1589f4b64582a5120Glenn Kasten    SLuint32 index = objectID;
12047550bf6cf5cf08a402a54b1589f4b64582a5120Glenn Kasten    if ((XA_OBJECTID_ENGINE <= index) && (index <= XA_OBJECTID_CAMERADEVICE)) {
1217b726bdcd996f1cab3a584c04ce1afc07bc8fbe7Glenn Kasten        ;
12247550bf6cf5cf08a402a54b1589f4b64582a5120Glenn Kasten    } else if ((SL_OBJECTID_ENGINE <= index) && (index <= SL_OBJECTID_METADATAEXTRACTOR)) {
12347550bf6cf5cf08a402a54b1589f4b64582a5120Glenn Kasten        index -= SL_OBJECTID_ENGINE - XA_OBJECTID_CAMERADEVICE - 1;
1247b726bdcd996f1cab3a584c04ce1afc07bc8fbe7Glenn Kasten    } else {
1257b726bdcd996f1cab3a584c04ce1afc07bc8fbe7Glenn Kasten        assert(false);
12647550bf6cf5cf08a402a54b1589f4b64582a5120Glenn Kasten        index = 0;
1273c170255cc71942f310b676d968cf73328aa5d70Jean-Michel Trivi    }
1283c170255cc71942f310b676d968cf73328aa5d70Jean-Michel Trivi
1297b726bdcd996f1cab3a584c04ce1afc07bc8fbe7Glenn Kasten    // first synchronously handle updates to attributes here, while object is still locked.
1307b726bdcd996f1cab3a584c04ce1afc07bc8fbe7Glenn Kasten    // This appears to be a loop, but actually typically runs through the loop only once.
1317b726bdcd996f1cab3a584c04ce1afc07bc8fbe7Glenn Kasten    unsigned asynchronous = attributes;
1327b726bdcd996f1cab3a584c04ce1afc07bc8fbe7Glenn Kasten    while (attributes) {
1337b726bdcd996f1cab3a584c04ce1afc07bc8fbe7Glenn Kasten        // this sequence is carefully crafted to be O(1); tread carefully when making changes
1347b726bdcd996f1cab3a584c04ce1afc07bc8fbe7Glenn Kasten        unsigned bit = ctz(attributes);
1357b726bdcd996f1cab3a584c04ce1afc07bc8fbe7Glenn Kasten        // ATTR_INDEX_MAX == next bit position after the last attribute
1367b726bdcd996f1cab3a584c04ce1afc07bc8fbe7Glenn Kasten        assert(ATTR_INDEX_MAX > bit);
1377b726bdcd996f1cab3a584c04ce1afc07bc8fbe7Glenn Kasten        // compute the entry in the handler table using object ID and bit number
13847550bf6cf5cf08a402a54b1589f4b64582a5120Glenn Kasten        AttributeHandler handler = handlerTable[index][bit];
1397b726bdcd996f1cab3a584c04ce1afc07bc8fbe7Glenn Kasten        if (NULL != handler) {
1407b726bdcd996f1cab3a584c04ce1afc07bc8fbe7Glenn Kasten            asynchronous &= ~(*handler)(thiz);
141e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten        }
1427b726bdcd996f1cab3a584c04ce1afc07bc8fbe7Glenn Kasten        attributes &= ~(1 << bit);
143e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten    }
1444b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten
1457b726bdcd996f1cab3a584c04ce1afc07bc8fbe7Glenn Kasten    // any remaining attributes are handled asynchronously in the sync thread
1467b726bdcd996f1cab3a584c04ce1afc07bc8fbe7Glenn Kasten    if (asynchronous) {
1477b726bdcd996f1cab3a584c04ce1afc07bc8fbe7Glenn Kasten        unsigned oldAttributesMask = thiz->mAttributesMask;
1487b726bdcd996f1cab3a584c04ce1afc07bc8fbe7Glenn Kasten        thiz->mAttributesMask = oldAttributesMask | asynchronous;
1497b726bdcd996f1cab3a584c04ce1afc07bc8fbe7Glenn Kasten        if (oldAttributesMask) {
1507b726bdcd996f1cab3a584c04ce1afc07bc8fbe7Glenn Kasten            asynchronous = ATTR_NONE;
151d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi        }
152d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi    }
1534b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten
15447550bf6cf5cf08a402a54b1589f4b64582a5120Glenn Kasten#ifdef ANDROID
155a60dbf554549d10780f473b6e1373aa07aec3a28Glenn Kasten    // FIXME hack to safely handle a post-unlock PrefetchStatus callback and/or AudioTrack::start()
156a60dbf554549d10780f473b6e1373aa07aec3a28Glenn Kasten    slPrefetchCallback prefetchCallback = NULL;
157a60dbf554549d10780f473b6e1373aa07aec3a28Glenn Kasten    void *prefetchContext = NULL;
158a60dbf554549d10780f473b6e1373aa07aec3a28Glenn Kasten    SLuint32 prefetchEvents = SL_PREFETCHEVENT_NONE;
15947550bf6cf5cf08a402a54b1589f4b64582a5120Glenn Kasten    android::sp<android::AudioTrackProxy> audioTrack;
16047550bf6cf5cf08a402a54b1589f4b64582a5120Glenn Kasten    if (SL_OBJECTID_AUDIOPLAYER == objectID) {
16147550bf6cf5cf08a402a54b1589f4b64582a5120Glenn Kasten        CAudioPlayer *ap = (CAudioPlayer *) thiz;
162a60dbf554549d10780f473b6e1373aa07aec3a28Glenn Kasten        prefetchCallback = ap->mPrefetchStatus.mDeferredPrefetchCallback;
163a60dbf554549d10780f473b6e1373aa07aec3a28Glenn Kasten        prefetchContext  = ap->mPrefetchStatus.mDeferredPrefetchContext;
164a60dbf554549d10780f473b6e1373aa07aec3a28Glenn Kasten        prefetchEvents   = ap->mPrefetchStatus.mDeferredPrefetchEvents;
165a60dbf554549d10780f473b6e1373aa07aec3a28Glenn Kasten        ap->mPrefetchStatus.mDeferredPrefetchCallback = NULL;
166a60dbf554549d10780f473b6e1373aa07aec3a28Glenn Kasten        // clearing these next two fields is not required, but avoids stale data during debugging
167a60dbf554549d10780f473b6e1373aa07aec3a28Glenn Kasten        ap->mPrefetchStatus.mDeferredPrefetchContext  = NULL;
168a60dbf554549d10780f473b6e1373aa07aec3a28Glenn Kasten        ap->mPrefetchStatus.mDeferredPrefetchEvents   = SL_PREFETCHEVENT_NONE;
16947550bf6cf5cf08a402a54b1589f4b64582a5120Glenn Kasten        if (ap->mDeferredStart) {
17047550bf6cf5cf08a402a54b1589f4b64582a5120Glenn Kasten            audioTrack = ap->mAudioTrack;
17147550bf6cf5cf08a402a54b1589f4b64582a5120Glenn Kasten            ap->mDeferredStart = false;
17247550bf6cf5cf08a402a54b1589f4b64582a5120Glenn Kasten        }
17347550bf6cf5cf08a402a54b1589f4b64582a5120Glenn Kasten    }
17447550bf6cf5cf08a402a54b1589f4b64582a5120Glenn Kasten#endif
17547550bf6cf5cf08a402a54b1589f4b64582a5120Glenn Kasten
176fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten#ifdef USE_DEBUG
177bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    memset(&thiz->mOwner, 0, sizeof(pthread_t));
178bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    thiz->mFile = file;
179bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    thiz->mLine = line;
180fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten#endif
181bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    ok = pthread_mutex_unlock(&thiz->mMutex);
182e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten    assert(0 == ok);
1837b726bdcd996f1cab3a584c04ce1afc07bc8fbe7Glenn Kasten
18447550bf6cf5cf08a402a54b1589f4b64582a5120Glenn Kasten#ifdef ANDROID
185a60dbf554549d10780f473b6e1373aa07aec3a28Glenn Kasten    // FIXME call the prefetch status callback while not holding the mutex on AudioPlayer
186a60dbf554549d10780f473b6e1373aa07aec3a28Glenn Kasten    if (NULL != prefetchCallback) {
187a60dbf554549d10780f473b6e1373aa07aec3a28Glenn Kasten        // note these are synchronous by the application's thread as it is about to return from API
188a60dbf554549d10780f473b6e1373aa07aec3a28Glenn Kasten        assert(prefetchEvents != SL_PREFETCHEVENT_NONE);
189a60dbf554549d10780f473b6e1373aa07aec3a28Glenn Kasten        CAudioPlayer *ap = (CAudioPlayer *) thiz;
190a60dbf554549d10780f473b6e1373aa07aec3a28Glenn Kasten        // spec requires separate callbacks for each event
191a60dbf554549d10780f473b6e1373aa07aec3a28Glenn Kasten        if (SL_PREFETCHEVENT_STATUSCHANGE & prefetchEvents) {
192a60dbf554549d10780f473b6e1373aa07aec3a28Glenn Kasten            (*prefetchCallback)(&ap->mPrefetchStatus.mItf, prefetchContext,
193a60dbf554549d10780f473b6e1373aa07aec3a28Glenn Kasten                    SL_PREFETCHEVENT_STATUSCHANGE);
194a60dbf554549d10780f473b6e1373aa07aec3a28Glenn Kasten        }
195a60dbf554549d10780f473b6e1373aa07aec3a28Glenn Kasten        if (SL_PREFETCHEVENT_FILLLEVELCHANGE & prefetchEvents) {
196a60dbf554549d10780f473b6e1373aa07aec3a28Glenn Kasten            (*prefetchCallback)(&ap->mPrefetchStatus.mItf, prefetchContext,
197a60dbf554549d10780f473b6e1373aa07aec3a28Glenn Kasten                    SL_PREFETCHEVENT_FILLLEVELCHANGE);
198a60dbf554549d10780f473b6e1373aa07aec3a28Glenn Kasten        }
199a60dbf554549d10780f473b6e1373aa07aec3a28Glenn Kasten    }
200a60dbf554549d10780f473b6e1373aa07aec3a28Glenn Kasten
20147550bf6cf5cf08a402a54b1589f4b64582a5120Glenn Kasten    // call AudioTrack::start() while not holding the mutex on AudioPlayer
20247550bf6cf5cf08a402a54b1589f4b64582a5120Glenn Kasten    if (audioTrack != 0) {
20347550bf6cf5cf08a402a54b1589f4b64582a5120Glenn Kasten        audioTrack->start();
20447550bf6cf5cf08a402a54b1589f4b64582a5120Glenn Kasten        audioTrack.clear();
20547550bf6cf5cf08a402a54b1589f4b64582a5120Glenn Kasten    }
20647550bf6cf5cf08a402a54b1589f4b64582a5120Glenn Kasten#endif
20747550bf6cf5cf08a402a54b1589f4b64582a5120Glenn Kasten
208f51dba65751107c930759938775b75531ec1f330Glenn Kasten    // first update to this interface since previous sync
2097b726bdcd996f1cab3a584c04ce1afc07bc8fbe7Glenn Kasten    if (ATTR_NONE != asynchronous) {
210bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        unsigned id = thiz->mInstanceID;
211f51dba65751107c930759938775b75531ec1f330Glenn Kasten        if (0 != id) {
212f51dba65751107c930759938775b75531ec1f330Glenn Kasten            --id;
213f51dba65751107c930759938775b75531ec1f330Glenn Kasten            assert(MAX_INSTANCE > id);
214bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten            IEngine *thisEngine = &thiz->mEngine->mEngine;
2157b726bdcd996f1cab3a584c04ce1afc07bc8fbe7Glenn Kasten            // FIXME atomic or here
216f51dba65751107c930759938775b75531ec1f330Glenn Kasten            interface_lock_exclusive(thisEngine);
217f51dba65751107c930759938775b75531ec1f330Glenn Kasten            thisEngine->mChangedMask |= 1 << id;
218f51dba65751107c930759938775b75531ec1f330Glenn Kasten            interface_unlock_exclusive(thisEngine);
219f51dba65751107c930759938775b75531ec1f330Glenn Kasten        }
220e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten    }
2217b726bdcd996f1cab3a584c04ce1afc07bc8fbe7Glenn Kasten
222e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten}
223e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten
2240b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
225928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten/** \brief Wait on the condition variable associated with the object; see pthread_cond_wait */
2260b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
2274f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten#ifdef USE_DEBUG
228bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kastenvoid object_cond_wait_(IObject *thiz, const char *file, int line)
2294f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten{
2304f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten    // note that this will unlock the mutex, so we have to clear the owner
231bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    assert(pthread_equal(pthread_self(), thiz->mOwner));
232bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    assert(NULL != thiz->mFile);
233bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    assert(0 != thiz->mLine);
234bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    memset(&thiz->mOwner, 0, sizeof(pthread_t));
235bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    thiz->mFile = file;
236bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    thiz->mLine = line;
2374f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten    // alas we don't know the new owner's identity
2384f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten    int ok;
239bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    ok = pthread_cond_wait(&thiz->mCond, &thiz->mMutex);
2404f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten    assert(0 == ok);
2414f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten    // restore my ownership
242bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    thiz->mOwner = pthread_self();
243bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    thiz->mFile = file;
244bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    thiz->mLine = line;
2454f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten}
2464f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten#else
247bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kastenvoid object_cond_wait(IObject *thiz)
248a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten{
249a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    int ok;
250bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    ok = pthread_cond_wait(&thiz->mCond, &thiz->mMutex);
251a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    assert(0 == ok);
252a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten}
2534f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten#endif
254a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten
2550b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
256928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten/** \brief Signal the condition variable associated with the object; see pthread_cond_signal */
2570b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
258bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kastenvoid object_cond_signal(IObject *thiz)
259a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten{
260a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    int ok;
261bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    ok = pthread_cond_signal(&thiz->mCond);
262a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    assert(0 == ok);
263a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten}
264a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten
2650b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
266928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten/** \brief Broadcast the condition variable associated with the object;
267928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten *  see pthread_cond_broadcast
268928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten */
2690b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
270bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kastenvoid object_cond_broadcast(IObject *thiz)
271a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten{
272a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten    int ok;
273bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    ok = pthread_cond_broadcast(&thiz->mCond);
274a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten    assert(0 == ok);
275a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten}
276