1 /*
2  * Copyright (C) 2010 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 /* ThreadSync implementation */
18 
19 #include "sles_allinclusive.h"
20 
21 
IThreadSync_EnterCriticalSection(SLThreadSyncItf self)22 static SLresult IThreadSync_EnterCriticalSection(SLThreadSyncItf self)
23 {
24     SL_ENTER_INTERFACE
25 
26     IThreadSync *thiz = (IThreadSync *) self;
27     interface_lock_exclusive(thiz);
28     for (;;) {
29         if (thiz->mInCriticalSection) {
30             if (!pthread_equal(thiz->mOwner, pthread_self())) {
31                 ++thiz->mWaiting;
32                 interface_cond_wait(thiz);
33                 continue;
34             }
35             // nested locks are not allowed
36             result = SL_RESULT_PRECONDITIONS_VIOLATED;
37             break;
38         }
39         thiz->mInCriticalSection = SL_BOOLEAN_TRUE;
40         thiz->mOwner = pthread_self();
41         result = SL_RESULT_SUCCESS;
42         break;
43     }
44     interface_unlock_exclusive(thiz);
45 
46     SL_LEAVE_INTERFACE
47 }
48 
49 
IThreadSync_ExitCriticalSection(SLThreadSyncItf self)50 static SLresult IThreadSync_ExitCriticalSection(SLThreadSyncItf self)
51 {
52     SL_ENTER_INTERFACE
53 
54     IThreadSync *thiz = (IThreadSync *) self;
55     interface_lock_exclusive(thiz);
56     if (!thiz->mInCriticalSection || !pthread_equal(thiz->mOwner, pthread_self())) {
57         result = SL_RESULT_PRECONDITIONS_VIOLATED;
58     } else {
59         thiz->mInCriticalSection = SL_BOOLEAN_FALSE;
60         memset(&thiz->mOwner, 0, sizeof(pthread_t));
61         if (thiz->mWaiting) {
62             --thiz->mWaiting;
63             interface_cond_signal(thiz);
64         }
65         result = SL_RESULT_SUCCESS;
66     }
67     interface_unlock_exclusive(thiz);
68 
69     SL_LEAVE_INTERFACE
70 }
71 
72 
73 static const struct SLThreadSyncItf_ IThreadSync_Itf = {
74     IThreadSync_EnterCriticalSection,
75     IThreadSync_ExitCriticalSection
76 };
77 
IThreadSync_init(void * self)78 void IThreadSync_init(void *self)
79 {
80     IThreadSync *thiz = (IThreadSync *) self;
81     thiz->mItf = &IThreadSync_Itf;
82     thiz->mInCriticalSection = SL_BOOLEAN_FALSE;
83     thiz->mWaiting = 0;
84     memset(&thiz->mOwner, 0, sizeof(pthread_t));
85 }
86 
IThreadSync_deinit(void * self)87 void IThreadSync_deinit(void *self)
88 {
89     IThreadSync *thiz = (IThreadSync *) self;
90     if (thiz->mInCriticalSection) {
91         SL_LOGW("ThreadSync::EnterCriticalSection was active at Engine::Destroy");
92     }
93 }
94