/src/openvswitch/lib/latch-unix.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (c) 2013 Nicira, Inc. |
3 | | * |
4 | | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | | * you may not use this file except in compliance with the License. |
6 | | * 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 <config.h> |
18 | | |
19 | | #include "latch.h" |
20 | | #include <errno.h> |
21 | | #include <poll.h> |
22 | | #include <unistd.h> |
23 | | #include "openvswitch/poll-loop.h" |
24 | | #include "socket-util.h" |
25 | | |
26 | | /* Initializes 'latch' as initially unset. */ |
27 | | void |
28 | | latch_init(struct latch *latch) |
29 | 0 | { |
30 | 0 | xpipe_nonblocking(latch->fds); |
31 | 0 | } |
32 | | |
33 | | /* Destroys 'latch'. */ |
34 | | void |
35 | | latch_destroy(struct latch *latch) |
36 | 0 | { |
37 | 0 | close(latch->fds[0]); |
38 | 0 | close(latch->fds[1]); |
39 | 0 | } |
40 | | |
41 | | /* Resets 'latch' to the unset state. Returns true if 'latch' was previously |
42 | | * set, false otherwise. */ |
43 | | bool |
44 | | latch_poll(struct latch *latch) |
45 | 0 | { |
46 | 0 | char latch_buffer[16]; |
47 | 0 | bool result = false; |
48 | 0 | int ret; |
49 | |
|
50 | 0 | do { |
51 | 0 | ret = read(latch->fds[0], &latch_buffer, sizeof latch_buffer); |
52 | 0 | result |= ret > 0; |
53 | | /* Repeat as long as read() reads a full buffer. */ |
54 | 0 | } while (ret == sizeof latch_buffer); |
55 | |
|
56 | 0 | return result; |
57 | 0 | } |
58 | | |
59 | | /* Sets 'latch'. |
60 | | * |
61 | | * Calls are not additive: a single latch_poll() clears out any number of |
62 | | * latch_set(). */ |
63 | | void |
64 | | latch_set(struct latch *latch) |
65 | 0 | { |
66 | 0 | ignore(write(latch->fds[1], "", 1)); |
67 | 0 | } |
68 | | |
69 | | /* Returns true if 'latch' is set, false otherwise. Does not reset 'latch' |
70 | | * to the unset state. */ |
71 | | bool |
72 | | latch_is_set(const struct latch *latch) |
73 | 0 | { |
74 | 0 | struct pollfd pfd; |
75 | 0 | int retval; |
76 | |
|
77 | 0 | pfd.fd = latch->fds[0]; |
78 | 0 | pfd.events = POLLIN; |
79 | 0 | do { |
80 | 0 | retval = poll(&pfd, 1, 0); |
81 | 0 | } while (retval < 0 && errno == EINTR); |
82 | |
|
83 | 0 | return pfd.revents & POLLIN; |
84 | 0 | } |
85 | | |
86 | | /* Causes the next poll_block() to wake up when 'latch' is set. |
87 | | * |
88 | | * ('where' is used in debug logging. Commonly one would use latch_wait() to |
89 | | * automatically provide the caller's source file and line number for |
90 | | * 'where'.) */ |
91 | | void |
92 | | latch_wait_at(const struct latch *latch, const char *where) |
93 | 0 | { |
94 | 0 | poll_fd_wait_at(latch->fds[0], POLLIN, where); |
95 | 0 | } |