123b3f68cab75e480ac93d656a6e4f60b979de6d2Glenn Kasten/*
223b3f68cab75e480ac93d656a6e4f60b979de6d2Glenn Kasten * Copyright (C) 2010 The Android Open Source Project
323b3f68cab75e480ac93d656a6e4f60b979de6d2Glenn Kasten *
423b3f68cab75e480ac93d656a6e4f60b979de6d2Glenn Kasten * Licensed under the Apache License, Version 2.0 (the "License");
523b3f68cab75e480ac93d656a6e4f60b979de6d2Glenn Kasten * you may not use this file except in compliance with the License.
623b3f68cab75e480ac93d656a6e4f60b979de6d2Glenn Kasten * You may obtain a copy of the License at
723b3f68cab75e480ac93d656a6e4f60b979de6d2Glenn Kasten *
823b3f68cab75e480ac93d656a6e4f60b979de6d2Glenn Kasten *      http://www.apache.org/licenses/LICENSE-2.0
923b3f68cab75e480ac93d656a6e4f60b979de6d2Glenn Kasten *
1023b3f68cab75e480ac93d656a6e4f60b979de6d2Glenn Kasten * Unless required by applicable law or agreed to in writing, software
1123b3f68cab75e480ac93d656a6e4f60b979de6d2Glenn Kasten * distributed under the License is distributed on an "AS IS" BASIS,
1223b3f68cab75e480ac93d656a6e4f60b979de6d2Glenn Kasten * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1323b3f68cab75e480ac93d656a6e4f60b979de6d2Glenn Kasten * See the License for the specific language governing permissions and
1423b3f68cab75e480ac93d656a6e4f60b979de6d2Glenn Kasten * limitations under the License.
1523b3f68cab75e480ac93d656a6e4f60b979de6d2Glenn Kasten */
1623b3f68cab75e480ac93d656a6e4f60b979de6d2Glenn Kasten
1723b3f68cab75e480ac93d656a6e4f60b979de6d2Glenn Kasten/* ThreadSync implementation */
1823b3f68cab75e480ac93d656a6e4f60b979de6d2Glenn Kasten
1923b3f68cab75e480ac93d656a6e4f60b979de6d2Glenn Kasten#include "sles_allinclusive.h"
2023b3f68cab75e480ac93d656a6e4f60b979de6d2Glenn Kasten
21f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten
2223b3f68cab75e480ac93d656a6e4f60b979de6d2Glenn Kastenstatic SLresult IThreadSync_EnterCriticalSection(SLThreadSyncItf self)
2323b3f68cab75e480ac93d656a6e4f60b979de6d2Glenn Kasten{
24f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten    SL_ENTER_INTERFACE
25f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten
2650bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten    IThreadSync *thiz = (IThreadSync *) self;
2750bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten    interface_lock_exclusive(thiz);
2823b3f68cab75e480ac93d656a6e4f60b979de6d2Glenn Kasten    for (;;) {
2950bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten        if (thiz->mInCriticalSection) {
3050bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten            if (!pthread_equal(thiz->mOwner, pthread_self())) {
3150bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten                ++thiz->mWaiting;
3250bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten                interface_cond_wait(thiz);
3323b3f68cab75e480ac93d656a6e4f60b979de6d2Glenn Kasten                continue;
3423b3f68cab75e480ac93d656a6e4f60b979de6d2Glenn Kasten            }
3515f9f5e609265dff9d6036af38bea084c42a702aGlenn Kasten            // nested locks are not allowed
3623b3f68cab75e480ac93d656a6e4f60b979de6d2Glenn Kasten            result = SL_RESULT_PRECONDITIONS_VIOLATED;
3723b3f68cab75e480ac93d656a6e4f60b979de6d2Glenn Kasten            break;
3823b3f68cab75e480ac93d656a6e4f60b979de6d2Glenn Kasten        }
3950bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten        thiz->mInCriticalSection = SL_BOOLEAN_TRUE;
4050bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten        thiz->mOwner = pthread_self();
4123b3f68cab75e480ac93d656a6e4f60b979de6d2Glenn Kasten        result = SL_RESULT_SUCCESS;
4223b3f68cab75e480ac93d656a6e4f60b979de6d2Glenn Kasten        break;
4323b3f68cab75e480ac93d656a6e4f60b979de6d2Glenn Kasten    }
4450bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten    interface_unlock_exclusive(thiz);
45f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten
46f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten    SL_LEAVE_INTERFACE
4723b3f68cab75e480ac93d656a6e4f60b979de6d2Glenn Kasten}
4823b3f68cab75e480ac93d656a6e4f60b979de6d2Glenn Kasten
49f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten
5023b3f68cab75e480ac93d656a6e4f60b979de6d2Glenn Kastenstatic SLresult IThreadSync_ExitCriticalSection(SLThreadSyncItf self)
5123b3f68cab75e480ac93d656a6e4f60b979de6d2Glenn Kasten{
52f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten    SL_ENTER_INTERFACE
53f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten
5450bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten    IThreadSync *thiz = (IThreadSync *) self;
5550bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten    interface_lock_exclusive(thiz);
5650bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten    if (!thiz->mInCriticalSection || !pthread_equal(thiz->mOwner, pthread_self())) {
5723b3f68cab75e480ac93d656a6e4f60b979de6d2Glenn Kasten        result = SL_RESULT_PRECONDITIONS_VIOLATED;
5823b3f68cab75e480ac93d656a6e4f60b979de6d2Glenn Kasten    } else {
5950bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten        thiz->mInCriticalSection = SL_BOOLEAN_FALSE;
6050bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten        memset(&thiz->mOwner, 0, sizeof(pthread_t));
6150bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten        if (thiz->mWaiting) {
6250bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten            --thiz->mWaiting;
6350bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten            interface_cond_signal(thiz);
6423b3f68cab75e480ac93d656a6e4f60b979de6d2Glenn Kasten        }
65f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten        result = SL_RESULT_SUCCESS;
6623b3f68cab75e480ac93d656a6e4f60b979de6d2Glenn Kasten    }
6750bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten    interface_unlock_exclusive(thiz);
68f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten
69f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten    SL_LEAVE_INTERFACE
7023b3f68cab75e480ac93d656a6e4f60b979de6d2Glenn Kasten}
7123b3f68cab75e480ac93d656a6e4f60b979de6d2Glenn Kasten
72f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten
7323b3f68cab75e480ac93d656a6e4f60b979de6d2Glenn Kastenstatic const struct SLThreadSyncItf_ IThreadSync_Itf = {
7423b3f68cab75e480ac93d656a6e4f60b979de6d2Glenn Kasten    IThreadSync_EnterCriticalSection,
7523b3f68cab75e480ac93d656a6e4f60b979de6d2Glenn Kasten    IThreadSync_ExitCriticalSection
7623b3f68cab75e480ac93d656a6e4f60b979de6d2Glenn Kasten};
7723b3f68cab75e480ac93d656a6e4f60b979de6d2Glenn Kasten
7823b3f68cab75e480ac93d656a6e4f60b979de6d2Glenn Kastenvoid IThreadSync_init(void *self)
7923b3f68cab75e480ac93d656a6e4f60b979de6d2Glenn Kasten{
8050bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten    IThreadSync *thiz = (IThreadSync *) self;
8150bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten    thiz->mItf = &IThreadSync_Itf;
8250bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten    thiz->mInCriticalSection = SL_BOOLEAN_FALSE;
8350bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten    thiz->mWaiting = 0;
8450bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten    memset(&thiz->mOwner, 0, sizeof(pthread_t));
8523b3f68cab75e480ac93d656a6e4f60b979de6d2Glenn Kasten}
862a25d97e40dbd5dd9195195a3a269095a4932097Glenn Kasten
872a25d97e40dbd5dd9195195a3a269095a4932097Glenn Kastenvoid IThreadSync_deinit(void *self)
882a25d97e40dbd5dd9195195a3a269095a4932097Glenn Kasten{
8950bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten    IThreadSync *thiz = (IThreadSync *) self;
9050bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten    if (thiz->mInCriticalSection) {
912a25d97e40dbd5dd9195195a3a269095a4932097Glenn Kasten        SL_LOGW("ThreadSync::EnterCriticalSection was active at Engine::Destroy");
922a25d97e40dbd5dd9195195a3a269095a4932097Glenn Kasten    }
932a25d97e40dbd5dd9195195a3a269095a4932097Glenn Kasten}
94