161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten/*
261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten * Copyright (C) 2010 The Android Open Source Project
361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten *
461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten * Licensed under the Apache License, Version 2.0 (the "License");
561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten * you may not use this file except in compliance with the License.
661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten * You may obtain a copy of the License at
761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten *
861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten *      http://www.apache.org/licenses/LICENSE-2.0
961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten *
1061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten * Unless required by applicable law or agreed to in writing, software
1161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten * distributed under the License is distributed on an "AS IS" BASIS,
1261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten * See the License for the specific language governing permissions and
1461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten * limitations under the License.
1561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten */
1661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
1761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten/* ThreadSync implementation */
1861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
1961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten#include "sles_allinclusive.h"
2061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
21ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
2261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic SLresult IThreadSync_EnterCriticalSection(SLThreadSyncItf self)
2361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
24ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_ENTER_INTERFACE
25ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
26bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    IThreadSync *thiz = (IThreadSync *) self;
27bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    interface_lock_exclusive(thiz);
2861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    for (;;) {
29bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        if (thiz->mInCriticalSection) {
30bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten            if (!pthread_equal(thiz->mOwner, pthread_self())) {
31bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten                ++thiz->mWaiting;
32bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten                interface_cond_wait(thiz);
3361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten                continue;
3461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten            }
35e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten            // nested locks are not allowed
3661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten            result = SL_RESULT_PRECONDITIONS_VIOLATED;
3761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten            break;
3861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        }
39bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        thiz->mInCriticalSection = SL_BOOLEAN_TRUE;
40bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        thiz->mOwner = pthread_self();
4161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        result = SL_RESULT_SUCCESS;
4261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        break;
4361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    }
44bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    interface_unlock_exclusive(thiz);
45ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
46ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_LEAVE_INTERFACE
4761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
4861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
49ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
5061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic SLresult IThreadSync_ExitCriticalSection(SLThreadSyncItf self)
5161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
52ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_ENTER_INTERFACE
53ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
54bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    IThreadSync *thiz = (IThreadSync *) self;
55bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    interface_lock_exclusive(thiz);
56bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    if (!thiz->mInCriticalSection || !pthread_equal(thiz->mOwner, pthread_self())) {
5761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        result = SL_RESULT_PRECONDITIONS_VIOLATED;
5861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    } else {
59bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        thiz->mInCriticalSection = SL_BOOLEAN_FALSE;
60bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        memset(&thiz->mOwner, 0, sizeof(pthread_t));
61bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        if (thiz->mWaiting) {
62bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten            --thiz->mWaiting;
63bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten            interface_cond_signal(thiz);
6461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        }
65ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        result = SL_RESULT_SUCCESS;
6661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    }
67bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    interface_unlock_exclusive(thiz);
68ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
69ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_LEAVE_INTERFACE
7061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
7161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
72ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
7361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic const struct SLThreadSyncItf_ IThreadSync_Itf = {
7461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IThreadSync_EnterCriticalSection,
7561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IThreadSync_ExitCriticalSection
7661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten};
7761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
7861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenvoid IThreadSync_init(void *self)
7961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
80bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    IThreadSync *thiz = (IThreadSync *) self;
81bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    thiz->mItf = &IThreadSync_Itf;
82bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    thiz->mInCriticalSection = SL_BOOLEAN_FALSE;
83bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    thiz->mWaiting = 0;
84bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    memset(&thiz->mOwner, 0, sizeof(pthread_t));
8561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
86a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten
87a9a70a4451545034c9263dd55b181f2912534c37Glenn Kastenvoid IThreadSync_deinit(void *self)
88a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten{
89bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    IThreadSync *thiz = (IThreadSync *) self;
90bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    if (thiz->mInCriticalSection) {
91a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten        SL_LOGW("ThreadSync::EnterCriticalSection was active at Engine::Destroy");
92a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    }
93a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten}
94