aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMilan Lenco <milan.lenco@pantheon.tech>2017-10-12 14:19:31 +0200
committerDamjan Marion <dmarion.lists@gmail.com>2017-10-12 18:18:54 +0000
commit0a47c99aed8124d2f4c3be0d90e961b82a6b9914 (patch)
tree0a1d68f9c45f645f8136bae84a1d6599987adde2
parent5f1231c5c2ba8483d1b723762d7001ee48956205 (diff)
libmemif: Add memif_cancel_poll_event() + bug fixing.
Change-Id: I27d6bf93216f1f639f01fad730506afdc7115e46 Signed-off-by: Milan Lenco <milan.lenco@pantheon.tech>
-rw-r--r--extras/libmemif/Makefile.am2
-rw-r--r--extras/libmemif/src/libmemif.h16
-rw-r--r--extras/libmemif/src/main.c90
3 files changed, 78 insertions, 30 deletions
diff --git a/extras/libmemif/Makefile.am b/extras/libmemif/Makefile.am
index 1ff7e7e5a5a..82280a401ae 100644
--- a/extras/libmemif/Makefile.am
+++ b/extras/libmemif/Makefile.am
@@ -82,7 +82,7 @@ noinst_PROGRAMS = icmpr icmpr-epoll icmpr-mt
check_PROGRAMS = unit_test
-include_HEADERS = src/libmemif.h
+include_HEADERS = src/libmemif.h src/memif.h
lib_LTLIBRARIES = libmemif.la
diff --git a/extras/libmemif/src/libmemif.h b/extras/libmemif/src/libmemif.h
index a2d1a5e28b5..da48edd4dee 100644
--- a/extras/libmemif/src/libmemif.h
+++ b/extras/libmemif/src/libmemif.h
@@ -72,6 +72,7 @@ typedef enum
MEMIF_ERR_DISCONNECT, /*!< disconenct received */
MEMIF_ERR_DISCONNECTED, /*!< peer interface disconnected */
MEMIF_ERR_UNKNOWN_MSG, /*!< unknown message type */
+ MEMIF_ERR_POLL_CANCEL, /*!< memif_poll_event() was cancelled */
} memif_err_t;
/**
@@ -438,6 +439,21 @@ int memif_rx_burst (memif_conn_handle_t conn, uint16_t qid,
\return memif_err_t
*/
int memif_poll_event (int timeout);
+
+/** \brief Send signal to stop concurrently running memif_poll_event().
+
+ The function, however, does not wait for memif_poll_event() to stop.
+ memif_poll_event() may still return simply because an event has occured
+ or the timeout has elapsed, but if called repeatedly in an infinite loop,
+ a canceled memif_poll_event() is guaranted to return MEMIF_ERR_POLL_CANCEL
+ in the shortest possible time.
+ This feature was not available in the first release.
+ Use macro MEMIF_HAVE_CANCEL_POLL_EVENT to check if the feature is present.
+
+ \return memif_err_t
+*/
+#define MEMIF_HAVE_CANCEL_POLL_EVENT 1
+int memif_cancel_poll_event ();
/** @} */
#endif /* _LIBMEMIF_H_ */
diff --git a/extras/libmemif/src/main.c b/extras/libmemif/src/main.c
index 8cc0d66a75b..b1176c6b7c9 100644
--- a/extras/libmemif/src/main.c
+++ b/extras/libmemif/src/main.c
@@ -54,17 +54,18 @@
/* private structs and functions */
#include <memif_private.h>
-#define ERRLIST_LEN 36
+#define ERRLIST_LEN 37
#define MAX_ERRBUF_LEN 256
#if __x86_x64__
#define MEMIF_MEMORY_BARRIER() __builtin_ia32_sfence ()
#else
-#define MEMIF_MEORY_BARRIER() __sync_synchronize ()
+#define MEMIF_MEMORY_BARRIER() __sync_synchronize ()
#endif /* __x86_x64__ */
libmemif_main_t libmemif_main;
int memif_epfd;
+int poll_cancel_fd = -1;
static char memif_buf[MAX_ERRBUF_LEN];
@@ -139,7 +140,9 @@ const char *memif_errlist[ERRLIST_LEN] = { /* MEMIF_ERR_SUCCESS */
/* MEMIF_ERR_DISCONNECTED */
"Interface is disconnected.",
/* MEMIF_ERR_UNKNOWN_MSG */
- "Unknown message type received on control channel. (internal error)"
+ "Unknown message type received on control channel. (internal error)",
+ /* MEMIF_ERR_POLL_CANCEL */
+ "Memif event polling was canceled."
};
#define MEMIF_ERR_UNDEFINED "undefined error"
@@ -423,6 +426,13 @@ memif_init (memif_control_fd_update_t * on_control_fd_update, char *app_name)
{
memif_epfd = epoll_create (1);
memif_control_fd_update_register (memif_control_fd_update);
+ if ((poll_cancel_fd = eventfd (0, EFD_NONBLOCK)) < 0)
+ {
+ err = errno;
+ DBG ("eventfd: %s", strerror (err));
+ return memif_syscall_error_handler (err);
+ }
+ lm->control_fd_update (poll_cancel_fd, MEMIF_FD_EVENT_READ);
DBG ("libmemif event polling initialized");
}
@@ -925,6 +935,8 @@ memif_poll_event (int timeout)
int en = 0, err = MEMIF_ERR_SUCCESS, i = 0; /* 0 */
uint16_t num;
uint32_t events = 0;
+ uint64_t counter = 0;
+ ssize_t r = 0;
memset (&evt, 0, sizeof (evt));
evt.events = EPOLLIN | EPOLLOUT;
sigset_t sigset;
@@ -932,11 +944,17 @@ memif_poll_event (int timeout)
en = epoll_pwait (memif_epfd, &evt, 1, timeout, &sigset);
if (en < 0)
{
- DBG ("epoll_pwait: %s", strerror (errno));
- return -1;
+ err = errno;
+ DBG ("epoll_pwait: %s", strerror (err));
+ return memif_syscall_error_handler (err);
}
if (en > 0)
{
+ if (evt.data.fd == poll_cancel_fd)
+ {
+ r = read (evt.data.fd, &counter, sizeof (counter));
+ return MEMIF_ERR_POLL_CANCEL;
+ }
if (evt.events & EPOLLIN)
events |= MEMIF_FD_EVENT_READ;
if (evt.events & EPOLLOUT)
@@ -949,6 +967,21 @@ memif_poll_event (int timeout)
return 0;
}
+int
+memif_cancel_poll_event ()
+{
+ uint64_t counter = 1;
+ ssize_t w = 0;
+
+ if (poll_cancel_fd == -1)
+ return 0;
+ w = write (poll_cancel_fd, &counter, sizeof (counter));
+ if (w < sizeof (counter))
+ return MEMIF_ERR_INT_WRITE;
+
+ return 0;
+}
+
static void
memif_msg_queue_free (memif_msg_queue_elt_t ** e)
{
@@ -1536,7 +1569,7 @@ memif_buffer_free (memif_conn_handle_t conn, uint16_t qid,
*count_out += 1;
mq->alloc_bufs -= chain_buf0;
}
- MEMIF_MEORY_BARRIER ();
+ MEMIF_MEMORY_BARRIER ();
ring->tail = tail;
DBG ("tail: %u", ring->tail);
@@ -1745,7 +1778,7 @@ memif_tx_burst (memif_conn_handle_t conn, uint16_t qid,
*tx += chain_buf0;
curr_buf++;
}
- MEMIF_MEORY_BARRIER ();
+ MEMIF_MEMORY_BARRIER ();
ring->head = head;
mq->alloc_bufs -= *tx;
@@ -1941,40 +1974,36 @@ memif_get_details (memif_conn_handle_t conn, memif_details_t * md,
l0 = 0;
l1 = strlen ((char *) c->args.interface_name);
- if (l0 + l1 <= buflen)
+ if (l0 + l1 < buflen)
{
- md->if_name = strncpy (buf + l0, (char *) c->args.interface_name, l1);
- md->if_name[l0 + l1] = '\0';
+ md->if_name = strcpy (buf + l0, (char *) c->args.interface_name);
l0 += l1 + 1;
}
else
err = MEMIF_ERR_NOBUF_DET;
l1 = strlen ((char *) c->args.instance_name);
- if (l0 + l1 <= buflen)
+ if (l0 + l1 < buflen)
{
- md->inst_name = strncpy (buf + l0, (char *) c->args.instance_name, l1);
- md->inst_name[l0 + l1] = '\0';
+ md->inst_name = strcpy (buf + l0, (char *) c->args.instance_name);
l0 += l1 + 1;
}
else
err = MEMIF_ERR_NOBUF_DET;
l1 = strlen ((char *) c->remote_if_name);
- if (l0 + l1 <= buflen)
+ if (l0 + l1 < buflen)
{
- md->remote_if_name = strncpy (buf + l0, (char *) c->remote_if_name, l1);
- md->remote_if_name[l0 + l1] = '\0';
+ md->remote_if_name = strcpy (buf + l0, (char *) c->remote_if_name);
l0 += l1 + 1;
}
else
err = MEMIF_ERR_NOBUF_DET;
l1 = strlen ((char *) c->remote_name);
- if (l0 + l1 <= buflen)
+ if (l0 + l1 < buflen)
{
- md->remote_inst_name = strncpy (buf + l0, (char *) c->remote_name, l1);
- md->remote_inst_name[l0 + l1] = '\0';
+ md->remote_inst_name = strcpy (buf + l0, (char *) c->remote_name);
l0 += l1 + 1;
}
else
@@ -1985,22 +2014,23 @@ memif_get_details (memif_conn_handle_t conn, memif_details_t * md,
if (c->args.secret)
{
l1 = strlen ((char *) c->args.secret);
- md->secret = strncpy (buf + l0, (char *) c->args.secret, l1);
- md->secret[l0 + l1] = '\0';
- l0 += l1 + 1;
+ if (l0 + l1 < buflen)
+ {
+ md->secret = strcpy (buf + l0, (char *) c->args.secret);
+ l0 += l1 + 1;
+ }
+ else
+ err = MEMIF_ERR_NOBUF_DET;
}
- else
- err = MEMIF_ERR_NOBUF_DET;
md->role = (c->args.is_master) ? 0 : 1;
md->mode = c->args.mode;
l1 = strlen ((char *) c->args.socket_filename);
- if (l0 + l1 <= buflen)
+ if (l0 + l1 < buflen)
{
md->socket_filename =
- strncpy (buf + l0, (char *) c->args.socket_filename, l1);
- md->socket_filename[l0 + l1] = '\0';
+ strcpy (buf + l0, (char *) c->args.socket_filename);
l0 += l1 + 1;
}
else
@@ -2014,7 +2044,7 @@ memif_get_details (memif_conn_handle_t conn, memif_details_t * md,
if (l0 + l1 <= buflen)
{
md->rx_queues = (memif_queue_details_t *) buf + l0;
- l0 = l1 + 1;
+ l0 += l1;
}
else
err = MEMIF_ERR_NOBUF_DET;
@@ -2034,7 +2064,7 @@ memif_get_details (memif_conn_handle_t conn, memif_details_t * md,
if (l0 + l1 <= buflen)
{
md->tx_queues = (memif_queue_details_t *) buf + l0;
- l0 = l1 + 1;
+ l0 += l1;
}
else
err = MEMIF_ERR_NOBUF_DET;
@@ -2090,6 +2120,8 @@ memif_cleanup ()
if (lm->pending_list)
free (lm->pending_list);
lm->pending_list = NULL;
+ if (poll_cancel_fd != -1)
+ close (poll_cancel_fd);
return MEMIF_ERR_SUCCESS; /* 0 */
}