From aad84c8ef17b0b5237904dd297487db9aae1f539 Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Mon, 15 Jul 2013 12:20:23 -0700 Subject: [PATCH 1/1] latch: New module for a thread-safe, signal-safe, pollable doorbell. Signed-off-by: Ben Pfaff Acked-by: Ed Maste --- lib/automake.mk | 2 ++ lib/latch.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++++ lib/latch.h | 42 +++++++++++++++++++++++++ 3 files changed, 127 insertions(+) create mode 100644 lib/latch.c create mode 100644 lib/latch.h diff --git a/lib/automake.mk b/lib/automake.mk index 280fc8beb..6b0972bd5 100644 --- a/lib/automake.mk +++ b/lib/automake.mk @@ -71,6 +71,8 @@ lib_libopenvswitch_a_SOURCES = \ lib/jsonrpc.h \ lib/lacp.c \ lib/lacp.h \ + lib/latch.c \ + lib/latch.h \ lib/learn.c \ lib/learn.h \ lib/learning-switch.c \ diff --git a/lib/latch.c b/lib/latch.c new file mode 100644 index 000000000..9b130062b --- /dev/null +++ b/lib/latch.c @@ -0,0 +1,83 @@ +/* + * 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 + +#include "latch.h" +#include +#include +#include +#include "poll-loop.h" +#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) +{ + char buffer[_POSIX_PIPE_BUF]; + + return read(latch->fds[0], buffer, sizeof buffer) > 0; +} + +/* 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; +} + +/* Causes the next poll_block() to wake up when 'latch' is set. */ +void +(latch_wait)(const struct latch *latch, const char *where) +{ + (poll_fd_wait)(latch->fds[0], POLLIN, where); +} diff --git a/lib/latch.h b/lib/latch.h new file mode 100644 index 000000000..08f45b117 --- /dev/null +++ b/lib/latch.h @@ -0,0 +1,42 @@ +/* + * 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. + */ + +#ifndef LATCH_H +#define LATCH_H 1 + +/* A thread-safe, signal-safe, pollable doorbell. + * + * This is a thin wrapper around a pipe that allows threads to notify each + * other that an event has occurred in a signal-safe way */ + +#include +#include "util.h" + +struct latch { + int fds[2]; +}; + +void latch_init(struct latch *); +void latch_destroy(struct latch *); + +bool latch_poll(struct latch *); +void latch_set(struct latch *); + +bool latch_is_set(const struct latch *); +void latch_wait(const struct latch *, const char *where); +#define latch_wait(latch) latch_wait(latch, SOURCE_LOCATOR) + +#endif /* latch.h */ -- 2.43.0