• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "ecmascript/platform/mutex.h"
17 
18 #include <cstring>
19 #include <ctime>
20 
21 namespace panda::ecmascript {
22 
Mutex(bool is_init)23 Mutex::Mutex(bool is_init) : mutex_()
24 {
25     if (is_init) {
26         Init(nullptr);
27     }
28 }
29 
~Mutex()30 Mutex::~Mutex()
31 {
32     [[maybe_unused]]int rc  = pthread_mutex_destroy(&mutex_);
33     FATAL_IF_ERROR("pthread_mutex_destroy", rc);
34 }
35 
Init(pthread_mutexattr_t * attrs)36 void Mutex::Init(pthread_mutexattr_t *attrs)
37 {
38     [[maybe_unused]]int rc = pthread_mutex_init(&mutex_, attrs);
39     FATAL_IF_ERROR("pthread_mutex_init", rc);
40 }
41 
Lock()42 void Mutex::Lock()
43 {
44     [[maybe_unused]]int rc = pthread_mutex_lock(&mutex_);
45     FATAL_IF_ERROR("pthread_mutex_lock", rc);
46 }
47 
TryLock()48 bool Mutex::TryLock()
49 {
50     int rc = pthread_mutex_trylock(&mutex_);
51     if (rc == EBUSY) {
52         return false;
53     }
54 
55     FATAL_IF_ERROR("pthread_mutex_trylock", rc);
56 
57     return true;
58 }
59 
Unlock()60 void Mutex::Unlock()
61 {
62     [[maybe_unused]]int rc = pthread_mutex_unlock(&mutex_);
63     FATAL_IF_ERROR("pthread_mutex_unlock", rc);
64 }
65 
RecursiveMutex()66 RecursiveMutex::RecursiveMutex() : Mutex(false)
67 {
68     pthread_mutexattr_t attrs;
69     pthread_mutexattr_init(&attrs);
70     pthread_mutexattr_settype(&attrs, PTHREAD_MUTEX_RECURSIVE);
71     Init(&attrs);
72 }
73 
RWLock()74 RWLock::RWLock() : rwlock_()
75 {
76     [[maybe_unused]]int rc = pthread_rwlock_init(&rwlock_, nullptr);
77     FATAL_IF_ERROR("pthread_rwlock_init", rc);
78 }
79 
~RWLock()80 RWLock::~RWLock()
81 {
82     [[maybe_unused]]int rc = pthread_rwlock_destroy(&rwlock_);
83     FATAL_IF_ERROR("pthread_rwlock_destroy", rc);
84 }
85 
ReadLock()86 void RWLock::ReadLock()
87 {
88     [[maybe_unused]]int rc = pthread_rwlock_rdlock(&rwlock_);
89     FATAL_IF_ERROR("pthread_rwlock_rdlock", rc);
90 }
91 
WriteLock()92 void RWLock::WriteLock()
93 {
94     [[maybe_unused]]int rc = pthread_rwlock_wrlock(&rwlock_);
95     FATAL_IF_ERROR("pthread_rwlock_wrlock", rc);
96 }
97 
TryReadLock()98 bool RWLock::TryReadLock()
99 {
100     int rc = pthread_rwlock_tryrdlock(&rwlock_);
101     if (rc == EBUSY) {
102         return false;
103     }
104 
105     FATAL_IF_ERROR("pthread_rwlock_tryrdlock", rc);
106 
107     return true;
108 }
109 
TryWriteLock()110 bool RWLock::TryWriteLock()
111 {
112     int rc = pthread_rwlock_trywrlock(&rwlock_);
113     if (rc == EBUSY) {
114         return false;
115     }
116 
117     FATAL_IF_ERROR("pthread_rwlock_trywrlock", rc);
118 
119     return true;
120 }
121 
Unlock()122 void RWLock::Unlock()
123 {
124     [[maybe_unused]]int rc = pthread_rwlock_unlock(&rwlock_);
125     FATAL_IF_ERROR("pthread_rwlock_unlock", rc);
126 }
127 
ConditionVariable()128 ConditionVariable::ConditionVariable() : cond_()
129 {
130     [[maybe_unused]]int rc = pthread_cond_init(&cond_, nullptr);
131     FATAL_IF_ERROR("pthread_cond_init", rc);
132 }
133 
~ConditionVariable()134 ConditionVariable::~ConditionVariable()
135 {
136     [[maybe_unused]]int rc = pthread_cond_destroy(&cond_);
137     FATAL_IF_ERROR("pthread_cond_destroy", rc);
138 }
139 
Signal()140 void ConditionVariable::Signal()
141 {
142     [[maybe_unused]]int rc = pthread_cond_signal(&cond_);
143     FATAL_IF_ERROR("pthread_cond_signal", rc);
144 }
145 
SignalAll()146 void ConditionVariable::SignalAll()
147 {
148     [[maybe_unused]]int rc = pthread_cond_broadcast(&cond_);
149     FATAL_IF_ERROR("pthread_cond_broadcast", rc);
150 }
151 
Wait(Mutex * mutex)152 void ConditionVariable::Wait(Mutex *mutex)
153 {
154     [[maybe_unused]]int rc = pthread_cond_wait(&cond_, &mutex->mutex_);
155     FATAL_IF_ERROR("pthread_cond_wait", rc);
156 }
157 
ConvertTime(uint64_t ms,uint64_t ns,bool is_absolute)158 struct timespec ConvertTime(uint64_t ms, uint64_t ns, bool is_absolute)
159 {
160     struct timespec abs_time = {0, 0};
161     if (!is_absolute) {
162         clock_gettime(CLOCK_REALTIME, &abs_time);
163     }
164     const int64_t MILLISECONDS_PER_SEC = 1000;
165     const int64_t NANOSECONDS_PER_MILLISEC = 1000000;
166     const int64_t NANOSECONDS_PER_SEC = 1000000000;
167     time_t seconds = ms / MILLISECONDS_PER_SEC;
168     time_t nanoseconds = (ms % MILLISECONDS_PER_SEC) * NANOSECONDS_PER_MILLISEC + ns;
169     abs_time.tv_sec += seconds;
170     abs_time.tv_nsec += nanoseconds;
171     if (abs_time.tv_nsec >= NANOSECONDS_PER_SEC) {
172         abs_time.tv_nsec -= NANOSECONDS_PER_SEC;
173         abs_time.tv_sec++;
174     }
175     return abs_time;
176 }
177 
TimedWait(Mutex * mutex,uint64_t ms,uint64_t ns,bool is_absolute)178 bool ConditionVariable::TimedWait(Mutex *mutex, uint64_t ms, uint64_t ns, bool is_absolute)
179 {
180     struct timespec abs_time = ConvertTime(ms, ns, is_absolute);
181     int rc = pthread_cond_timedwait(&cond_, &mutex->mutex_, &abs_time);
182     if (rc != 0) {
183         if (rc == ETIMEDOUT) {
184             // interrupted
185             return true;
186         }
187     }
188     FATAL_IF_ERROR("pthread_cond_timedwait", rc);
189     return false;
190 }
191 }  // namespace panda::ecmascript