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 "libpandabase/os/mutex.h"
17 #include "plugins/ets/runtime/ets_coroutine.h"
18 #include "plugins/ets/runtime/types/ets_primitives.h"
19 #include "runtime/coroutines/coroutine_events.h"
20 #include "runtime/include/runtime.h"
21
22 namespace ark::ets::intrinsics {
23
24 /// @brief Mutex creation in internal space
InitializeMutex()25 extern "C" EtsLong InitializeMutex()
26 {
27 auto allocator = Runtime::GetCurrent()->GetInternalAllocator();
28 auto *mutex = allocator->New<os::memory::Mutex>();
29 return reinterpret_cast<EtsLong>(mutex);
30 }
31
32 /// @brief Event creation in internal space
InitializeEvent()33 extern "C" EtsLong InitializeEvent()
34 {
35 EtsCoroutine *currentCoro = EtsCoroutine::GetCurrent();
36 auto allocator = Runtime::GetCurrent()->GetInternalAllocator();
37 auto *event = allocator->New<GenericEvent>(currentCoro->GetCoroutineManager());
38 return reinterpret_cast<EtsLong>(event);
39 }
40
41 /// @brief Mutex deletion
DeleteMutex(EtsLong mutexPtr)42 extern "C" void DeleteMutex(EtsLong mutexPtr)
43 {
44 auto allocator = Runtime::GetCurrent()->GetInternalAllocator();
45 allocator->Delete(reinterpret_cast<os::memory::Mutex *>(mutexPtr));
46 }
47
48 /// @brief Event deletion
DeleteEvent(EtsLong eventPtr)49 extern "C" void DeleteEvent(EtsLong eventPtr)
50 {
51 auto allocator = Runtime::GetCurrent()->GetInternalAllocator();
52 allocator->Delete(reinterpret_cast<GenericEvent *>(eventPtr));
53 }
54
55 // Disable thread-safety-analysis because it creates warnings
56 // due to mutexes' manipulations at the end of functions
57 #if defined(__clang__)
58 #pragma clang diagnostic push
59 #pragma clang diagnostic ignored "-Wthread-safety-analysis"
60 #endif
61
62 /**
63 * @brief Locking mutex
64 * Mutex may be unlocked with MutexUnlock or UnblockWaiters functions
65 */
MutexLock(EtsLong mutexPtr)66 extern "C" void MutexLock(EtsLong mutexPtr)
67 {
68 auto *mutex = reinterpret_cast<os::memory::Mutex *>(mutexPtr);
69 mutex->Lock();
70 }
71
72 /// @brief Unlocking mutex that was locked with MutexLock function
MutexUnlock(EtsLong mutexPtr)73 extern "C" void MutexUnlock(EtsLong mutexPtr)
74 {
75 auto *mutex = reinterpret_cast<os::memory::Mutex *>(mutexPtr);
76 mutex->Unlock();
77 }
78
79 /**
80 * @brief Setting event to be "not happened", unlocking mutex and
81 * awaiting for the event to happen. After "await" we try to lock
82 * the mutex again to continue working with the BlockingQueue
83 */
Await(EtsLong mutexPtr,EtsLong eventPtr)84 extern "C" void Await(EtsLong mutexPtr, EtsLong eventPtr)
85 {
86 EtsCoroutine *currentCoro = EtsCoroutine::GetCurrent();
87 auto *event = reinterpret_cast<GenericEvent *>(eventPtr);
88 auto *mutex = reinterpret_cast<os::memory::Mutex *>(mutexPtr);
89 event->SetNotHappened();
90 event->Lock();
91 mutex->Unlock();
92 currentCoro->GetCoroutineManager()->Await(event);
93 mutex->Lock();
94 }
95
96 /**
97 * @brief Setting event to be "happened" and unlocking mutex.
98 * This function should be called after successful push() to the BlockingQueue
99 */
UnblockWaiters(EtsLong mutexPtr,EtsLong eventPtr)100 extern "C" void UnblockWaiters(EtsLong mutexPtr, EtsLong eventPtr)
101 {
102 auto *event = reinterpret_cast<GenericEvent *>(eventPtr);
103 auto *mutex = reinterpret_cast<os::memory::Mutex *>(mutexPtr);
104 event->Happen();
105 mutex->Unlock();
106 }
107
108 #if defined(__clang__)
109 #pragma clang diagnostic pop
110 #endif
111
112 } // namespace ark::ets::intrinsics
113