locks.c revision 4597a7427b697df31d0bbf4c2040806d0c27b6e0
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
200b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten/* Exclusively lock an object */
210b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
22fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten#ifdef USE_DEBUG
23fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kastenvoid object_lock_exclusive_(IObject *this, const char *file, int line)
24fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten{
25fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten    int ok;
26fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten    ok = pthread_mutex_trylock(&this->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]);
334f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten            ok = pthread_mutex_trylock(&this->mMutex);
344f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten            if (0 == ok)
354f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten                break;
364f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten            if (++i >= (sizeof(backoffs) / sizeof(backoffs[0]))) {
374f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten                SL_LOGE("%s:%d: object %p was locked by %p at %s:%d\n",
384f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten                    file, line, this, *(void **)&this->mOwner, this->mFile, this->mLine);
394f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten                // attempt one more time; maybe this time we will be successful
404f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten                ok = pthread_mutex_lock(&this->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));
484f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten    if (0 != memcmp(&zero, &this->mOwner, sizeof(pthread_t))) {
494f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten        if (pthread_equal(pthread_self(), this->mOwner)) {
504f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten            SL_LOGE("%s:%d: object %p was recursively locked by %p at %s:%d\n",
514f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten                file, line, this, *(void **)&this->mOwner, this->mFile, this->mLine);
524f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten        } else {
534f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten            SL_LOGE("%s:%d: object %p was left unlocked in unexpected state by %p at %s:%d\n",
544f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten                file, line, this, *(void **)&this->mOwner, this->mFile, this->mLine);
554f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten        }
564f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten        assert(false);
574f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten    }
58fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten    this->mOwner = pthread_self();
59fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten    this->mFile = file;
60fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten    this->mLine = line;
61fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten}
62fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten#else
634f064c143ef2b26347130a49788116b5d2e1252aGlenn Kastenvoid object_lock_exclusive(IObject *this)
64a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten{
65a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    int ok;
66a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    ok = pthread_mutex_lock(&this->mMutex);
67a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    assert(0 == ok);
68a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten}
69fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten#endif
70a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten
710b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
720b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten/* Exclusively unlock an object and do not report any updates */
730b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
74fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten#ifdef USE_DEBUG
754597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kastenvoid object_unlock_exclusive_(IObject *this, const char *file, int line)
764597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten{
77fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten    assert(pthread_equal(pthread_self(), this->mOwner));
78fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten    assert(NULL != this->mFile);
79fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten    assert(0 != this->mLine);
80fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten    memset(&this->mOwner, 0, sizeof(pthread_t));
814597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten    this->mFile = file;
824597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten    this->mLine = line;
83a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    int ok;
84a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    ok = pthread_mutex_unlock(&this->mMutex);
85a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    assert(0 == ok);
86a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten}
874597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten#else
884597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kastenvoid object_unlock_exclusive(IObject *this)
894597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten{
904597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten    int ok;
914597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten    ok = pthread_mutex_unlock(&this->mMutex);
924597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten    assert(0 == ok);
934597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten}
944597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten#endif
95a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten
960b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
970b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten/* Exclusively unlock an object and report updates to the specified bit-mask of attributes */
980b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
994597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten#ifdef USE_DEBUG
1004597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kastenvoid object_unlock_exclusive_attributes_(IObject *this, unsigned attributes,
1014597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten    const char *file, int line)
1024597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten#else
103e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kastenvoid object_unlock_exclusive_attributes(IObject *this, unsigned attributes)
1044597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten#endif
105e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten{
106fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten
107fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten#ifdef USE_DEBUG
108fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten    assert(pthread_equal(pthread_self(), this->mOwner));
109fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten    assert(NULL != this->mFile);
110fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten    assert(0 != this->mLine);
111fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten#endif
112fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten
113e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten    int ok;
114e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten    SLuint32 objectID = IObjectToObjectID(this);
115e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten    CAudioPlayer *ap;
1164b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten
1174b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten    // FIXME The endless if statements are getting ugly, should use bit search
1184b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten
119e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten    // Android likes to see certain updates synchronously
1203c170255cc71942f310b676d968cf73328aa5d70Jean-Michel Trivi
121e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten    if (attributes & ATTR_GAIN) {
122e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten        switch (objectID) {
123e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten        case SL_OBJECTID_AUDIOPLAYER:
124e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten            attributes &= ~ATTR_GAIN;   // no need to process asynchronously also
125e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten            ap = (CAudioPlayer *) this;
126e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten#ifdef ANDROID
127d739e18bea1deaf7c487f99a512c0ae7649615c2Jean-Michel Trivi            android_audioPlayer_volumeUpdate(ap);
128e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten#else
129e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten            audioPlayerGainUpdate(ap);
130e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten#endif
131e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten            break;
132e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten        case SL_OBJECTID_OUTPUTMIX:
133e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten            // FIXME update gains on all players attached to this outputmix
1340b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten            SL_LOGE("[ FIXME: gain update on an SL_OBJECTID_OUTPUTMIX to be implemented ]");
1353c170255cc71942f310b676d968cf73328aa5d70Jean-Michel Trivi            break;
1363c170255cc71942f310b676d968cf73328aa5d70Jean-Michel Trivi        case SL_OBJECTID_MIDIPLAYER:
1377a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten            // MIDI
1380b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten            SL_LOGE("[ FIXME: gain update on an SL_OBJECTID_MIDIPLAYER to be implemented ]");
139e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten            break;
140e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten        default:
141e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten            break;
142e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten        }
143e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten    }
1443c170255cc71942f310b676d968cf73328aa5d70Jean-Michel Trivi
1453c170255cc71942f310b676d968cf73328aa5d70Jean-Michel Trivi    if (attributes & ATTR_POSITION) {
1463c170255cc71942f310b676d968cf73328aa5d70Jean-Michel Trivi        switch (objectID) {
1473c170255cc71942f310b676d968cf73328aa5d70Jean-Michel Trivi        case SL_OBJECTID_AUDIOPLAYER:
1483c170255cc71942f310b676d968cf73328aa5d70Jean-Michel Trivi            ap = (CAudioPlayer *) this;
1493c170255cc71942f310b676d968cf73328aa5d70Jean-Michel Trivi#ifdef ANDROID
1504b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten            attributes &= ~ATTR_POSITION;   // no need to process asynchronously also
151d739e18bea1deaf7c487f99a512c0ae7649615c2Jean-Michel Trivi            android_audioPlayer_seek(ap, ap->mSeek.mPos);
1523c170255cc71942f310b676d968cf73328aa5d70Jean-Michel Trivi#else
1534b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten            //audioPlayerTransportUpdate(ap);
1543c170255cc71942f310b676d968cf73328aa5d70Jean-Michel Trivi#endif
1553c170255cc71942f310b676d968cf73328aa5d70Jean-Michel Trivi            break;
1563c170255cc71942f310b676d968cf73328aa5d70Jean-Michel Trivi        case SL_OBJECTID_MIDIPLAYER:
1577a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten            // MIDI
1580b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten            SL_LOGE("[ FIXME: position update on an SL_OBJECTID_MIDIPLAYER to be implemented ]");
1593c170255cc71942f310b676d968cf73328aa5d70Jean-Michel Trivi            break;
1603c170255cc71942f310b676d968cf73328aa5d70Jean-Michel Trivi        default:
1613c170255cc71942f310b676d968cf73328aa5d70Jean-Michel Trivi            break;
1623c170255cc71942f310b676d968cf73328aa5d70Jean-Michel Trivi        }
1633c170255cc71942f310b676d968cf73328aa5d70Jean-Michel Trivi    }
1643c170255cc71942f310b676d968cf73328aa5d70Jean-Michel Trivi
165e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten    if (attributes & ATTR_TRANSPORT) {
166e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten        if (SL_OBJECTID_AUDIOPLAYER == objectID) {
1674b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten#ifdef ANDROID
168e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten            attributes &= ~ATTR_TRANSPORT;   // no need to process asynchronously also
169e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten            ap = (CAudioPlayer *) this;
170e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten            // FIXME should only call when state changes
171d739e18bea1deaf7c487f99a512c0ae7649615c2Jean-Michel Trivi            android_audioPlayer_setPlayState(ap);
172e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten            // FIXME ditto, but for either eventflags or marker position
173d739e18bea1deaf7c487f99a512c0ae7649615c2Jean-Michel Trivi            android_audioPlayer_useEventMask(ap);
174e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten#else
1754b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten            //audioPlayerTransportUpdate(ap);
176e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten#endif
177e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten        }
178e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten    }
1794b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten
1804b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten    // ( buffer queue count is non-empty and play state == PLAYING ) became true
1814b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten    if (attributes & ATTR_ENQUEUE) {
1824b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten        if (SL_OBJECTID_AUDIOPLAYER == objectID) {
1834b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten            attributes &= ~ATTR_ENQUEUE;
1844b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten            ap = (CAudioPlayer *) this;
1854b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten            if (SL_PLAYSTATE_PLAYING == ap->mPlay.mState) {
186b44084fdb096a2662085af0199b69ccb0dce5c30Jean-Michel Trivi#ifdef ANDROID
187a05622c974763d8ca038f3d39743c926309ab2c2Jean-Michel Trivi                android_audioPlayer_bufferQueueRefilled(ap);
188b44084fdb096a2662085af0199b69ccb0dce5c30Jean-Michel Trivi#endif
1894b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten            }
1904b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten        }
1914b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten    }
1924b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten
193e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten    if (attributes) {
194e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten        unsigned oldAttributesMask = this->mAttributesMask;
195e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten        this->mAttributesMask = oldAttributesMask | attributes;
196e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten        if (oldAttributesMask)
197e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten            attributes = ATTR_NONE;
198e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten    }
199fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten#ifdef USE_DEBUG
200fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten    memset(&this->mOwner, 0, sizeof(pthread_t));
2014597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten    this->mFile = file;
2024597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten    this->mLine = line;
203fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten#endif
204e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten    ok = pthread_mutex_unlock(&this->mMutex);
205e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten    assert(0 == ok);
206e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten    if (attributes) {   // first update to this interface since previous sync
207e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten        IEngine *thisEngine = this->mEngine;
208e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten        interface_lock_exclusive(thisEngine);
209e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten        thisEngine->mChangedMask |= 1 << (this->mInstanceID - 1);
210e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten        interface_unlock_exclusive(thisEngine);
211e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten    }
212e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten}
213e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten
2140b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
2150b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten/* Wait on the condition variable associated with the object; see pthread_cond_wait */
2160b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
2174f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten#ifdef USE_DEBUG
2184f064c143ef2b26347130a49788116b5d2e1252aGlenn Kastenvoid object_cond_wait_(IObject *this, const char *file, int line)
2194f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten{
2204f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten    // note that this will unlock the mutex, so we have to clear the owner
2214f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten    assert(pthread_equal(pthread_self(), this->mOwner));
2224f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten    assert(NULL != this->mFile);
2234f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten    assert(0 != this->mLine);
2244f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten    memset(&this->mOwner, 0, sizeof(pthread_t));
2254597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten    this->mFile = file;
2264597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten    this->mLine = line;
2274f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten    // alas we don't know the new owner's identity
2284f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten    int ok;
2294f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten    ok = pthread_cond_wait(&this->mCond, &this->mMutex);
2304f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten    assert(0 == ok);
2314f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten    // restore my ownership
2324f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten    this->mOwner = pthread_self();
2334f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten    this->mFile = file;
2344f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten    this->mLine = line;
2354f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten}
2364f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten#else
237a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kastenvoid object_cond_wait(IObject *this)
238a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten{
239a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    int ok;
240a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    ok = pthread_cond_wait(&this->mCond, &this->mMutex);
241a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    assert(0 == ok);
242a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten}
2434f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten#endif
244a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten
2450b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
2460b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten/* Signal the condition variable associated with the object; see pthread_cond_signal */
2470b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
248a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kastenvoid object_cond_signal(IObject *this)
249a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten{
250a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    int ok;
251a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    ok = pthread_cond_signal(&this->mCond);
252a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    assert(0 == ok);
253a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten}
254a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten
2550b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
2560b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten/* Broadcast the condition variable associated with the object; see pthread_cond_broadcast */
2570b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
258a438eb1cf1ae602afab00336528dd230bd929206Glenn Kastenvoid object_cond_broadcast(IObject *this)
259a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten{
260a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten    int ok;
261a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten    ok = pthread_cond_broadcast(&this->mCond);
262a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten    assert(0 == ok);
263a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten}
264