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
16 #include "platform/include/semaphore.h"
17 #include <fcntl.h>
18 #include <stdlib.h>
19 #include <unistd.h>
20 #include <sys/eventfd.h>
21 #include "platform/include/mutex.h"
22 #include "platform/include/platform_def.h"
23
24 #if !defined(EFD_SEMAPHORE)
25 #define EFD_SEMAPHORE (1 << 0)
26 #endif
27
28 typedef struct Semaphore {
29 Mutex *mutex;
30 int fd;
31 } SemaphoreInternal;
32
SemaphoreCreate(uint32_t val)33 Semaphore *SemaphoreCreate(uint32_t val)
34 {
35 int efd = eventfd(val, EFD_SEMAPHORE);
36 if (efd == -1) {
37 LOG_ERROR("SemaphoreCreate: create eventfd failed, error no: %{public}d.", errno);
38 return NULL;
39 }
40
41 Mutex *mutex = MutexCreate();
42 if (mutex == NULL) {
43 close(efd);
44 LOG_ERROR("SemaphoreCreate: create Mutex failed.");
45 return NULL;
46 }
47
48 Semaphore *semaphore = (Semaphore *)malloc(sizeof(Semaphore));
49 if (semaphore == NULL) {
50 close(efd);
51 MutexDelete(mutex);
52 LOG_ERROR("SemaphoreCreate: create Semaphore failed.");
53 return NULL;
54 }
55 semaphore->fd = efd;
56 semaphore->mutex = mutex;
57
58 return semaphore;
59 }
60
SemaphoreDelete(Semaphore * sem)61 void SemaphoreDelete(Semaphore *sem)
62 {
63 if (sem == NULL) {
64 return;
65 }
66
67 if (sem->fd != -1) {
68 close(sem->fd);
69 }
70
71 MutexDelete(sem->mutex);
72 free(sem);
73 }
74
SemaphoreWait(const Semaphore * sem)75 void SemaphoreWait(const Semaphore *sem)
76 {
77 ASSERT(sem);
78
79 eventfd_t val;
80 eventfd_read(sem->fd, &val);
81 }
82
SemaphoreTryWait(Semaphore * sem)83 int32_t SemaphoreTryWait(Semaphore *sem)
84 {
85 ASSERT(sem);
86
87 MutexLock(sem->mutex);
88 int flags = fcntl(sem->fd, F_GETFL);
89 if (flags == -1) {
90 goto ERROR;
91 }
92
93 if (fcntl(sem->fd, F_SETFL, flags | EFD_NONBLOCK) == -1) {
94 goto ERROR;
95 }
96
97 eventfd_t val;
98 if (eventfd_read(sem->fd, &val) == -1) {
99 goto ERROR;
100 }
101
102 if (fcntl(sem->fd, F_SETFL, flags) == -1) {
103 goto ERROR;
104 }
105
106 MutexUnlock(sem->mutex);
107 return 0;
108
109 ERROR:
110 MutexUnlock(sem->mutex);
111 return -1;
112 }
113
SemaphorePost(const Semaphore * sem)114 void SemaphorePost(const Semaphore *sem)
115 {
116 ASSERT(sem);
117
118 eventfd_write(sem->fd, 1);
119 }
120
SemaphoreTryPost(Semaphore * sem)121 int32_t SemaphoreTryPost(Semaphore *sem)
122 {
123 ASSERT(sem);
124
125 MutexLock(sem->mutex);
126 int flags = fcntl(sem->fd, F_GETFL);
127 if (flags == -1) {
128 goto ERROR;
129 }
130
131 if (fcntl(sem->fd, F_SETFL, flags | EFD_NONBLOCK) == -1) {
132 goto ERROR;
133 }
134
135 if (eventfd_write(sem->fd, 1) == -1) {
136 goto ERROR;
137 }
138
139 if (fcntl(sem->fd, F_SETFL, flags) == -1) {
140 goto ERROR;
141 }
142
143 MutexUnlock(sem->mutex);
144 return 0;
145
146 ERROR:
147 MutexUnlock(sem->mutex);
148 return -1;
149 }
150
SemaphoreGetfd(const Semaphore * sem)151 int SemaphoreGetfd(const Semaphore *sem)
152 {
153 ASSERT(sem);
154
155 return sem->fd;
156 }
157