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"))) 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"))) 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"))) 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"))) 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"))) 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"))) 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