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_SOCKETS && !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 212 : inline int SetNonBlockingMode(int fd)
55 : {
56 212 : int flags = ::fcntl(fd, F_GETFL, 0);
57 212 : return ::fcntl(fd, F_SETFL, flags | O_NONBLOCK);
58 : }
59 : } // anonymous namespace
60 :
61 106 : CHIP_ERROR WakeEvent::Open(LayerSockets & systemLayer)
62 : {
63 : enum
64 : {
65 : FD_READ = 0,
66 : FD_WRITE = 1
67 : };
68 : int fds[2];
69 :
70 106 : if (::pipe(fds) < 0)
71 0 : return CHIP_ERROR_POSIX(errno);
72 :
73 106 : if (SetNonBlockingMode(fds[FD_READ]) < 0)
74 0 : return CHIP_ERROR_POSIX(errno);
75 :
76 106 : if (SetNonBlockingMode(fds[FD_WRITE]) < 0)
77 0 : return CHIP_ERROR_POSIX(errno);
78 :
79 106 : mReadFD = fds[FD_READ];
80 106 : mWriteFD = fds[FD_WRITE];
81 :
82 106 : ReturnErrorOnFailure(systemLayer.StartWatchingSocket(mReadFD, &mReadWatch));
83 106 : ReturnErrorOnFailure(systemLayer.SetCallback(mReadWatch, Confirm, reinterpret_cast<intptr_t>(this)));
84 106 : ReturnErrorOnFailure(systemLayer.RequestCallbackOnPendingRead(mReadWatch));
85 :
86 106 : return CHIP_NO_ERROR;
87 : }
88 :
89 106 : void WakeEvent::Close(LayerSockets & systemLayer)
90 : {
91 106 : systemLayer.StopWatchingSocket(&mReadWatch);
92 106 : VerifyOrDie(::close(mReadFD) == 0);
93 106 : VerifyOrDie(::close(mWriteFD) == 0);
94 106 : mReadFD = -1;
95 106 : mWriteFD = -1;
96 106 : }
97 :
98 6601575 : void WakeEvent::Confirm() const
99 : {
100 : uint8_t buffer[128];
101 : ssize_t res;
102 :
103 : do
104 : {
105 6601575 : res = ::read(mReadFD, buffer, sizeof(buffer));
106 6601575 : if (res < 0 && errno != EAGAIN && errno != EWOULDBLOCK)
107 : {
108 0 : ChipLogError(chipSystemLayer, "System wake event confirm failed: %" CHIP_ERROR_FORMAT,
109 : CHIP_ERROR_POSIX(errno).Format());
110 0 : return;
111 : }
112 6601575 : } while (res == sizeof(buffer));
113 : }
114 :
115 13087882 : CHIP_ERROR WakeEvent::Notify() const
116 : {
117 13087882 : char byte = 1;
118 :
119 13087882 : if (::write(mWriteFD, &byte, 1) < 0 && errno != EAGAIN && errno != EWOULDBLOCK)
120 : {
121 11 : return CHIP_ERROR_POSIX(errno);
122 : }
123 :
124 13087871 : return CHIP_NO_ERROR;
125 : }
126 :
127 : #else // CHIP_SYSTEM_CONFIG_USE_POSIX_PIPE
128 :
129 : namespace {
130 :
131 : #if CHIP_SYSTEM_CONFIG_USE_ZEPHYR_EVENTFD
132 :
133 : int ReadEvent(int eventFd)
134 : {
135 : eventfd_t value;
136 :
137 : return eventfd_read(eventFd, &value);
138 : }
139 :
140 : int WriteEvent(int eventFd)
141 : {
142 : return eventfd_write(eventFd, 1);
143 : }
144 :
145 : #else
146 :
147 : ssize_t ReadEvent(int eventFd)
148 : {
149 : uint64_t value;
150 :
151 : return ::read(eventFd, &value, sizeof(value));
152 : }
153 :
154 : ssize_t WriteEvent(int eventFd)
155 : {
156 : uint64_t value = 1;
157 :
158 : return ::write(eventFd, &value, sizeof(value));
159 : }
160 :
161 : #endif
162 :
163 : } // namespace
164 :
165 : CHIP_ERROR WakeEvent::Open(LayerSockets & systemLayer)
166 : {
167 : mReadFD = ::eventfd(0, 0);
168 : if (mReadFD == -1)
169 : {
170 : return CHIP_ERROR_POSIX(errno);
171 : }
172 :
173 : ReturnErrorOnFailure(systemLayer.StartWatchingSocket(mReadFD, &mReadWatch));
174 : ReturnErrorOnFailure(systemLayer.SetCallback(mReadWatch, Confirm, reinterpret_cast<intptr_t>(this)));
175 : ReturnErrorOnFailure(systemLayer.RequestCallbackOnPendingRead(mReadWatch));
176 :
177 : return CHIP_NO_ERROR;
178 : }
179 :
180 : void WakeEvent::Close(LayerSockets & systemLayer)
181 : {
182 : systemLayer.StopWatchingSocket(&mReadWatch);
183 : VerifyOrDie(::close(mReadFD) == 0);
184 : mReadFD = -1;
185 : }
186 :
187 : void WakeEvent::Confirm() const
188 : {
189 : if (ReadEvent(mReadFD) < 0 && errno != EAGAIN && errno != EWOULDBLOCK)
190 : {
191 : ChipLogError(chipSystemLayer, "System wake event confirm failed: %" CHIP_ERROR_FORMAT, CHIP_ERROR_POSIX(errno).Format());
192 : }
193 : }
194 :
195 : CHIP_ERROR WakeEvent::Notify() const
196 : {
197 : if (WriteEvent(mReadFD) < 0 && errno != EAGAIN && errno != EWOULDBLOCK)
198 : {
199 : return CHIP_ERROR_POSIX(errno);
200 : }
201 :
202 : return CHIP_NO_ERROR;
203 : }
204 :
205 : #endif // CHIP_SYSTEM_CONFIG_USE_POSIX_PIPE
206 :
207 : } // namespace System
208 : } // namespace chip
209 :
210 : #endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS && !CHIP_SYSTEM_CONFIG_USE_LIBEV
|