root / src / xseg_posixfd.c @ a86ebfc3
History | View | Annotate | Download (10.8 kB)
1 | 8cbf5379 | Filippos Giannakos | /*
|
---|---|---|---|
2 | 8cbf5379 | Filippos Giannakos | * Copyright 2012 GRNET S.A. All rights reserved.
|
3 | 8cbf5379 | Filippos Giannakos | *
|
4 | 8cbf5379 | Filippos Giannakos | * Redistribution and use in source and binary forms, with or
|
5 | 8cbf5379 | Filippos Giannakos | * without modification, are permitted provided that the following
|
6 | 8cbf5379 | Filippos Giannakos | * conditions are met:
|
7 | 8cbf5379 | Filippos Giannakos | *
|
8 | 8cbf5379 | Filippos Giannakos | * 1. Redistributions of source code must retain the above
|
9 | 8cbf5379 | Filippos Giannakos | * copyright notice, this list of conditions and the following
|
10 | 8cbf5379 | Filippos Giannakos | * disclaimer.
|
11 | 8cbf5379 | Filippos Giannakos | * 2. Redistributions in binary form must reproduce the above
|
12 | 8cbf5379 | Filippos Giannakos | * copyright notice, this list of conditions and the following
|
13 | 8cbf5379 | Filippos Giannakos | * disclaimer in the documentation and/or other materials
|
14 | 8cbf5379 | Filippos Giannakos | * provided with the distribution.
|
15 | 8cbf5379 | Filippos Giannakos | *
|
16 | 8cbf5379 | Filippos Giannakos | * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
|
17 | 8cbf5379 | Filippos Giannakos | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
18 | 8cbf5379 | Filippos Giannakos | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
19 | 8cbf5379 | Filippos Giannakos | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
|
20 | 8cbf5379 | Filippos Giannakos | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
21 | 8cbf5379 | Filippos Giannakos | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
22 | 8cbf5379 | Filippos Giannakos | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
23 | 8cbf5379 | Filippos Giannakos | * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
24 | 8cbf5379 | Filippos Giannakos | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
25 | 8cbf5379 | Filippos Giannakos | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
26 | 8cbf5379 | Filippos Giannakos | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
27 | 8cbf5379 | Filippos Giannakos | * POSSIBILITY OF SUCH DAMAGE.
|
28 | 8cbf5379 | Filippos Giannakos | *
|
29 | 8cbf5379 | Filippos Giannakos | * The views and conclusions contained in the software and
|
30 | 8cbf5379 | Filippos Giannakos | * documentation are those of the authors and should not be
|
31 | 8cbf5379 | Filippos Giannakos | * interpreted as representing official policies, either expressed
|
32 | 8cbf5379 | Filippos Giannakos | * or implied, of GRNET S.A.
|
33 | 8cbf5379 | Filippos Giannakos | */
|
34 | 8cbf5379 | Filippos Giannakos | |
35 | 8cbf5379 | Filippos Giannakos | #define _GNU_SOURCE
|
36 | 8cbf5379 | Filippos Giannakos | #include <stdio.h> |
37 | 8cbf5379 | Filippos Giannakos | #include <stdlib.h> |
38 | 8cbf5379 | Filippos Giannakos | #include <unistd.h> |
39 | 8cbf5379 | Filippos Giannakos | #include <sys/types.h> |
40 | 8cbf5379 | Filippos Giannakos | #include <sys/time.h> |
41 | 8cbf5379 | Filippos Giannakos | #include <sys/select.h> |
42 | 8cbf5379 | Filippos Giannakos | #include <sys/stat.h> |
43 | 8cbf5379 | Filippos Giannakos | #include <sys/mman.h> |
44 | 8cbf5379 | Filippos Giannakos | #include <sys/syscall.h> |
45 | 8cbf5379 | Filippos Giannakos | #include <fcntl.h> |
46 | 8cbf5379 | Filippos Giannakos | #include <errno.h> |
47 | 8cbf5379 | Filippos Giannakos | #include <string.h> |
48 | 8cbf5379 | Filippos Giannakos | #include <signal.h> |
49 | 51eafc68 | Filippos Giannakos | #include <xseg/util.h> |
50 | 8cbf5379 | Filippos Giannakos | #include <xseg/xseg.h> |
51 | 51eafc68 | Filippos Giannakos | #include <xseg/xobj.h> |
52 | 51eafc68 | Filippos Giannakos | #include <xseg_posixfd.h> |
53 | 8cbf5379 | Filippos Giannakos | #define ERRSIZE 512 |
54 | 8cbf5379 | Filippos Giannakos | char errbuf[ERRSIZE];
|
55 | 8cbf5379 | Filippos Giannakos | |
56 | 8cbf5379 | Filippos Giannakos | static long posixfd_allocate(const char *name, uint64_t size) |
57 | 8cbf5379 | Filippos Giannakos | { |
58 | 8cbf5379 | Filippos Giannakos | int fd, r;
|
59 | e615a1d0 | Filippos Giannakos | off_t lr; |
60 | 8cbf5379 | Filippos Giannakos | fd = shm_open(name, O_RDWR | O_CREAT | O_EXCL, 0770);
|
61 | 8cbf5379 | Filippos Giannakos | if (fd < 0) { |
62 | 8cbf5379 | Filippos Giannakos | XSEGLOG("Cannot create shared segment: %s\n",
|
63 | 8cbf5379 | Filippos Giannakos | strerror_r(errno, errbuf, ERRSIZE)); |
64 | 8cbf5379 | Filippos Giannakos | return fd;
|
65 | 8cbf5379 | Filippos Giannakos | } |
66 | 8cbf5379 | Filippos Giannakos | |
67 | e615a1d0 | Filippos Giannakos | lr = lseek(fd, size -1, SEEK_SET);
|
68 | e615a1d0 | Filippos Giannakos | if (lr == (off_t)-1) { |
69 | 8cbf5379 | Filippos Giannakos | close(fd); |
70 | 8cbf5379 | Filippos Giannakos | XSEGLOG("Cannot seek into segment file: %s\n",
|
71 | 8cbf5379 | Filippos Giannakos | strerror_r(errno, errbuf, ERRSIZE)); |
72 | 8cbf5379 | Filippos Giannakos | return r;
|
73 | 8cbf5379 | Filippos Giannakos | } |
74 | 8cbf5379 | Filippos Giannakos | |
75 | 8cbf5379 | Filippos Giannakos | errbuf[0] = 0; |
76 | 8cbf5379 | Filippos Giannakos | r = write(fd, errbuf, 1);
|
77 | 8cbf5379 | Filippos Giannakos | if (r != 1) { |
78 | 8cbf5379 | Filippos Giannakos | close(fd); |
79 | 8cbf5379 | Filippos Giannakos | XSEGLOG("Failed to set segment size: %s\n",
|
80 | 8cbf5379 | Filippos Giannakos | strerror_r(errno, errbuf, ERRSIZE)); |
81 | 8cbf5379 | Filippos Giannakos | return r;
|
82 | 8cbf5379 | Filippos Giannakos | } |
83 | 8cbf5379 | Filippos Giannakos | |
84 | 8cbf5379 | Filippos Giannakos | close(fd); |
85 | 8cbf5379 | Filippos Giannakos | return 0; |
86 | 8cbf5379 | Filippos Giannakos | } |
87 | 8cbf5379 | Filippos Giannakos | |
88 | 8cbf5379 | Filippos Giannakos | static long posixfd_deallocate(const char *name) |
89 | 8cbf5379 | Filippos Giannakos | { |
90 | 8cbf5379 | Filippos Giannakos | return shm_unlink(name);
|
91 | 8cbf5379 | Filippos Giannakos | } |
92 | 8cbf5379 | Filippos Giannakos | |
93 | 8cbf5379 | Filippos Giannakos | static void *posixfd_map(const char *name, uint64_t size, struct xseg *seg) |
94 | 8cbf5379 | Filippos Giannakos | { |
95 | 8cbf5379 | Filippos Giannakos | struct xseg *xseg;
|
96 | 8cbf5379 | Filippos Giannakos | int fd;
|
97 | 8cbf5379 | Filippos Giannakos | |
98 | 8cbf5379 | Filippos Giannakos | fd = shm_open(name, O_RDWR, 0000);
|
99 | 8cbf5379 | Filippos Giannakos | if (fd < 0) { |
100 | 8cbf5379 | Filippos Giannakos | XSEGLOG("Failed to open '%s' for mapping: %s\n",
|
101 | 8cbf5379 | Filippos Giannakos | name, strerror_r(errno, errbuf, ERRSIZE)); |
102 | 8cbf5379 | Filippos Giannakos | return NULL; |
103 | 8cbf5379 | Filippos Giannakos | } |
104 | 8cbf5379 | Filippos Giannakos | |
105 | 8cbf5379 | Filippos Giannakos | xseg = mmap ( XSEG_BASE_AS_PTR, |
106 | 8cbf5379 | Filippos Giannakos | size, |
107 | 8cbf5379 | Filippos Giannakos | PROT_READ | PROT_WRITE, |
108 | 8cbf5379 | Filippos Giannakos | MAP_SHARED | MAP_FIXED /* | MAP_LOCKED */,
|
109 | 8cbf5379 | Filippos Giannakos | fd, 0 );
|
110 | 8cbf5379 | Filippos Giannakos | |
111 | 8cbf5379 | Filippos Giannakos | if (xseg == MAP_FAILED) {
|
112 | 8cbf5379 | Filippos Giannakos | XSEGLOG("Could not map segment: %s\n",
|
113 | 8cbf5379 | Filippos Giannakos | strerror_r(errno, errbuf, ERRSIZE)); |
114 | 8cbf5379 | Filippos Giannakos | return NULL; |
115 | 8cbf5379 | Filippos Giannakos | } |
116 | 8cbf5379 | Filippos Giannakos | |
117 | 8cbf5379 | Filippos Giannakos | close(fd); |
118 | 8cbf5379 | Filippos Giannakos | return xseg;
|
119 | 8cbf5379 | Filippos Giannakos | } |
120 | 8cbf5379 | Filippos Giannakos | |
121 | 8cbf5379 | Filippos Giannakos | static void posixfd_unmap(void *ptr, uint64_t size) |
122 | 8cbf5379 | Filippos Giannakos | { |
123 | 8cbf5379 | Filippos Giannakos | struct xseg *xseg = ptr;
|
124 | 8cbf5379 | Filippos Giannakos | (void)munmap(xseg, xseg->segment_size);
|
125 | 8cbf5379 | Filippos Giannakos | } |
126 | 8cbf5379 | Filippos Giannakos | |
127 | 8cbf5379 | Filippos Giannakos | static struct posixfd_signal_desc * __get_signal_desc(struct xseg *xseg, xport portno) |
128 | 8cbf5379 | Filippos Giannakos | { |
129 | 8cbf5379 | Filippos Giannakos | struct xseg_port *port = xseg_get_port(xseg, portno);
|
130 | 8cbf5379 | Filippos Giannakos | if (!port)
|
131 | 8cbf5379 | Filippos Giannakos | return NULL; |
132 | 8cbf5379 | Filippos Giannakos | struct posixfd_signal_desc *psd = xseg_get_signal_desc(xseg, port);
|
133 | 8cbf5379 | Filippos Giannakos | if (!psd)
|
134 | 8cbf5379 | Filippos Giannakos | return NULL; |
135 | 8cbf5379 | Filippos Giannakos | return psd;
|
136 | 8cbf5379 | Filippos Giannakos | } |
137 | 8cbf5379 | Filippos Giannakos | |
138 | 8cbf5379 | Filippos Giannakos | static void __get_filename(struct posixfd_signal_desc *psd, char *filename) |
139 | 8cbf5379 | Filippos Giannakos | { |
140 | 8cbf5379 | Filippos Giannakos | int pos = 0; |
141 | 8cbf5379 | Filippos Giannakos | strncpy(filename+pos, POSIXFD_DIR, POSIXFD_DIR_LEN); |
142 | 8cbf5379 | Filippos Giannakos | pos += POSIXFD_DIR_LEN; |
143 | 8cbf5379 | Filippos Giannakos | strncpy(filename + pos, psd->signal_file, POSIXFD_FILENAME_LEN); |
144 | 8cbf5379 | Filippos Giannakos | pos += POSIXFD_FILENAME_LEN; |
145 | 8cbf5379 | Filippos Giannakos | filename[pos] = 0;
|
146 | 8cbf5379 | Filippos Giannakos | } |
147 | 8cbf5379 | Filippos Giannakos | |
148 | 8cbf5379 | Filippos Giannakos | /*
|
149 | 8cbf5379 | Filippos Giannakos | * In order to be able to accept signals we must:
|
150 | 8cbf5379 | Filippos Giannakos | *
|
151 | 8cbf5379 | Filippos Giannakos | * a) Create the name piped for our signal descriptor.
|
152 | 8cbf5379 | Filippos Giannakos | * b) Open the named pipe and get an fd.
|
153 | 8cbf5379 | Filippos Giannakos | */
|
154 | 8cbf5379 | Filippos Giannakos | static int posixfd_local_signal_init(struct xseg *xseg, xport portno) |
155 | 8cbf5379 | Filippos Giannakos | { |
156 | 8cbf5379 | Filippos Giannakos | /* create or truncate POSIXFD+portno file */
|
157 | 8cbf5379 | Filippos Giannakos | int r, fd;
|
158 | 8cbf5379 | Filippos Giannakos | char filename[POSIXFD_DIR_LEN + POSIXFD_FILENAME_LEN + 1]; |
159 | 8cbf5379 | Filippos Giannakos | |
160 | 8cbf5379 | Filippos Giannakos | struct posixfd_signal_desc *psd = __get_signal_desc(xseg, portno);
|
161 | 8cbf5379 | Filippos Giannakos | if (!psd) {
|
162 | 8cbf5379 | Filippos Giannakos | return -1; |
163 | 8cbf5379 | Filippos Giannakos | } |
164 | 8cbf5379 | Filippos Giannakos | __get_filename(psd, filename); |
165 | 8cbf5379 | Filippos Giannakos | |
166 | 8cbf5379 | Filippos Giannakos | retry:
|
167 | 8cbf5379 | Filippos Giannakos | r = mkfifo(filename, S_IRUSR|S_IWUSR); |
168 | 8cbf5379 | Filippos Giannakos | if (r < 0) { |
169 | 8cbf5379 | Filippos Giannakos | if (errno == EEXIST) {
|
170 | 8cbf5379 | Filippos Giannakos | unlink(filename); |
171 | 8cbf5379 | Filippos Giannakos | goto retry;
|
172 | 8cbf5379 | Filippos Giannakos | } |
173 | 8cbf5379 | Filippos Giannakos | return -1; |
174 | 8cbf5379 | Filippos Giannakos | } |
175 | 8cbf5379 | Filippos Giannakos | |
176 | 8cbf5379 | Filippos Giannakos | fd = open(filename, O_RDONLY | O_NONBLOCK); |
177 | 8cbf5379 | Filippos Giannakos | if (fd < 0) { |
178 | 8cbf5379 | Filippos Giannakos | unlink(filename); |
179 | 8cbf5379 | Filippos Giannakos | return -1; |
180 | 8cbf5379 | Filippos Giannakos | } |
181 | 8cbf5379 | Filippos Giannakos | psd->fd = fd; |
182 | 8cbf5379 | Filippos Giannakos | open(filename, O_WRONLY | O_NONBLOCK); |
183 | 8cbf5379 | Filippos Giannakos | |
184 | 8cbf5379 | Filippos Giannakos | return 0; |
185 | 8cbf5379 | Filippos Giannakos | } |
186 | 8cbf5379 | Filippos Giannakos | |
187 | 8cbf5379 | Filippos Giannakos | /*
|
188 | 8cbf5379 | Filippos Giannakos | * To clean up after our signal initialiazation, we should:
|
189 | 8cbf5379 | Filippos Giannakos | *
|
190 | 8cbf5379 | Filippos Giannakos | * a) close the open fd for our named pipe
|
191 | 8cbf5379 | Filippos Giannakos | * b) unlink the named pipe from the file system.
|
192 | 8cbf5379 | Filippos Giannakos | */
|
193 | 8cbf5379 | Filippos Giannakos | static void posixfd_local_signal_quit(struct xseg *xseg, xport portno) |
194 | 8cbf5379 | Filippos Giannakos | { |
195 | 8cbf5379 | Filippos Giannakos | char filename[POSIXFD_DIR_LEN + POSIXFD_FILENAME_LEN + 1]; |
196 | 8cbf5379 | Filippos Giannakos | struct posixfd_signal_desc *psd = __get_signal_desc(xseg, portno);
|
197 | 8cbf5379 | Filippos Giannakos | if (psd->fd >=0) { |
198 | 8cbf5379 | Filippos Giannakos | close(psd->fd); |
199 | 8cbf5379 | Filippos Giannakos | psd->fd = -1;
|
200 | 8cbf5379 | Filippos Giannakos | } |
201 | 8cbf5379 | Filippos Giannakos | __get_filename(psd, filename); |
202 | 8cbf5379 | Filippos Giannakos | unlink(filename); |
203 | 8cbf5379 | Filippos Giannakos | return;
|
204 | 8cbf5379 | Filippos Giannakos | } |
205 | 8cbf5379 | Filippos Giannakos | |
206 | 8cbf5379 | Filippos Giannakos | /*
|
207 | 8cbf5379 | Filippos Giannakos | * When this peer type is initialized, we must make sure the directory where the
|
208 | 8cbf5379 | Filippos Giannakos | * named pipes will be created, exist.
|
209 | 8cbf5379 | Filippos Giannakos | */
|
210 | 8cbf5379 | Filippos Giannakos | static int posixfd_remote_signal_init(void) |
211 | 8cbf5379 | Filippos Giannakos | { |
212 | 8cbf5379 | Filippos Giannakos | int r;
|
213 | 8cbf5379 | Filippos Giannakos | r = mkdir(POSIXFD_DIR, 01755);
|
214 | 8cbf5379 | Filippos Giannakos | |
215 | 8cbf5379 | Filippos Giannakos | if (r < 0) { |
216 | 8cbf5379 | Filippos Giannakos | if (errno != EEXIST) // && isdir(POSIXFD_DIR) |
217 | 8cbf5379 | Filippos Giannakos | return -1; |
218 | 8cbf5379 | Filippos Giannakos | } |
219 | 8cbf5379 | Filippos Giannakos | |
220 | 8cbf5379 | Filippos Giannakos | return 0; |
221 | 8cbf5379 | Filippos Giannakos | } |
222 | 8cbf5379 | Filippos Giannakos | |
223 | 8cbf5379 | Filippos Giannakos | static void posixfd_remote_signal_quit(void) |
224 | 8cbf5379 | Filippos Giannakos | { |
225 | 8cbf5379 | Filippos Giannakos | return;
|
226 | 8cbf5379 | Filippos Giannakos | } |
227 | 8cbf5379 | Filippos Giannakos | |
228 | 8cbf5379 | Filippos Giannakos | static int posixfd_prepare_wait(struct xseg *xseg, uint32_t portno) |
229 | 8cbf5379 | Filippos Giannakos | { |
230 | 8cbf5379 | Filippos Giannakos | char buf[512]; |
231 | 8cbf5379 | Filippos Giannakos | int buf_size = 512; |
232 | 8cbf5379 | Filippos Giannakos | struct posixfd_signal_desc *psd = __get_signal_desc(xseg, portno);
|
233 | 8cbf5379 | Filippos Giannakos | if (!psd)
|
234 | 8cbf5379 | Filippos Giannakos | return -1; |
235 | 8cbf5379 | Filippos Giannakos | psd->flag = 1;
|
236 | 8cbf5379 | Filippos Giannakos | while (read(psd->fd, buf, buf_size) > 0); |
237 | 8cbf5379 | Filippos Giannakos | |
238 | 8cbf5379 | Filippos Giannakos | return 0; |
239 | 8cbf5379 | Filippos Giannakos | } |
240 | 8cbf5379 | Filippos Giannakos | |
241 | 8cbf5379 | Filippos Giannakos | static int posixfd_cancel_wait(struct xseg *xseg, uint32_t portno) |
242 | 8cbf5379 | Filippos Giannakos | { |
243 | 8cbf5379 | Filippos Giannakos | char buf[512]; |
244 | 8cbf5379 | Filippos Giannakos | int buf_size = 512; |
245 | 8cbf5379 | Filippos Giannakos | struct posixfd_signal_desc *psd = __get_signal_desc(xseg, portno);
|
246 | 8cbf5379 | Filippos Giannakos | if (!psd)
|
247 | 8cbf5379 | Filippos Giannakos | return -1; |
248 | 8cbf5379 | Filippos Giannakos | psd->flag = 0;
|
249 | 8cbf5379 | Filippos Giannakos | while (read(psd->fd, buf, buf_size) > 0); |
250 | 8cbf5379 | Filippos Giannakos | |
251 | 8cbf5379 | Filippos Giannakos | return 0; |
252 | 8cbf5379 | Filippos Giannakos | } |
253 | 8cbf5379 | Filippos Giannakos | |
254 | 8cbf5379 | Filippos Giannakos | /*
|
255 | 8cbf5379 | Filippos Giannakos | * To wait a signal, the posixfd peer must use select on the fd of its named
|
256 | 8cbf5379 | Filippos Giannakos | * pipe.
|
257 | 8cbf5379 | Filippos Giannakos | *
|
258 | 8cbf5379 | Filippos Giannakos | * When the peer wakes up from the select, if it wasn't waked up because of a
|
259 | 8cbf5379 | Filippos Giannakos | * timeout, it should read as much as it can from the named pipe to clean it and
|
260 | 8cbf5379 | Filippos Giannakos | * prepare it for the next select.
|
261 | 8cbf5379 | Filippos Giannakos | */
|
262 | 8cbf5379 | Filippos Giannakos | static int posixfd_wait_signal(struct xseg *xseg, void *sd, uint32_t usec_timeout) |
263 | 8cbf5379 | Filippos Giannakos | { |
264 | 8cbf5379 | Filippos Giannakos | int r;
|
265 | 8cbf5379 | Filippos Giannakos | struct timeval tv;
|
266 | 8cbf5379 | Filippos Giannakos | char buf[512]; |
267 | 8cbf5379 | Filippos Giannakos | int buf_size = 512; |
268 | 8cbf5379 | Filippos Giannakos | fd_set fds; |
269 | 8cbf5379 | Filippos Giannakos | |
270 | 8cbf5379 | Filippos Giannakos | struct posixfd_signal_desc *psd = (struct posixfd_signal_desc *)sd; |
271 | 8cbf5379 | Filippos Giannakos | if (!psd)
|
272 | 8cbf5379 | Filippos Giannakos | return -1; |
273 | 8cbf5379 | Filippos Giannakos | |
274 | 8cbf5379 | Filippos Giannakos | tv.tv_sec = usec_timeout / 1000000;
|
275 | 8cbf5379 | Filippos Giannakos | tv.tv_usec = usec_timeout - tv.tv_sec * 1000000;
|
276 | 8cbf5379 | Filippos Giannakos | |
277 | 8cbf5379 | Filippos Giannakos | FD_ZERO(&fds); |
278 | 8cbf5379 | Filippos Giannakos | FD_SET(psd->fd, &fds); |
279 | 8cbf5379 | Filippos Giannakos | |
280 | 8cbf5379 | Filippos Giannakos | r = select(psd->fd + 1, &fds, NULL, NULL, &tv); |
281 | 8cbf5379 | Filippos Giannakos | //XSEGLOG("Tv sec: %ld, tv_usec: %ld", tv.tv_sec, tv.tv_usec);
|
282 | 8cbf5379 | Filippos Giannakos | |
283 | 8cbf5379 | Filippos Giannakos | if (r < 0) { |
284 | 8cbf5379 | Filippos Giannakos | if (errno != EINTR) {
|
285 | 8cbf5379 | Filippos Giannakos | return -1; |
286 | 8cbf5379 | Filippos Giannakos | } else {
|
287 | 8cbf5379 | Filippos Giannakos | return 0; |
288 | 8cbf5379 | Filippos Giannakos | } |
289 | 8cbf5379 | Filippos Giannakos | } |
290 | 8cbf5379 | Filippos Giannakos | |
291 | 8cbf5379 | Filippos Giannakos | if (r != 0) { |
292 | 8cbf5379 | Filippos Giannakos | /* clean up pipe */
|
293 | 8cbf5379 | Filippos Giannakos | while (read(psd->fd, buf, buf_size) > 0); |
294 | 8cbf5379 | Filippos Giannakos | } |
295 | 8cbf5379 | Filippos Giannakos | |
296 | 8cbf5379 | Filippos Giannakos | return 0; |
297 | 8cbf5379 | Filippos Giannakos | } |
298 | 8cbf5379 | Filippos Giannakos | |
299 | 8cbf5379 | Filippos Giannakos | /*
|
300 | 8cbf5379 | Filippos Giannakos | * To signal a posixfd peer, we must:
|
301 | 8cbf5379 | Filippos Giannakos | *
|
302 | 8cbf5379 | Filippos Giannakos | * a) Check if the peer wants to be signaled.
|
303 | 8cbf5379 | Filippos Giannakos | * b) Open the named pipe, it provides.
|
304 | 8cbf5379 | Filippos Giannakos | * c) Write some data to the named pipe, so the peer's fd will be selectable for
|
305 | 8cbf5379 | Filippos Giannakos | * writing.
|
306 | 8cbf5379 | Filippos Giannakos | * d) Close the named pipe.
|
307 | 8cbf5379 | Filippos Giannakos | */
|
308 | 8cbf5379 | Filippos Giannakos | static int posixfd_signal(struct xseg *xseg, uint32_t portno) |
309 | 8cbf5379 | Filippos Giannakos | { |
310 | 8cbf5379 | Filippos Giannakos | int r, fd;
|
311 | 8cbf5379 | Filippos Giannakos | /* NULL terminated */
|
312 | 8cbf5379 | Filippos Giannakos | char filename[POSIXFD_DIR_LEN + POSIXFD_FILENAME_LEN + 1] = POSIXFD_DIR; |
313 | 8cbf5379 | Filippos Giannakos | |
314 | 8cbf5379 | Filippos Giannakos | struct posixfd_signal_desc *psd = __get_signal_desc(xseg, portno);
|
315 | 8cbf5379 | Filippos Giannakos | if (!psd)
|
316 | 8cbf5379 | Filippos Giannakos | return -1; |
317 | 8cbf5379 | Filippos Giannakos | |
318 | 8cbf5379 | Filippos Giannakos | if (!psd->flag) {
|
319 | 8cbf5379 | Filippos Giannakos | /* If the peer advises not to signal, we respect it. */
|
320 | 8cbf5379 | Filippos Giannakos | return 0; |
321 | 8cbf5379 | Filippos Giannakos | } |
322 | 8cbf5379 | Filippos Giannakos | __get_filename(psd, filename); |
323 | 8cbf5379 | Filippos Giannakos | |
324 | 8cbf5379 | Filippos Giannakos | fd = open(filename, O_WRONLY|O_NONBLOCK); |
325 | 8cbf5379 | Filippos Giannakos | if (fd < 0) { |
326 | 8cbf5379 | Filippos Giannakos | return -1; |
327 | 8cbf5379 | Filippos Giannakos | } |
328 | 8cbf5379 | Filippos Giannakos | r = write(fd, "a", 1); |
329 | 8cbf5379 | Filippos Giannakos | if (r < 0) { |
330 | 8cbf5379 | Filippos Giannakos | close(fd); |
331 | 8cbf5379 | Filippos Giannakos | return -1; |
332 | 8cbf5379 | Filippos Giannakos | } |
333 | 8cbf5379 | Filippos Giannakos | /* FIXME what here? */
|
334 | 8cbf5379 | Filippos Giannakos | r = close(fd); |
335 | 8cbf5379 | Filippos Giannakos | |
336 | 8cbf5379 | Filippos Giannakos | return 0; |
337 | 8cbf5379 | Filippos Giannakos | } |
338 | 8cbf5379 | Filippos Giannakos | |
339 | 8cbf5379 | Filippos Giannakos | static void *posixfd_malloc(uint64_t size) |
340 | 8cbf5379 | Filippos Giannakos | { |
341 | 8cbf5379 | Filippos Giannakos | return malloc((size_t)size);
|
342 | 8cbf5379 | Filippos Giannakos | } |
343 | 8cbf5379 | Filippos Giannakos | |
344 | 8cbf5379 | Filippos Giannakos | static void *posixfd_realloc(void *mem, uint64_t size) |
345 | 8cbf5379 | Filippos Giannakos | { |
346 | 8cbf5379 | Filippos Giannakos | return realloc(mem, (size_t)size);
|
347 | 8cbf5379 | Filippos Giannakos | } |
348 | 8cbf5379 | Filippos Giannakos | |
349 | 8cbf5379 | Filippos Giannakos | static void posixfd_mfree(void *mem) |
350 | 8cbf5379 | Filippos Giannakos | { |
351 | 8cbf5379 | Filippos Giannakos | free(mem); |
352 | 8cbf5379 | Filippos Giannakos | } |
353 | 8cbf5379 | Filippos Giannakos | |
354 | 8cbf5379 | Filippos Giannakos | /* taken from user/hash.c */
|
355 | 8cbf5379 | Filippos Giannakos | static char get_hex(unsigned int h) |
356 | 8cbf5379 | Filippos Giannakos | { |
357 | 8cbf5379 | Filippos Giannakos | switch (h)
|
358 | 8cbf5379 | Filippos Giannakos | { |
359 | 8cbf5379 | Filippos Giannakos | case 0: |
360 | 8cbf5379 | Filippos Giannakos | case 1: |
361 | 8cbf5379 | Filippos Giannakos | case 2: |
362 | 8cbf5379 | Filippos Giannakos | case 3: |
363 | 8cbf5379 | Filippos Giannakos | case 4: |
364 | 8cbf5379 | Filippos Giannakos | case 5: |
365 | 8cbf5379 | Filippos Giannakos | case 6: |
366 | 8cbf5379 | Filippos Giannakos | case 7: |
367 | 8cbf5379 | Filippos Giannakos | case 8: |
368 | 8cbf5379 | Filippos Giannakos | case 9: |
369 | 8cbf5379 | Filippos Giannakos | return h + '0'; |
370 | 8cbf5379 | Filippos Giannakos | case 10: |
371 | 8cbf5379 | Filippos Giannakos | return 'a'; |
372 | 8cbf5379 | Filippos Giannakos | case 11: |
373 | 8cbf5379 | Filippos Giannakos | return 'b'; |
374 | 8cbf5379 | Filippos Giannakos | case 12: |
375 | 8cbf5379 | Filippos Giannakos | return 'c'; |
376 | 8cbf5379 | Filippos Giannakos | case 13: |
377 | 8cbf5379 | Filippos Giannakos | return 'd'; |
378 | 8cbf5379 | Filippos Giannakos | case 14: |
379 | 8cbf5379 | Filippos Giannakos | return 'e'; |
380 | 8cbf5379 | Filippos Giannakos | case 15: |
381 | 8cbf5379 | Filippos Giannakos | return 'f'; |
382 | 8cbf5379 | Filippos Giannakos | } |
383 | 8cbf5379 | Filippos Giannakos | /* not reachable */
|
384 | 8cbf5379 | Filippos Giannakos | return '0'; |
385 | 8cbf5379 | Filippos Giannakos | } |
386 | 8cbf5379 | Filippos Giannakos | |
387 | 8cbf5379 | Filippos Giannakos | static void hexlify(unsigned char *data, long datalen, char *hex) |
388 | 8cbf5379 | Filippos Giannakos | { |
389 | 8cbf5379 | Filippos Giannakos | long i;
|
390 | 8cbf5379 | Filippos Giannakos | for (i=0; i<datalen; i++){ |
391 | 8cbf5379 | Filippos Giannakos | hex[2*i] = get_hex((data[i] & 0xF0) >> 4); |
392 | 8cbf5379 | Filippos Giannakos | hex[2*i + 1] = get_hex(data[i] & 0x0F); |
393 | 8cbf5379 | Filippos Giannakos | } |
394 | 8cbf5379 | Filippos Giannakos | } |
395 | 8cbf5379 | Filippos Giannakos | |
396 | 8cbf5379 | Filippos Giannakos | |
397 | 8cbf5379 | Filippos Giannakos | |
398 | 8cbf5379 | Filippos Giannakos | int posixfd_init_signal_desc(struct xseg *xseg, void *sd) |
399 | 8cbf5379 | Filippos Giannakos | { |
400 | 8cbf5379 | Filippos Giannakos | struct posixfd_signal_desc *psd = sd;
|
401 | 8cbf5379 | Filippos Giannakos | if (!psd)
|
402 | 8cbf5379 | Filippos Giannakos | return -1; |
403 | 8cbf5379 | Filippos Giannakos | psd->flag = 0;
|
404 | 8cbf5379 | Filippos Giannakos | psd->signal_file[0] = 0; |
405 | 8cbf5379 | Filippos Giannakos | hexlify(&sd, POSIXFD_FILENAME_LEN, psd->signal_file); |
406 | 8cbf5379 | Filippos Giannakos | psd->fd = -1;
|
407 | 8cbf5379 | Filippos Giannakos | |
408 | 8cbf5379 | Filippos Giannakos | return 0; |
409 | 8cbf5379 | Filippos Giannakos | } |
410 | 8cbf5379 | Filippos Giannakos | |
411 | 8cbf5379 | Filippos Giannakos | void posixfd_quit_signal_desc(struct xseg *xseg, void *sd) |
412 | 8cbf5379 | Filippos Giannakos | { |
413 | 8cbf5379 | Filippos Giannakos | return;
|
414 | 8cbf5379 | Filippos Giannakos | } |
415 | 8cbf5379 | Filippos Giannakos | |
416 | 8cbf5379 | Filippos Giannakos | void * posixfd_alloc_data(struct xseg *xseg) |
417 | 8cbf5379 | Filippos Giannakos | { |
418 | 8cbf5379 | Filippos Giannakos | struct xobject_h *sd_h = xseg_get_objh(xseg, MAGIC_POSIX_SD,
|
419 | 8cbf5379 | Filippos Giannakos | sizeof(struct posixfd_signal_desc)); |
420 | 8cbf5379 | Filippos Giannakos | return sd_h;
|
421 | 8cbf5379 | Filippos Giannakos | } |
422 | 8cbf5379 | Filippos Giannakos | |
423 | 8cbf5379 | Filippos Giannakos | void posixfd_free_data(struct xseg *xseg, void *data) |
424 | 8cbf5379 | Filippos Giannakos | { |
425 | 8cbf5379 | Filippos Giannakos | if (data)
|
426 | 8cbf5379 | Filippos Giannakos | xseg_put_objh(xseg, (struct xobject_h *)data);
|
427 | 8cbf5379 | Filippos Giannakos | } |
428 | 8cbf5379 | Filippos Giannakos | |
429 | 8cbf5379 | Filippos Giannakos | void *posixfd_alloc_signal_desc(struct xseg *xseg, void *data) |
430 | 8cbf5379 | Filippos Giannakos | { |
431 | 8cbf5379 | Filippos Giannakos | struct xobject_h *sd_h = (struct xobject_h *) data; |
432 | 8cbf5379 | Filippos Giannakos | if (!sd_h)
|
433 | 8cbf5379 | Filippos Giannakos | return NULL; |
434 | 8cbf5379 | Filippos Giannakos | struct posixfd_signal_desc *psd = xobj_get_obj(sd_h, X_ALLOC);
|
435 | 8cbf5379 | Filippos Giannakos | if (!psd)
|
436 | 8cbf5379 | Filippos Giannakos | return NULL; |
437 | 8cbf5379 | Filippos Giannakos | return psd;
|
438 | 8cbf5379 | Filippos Giannakos | |
439 | 8cbf5379 | Filippos Giannakos | } |
440 | 8cbf5379 | Filippos Giannakos | |
441 | 8cbf5379 | Filippos Giannakos | void posixfd_free_signal_desc(struct xseg *xseg, void *data, void *sd) |
442 | 8cbf5379 | Filippos Giannakos | { |
443 | 8cbf5379 | Filippos Giannakos | struct xobject_h *sd_h = (struct xobject_h *) data; |
444 | 8cbf5379 | Filippos Giannakos | if (!sd_h)
|
445 | 8cbf5379 | Filippos Giannakos | return;
|
446 | 8cbf5379 | Filippos Giannakos | if (sd)
|
447 | 8cbf5379 | Filippos Giannakos | xobj_put_obj(sd_h, sd); |
448 | 8cbf5379 | Filippos Giannakos | return;
|
449 | 8cbf5379 | Filippos Giannakos | } |
450 | 8cbf5379 | Filippos Giannakos | |
451 | 8cbf5379 | Filippos Giannakos | static struct xseg_type xseg_posixfd = { |
452 | 8cbf5379 | Filippos Giannakos | /* xseg_operations */
|
453 | 8cbf5379 | Filippos Giannakos | { |
454 | 8cbf5379 | Filippos Giannakos | .mfree = posixfd_mfree, |
455 | 8cbf5379 | Filippos Giannakos | .allocate = posixfd_allocate, |
456 | 8cbf5379 | Filippos Giannakos | .deallocate = posixfd_deallocate, |
457 | 8cbf5379 | Filippos Giannakos | .map = posixfd_map, |
458 | 8cbf5379 | Filippos Giannakos | .unmap = posixfd_unmap, |
459 | 8cbf5379 | Filippos Giannakos | }, |
460 | 8cbf5379 | Filippos Giannakos | /* name */
|
461 | 8cbf5379 | Filippos Giannakos | "posixfd"
|
462 | 8cbf5379 | Filippos Giannakos | }; |
463 | 8cbf5379 | Filippos Giannakos | |
464 | 8cbf5379 | Filippos Giannakos | static struct xseg_peer xseg_peer_posixfd = { |
465 | 8cbf5379 | Filippos Giannakos | /* xseg_peer_operations */
|
466 | 8cbf5379 | Filippos Giannakos | { |
467 | 8cbf5379 | Filippos Giannakos | .init_signal_desc = posixfd_init_signal_desc, |
468 | 8cbf5379 | Filippos Giannakos | .quit_signal_desc = posixfd_quit_signal_desc, |
469 | 8cbf5379 | Filippos Giannakos | .alloc_data = posixfd_alloc_data, |
470 | 8cbf5379 | Filippos Giannakos | .free_data = posixfd_free_data, |
471 | 8cbf5379 | Filippos Giannakos | .alloc_signal_desc = posixfd_alloc_signal_desc, |
472 | 8cbf5379 | Filippos Giannakos | .free_signal_desc = posixfd_free_signal_desc, |
473 | 8cbf5379 | Filippos Giannakos | .local_signal_init = posixfd_local_signal_init, |
474 | 8cbf5379 | Filippos Giannakos | .local_signal_quit = posixfd_local_signal_quit, |
475 | 8cbf5379 | Filippos Giannakos | .remote_signal_init = posixfd_remote_signal_init, |
476 | 8cbf5379 | Filippos Giannakos | .remote_signal_quit = posixfd_remote_signal_quit, |
477 | 8cbf5379 | Filippos Giannakos | .prepare_wait = posixfd_prepare_wait, |
478 | 8cbf5379 | Filippos Giannakos | .cancel_wait = posixfd_cancel_wait, |
479 | 8cbf5379 | Filippos Giannakos | .wait_signal = posixfd_wait_signal, |
480 | 8cbf5379 | Filippos Giannakos | .signal = posixfd_signal, |
481 | 8cbf5379 | Filippos Giannakos | .malloc = posixfd_malloc, |
482 | 8cbf5379 | Filippos Giannakos | .realloc = posixfd_realloc, |
483 | 8cbf5379 | Filippos Giannakos | .mfree = posixfd_mfree, |
484 | 8cbf5379 | Filippos Giannakos | }, |
485 | 8cbf5379 | Filippos Giannakos | /* name */
|
486 | 8cbf5379 | Filippos Giannakos | "posixfd"
|
487 | 8cbf5379 | Filippos Giannakos | }; |
488 | 8cbf5379 | Filippos Giannakos | |
489 | 8cbf5379 | Filippos Giannakos | void xseg_posixfd_init(void) |
490 | 8cbf5379 | Filippos Giannakos | { |
491 | 8cbf5379 | Filippos Giannakos | xseg_register_type(&xseg_posixfd); |
492 | 8cbf5379 | Filippos Giannakos | xseg_register_peer(&xseg_peer_posixfd); |
493 | 8cbf5379 | Filippos Giannakos | } |