1/*
2 * Copyright (c) 2023 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#ifndef UTIL_SYNC_HPP
17#define UTIL_SYNC_HPP
18// Provide synchronization primitives
19
20#include <atomic>
21#include <thread>
22#include <mutex>
23#include <condition_variable>
24#include <unistd.h>
25#include <sys/syscall.h>
26#include <linux/futex.h>
27#include "sched/execute_ctx.h"
28
29namespace ffrt {
30namespace sync_detail {
31const int UNLOCK = 0;
32const int LOCK = 1;
33const int WAIT = 2;
34} // namespace sync_detail
35
36class spin_mutex {
37    std::atomic<int> l;
38    void lock_contended();
39
40public:
41    spin_mutex() : l(sync_detail::UNLOCK)
42    {
43    }
44    spin_mutex(spin_mutex const&) = delete;
45    void operator=(spin_mutex const&) = delete;
46
47    void lock()
48    {
49        if (l.exchange(sync_detail::LOCK, std::memory_order_acquire) == sync_detail::UNLOCK) {
50            return;
51        }
52        lock_contended();
53    }
54
55    void unlock()
56    {
57        l.store(sync_detail::UNLOCK, std::memory_order_release);
58    }
59};
60
61class fast_mutex {
62    int l;
63    void lock_contended();
64
65public:
66    fast_mutex() : l(sync_detail::UNLOCK)
67    {
68    }
69    fast_mutex(fast_mutex const&) = delete;
70    void operator=(fast_mutex const&) = delete;
71
72    void lock()
73    {
74        int v = sync_detail::UNLOCK;
75        if (__atomic_compare_exchange_n(&l, &v, sync_detail::LOCK, 0, __ATOMIC_ACQUIRE, __ATOMIC_RELAXED)) {
76            return;
77        }
78        lock_contended();
79    }
80
81    bool try_lock()
82    {
83        int v = sync_detail::UNLOCK;
84        return __atomic_compare_exchange_n(&l, &v, sync_detail::LOCK, 0, __ATOMIC_ACQUIRE, __ATOMIC_RELAXED);
85    }
86
87    void unlock()
88    {
89        if (__atomic_exchange_n(&l, sync_detail::UNLOCK, __ATOMIC_RELEASE) == sync_detail::WAIT) {
90            syscall(SYS_futex, &l, FUTEX_WAKE_PRIVATE, 1, nullptr, nullptr, 0);
91        }
92    }
93};
94
95bool DelayedWakeup(const TimePoint& to, WaitEntry* we, const std::function<void(WaitEntry*)>& wakeup);
96bool DelayedRemove(const TimePoint& to, WaitEntry* we);
97} // namespace ffrt
98#endif
99