diff --git a/tests/bench_thread_flags_pingpong/Makefile b/tests/bench_thread_flags_pingpong/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..3ce9af7db31f9a476bc9ac4cd3f0ae56852400ea
--- /dev/null
+++ b/tests/bench_thread_flags_pingpong/Makefile
@@ -0,0 +1,13 @@
+include ../Makefile.tests_common
+
+BOARD_INSUFFICIENT_MEMORY := nucleo-f031k6
+
+USEMODULE += core_thread_flags
+USEMODULE += xtimer
+
+TEST_ON_CI_WHITELIST += all
+
+include $(RIOTBASE)/Makefile.include
+
+test:
+	tests/01-run.py
diff --git a/tests/bench_thread_flags_pingpong/README.md b/tests/bench_thread_flags_pingpong/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..44c2b3eddcdf980a8da45f87220c90468281834d
--- /dev/null
+++ b/tests/bench_thread_flags_pingpong/README.md
@@ -0,0 +1,9 @@
+# About
+
+This test measures the number of times one thread can set (and wakeup) another
+thread using thread_flags(). The result amounts to the number of times the
+thread flag was set, which is half the number of context switches incurred in
+that time.
+
+This test application intentionally duplicates code with some similar benchmark
+applications in order to be able to compare code sizes.
diff --git a/tests/bench_thread_flags_pingpong/main.c b/tests/bench_thread_flags_pingpong/main.c
new file mode 100644
index 0000000000000000000000000000000000000000..ef5e037745fbc67425f5f75f7f00d7d97183d21a
--- /dev/null
+++ b/tests/bench_thread_flags_pingpong/main.c
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2017 Kaspar Schleiser <kaspar@schleiser.de>
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser
+ * General Public License v2.1. See the file LICENSE in the top level
+ * directory for more details.
+ */
+
+/**
+ * @ingroup     tests
+ * @{
+ *
+ * @file
+ * @brief       Thread flags benchmark test application
+ *
+ * @author      Kaspar Schleiser <kaspar@schleiser.de>
+ *
+ * @}
+ */
+
+#include <stdio.h>
+#include "thread.h"
+
+#include "thread_flags.h"
+#include "xtimer.h"
+
+#ifndef TEST_DURATION
+#define TEST_DURATION       (1000000U)
+#endif
+
+volatile unsigned _flag = 0;
+static char _stack[THREAD_STACKSIZE_MAIN];
+
+static void _timer_callback(void*arg)
+{
+    (void)arg;
+
+    _flag = 1;
+}
+
+static void *_second_thread(void *arg)
+{
+    (void)arg;
+
+    while(1) {
+        thread_flags_wait_any(0x0 - 1);
+    }
+
+    return NULL;
+}
+
+int main(void)
+{
+    printf("main starting\n");
+
+    kernel_pid_t other = thread_create(_stack,
+                                       sizeof(_stack),
+                                       (THREAD_PRIORITY_MAIN - 1),
+                                       THREAD_CREATE_STACKTEST,
+                                       _second_thread,
+                                       NULL,
+                                       "second_thread");
+
+    thread_t *tcb = (thread_t *)sched_threads[other];
+
+    xtimer_t timer;
+    timer.callback = _timer_callback;
+
+    uint32_t n = 0;
+
+    xtimer_set(&timer, TEST_DURATION);
+    while(!_flag) {
+        thread_flags_set(tcb, 0x1);
+        n++;
+    }
+
+    printf("{ \"result\" : %"PRIu32" }\n", n);
+
+    return 0;
+}
diff --git a/tests/bench_thread_flags_pingpong/tests/01-run.py b/tests/bench_thread_flags_pingpong/tests/01-run.py
new file mode 100755
index 0000000000000000000000000000000000000000..3a1e733980e94fd7216e5d68884880abafc9eaf1
--- /dev/null
+++ b/tests/bench_thread_flags_pingpong/tests/01-run.py
@@ -0,0 +1,21 @@
+#!/usr/bin/env python3
+
+# Copyright (C) 2018 Kaspar Schleiser <kaspar@schleiser.de>
+#               2017 Sebastian Meiling <s@mlng.net>
+#
+# This file is subject to the terms and conditions of the GNU Lesser
+# General Public License v2.1. See the file LICENSE in the top level
+# directory for more details.
+
+import os
+import sys
+
+
+def testfunc(child):
+    child.expect(r"{ \"result\" : \d+ }")
+
+
+if __name__ == "__main__":
+    sys.path.append(os.path.join(os.environ['RIOTTOOLS'], 'testrunner'))
+    from testrunner import run
+    sys.exit(run(testfunc))