1/*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "ecmascript/mutator_lock.h"
17#include "ecmascript/js_thread.h"
18
19namespace panda::ecmascript {
20#ifndef NDEBUG
21void MutatorLock::ReadLock()
22{
23    ASSERT(!HasLock());
24    RWLock::ReadLock();
25    SetState(MutatorLockState::RDLOCK);
26}
27
28void MutatorLock::WriteLock()
29{
30    ASSERT(!HasLock());
31    RWLock::WriteLock();
32    SetState(MutatorLockState::WRLOCK);
33}
34
35bool MutatorLock::TryReadLock()
36{
37    ASSERT(!HasLock());
38    bool res = RWLock::TryReadLock();
39    if (res) {
40        SetState(MutatorLockState::RDLOCK);
41    }
42    return res;
43}
44
45bool MutatorLock::TryWriteLock()
46{
47    ASSERT(!HasLock());
48    bool res = RWLock::TryWriteLock();
49    if (res) {
50        SetState(MutatorLockState::WRLOCK);
51    }
52    return res;
53}
54
55void MutatorLock::Unlock()
56{
57    ASSERT(HasLock());
58    RWLock::Unlock();
59    SetState(MutatorLockState::UNLOCKED);
60}
61
62bool MutatorLock::HasLock() const
63{
64    return GetState() != MutatorLockState::UNLOCKED;
65}
66
67MutatorLock::MutatorLockState MutatorLock::GetState() const
68{
69    return JSThread::GetCurrent()->GetMutatorLockState();
70}
71
72void MutatorLock::SetState(MutatorLock::MutatorLockState newState)
73{
74    JSThread::GetCurrent()->SetMutatorLockState(newState);
75}
76#endif
77
78void SuspendBarrier::Wait()
79{
80    while (true) {
81        int32_t curCount = passBarrierCount_.load(std::memory_order_relaxed);
82        if (LIKELY(curCount > 0)) {
83#if defined(PANDA_TARGET_OHOS)
84            sched_yield();
85#endif
86        } else {
87            // Use seq_cst to synchronize memory.
88            curCount = passBarrierCount_.load(std::memory_order_seq_cst);
89            ASSERT(curCount == 0);
90            break;
91        }
92    }
93}
94
95void SuspendBarrier::PassCount(int32_t delta)
96{
97    bool done = false;
98    do {
99        int32_t curCount = passBarrierCount_.load(std::memory_order_relaxed);
100        // Reduce value by 1.
101        done = passBarrierCount_.compare_exchange_strong(curCount, curCount + delta);
102    } while (!done);
103}
104}  // namespace panda::ecmascript