1 /*
2 * Copyright (c) 2021 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 #include "semaphore_ex.h"
16
17 #include <pthread.h> // pthread_mutex_lock
18 #include <sys/types.h> // pid_t
19 #include <unistd.h> // getpid
20 #include <fcntl.h> // O_CREAT
21 #include <semaphore.h> // sem_t
22
23 #include <sstream> // ostringstream
24 #include <iomanip> // setw/setfill
25
26 using namespace std;
27
28 namespace OHOS {
29
GenUniqueName()30 std::string GenUniqueName()
31 {
32 static const uint64_t magic = 0xbcdecdeffedcedcbULL;
33 static uint64_t count = 0;
34 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
35
36 pthread_mutex_lock(&mutex);
37 count++;
38 std::ostringstream fmt;
39 static const int outWidth = 20;
40 fmt << "_unnamed_sema_" << getpid() << "_" << magic << "_"
41 << std::setw(outWidth) << std::setfill('0') << count++;
42 pthread_mutex_unlock(&mutex);
43 return fmt.str();
44 }
45
NamedSemaphore(size_t size)46 NamedSemaphore::NamedSemaphore(size_t size)
47 :name_(GenUniqueName()), maxCount_(size), sema_(nullptr), named_(false)
48 {
49 }
50
NamedSemaphore(const std::string & name,size_t size)51 NamedSemaphore::NamedSemaphore(const std::string& name, size_t size)
52 :name_(name), maxCount_(size), sema_(nullptr), named_(true)
53 {
54 }
55
~NamedSemaphore()56 NamedSemaphore::~NamedSemaphore()
57 {
58 if (!named_) {
59 Unlink();
60 }
61 }
62
Create()63 bool NamedSemaphore::Create()
64 {
65 Unlink();
66 sema_ = sem_open(name_.c_str(), O_CREAT,
67 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, maxCount_); // mode: 0666
68 return (sema_ != SEM_FAILED);
69 }
70
Unlink()71 bool NamedSemaphore::Unlink()
72 {
73 return sem_unlink(name_.c_str()) == 0;
74 }
75
Open()76 bool NamedSemaphore::Open()
77 {
78 sema_ = sem_open(name_.c_str(), 0);
79 return (sema_ != SEM_FAILED);
80 }
81
Close()82 bool NamedSemaphore::Close()
83 {
84 if (sema_ == nullptr) {
85 return false;
86 }
87
88 if (sem_close(reinterpret_cast<sem_t *>(sema_)) == 0) {
89 sema_ = nullptr;
90 return true;
91 }
92 return false;
93 }
94
Wait()95 bool NamedSemaphore::Wait()
96 {
97 if (sema_ == nullptr) {
98 return false;
99 }
100
101 return (sem_wait(reinterpret_cast<sem_t *>(sema_)) == 0);
102 }
103
TimedWait(const struct timespec & ts)104 bool NamedSemaphore::TimedWait(const struct timespec& ts)
105 {
106 if (sema_ == nullptr) {
107 return false;
108 }
109
110 return (sem_timedwait(reinterpret_cast<sem_t *>(sema_), &ts) == 0);
111 }
112
TryWait()113 bool NamedSemaphore::TryWait()
114 {
115 if (sema_ == nullptr) {
116 return false;
117 }
118
119 return (sem_trywait(reinterpret_cast<sem_t *>(sema_)) == 0);
120
121 }
122
Post()123 bool NamedSemaphore::Post()
124 {
125 if ((sema_ == nullptr) || (GetValue() >= maxCount_)) {
126 return false;
127 }
128
129 return (sem_post(reinterpret_cast<sem_t *>(sema_)) == 0);
130 }
131
GetValue() const132 int NamedSemaphore::GetValue() const
133 {
134 if (sema_ == nullptr) {
135 return INVALID_SEMA_VALUE;
136 }
137
138 int val = -1;
139 if (sem_getvalue(reinterpret_cast<sem_t *>(sema_), &val) == 0) {
140 return val;
141 }
142 return INVALID_SEMA_VALUE;
143 }
144
Wait()145 void Semaphore::Wait()
146 {
147 std::unique_lock<std::mutex> lck(mutex_);
148 if (--count_ < 0) {
149 cv_.wait(lck);
150 }
151 }
152
Post()153 void Semaphore::Post()
154 {
155 std::unique_lock<mutex> lck(mutex_);
156 if (++count_ <= 0) {
157 cv_.notify_one();
158 }
159 }
160
161 } // namespace OHOS
162