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