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 "cpp/condition_variable.h"
17 #include "c/condition_variable.h"
18 #include "sync/wait_queue.h"
19 #include "sync/mutex_private.h"
20 #include "internal_inc/osal.h"
21 #include "dfx/log/ffrt_log_api.h"
22
23 namespace ffrt {
24 using condition_variable_private = WaitQueue;
25 }
26
27 #ifdef __cplusplus
28 extern "C" {
29 #endif
30 API_ATTRIBUTE((visibility("default")))
ffrt_cond_init(ffrt_cond_t * cond,const ffrt_condattr_t * attr)31 int ffrt_cond_init(ffrt_cond_t* cond, const ffrt_condattr_t* attr)
32 {
33 if (!cond) {
34 FFRT_LOGE("cond should not be empty");
35 return ffrt_error_inval;
36 }
37 static_assert(sizeof(ffrt::condition_variable_private) <= ffrt_cond_storage_size,
38 "size must be less than ffrt_cond_storage_size");
39
40 new (cond) ffrt::condition_variable_private();
41 return ffrt_success;
42 }
43
44 API_ATTRIBUTE((visibility("default")))
ffrt_cond_signal(ffrt_cond_t * cond)45 int ffrt_cond_signal(ffrt_cond_t* cond)
46 {
47 if (!cond) {
48 FFRT_LOGE("cond should not be empty");
49 return ffrt_error_inval;
50 }
51 auto p = reinterpret_cast<ffrt::condition_variable_private *>(cond);
52 p->NotifyOne();
53 return ffrt_success;
54 }
55
56 API_ATTRIBUTE((visibility("default")))
ffrt_cond_broadcast(ffrt_cond_t * cond)57 int ffrt_cond_broadcast(ffrt_cond_t* cond)
58 {
59 if (!cond) {
60 FFRT_LOGE("cond should not be empty");
61 return ffrt_error_inval;
62 }
63 auto p = reinterpret_cast<ffrt::condition_variable_private *>(cond);
64 p->NotifyAll();
65 return ffrt_success;
66 }
67
68 API_ATTRIBUTE((visibility("default")))
ffrt_cond_wait(ffrt_cond_t * cond,ffrt_mutex_t * mutex)69 int ffrt_cond_wait(ffrt_cond_t* cond, ffrt_mutex_t* mutex)
70 {
71 if (!cond || !mutex) {
72 FFRT_LOGE("cond and mutex should not be empty");
73 return ffrt_error_inval;
74 }
75 auto pc = reinterpret_cast<ffrt::condition_variable_private *>(cond);
76 auto pm = reinterpret_cast<ffrt::mutexPrivate *>(mutex);
77 pc->SuspendAndWait(pm);
78 return ffrt_success;
79 }
80
81 API_ATTRIBUTE((visibility("default")))
ffrt_cond_timedwait(ffrt_cond_t * cond,ffrt_mutex_t * mutex,const struct timespec * time_point)82 int ffrt_cond_timedwait(ffrt_cond_t* cond, ffrt_mutex_t* mutex, const struct timespec* time_point)
83 {
84 if (!cond || !mutex || !time_point) {
85 FFRT_LOGE("cond, mutex and time_point should not be empty");
86 return ffrt_error_inval;
87 }
88 auto pc = reinterpret_cast<ffrt::condition_variable_private *>(cond);
89 auto pm = reinterpret_cast<ffrt::mutexPrivate *>(mutex);
90
91 using namespace std::chrono;
92 auto duration = seconds{ time_point->tv_sec } + nanoseconds{ time_point->tv_nsec };
93 auto tp = ffrt::TimePoint {
94 duration_cast<steady_clock::duration>(duration_cast<nanoseconds>(duration))
95 };
96
97 return pc->SuspendAndWaitUntil(pm, tp) ? ffrt_error_timedout : ffrt_success;
98 }
99
100 API_ATTRIBUTE((visibility("default")))
ffrt_cond_destroy(ffrt_cond_t * cond)101 int ffrt_cond_destroy(ffrt_cond_t* cond)
102 {
103 if (!cond) {
104 FFRT_LOGE("cond should not be empty");
105 return ffrt_error_inval;
106 }
107 auto p = reinterpret_cast<ffrt::condition_variable_private *>(cond);
108 p->~WaitQueue();
109 return ffrt_success;
110 }
111 #ifdef __cplusplus
112 }
113 #endif
114