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" 184ce38604afa7e4f629d568f400b0634504e60a2eGlenn Kasten 194ce38604afa7e4f629d568f400b0634504e60a2eGlenn Kasten 20d3adefc646c15be3f6ba73b6afaaa610f4538246Elliott Hughes// Use this macro to validate a pthread_t before passing it into pthread_gettid_np. 214ce38604afa7e4f629d568f400b0634504e60a2eGlenn Kasten// One of the common reasons for deadlock is trying to lock a mutex for an object 224ce38604afa7e4f629d568f400b0634504e60a2eGlenn Kasten// which has been destroyed (which does memset to 0x00 or 0x55 as the final step). 234ce38604afa7e4f629d568f400b0634504e60a2eGlenn Kasten// To avoid crashing with a SIGSEGV right before we're about to log a deadlock warning, 244ce38604afa7e4f629d568f400b0634504e60a2eGlenn Kasten// we check that the pthread_t is probably valid. Note that it is theoretically 254ce38604afa7e4f629d568f400b0634504e60a2eGlenn Kasten// possible for something to look like a valid pthread_t but not actually be valid. 264ce38604afa7e4f629d568f400b0634504e60a2eGlenn Kasten// So we might still crash, but only in the case where a deadlock was imminent anyway. 274ce38604afa7e4f629d568f400b0634504e60a2eGlenn Kasten#define LIKELY_VALID(ptr) (((ptr) != (pthread_t) 0) && ((((size_t) (ptr)) & 3) == 0)) 28a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten 290b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten 30928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten/** \brief Exclusively lock an object */ 310b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten 32fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten#ifdef USE_DEBUG 337e7826821d0e82c13a4f9f34525d0cdaf323f34aNarayan Kamath 347e7826821d0e82c13a4f9f34525d0cdaf323f34aNarayan Kamathvoid init_time_spec(timespec* ts, long delta) { 357e7826821d0e82c13a4f9f34525d0cdaf323f34aNarayan Kamath clock_gettime(CLOCK_REALTIME, ts); 367e7826821d0e82c13a4f9f34525d0cdaf323f34aNarayan Kamath ts->tv_nsec += delta; 377e7826821d0e82c13a4f9f34525d0cdaf323f34aNarayan Kamath 387e7826821d0e82c13a4f9f34525d0cdaf323f34aNarayan Kamath if (ts->tv_nsec >= 1000000000L) { 397e7826821d0e82c13a4f9f34525d0cdaf323f34aNarayan Kamath ts->tv_sec++; 407e7826821d0e82c13a4f9f34525d0cdaf323f34aNarayan Kamath ts->tv_nsec -= 1000000000L; 417e7826821d0e82c13a4f9f34525d0cdaf323f34aNarayan Kamath } 427e7826821d0e82c13a4f9f34525d0cdaf323f34aNarayan Kamath} 437e7826821d0e82c13a4f9f34525d0cdaf323f34aNarayan Kamath 44bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kastenvoid object_lock_exclusive_(IObject *thiz, const char *file, int line) 45fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten{ 46fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten int ok; 47bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten ok = pthread_mutex_trylock(&thiz->mMutex); 48fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten if (0 != ok) { 494ce38604afa7e4f629d568f400b0634504e60a2eGlenn Kasten // not android_atomic_acquire_load because we don't care about relative load/load ordering 504ce38604afa7e4f629d568f400b0634504e60a2eGlenn Kasten int32_t oldGeneration = thiz->mGeneration; 514ce38604afa7e4f629d568f400b0634504e60a2eGlenn Kasten // wait up to a total of 250 ms 527e7826821d0e82c13a4f9f34525d0cdaf323f34aNarayan Kamath static const long nanoBackoffs[] = { 537e7826821d0e82c13a4f9f34525d0cdaf323f34aNarayan Kamath 10 * 1000000, 20 * 1000000, 30 * 1000000, 40 * 1000000, 50 * 1000000, 100 * 1000000}; 544f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten unsigned i = 0; 557e7826821d0e82c13a4f9f34525d0cdaf323f34aNarayan Kamath timespec ts; 567e7826821d0e82c13a4f9f34525d0cdaf323f34aNarayan Kamath memset(&ts, 0, sizeof(timespec)); 574f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten for (;;) { 587e7826821d0e82c13a4f9f34525d0cdaf323f34aNarayan Kamath init_time_spec(&ts, nanoBackoffs[i]); 597e7826821d0e82c13a4f9f34525d0cdaf323f34aNarayan Kamath ok = pthread_mutex_timedlock(&thiz->mMutex, &ts); 604ce38604afa7e4f629d568f400b0634504e60a2eGlenn Kasten if (0 == ok) { 614f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten break; 624ce38604afa7e4f629d568f400b0634504e60a2eGlenn Kasten } 634ce38604afa7e4f629d568f400b0634504e60a2eGlenn Kasten if (EBUSY == ok) { 644ce38604afa7e4f629d568f400b0634504e60a2eGlenn Kasten // this is the expected return value for timeout, and will be handled below 654ce38604afa7e4f629d568f400b0634504e60a2eGlenn Kasten } else if (EDEADLK == ok) { 664ce38604afa7e4f629d568f400b0634504e60a2eGlenn Kasten // we don't use the kind of mutex that can return this error, but just in case 674ce38604afa7e4f629d568f400b0634504e60a2eGlenn Kasten SL_LOGE("%s:%d: recursive lock detected", file, line); 684ce38604afa7e4f629d568f400b0634504e60a2eGlenn Kasten } else { 694ce38604afa7e4f629d568f400b0634504e60a2eGlenn Kasten // some other return value 704ce38604afa7e4f629d568f400b0634504e60a2eGlenn Kasten SL_LOGE("%s:%d: pthread_mutex_lock_timeout_np returned %d", file, line, ok); 714ce38604afa7e4f629d568f400b0634504e60a2eGlenn Kasten } 724ce38604afa7e4f629d568f400b0634504e60a2eGlenn Kasten // is anyone else making forward progress? 734ce38604afa7e4f629d568f400b0634504e60a2eGlenn Kasten int32_t newGeneration = thiz->mGeneration; 744ce38604afa7e4f629d568f400b0634504e60a2eGlenn Kasten if (newGeneration != oldGeneration) { 754ce38604afa7e4f629d568f400b0634504e60a2eGlenn Kasten // if we ever see forward progress then lock without timeout (more efficient) 764ce38604afa7e4f629d568f400b0634504e60a2eGlenn Kasten goto forward_progress; 774ce38604afa7e4f629d568f400b0634504e60a2eGlenn Kasten } 784ce38604afa7e4f629d568f400b0634504e60a2eGlenn Kasten // no, then continue trying to lock but with increasing timeouts 797e7826821d0e82c13a4f9f34525d0cdaf323f34aNarayan Kamath if (++i >= (sizeof(nanoBackoffs) / sizeof(nanoBackoffs[0]))) { 804ce38604afa7e4f629d568f400b0634504e60a2eGlenn Kasten // the extra block avoids a C++ compiler error about goto past initialization 814ce38604afa7e4f629d568f400b0634504e60a2eGlenn Kasten { 824ce38604afa7e4f629d568f400b0634504e60a2eGlenn Kasten pthread_t me = pthread_self(); 834ce38604afa7e4f629d568f400b0634504e60a2eGlenn Kasten pthread_t owner = thiz->mOwner; 844ce38604afa7e4f629d568f400b0634504e60a2eGlenn Kasten // unlikely, but this could result in a memory fault if owner is corrupt 85d3adefc646c15be3f6ba73b6afaaa610f4538246Elliott Hughes pid_t ownerTid = LIKELY_VALID(owner) ? pthread_gettid_np(owner) : -1; 864ce38604afa7e4f629d568f400b0634504e60a2eGlenn Kasten SL_LOGW("%s:%d: pthread %p (tid %d) sees object %p was locked by pthread %p" 874ce38604afa7e4f629d568f400b0634504e60a2eGlenn Kasten " (tid %d) at %s:%d\n", file, line, *(void **)&me, gettid(), thiz, 884ce38604afa7e4f629d568f400b0634504e60a2eGlenn Kasten *(void **)&owner, ownerTid, thiz->mFile, thiz->mLine); 894ce38604afa7e4f629d568f400b0634504e60a2eGlenn Kasten } 904ce38604afa7e4f629d568f400b0634504e60a2eGlenn Kastenforward_progress: 914ce38604afa7e4f629d568f400b0634504e60a2eGlenn Kasten // attempt one more time without timeout; maybe this time we will be successful 92bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten ok = pthread_mutex_lock(&thiz->mMutex); 934f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten assert(0 == ok); 944f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten break; 954f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten } 964f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten } 97fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten } 984ce38604afa7e4f629d568f400b0634504e60a2eGlenn Kasten // here if mutex was successfully locked 99fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten pthread_t zero; 100fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten memset(&zero, 0, sizeof(pthread_t)); 101bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten if (0 != memcmp(&zero, &thiz->mOwner, sizeof(pthread_t))) { 1024ce38604afa7e4f629d568f400b0634504e60a2eGlenn Kasten pthread_t me = pthread_self(); 1034ce38604afa7e4f629d568f400b0634504e60a2eGlenn Kasten pthread_t owner = thiz->mOwner; 104d3adefc646c15be3f6ba73b6afaaa610f4538246Elliott Hughes pid_t ownerTid = LIKELY_VALID(owner) ? pthread_gettid_np(owner) : -1; 1054ce38604afa7e4f629d568f400b0634504e60a2eGlenn Kasten if (pthread_equal(pthread_self(), owner)) { 1064ce38604afa7e4f629d568f400b0634504e60a2eGlenn Kasten SL_LOGE("%s:%d: pthread %p (tid %d) sees object %p was recursively locked by pthread" 1074ce38604afa7e4f629d568f400b0634504e60a2eGlenn Kasten " %p (tid %d) at %s:%d\n", file, line, *(void **)&me, gettid(), thiz, 1084ce38604afa7e4f629d568f400b0634504e60a2eGlenn Kasten *(void **)&owner, ownerTid, thiz->mFile, thiz->mLine); 1094f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten } else { 1104ce38604afa7e4f629d568f400b0634504e60a2eGlenn Kasten SL_LOGE("%s:%d: pthread %p (tid %d) sees object %p was left unlocked in unexpected" 1114ce38604afa7e4f629d568f400b0634504e60a2eGlenn Kasten " state by pthread %p (tid %d) at %s:%d\n", file, line, *(void **)&me, gettid(), 1124ce38604afa7e4f629d568f400b0634504e60a2eGlenn Kasten thiz, *(void **)&owner, ownerTid, thiz->mFile, thiz->mLine); 1134f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten } 1144f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten assert(false); 1154f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten } 116bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten thiz->mOwner = pthread_self(); 117bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten thiz->mFile = file; 118bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten thiz->mLine = line; 1194ce38604afa7e4f629d568f400b0634504e60a2eGlenn Kasten // not android_atomic_inc because we are already holding a mutex 1204ce38604afa7e4f629d568f400b0634504e60a2eGlenn Kasten ++thiz->mGeneration; 121fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten} 122fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten#else 123bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kastenvoid object_lock_exclusive(IObject *thiz) 124a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten{ 125a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten int ok; 126bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten ok = pthread_mutex_lock(&thiz->mMutex); 127a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten assert(0 == ok); 128a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten} 129fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten#endif 130a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten 1310b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten 132928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten/** \brief Exclusively unlock an object and do not report any updates */ 1330b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten 134fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten#ifdef USE_DEBUG 135bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kastenvoid object_unlock_exclusive_(IObject *thiz, const char *file, int line) 1364597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten{ 137bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten assert(pthread_equal(pthread_self(), thiz->mOwner)); 138bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten assert(NULL != thiz->mFile); 139bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten assert(0 != thiz->mLine); 140bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten memset(&thiz->mOwner, 0, sizeof(pthread_t)); 141bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten thiz->mFile = file; 142bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten thiz->mLine = line; 143a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten int ok; 144bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten ok = pthread_mutex_unlock(&thiz->mMutex); 145a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten assert(0 == ok); 146a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten} 1474597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten#else 148bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kastenvoid object_unlock_exclusive(IObject *thiz) 1494597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten{ 1504597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten int ok; 151bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten ok = pthread_mutex_unlock(&thiz->mMutex); 1524597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten assert(0 == ok); 1534597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten} 1544597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten#endif 155a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten 1560b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten 157928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten/** \brief Exclusively unlock an object and report updates to the specified bit-mask of 158928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten * attributes 159928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten */ 1600b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten 1614597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten#ifdef USE_DEBUG 162bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kastenvoid object_unlock_exclusive_attributes_(IObject *thiz, unsigned attributes, 1634597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten const char *file, int line) 1644597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten#else 165bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kastenvoid object_unlock_exclusive_attributes(IObject *thiz, unsigned attributes) 1664597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten#endif 167e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten{ 168fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten 169fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten#ifdef USE_DEBUG 170bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten assert(pthread_equal(pthread_self(), thiz->mOwner)); 171bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten assert(NULL != thiz->mFile); 172bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten assert(0 != thiz->mLine); 173fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten#endif 174fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten 175e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten int ok; 1763c170255cc71942f310b676d968cf73328aa5d70Jean-Michel Trivi 1777b726bdcd996f1cab3a584c04ce1afc07bc8fbe7Glenn Kasten // make SL object IDs be contiguous with XA object IDs 1787b726bdcd996f1cab3a584c04ce1afc07bc8fbe7Glenn Kasten SLuint32 objectID = IObjectToObjectID(thiz); 17947550bf6cf5cf08a402a54b1589f4b64582a5120Glenn Kasten SLuint32 index = objectID; 18047550bf6cf5cf08a402a54b1589f4b64582a5120Glenn Kasten if ((XA_OBJECTID_ENGINE <= index) && (index <= XA_OBJECTID_CAMERADEVICE)) { 1817b726bdcd996f1cab3a584c04ce1afc07bc8fbe7Glenn Kasten ; 18247550bf6cf5cf08a402a54b1589f4b64582a5120Glenn Kasten } else if ((SL_OBJECTID_ENGINE <= index) && (index <= SL_OBJECTID_METADATAEXTRACTOR)) { 18347550bf6cf5cf08a402a54b1589f4b64582a5120Glenn Kasten index -= SL_OBJECTID_ENGINE - XA_OBJECTID_CAMERADEVICE - 1; 1847b726bdcd996f1cab3a584c04ce1afc07bc8fbe7Glenn Kasten } else { 1857b726bdcd996f1cab3a584c04ce1afc07bc8fbe7Glenn Kasten assert(false); 18647550bf6cf5cf08a402a54b1589f4b64582a5120Glenn Kasten index = 0; 1873c170255cc71942f310b676d968cf73328aa5d70Jean-Michel Trivi } 1883c170255cc71942f310b676d968cf73328aa5d70Jean-Michel Trivi 1897b726bdcd996f1cab3a584c04ce1afc07bc8fbe7Glenn Kasten // first synchronously handle updates to attributes here, while object is still locked. 1907b726bdcd996f1cab3a584c04ce1afc07bc8fbe7Glenn Kasten // This appears to be a loop, but actually typically runs through the loop only once. 1917b726bdcd996f1cab3a584c04ce1afc07bc8fbe7Glenn Kasten unsigned asynchronous = attributes; 1927b726bdcd996f1cab3a584c04ce1afc07bc8fbe7Glenn Kasten while (attributes) { 1937b726bdcd996f1cab3a584c04ce1afc07bc8fbe7Glenn Kasten // this sequence is carefully crafted to be O(1); tread carefully when making changes 1947b726bdcd996f1cab3a584c04ce1afc07bc8fbe7Glenn Kasten unsigned bit = ctz(attributes); 1957b726bdcd996f1cab3a584c04ce1afc07bc8fbe7Glenn Kasten // ATTR_INDEX_MAX == next bit position after the last attribute 1967b726bdcd996f1cab3a584c04ce1afc07bc8fbe7Glenn Kasten assert(ATTR_INDEX_MAX > bit); 1977b726bdcd996f1cab3a584c04ce1afc07bc8fbe7Glenn Kasten // compute the entry in the handler table using object ID and bit number 19847550bf6cf5cf08a402a54b1589f4b64582a5120Glenn Kasten AttributeHandler handler = handlerTable[index][bit]; 1997b726bdcd996f1cab3a584c04ce1afc07bc8fbe7Glenn Kasten if (NULL != handler) { 2007b726bdcd996f1cab3a584c04ce1afc07bc8fbe7Glenn Kasten asynchronous &= ~(*handler)(thiz); 201e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten } 2027b726bdcd996f1cab3a584c04ce1afc07bc8fbe7Glenn Kasten attributes &= ~(1 << bit); 203e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten } 2044b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten 2057b726bdcd996f1cab3a584c04ce1afc07bc8fbe7Glenn Kasten // any remaining attributes are handled asynchronously in the sync thread 2067b726bdcd996f1cab3a584c04ce1afc07bc8fbe7Glenn Kasten if (asynchronous) { 2077b726bdcd996f1cab3a584c04ce1afc07bc8fbe7Glenn Kasten unsigned oldAttributesMask = thiz->mAttributesMask; 2087b726bdcd996f1cab3a584c04ce1afc07bc8fbe7Glenn Kasten thiz->mAttributesMask = oldAttributesMask | asynchronous; 2097b726bdcd996f1cab3a584c04ce1afc07bc8fbe7Glenn Kasten if (oldAttributesMask) { 2107b726bdcd996f1cab3a584c04ce1afc07bc8fbe7Glenn Kasten asynchronous = ATTR_NONE; 211d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi } 212d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi } 2134b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten 21447550bf6cf5cf08a402a54b1589f4b64582a5120Glenn Kasten#ifdef ANDROID 215a60dbf554549d10780f473b6e1373aa07aec3a28Glenn Kasten // FIXME hack to safely handle a post-unlock PrefetchStatus callback and/or AudioTrack::start() 216a60dbf554549d10780f473b6e1373aa07aec3a28Glenn Kasten slPrefetchCallback prefetchCallback = NULL; 217a60dbf554549d10780f473b6e1373aa07aec3a28Glenn Kasten void *prefetchContext = NULL; 218a60dbf554549d10780f473b6e1373aa07aec3a28Glenn Kasten SLuint32 prefetchEvents = SL_PREFETCHEVENT_NONE; 219ae1a5c8dc1fccf7c121eda830f8d23bd094c0f16Glenn Kasten android::sp<android::AudioTrack> audioTrack; 22047550bf6cf5cf08a402a54b1589f4b64582a5120Glenn Kasten if (SL_OBJECTID_AUDIOPLAYER == objectID) { 22147550bf6cf5cf08a402a54b1589f4b64582a5120Glenn Kasten CAudioPlayer *ap = (CAudioPlayer *) thiz; 222a60dbf554549d10780f473b6e1373aa07aec3a28Glenn Kasten prefetchCallback = ap->mPrefetchStatus.mDeferredPrefetchCallback; 223a60dbf554549d10780f473b6e1373aa07aec3a28Glenn Kasten prefetchContext = ap->mPrefetchStatus.mDeferredPrefetchContext; 224a60dbf554549d10780f473b6e1373aa07aec3a28Glenn Kasten prefetchEvents = ap->mPrefetchStatus.mDeferredPrefetchEvents; 225a60dbf554549d10780f473b6e1373aa07aec3a28Glenn Kasten ap->mPrefetchStatus.mDeferredPrefetchCallback = NULL; 226a60dbf554549d10780f473b6e1373aa07aec3a28Glenn Kasten // clearing these next two fields is not required, but avoids stale data during debugging 227a60dbf554549d10780f473b6e1373aa07aec3a28Glenn Kasten ap->mPrefetchStatus.mDeferredPrefetchContext = NULL; 228a60dbf554549d10780f473b6e1373aa07aec3a28Glenn Kasten ap->mPrefetchStatus.mDeferredPrefetchEvents = SL_PREFETCHEVENT_NONE; 22947550bf6cf5cf08a402a54b1589f4b64582a5120Glenn Kasten if (ap->mDeferredStart) { 23047550bf6cf5cf08a402a54b1589f4b64582a5120Glenn Kasten audioTrack = ap->mAudioTrack; 23147550bf6cf5cf08a402a54b1589f4b64582a5120Glenn Kasten ap->mDeferredStart = false; 23247550bf6cf5cf08a402a54b1589f4b64582a5120Glenn Kasten } 23347550bf6cf5cf08a402a54b1589f4b64582a5120Glenn Kasten } 23447550bf6cf5cf08a402a54b1589f4b64582a5120Glenn Kasten#endif 23547550bf6cf5cf08a402a54b1589f4b64582a5120Glenn Kasten 236fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten#ifdef USE_DEBUG 237bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten memset(&thiz->mOwner, 0, sizeof(pthread_t)); 238bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten thiz->mFile = file; 239bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten thiz->mLine = line; 240fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten#endif 241bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten ok = pthread_mutex_unlock(&thiz->mMutex); 242e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten assert(0 == ok); 2437b726bdcd996f1cab3a584c04ce1afc07bc8fbe7Glenn Kasten 24447550bf6cf5cf08a402a54b1589f4b64582a5120Glenn Kasten#ifdef ANDROID 245a60dbf554549d10780f473b6e1373aa07aec3a28Glenn Kasten // FIXME call the prefetch status callback while not holding the mutex on AudioPlayer 246a60dbf554549d10780f473b6e1373aa07aec3a28Glenn Kasten if (NULL != prefetchCallback) { 247a60dbf554549d10780f473b6e1373aa07aec3a28Glenn Kasten // note these are synchronous by the application's thread as it is about to return from API 248a60dbf554549d10780f473b6e1373aa07aec3a28Glenn Kasten assert(prefetchEvents != SL_PREFETCHEVENT_NONE); 249a60dbf554549d10780f473b6e1373aa07aec3a28Glenn Kasten CAudioPlayer *ap = (CAudioPlayer *) thiz; 250a60dbf554549d10780f473b6e1373aa07aec3a28Glenn Kasten // spec requires separate callbacks for each event 251a60dbf554549d10780f473b6e1373aa07aec3a28Glenn Kasten if (SL_PREFETCHEVENT_STATUSCHANGE & prefetchEvents) { 252a60dbf554549d10780f473b6e1373aa07aec3a28Glenn Kasten (*prefetchCallback)(&ap->mPrefetchStatus.mItf, prefetchContext, 253a60dbf554549d10780f473b6e1373aa07aec3a28Glenn Kasten SL_PREFETCHEVENT_STATUSCHANGE); 254a60dbf554549d10780f473b6e1373aa07aec3a28Glenn Kasten } 255a60dbf554549d10780f473b6e1373aa07aec3a28Glenn Kasten if (SL_PREFETCHEVENT_FILLLEVELCHANGE & prefetchEvents) { 256a60dbf554549d10780f473b6e1373aa07aec3a28Glenn Kasten (*prefetchCallback)(&ap->mPrefetchStatus.mItf, prefetchContext, 257a60dbf554549d10780f473b6e1373aa07aec3a28Glenn Kasten SL_PREFETCHEVENT_FILLLEVELCHANGE); 258a60dbf554549d10780f473b6e1373aa07aec3a28Glenn Kasten } 259a60dbf554549d10780f473b6e1373aa07aec3a28Glenn Kasten } 260a60dbf554549d10780f473b6e1373aa07aec3a28Glenn Kasten 26147550bf6cf5cf08a402a54b1589f4b64582a5120Glenn Kasten // call AudioTrack::start() while not holding the mutex on AudioPlayer 26247550bf6cf5cf08a402a54b1589f4b64582a5120Glenn Kasten if (audioTrack != 0) { 26347550bf6cf5cf08a402a54b1589f4b64582a5120Glenn Kasten audioTrack->start(); 26447550bf6cf5cf08a402a54b1589f4b64582a5120Glenn Kasten audioTrack.clear(); 26547550bf6cf5cf08a402a54b1589f4b64582a5120Glenn Kasten } 26647550bf6cf5cf08a402a54b1589f4b64582a5120Glenn Kasten#endif 26747550bf6cf5cf08a402a54b1589f4b64582a5120Glenn Kasten 268f51dba65751107c930759938775b75531ec1f330Glenn Kasten // first update to this interface since previous sync 2697b726bdcd996f1cab3a584c04ce1afc07bc8fbe7Glenn Kasten if (ATTR_NONE != asynchronous) { 270bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten unsigned id = thiz->mInstanceID; 271f51dba65751107c930759938775b75531ec1f330Glenn Kasten if (0 != id) { 272f51dba65751107c930759938775b75531ec1f330Glenn Kasten --id; 273f51dba65751107c930759938775b75531ec1f330Glenn Kasten assert(MAX_INSTANCE > id); 274bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten IEngine *thisEngine = &thiz->mEngine->mEngine; 2757b726bdcd996f1cab3a584c04ce1afc07bc8fbe7Glenn Kasten // FIXME atomic or here 276f51dba65751107c930759938775b75531ec1f330Glenn Kasten interface_lock_exclusive(thisEngine); 277f51dba65751107c930759938775b75531ec1f330Glenn Kasten thisEngine->mChangedMask |= 1 << id; 278f51dba65751107c930759938775b75531ec1f330Glenn Kasten interface_unlock_exclusive(thisEngine); 279f51dba65751107c930759938775b75531ec1f330Glenn Kasten } 280e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten } 2817b726bdcd996f1cab3a584c04ce1afc07bc8fbe7Glenn Kasten 282e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten} 283e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten 2840b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten 285928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten/** \brief Wait on the condition variable associated with the object; see pthread_cond_wait */ 2860b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten 2874f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten#ifdef USE_DEBUG 288bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kastenvoid object_cond_wait_(IObject *thiz, const char *file, int line) 2894f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten{ 2904f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten // note that this will unlock the mutex, so we have to clear the owner 291bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten assert(pthread_equal(pthread_self(), thiz->mOwner)); 292bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten assert(NULL != thiz->mFile); 293bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten assert(0 != thiz->mLine); 294bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten memset(&thiz->mOwner, 0, sizeof(pthread_t)); 295bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten thiz->mFile = file; 296bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten thiz->mLine = line; 2974f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten // alas we don't know the new owner's identity 2984f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten int ok; 299bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten ok = pthread_cond_wait(&thiz->mCond, &thiz->mMutex); 3004f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten assert(0 == ok); 3014f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten // restore my ownership 302bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten thiz->mOwner = pthread_self(); 303bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten thiz->mFile = file; 304bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten thiz->mLine = line; 3054f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten} 3064f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten#else 307bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kastenvoid object_cond_wait(IObject *thiz) 308a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten{ 309a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten int ok; 310bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten ok = pthread_cond_wait(&thiz->mCond, &thiz->mMutex); 311a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten assert(0 == ok); 312a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten} 3134f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten#endif 314a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten 3150b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten 316928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten/** \brief Signal the condition variable associated with the object; see pthread_cond_signal */ 3170b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten 318bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kastenvoid object_cond_signal(IObject *thiz) 319a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten{ 320a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten int ok; 321bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten ok = pthread_cond_signal(&thiz->mCond); 322a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten assert(0 == ok); 323a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten} 324a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten 3250b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten 326928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten/** \brief Broadcast the condition variable associated with the object; 327928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten * see pthread_cond_broadcast 328928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten */ 3290b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten 330bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kastenvoid object_cond_broadcast(IObject *thiz) 331a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten{ 332a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten int ok; 333bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten ok = pthread_cond_broadcast(&thiz->mCond); 334a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten assert(0 == ok); 335a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten} 336