Line data Source code
1 : /*
2 : *
3 : * Copyright (c) 2020-2021 Project CHIP Authors
4 : *
5 : * Licensed under the Apache License, Version 2.0 (the "License");
6 : * you may not use this file except in compliance with the License.
7 : * You may obtain a copy of the License at
8 : *
9 : * http://www.apache.org/licenses/LICENSE-2.0
10 : *
11 : * Unless required by applicable law or agreed to in writing, software
12 : * distributed under the License is distributed on an "AS IS" BASIS,
13 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 : * See the License for the specific language governing permissions and
15 : * limitations under the License.
16 : */
17 :
18 : /**
19 : * @file
20 : * This file declares the abstraction of one-directional, anonymous
21 : * data stream built on top of two file descriptors.
22 : */
23 :
24 : #include <system/SystemConfig.h>
25 :
26 : #if !CHIP_SYSTEM_CONFIG_USE_LIBEV
27 :
28 : #include <system/WakeEvent.h>
29 :
30 : // Include additional CHIP headers
31 : #include <lib/support/CodeUtils.h>
32 : #include <system/SystemError.h>
33 : #include <system/SystemLayer.h>
34 :
35 : // Include system and language headers
36 : #include <errno.h>
37 : #include <fcntl.h>
38 : #include <unistd.h>
39 :
40 : #if !CHIP_SYSTEM_CONFIG_USE_POSIX_PIPE
41 : #if CHIP_SYSTEM_CONFIG_USE_ZEPHYR_EVENTFD
42 : #include <zephyr/posix/sys/eventfd.h>
43 : #else
44 : #include <sys/eventfd.h>
45 : #endif
46 : #endif // !CHIP_SYSTEM_CONFIG_USE_POSIX_PIPE
47 :
48 : namespace chip {
49 : namespace System {
50 :
51 : #if CHIP_SYSTEM_CONFIG_USE_POSIX_PIPE
52 :
53 : namespace {
54 254 : inline int SetNonBlockingMode(int fd)
55 : {
56 254 : int flags = ::fcntl(fd, F_GETFL, 0);
57 254 : return ::fcntl(fd, F_SETFL, flags | O_NONBLOCK);
58 : }
59 : } // anonymous namespace
60 :
61 127 : CHIP_ERROR WakeEvent::Open()
62 : {
63 : enum
64 : {
65 : FD_READ = 0,
66 : FD_WRITE = 1
67 : };
68 : int fds[2];
69 :
70 127 : if (::pipe(fds) < 0)
71 0 : return CHIP_ERROR_POSIX(errno);
72 :
73 127 : if (SetNonBlockingMode(fds[FD_READ]) < 0)
74 0 : return CHIP_ERROR_POSIX(errno);
75 :
76 127 : if (SetNonBlockingMode(fds[FD_WRITE]) < 0)
77 0 : return CHIP_ERROR_POSIX(errno);
78 :
79 127 : mReadFD = fds[FD_READ];
80 127 : mWriteFD = fds[FD_WRITE];
81 :
82 127 : return CHIP_NO_ERROR;
83 : }
84 :
85 127 : void WakeEvent::Close()
86 : {
87 127 : VerifyOrDie(::close(mReadFD) == 0);
88 127 : VerifyOrDie(::close(mWriteFD) == 0);
89 127 : mReadFD = -1;
90 127 : mWriteFD = -1;
91 127 : }
92 :
93 23852517 : void WakeEvent::Confirm() const
94 : {
95 : uint8_t buffer[128];
96 : ssize_t res;
97 :
98 : do
99 : {
100 23852517 : res = ::read(mReadFD, buffer, sizeof(buffer));
101 23852517 : if (res < 0 && errno != EAGAIN && errno != EWOULDBLOCK)
102 : {
103 0 : ChipLogError(chipSystemLayer, "System wake event confirm failed: %" CHIP_ERROR_FORMAT,
104 : CHIP_ERROR_POSIX(errno).Format());
105 0 : return;
106 : }
107 23852517 : } while (res == sizeof(buffer));
108 : }
109 :
110 47552024 : CHIP_ERROR WakeEvent::Notify() const
111 : {
112 47552024 : char byte = 1;
113 :
114 47552024 : if (::write(mWriteFD, &byte, 1) < 0 && errno != EAGAIN && errno != EWOULDBLOCK)
115 : {
116 11 : return CHIP_ERROR_POSIX(errno);
117 : }
118 :
119 47552013 : return CHIP_NO_ERROR;
120 : }
121 :
122 : #else // CHIP_SYSTEM_CONFIG_USE_POSIX_PIPE
123 :
124 : namespace {
125 :
126 : #if CHIP_SYSTEM_CONFIG_USE_ZEPHYR_EVENTFD
127 :
128 : int ReadEvent(int eventFd)
129 : {
130 : eventfd_t value;
131 :
132 : return eventfd_read(eventFd, &value);
133 : }
134 :
135 : int WriteEvent(int eventFd)
136 : {
137 : return eventfd_write(eventFd, 1);
138 : }
139 :
140 : #else
141 :
142 : ssize_t ReadEvent(int eventFd)
143 : {
144 : uint64_t value;
145 :
146 : return ::read(eventFd, &value, sizeof(value));
147 : }
148 :
149 : ssize_t WriteEvent(int eventFd)
150 : {
151 : uint64_t value = 1;
152 :
153 : return ::write(eventFd, &value, sizeof(value));
154 : }
155 :
156 : #endif
157 :
158 : } // namespace
159 :
160 : CHIP_ERROR WakeEvent::Open()
161 : {
162 : mReadFD = ::eventfd(0, 0);
163 : if (mReadFD == -1)
164 : {
165 : return CHIP_ERROR_POSIX(errno);
166 : }
167 :
168 : return CHIP_NO_ERROR;
169 : }
170 :
171 : void WakeEvent::Close()
172 : {
173 : VerifyOrDie(::close(mReadFD) == 0);
174 : mReadFD = -1;
175 : }
176 :
177 : void WakeEvent::Confirm() const
178 : {
179 : if (ReadEvent(mReadFD) < 0 && errno != EAGAIN && errno != EWOULDBLOCK)
180 : {
181 : ChipLogError(chipSystemLayer, "System wake event confirm failed: %" CHIP_ERROR_FORMAT, CHIP_ERROR_POSIX(errno).Format());
182 : }
183 : }
184 :
185 : CHIP_ERROR WakeEvent::Notify() const
186 : {
187 : if (WriteEvent(mReadFD) < 0 && errno != EAGAIN && errno != EWOULDBLOCK)
188 : {
189 : return CHIP_ERROR_POSIX(errno);
190 : }
191 :
192 : return CHIP_NO_ERROR;
193 : }
194 :
195 : #endif // CHIP_SYSTEM_CONFIG_USE_POSIX_PIPE
196 :
197 : } // namespace System
198 : } // namespace chip
199 :
200 : #endif // !CHIP_SYSTEM_CONFIG_USE_LIBEV
|