tizen: kdbus: make i explicitly positive in make_single_header_vector
[platform/upstream/glib.git] / glib / gwakeup.c
1 /*
2  * Copyright © 2011 Canonical Limited
3  *
4  * SPDX-License-Identifier: LGPL-2.1-or-later
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18  *
19  * Author: Ryan Lortie <desrt@desrt.ca>
20  */
21
22 #include "config.h"
23
24 #include <stdint.h>
25
26 /* gwakeup.c is special -- GIO and some test cases include it.  As such,
27  * it cannot include other glib headers without triggering the single
28  * includes warnings.  We have to manually include its dependencies here
29  * (and at all other use sites).
30  */
31 #ifdef GLIB_COMPILATION
32 #include "gtypes.h"
33 #include "gpoll.h"
34 #else
35 #include <glib.h>
36 #endif
37
38 #include "gwakeup.h"
39
40 /*< private >
41  * GWakeup:
42  *
43  * `GWakeup` is a simple and portable way of signaling events between
44  * different threads in a way that integrates nicely with g_poll().
45  * GLib uses it internally for cross-thread signalling in the
46  * implementation of #GMainContext and #GCancellable.
47  *
48  * You first create a #GWakeup with g_wakeup_new() and initialise a
49  * #GPollFD from it using g_wakeup_get_pollfd().  Polling on the created
50  * #GPollFD will block until g_wakeup_signal() is called, at which point
51  * it will immediately return.  Future attempts to poll will continue to
52  * return until g_wakeup_acknowledge() is called.  g_wakeup_free() is
53  * used to free a #GWakeup.
54  *
55  * On sufficiently modern Linux, this is implemented using eventfd.  On
56  * Windows it is implemented using an event handle.  On other systems it
57  * is implemented with a pair of pipes.
58  *
59  * Since: 2.30
60  */
61 #ifdef _WIN32
62
63 #include <windows.h>
64
65 #ifdef GLIB_COMPILATION
66 #include "gmessages.h"
67 #include "giochannel.h"
68 #include "gwin32.h"
69 #endif
70
71 GWakeup *
72 g_wakeup_new (void)
73 {
74   HANDLE wakeup;
75
76   wakeup = CreateEvent (NULL, TRUE, FALSE, NULL);
77
78   if (wakeup == NULL)
79     g_error ("Cannot create event for GWakeup: %s",
80              g_win32_error_message (GetLastError ()));
81
82   return (GWakeup *) wakeup;
83 }
84
85 void
86 g_wakeup_get_pollfd (GWakeup *wakeup,
87                      GPollFD *poll_fd)
88 {
89   poll_fd->fd = (gintptr) wakeup;
90   poll_fd->events = G_IO_IN;
91 }
92
93 void
94 g_wakeup_acknowledge (GWakeup *wakeup)
95 {
96   ResetEvent ((HANDLE) wakeup);
97 }
98
99 void
100 g_wakeup_signal (GWakeup *wakeup)
101 {
102   SetEvent ((HANDLE) wakeup);
103 }
104
105 void
106 g_wakeup_free (GWakeup *wakeup)
107 {
108   CloseHandle ((HANDLE) wakeup);
109 }
110
111 #else
112
113 #include "glib-unix.h"
114 #include <fcntl.h>
115
116 #if defined (HAVE_EVENTFD)
117 #include <sys/eventfd.h>
118 #endif
119
120 struct _GWakeup
121 {
122   gint fds[2];
123 };
124
125 /*< private >
126  * g_wakeup_new:
127  *
128  * Creates a new #GWakeup.
129  *
130  * You should use g_wakeup_free() to free it when you are done.
131  *
132  * Returns: a new #GWakeup
133  *
134  * Since: 2.30
135  **/
136 GWakeup *
137 g_wakeup_new (void)
138 {
139   GError *error = NULL;
140   GWakeup *wakeup;
141
142   wakeup = g_slice_new (GWakeup);
143
144   /* try eventfd first, if we think we can */
145 #if defined (HAVE_EVENTFD)
146 #ifndef TEST_EVENTFD_FALLBACK
147   wakeup->fds[0] = eventfd (0, EFD_CLOEXEC | EFD_NONBLOCK);
148 #else
149   wakeup->fds[0] = -1;
150 #endif
151
152   if (wakeup->fds[0] != -1)
153     {
154       wakeup->fds[1] = -1;
155       return wakeup;
156     }
157
158   /* for any failure, try a pipe instead */
159 #endif
160
161   if (!g_unix_open_pipe (wakeup->fds, O_CLOEXEC | O_NONBLOCK, &error))
162     g_error ("Creating pipes for GWakeup: %s", error->message);
163
164   if (!g_unix_set_fd_nonblocking (wakeup->fds[0], TRUE, &error) ||
165       !g_unix_set_fd_nonblocking (wakeup->fds[1], TRUE, &error))
166     g_error ("Set pipes non-blocking for GWakeup: %s", error->message);
167
168   return wakeup;
169 }
170
171 /*< private >
172  * g_wakeup_get_pollfd:
173  * @wakeup: a #GWakeup
174  * @poll_fd: a #GPollFD
175  *
176  * Prepares a @poll_fd such that polling on it will succeed when
177  * g_wakeup_signal() has been called on @wakeup.
178  *
179  * @poll_fd is valid until @wakeup is freed.
180  *
181  * Since: 2.30
182  **/
183 void
184 g_wakeup_get_pollfd (GWakeup *wakeup,
185                      GPollFD *poll_fd)
186 {
187   poll_fd->fd = wakeup->fds[0];
188   poll_fd->events = G_IO_IN;
189 }
190
191 /*< private >
192  * g_wakeup_acknowledge:
193  * @wakeup: a #GWakeup
194  *
195  * Acknowledges receipt of a wakeup signal on @wakeup.
196  *
197  * You must call this after @wakeup polls as ready.  If not, it will
198  * continue to poll as ready until you do so.
199  *
200  * If you call this function and @wakeup is not signaled, nothing
201  * happens.
202  *
203  * Since: 2.30
204  **/
205 void
206 g_wakeup_acknowledge (GWakeup *wakeup)
207 {
208   int res;
209
210   if (wakeup->fds[1] == -1)
211     {
212       uint64_t value;
213
214       /* eventfd() read resets counter */
215       do
216         res = read (wakeup->fds[0], &value, sizeof (value));
217       while (G_UNLIKELY (res == -1 && errno == EINTR));
218     }
219   else
220     {
221       uint8_t value;
222
223       /* read until it is empty */
224       do
225         res = read (wakeup->fds[0], &value, sizeof (value));
226       while (res == sizeof (value) || G_UNLIKELY (res == -1 && errno == EINTR));
227     }
228 }
229
230 /*< private >
231  * g_wakeup_signal:
232  * @wakeup: a #GWakeup
233  *
234  * Signals @wakeup.
235  *
236  * Any future (or present) polling on the #GPollFD returned by
237  * g_wakeup_get_pollfd() will immediately succeed until such a time as
238  * g_wakeup_acknowledge() is called.
239  *
240  * This function is safe to call from a UNIX signal handler.
241  *
242  * Since: 2.30
243  **/
244 void
245 g_wakeup_signal (GWakeup *wakeup)
246 {
247   int res;
248
249   if (wakeup->fds[1] == -1)
250     {
251       uint64_t one = 1;
252
253       /* eventfd() case. It requires a 64-bit counter increment value to be
254        * written. */
255       do
256         res = write (wakeup->fds[0], &one, sizeof one);
257       while (G_UNLIKELY (res == -1 && errno == EINTR));
258     }
259   else
260     {
261       uint8_t one = 1;
262
263       /* Non-eventfd() case. Only a single byte needs to be written, and it can
264        * have an arbitrary value. */
265       do
266         res = write (wakeup->fds[1], &one, sizeof one);
267       while (G_UNLIKELY (res == -1 && errno == EINTR));
268     }
269 }
270
271 /*< private >
272  * g_wakeup_free:
273  * @wakeup: a #GWakeup
274  *
275  * Frees @wakeup.
276  *
277  * You must not currently be polling on the #GPollFD returned by
278  * g_wakeup_get_pollfd(), or the result is undefined.
279  **/
280 void
281 g_wakeup_free (GWakeup *wakeup)
282 {
283   close (wakeup->fds[0]);
284
285   if (wakeup->fds[1] != -1)
286     close (wakeup->fds[1]);
287
288   g_slice_free (GWakeup, wakeup);
289 }
290
291 #endif /* !_WIN32 */