2013-07-15 12:20:23 -07:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2013 Nicira, Inc.
|
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at:
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
|
|
|
#include "latch.h"
|
|
|
|
#include <errno.h>
|
|
|
|
#include <poll.h>
|
|
|
|
#include <unistd.h>
|
2017-11-03 13:53:53 +08:00
|
|
|
#include "openvswitch/poll-loop.h"
|
2013-07-15 12:20:23 -07:00
|
|
|
#include "socket-util.h"
|
|
|
|
|
|
|
|
/* Initializes 'latch' as initially unset. */
|
|
|
|
void
|
|
|
|
latch_init(struct latch *latch)
|
|
|
|
{
|
|
|
|
xpipe_nonblocking(latch->fds);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Destroys 'latch'. */
|
|
|
|
void
|
|
|
|
latch_destroy(struct latch *latch)
|
|
|
|
{
|
|
|
|
close(latch->fds[0]);
|
|
|
|
close(latch->fds[1]);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Resets 'latch' to the unset state. Returns true if 'latch' was previously
|
|
|
|
* set, false otherwise. */
|
|
|
|
bool
|
|
|
|
latch_poll(struct latch *latch)
|
|
|
|
{
|
2021-07-15 16:28:12 +01:00
|
|
|
char latch_buffer[16];
|
|
|
|
bool result = false;
|
|
|
|
int ret;
|
2013-07-15 12:20:23 -07:00
|
|
|
|
2021-07-15 16:28:12 +01:00
|
|
|
do {
|
|
|
|
ret = read(latch->fds[0], &latch_buffer, sizeof latch_buffer);
|
|
|
|
result |= ret > 0;
|
|
|
|
/* Repeat as long as read() reads a full buffer. */
|
|
|
|
} while (ret == sizeof latch_buffer);
|
|
|
|
|
|
|
|
return result;
|
2013-07-15 12:20:23 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Sets 'latch'.
|
|
|
|
*
|
|
|
|
* Calls are not additive: a single latch_poll() clears out any number of
|
|
|
|
* latch_set(). */
|
|
|
|
void
|
|
|
|
latch_set(struct latch *latch)
|
|
|
|
{
|
|
|
|
ignore(write(latch->fds[1], "", 1));
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Returns true if 'latch' is set, false otherwise. Does not reset 'latch'
|
|
|
|
* to the unset state. */
|
|
|
|
bool
|
|
|
|
latch_is_set(const struct latch *latch)
|
|
|
|
{
|
|
|
|
struct pollfd pfd;
|
|
|
|
int retval;
|
|
|
|
|
|
|
|
pfd.fd = latch->fds[0];
|
|
|
|
pfd.events = POLLIN;
|
|
|
|
do {
|
|
|
|
retval = poll(&pfd, 1, 0);
|
|
|
|
} while (retval < 0 && errno == EINTR);
|
|
|
|
|
|
|
|
return pfd.revents & POLLIN;
|
|
|
|
}
|
|
|
|
|
2013-07-29 15:24:45 -07:00
|
|
|
/* Causes the next poll_block() to wake up when 'latch' is set.
|
|
|
|
*
|
|
|
|
* ('where' is used in debug logging. Commonly one would use latch_wait() to
|
|
|
|
* automatically provide the caller's source file and line number for
|
|
|
|
* 'where'.) */
|
2013-07-15 12:20:23 -07:00
|
|
|
void
|
2013-07-29 15:24:45 -07:00
|
|
|
latch_wait_at(const struct latch *latch, const char *where)
|
2013-07-15 12:20:23 -07:00
|
|
|
{
|
poll-loop: Create Windows event handles for sockets automatically.
We currently have a poll_fd_wait_event(fd, wevent, events) function that
is used at places common to Windows and Linux where we have to wait on
sockets. On Linux, 'wevent' is always set as zero. On Windows, for sockets,
when we send both 'fd' and 'wevent', we associate them with each other for
'events' and then wait on 'wevent'. Also on Windows, when we only send 'wevent'
to this function, we would simply wait for all events for that 'wevent'.
There is a disadvantage with this approach.
* Windows clients need to create a 'wevent' and then pass it along. This
means that at a lot of places where we create sockets, we also are forced
to create a 'wevent'.
With this commit, we pass the responsibility of creating a 'wevent' to
poll_fd_wait() in case of sockets. That way, a client using poll_fd_wait()
is only concerned about sockets and not about 'wevents'. There is a potential
disadvantage with this change in that we create events more often and that
may have a performance penalty. If that turns out to be the case, we will
eventually need to create a pool of wevents that can be re-used.
In Windows, there are cases where we want to wait on a event (not
associated with any sockets) and then control it using functions
like SetEvent() etc. For that purpose, introduce a new function
poll_wevent_wait(). For this function, the client needs to create a event
and then pass it along as an argument.
Signed-off-by: Gurucharan Shetty <gshetty@nicira.com>
Acked-By: Ben Pfaff <blp@nicira.com>
2014-06-27 13:30:49 -07:00
|
|
|
poll_fd_wait_at(latch->fds[0], POLLIN, where);
|
2013-07-15 12:20:23 -07:00
|
|
|
}
|