]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/apr/poll/unix/wakeup.c
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / apr / poll / unix / wakeup.c
1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2  * contributor license agreements.  See the NOTICE file distributed with
3  * this work for additional information regarding copyright ownership.
4  * The ASF licenses this file to You under the Apache License, Version 2.0
5  * (the "License"); you may not use this file except in compliance with
6  * the License.  You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include "apr.h"
18 #include "apr_poll.h"
19 #include "apr_time.h"
20 #include "apr_portable.h"
21 #include "apr_arch_file_io.h"
22 #include "apr_arch_networkio.h"
23 #include "apr_arch_poll_private.h"
24 #include "apr_arch_inherit.h"
25
26 #if !APR_FILES_AS_SOCKETS
27
28 #ifdef WIN32
29
30 apr_status_t apr_poll_create_wakeup_pipe(apr_pool_t *pool, apr_pollfd_t *pfd,
31                                          apr_file_t **wakeup_pipe)
32 {
33     apr_status_t rv;
34
35     if ((rv = apr_file_socket_pipe_create(&wakeup_pipe[0], &wakeup_pipe[1],
36                                       pool)) != APR_SUCCESS)
37         return rv;
38
39     pfd->reqevents = APR_POLLIN;
40     pfd->desc_type = APR_POLL_FILE;
41     pfd->desc.f = wakeup_pipe[0];
42     return APR_SUCCESS;
43 }
44
45 apr_status_t apr_poll_close_wakeup_pipe(apr_file_t **wakeup_pipe)
46 {
47     apr_status_t rv0 = APR_SUCCESS;
48     apr_status_t rv1 = APR_SUCCESS;
49
50     /* Close both sides of the wakeup pipe */
51     if (wakeup_pipe[0]) {
52         rv0 = apr_file_socket_pipe_close(wakeup_pipe[0]);
53         wakeup_pipe[0] = NULL;
54     }
55     if (wakeup_pipe[1]) {
56         rv1 = apr_file_socket_pipe_close(wakeup_pipe[1]);
57         wakeup_pipe[1] = NULL;
58     }
59     return rv0 ? rv0 : rv1;
60 }
61
62 #else /* !WIN32 */
63
64 apr_status_t apr_poll_create_wakeup_pipe(apr_pollfd_t *pfd, apr_file_t **wakeup_pipe)
65 {
66     return APR_ENOTIMPL;
67 }
68
69 apr_status_t apr_poll_close_wakeup_pipe(apr_file_t **wakeup_pipe)
70 {
71     return APR_ENOTIMPL;
72 }
73
74 #endif /* !WIN32 */
75
76 #else  /* APR_FILES_AS_SOCKETS */
77
78 apr_status_t apr_poll_create_wakeup_pipe(apr_pool_t *pool, apr_pollfd_t *pfd,
79                                          apr_file_t **wakeup_pipe)
80 {
81     apr_status_t rv;
82
83     if ((rv = apr_file_pipe_create(&wakeup_pipe[0], &wakeup_pipe[1],
84                                    pool)) != APR_SUCCESS)
85         return rv;
86
87     pfd->p = pool;
88     pfd->reqevents = APR_POLLIN;
89     pfd->desc_type = APR_POLL_FILE;
90     pfd->desc.f = wakeup_pipe[0];
91
92     {
93         int flags;
94
95         if ((flags = fcntl(wakeup_pipe[0]->filedes, F_GETFD)) == -1)
96             return errno;
97
98         flags |= FD_CLOEXEC;
99         if (fcntl(wakeup_pipe[0]->filedes, F_SETFD, flags) == -1)
100             return errno;
101     }
102     {
103         int flags;
104
105         if ((flags = fcntl(wakeup_pipe[1]->filedes, F_GETFD)) == -1)
106             return errno;
107
108         flags |= FD_CLOEXEC;
109         if (fcntl(wakeup_pipe[1]->filedes, F_SETFD, flags) == -1)
110             return errno;
111     }
112
113     return APR_SUCCESS;
114 }
115
116 apr_status_t apr_poll_close_wakeup_pipe(apr_file_t **wakeup_pipe)
117 {
118     apr_status_t rv0 = APR_SUCCESS;
119     apr_status_t rv1 = APR_SUCCESS;
120
121     /* Close both sides of the wakeup pipe */
122     if (wakeup_pipe[0]) {
123         rv0 = apr_file_close(wakeup_pipe[0]);
124         wakeup_pipe[0] = NULL;
125     }
126     if (wakeup_pipe[1]) {
127         rv1 = apr_file_close(wakeup_pipe[1]);
128         wakeup_pipe[1] = NULL;
129     }
130     return rv0 ? rv0 : rv1;
131 }
132
133 #endif /* APR_FILES_AS_SOCKETS */
134
135 /* Read and discard whatever is in the wakeup pipe.
136  */
137 void apr_poll_drain_wakeup_pipe(apr_file_t **wakeup_pipe)
138 {
139     char rb[512];
140     apr_size_t nr = sizeof(rb);
141
142     while (apr_file_read(wakeup_pipe[0], rb, &nr) == APR_SUCCESS) {
143         /* Although we write just one byte to the other end of the pipe
144          * during wakeup, multiple threads could call the wakeup.
145          * So simply drain out from the input side of the pipe all
146          * the data.
147          */
148         if (nr != sizeof(rb))
149             break;
150     }
151 }