summaryrefslogtreecommitdiffstats
path: root/tests/lib
diff options
context:
space:
mode:
authorDavid Lamparter <equinox@opensourcerouting.org>2015-05-25 06:36:10 +0200
committerDavid Lamparter <equinox@diac24.net>2019-04-18 12:44:29 +0200
commit440d5faa3a328e226435785afe7793251746175f (patch)
tree365d7c2f8c5378ea8b213b2e4b5d2dfe8196c0e1 /tests/lib
parentlib: add cmpxchg_strong to frratomic.h (diff)
downloadfrr-440d5faa3a328e226435785afe7793251746175f.tar.xz
frr-440d5faa3a328e226435785afe7793251746175f.zip
lib: add "seqlock" wait/broadcast primitive
Manually tested rather extensively in addition to included unit tests, should work as intended. NB: The OpenBSD futex() code is "future"; it's not actually in OpenBSD (yet?) and thus untested. Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
Diffstat (limited to 'tests/lib')
-rw-r--r--tests/lib/test_seqlock.c122
1 files changed, 122 insertions, 0 deletions
diff --git a/tests/lib/test_seqlock.c b/tests/lib/test_seqlock.c
new file mode 100644
index 000000000..6b2b9ed8a
--- /dev/null
+++ b/tests/lib/test_seqlock.c
@@ -0,0 +1,122 @@
+/*
+ * basic test for seqlock
+ *
+ * Copyright (C) 2015 David Lamparter
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <string.h>
+#include <unistd.h>
+#include <assert.h>
+#include <sys/uio.h>
+
+#include "monotime.h"
+#include "seqlock.h"
+
+static struct seqlock sqlo;
+static pthread_t thr1;
+static struct timeval start;
+
+static void writestr(const char *str)
+{
+ struct iovec iov[2];
+ char buf[32];
+ int64_t usec = monotime_since(&start, NULL);
+
+ snprintf(buf, sizeof(buf), "[%02"PRId64"] ", usec / 100000);
+
+ iov[0].iov_base = buf;
+ iov[0].iov_len = strlen(buf);
+ iov[1].iov_base = (char *)str;
+ iov[1].iov_len = strlen(str);
+ writev(1, iov, 2);
+}
+
+static void *thr1func(void *arg)
+{
+ assert(!seqlock_held(&sqlo));
+ assert(seqlock_check(&sqlo, 1));
+ seqlock_wait(&sqlo, 1);
+ writestr("thr1 (unheld)\n");
+
+ sleep(2);
+
+ assert(seqlock_held(&sqlo));
+ assert(seqlock_check(&sqlo, 1));
+ seqlock_wait(&sqlo, 1);
+ writestr("thr1 @1\n");
+
+ seqlock_wait(&sqlo, 3);
+ writestr("thr1 @3\n");
+
+ seqlock_wait(&sqlo, 5);
+ writestr("thr1 @5\n");
+
+ seqlock_wait(&sqlo, 7);
+ writestr("thr1 @7\n");
+
+ seqlock_wait(&sqlo, 9);
+ writestr("thr1 @9\n");
+
+ seqlock_wait(&sqlo, 11);
+ writestr("thr1 @11\n");
+ return NULL;
+}
+
+int main(int argc, char **argv)
+{
+ monotime(&start);
+
+ seqlock_init(&sqlo);
+
+ assert(!seqlock_held(&sqlo));
+ seqlock_acquire_val(&sqlo, 1);
+ assert(seqlock_held(&sqlo));
+
+ assert(seqlock_cur(&sqlo) == 1);
+ assert(seqlock_bump(&sqlo) == 1);
+ assert(seqlock_cur(&sqlo) == 3);
+ assert(seqlock_bump(&sqlo) == 3);
+ assert(seqlock_bump(&sqlo) == 5);
+ assert(seqlock_bump(&sqlo) == 7);
+ assert(seqlock_cur(&sqlo) == 9);
+
+ assert(seqlock_held(&sqlo));
+ seqlock_release(&sqlo);
+ assert(!seqlock_held(&sqlo));
+
+ pthread_create(&thr1, NULL, thr1func, NULL);
+ sleep(1);
+
+ writestr("main @3\n");
+ seqlock_acquire_val(&sqlo, 3);
+ sleep(2);
+
+ writestr("main @5\n");
+ seqlock_bump(&sqlo);
+ sleep(1);
+
+ writestr("main @9\n");
+ seqlock_acquire_val(&sqlo, 9);
+ sleep(1);
+
+ writestr("main @release\n");
+ seqlock_release(&sqlo);
+ sleep(1);
+}