diff --git a/repos/base/run/slab.run b/repos/base/run/slab.run
new file mode 100644
index 0000000000..98fce646d3
--- /dev/null
+++ b/repos/base/run/slab.run
@@ -0,0 +1,39 @@
+build "core init drivers/timer test/slab"
+
+create_boot_directory
+
+install_config {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+}
+
+build_boot_image "core init timer test-slab"
+
+append qemu_args "-nographic -m 128"
+
+run_genode_until {child "test-slab" exited with exit value 0.*\n} 100
+
+puts "Test succeeded"
diff --git a/repos/base/src/test/slab/main.cc b/repos/base/src/test/slab/main.cc
new file mode 100644
index 0000000000..1f2ba92e9a
--- /dev/null
+++ b/repos/base/src/test/slab/main.cc
@@ -0,0 +1,113 @@
+/*
+ * \brief Slab allocator test
+ * \author Norman Feske
+ * \date 2015-03-31
+ *
+ */
+
+/*
+ * Copyright (C) 2015 Genode Labs GmbH
+ *
+ * This file is part of the Genode OS framework, which is distributed
+ * under the terms of the GNU General Public License version 2.
+ */
+
+#include
+#include
+#include
+#include
+#include
+
+
+using Genode::size_t;
+using Genode::printf;
+
+
+struct Array_of_slab_elements
+{
+ Genode::Slab &slab;
+
+ size_t const num_elem;
+ size_t const slab_size;
+
+ void **elem;
+
+ /**
+ * Return size of 'elem' array in bytes
+ */
+ size_t _elem_array_size() const { return num_elem*sizeof(void *); }
+
+ struct Alloc_failed { };
+
+ /**
+ * Constructor
+ *
+ * \throw Alloc_failed
+ */
+ Array_of_slab_elements(Genode::Slab &slab, size_t num_elem, size_t slab_size)
+ :
+ slab(slab), num_elem(num_elem), slab_size(slab_size)
+ {
+ elem = (void **)Genode::env()->heap()->alloc(_elem_array_size());
+
+ printf(" allocate %zu elements\n", num_elem);
+ for (size_t i = 0; i < num_elem; i++)
+ if (!slab.alloc(slab_size, &elem[i]))
+ throw Alloc_failed();
+ }
+
+ ~Array_of_slab_elements()
+ {
+ printf(" free %zu elements\n", num_elem);
+ for (size_t i = 0; i < num_elem; i++)
+ slab.free(elem[i], slab_size);
+
+ Genode::env()->heap()->free(elem, _elem_array_size());
+ }
+};
+
+
+int main(int argc, char **argv)
+{
+ printf("--- slab test ---\n");
+
+ static Timer::Connection timer;
+
+ enum { SLAB_SIZE = 16, BLOCK_SIZE = 256 };
+ static Genode::Allocator_guard alloc(Genode::env()->heap(), ~0UL);
+
+ {
+ Genode::Slab slab(SLAB_SIZE, BLOCK_SIZE, nullptr, &alloc);
+
+ for (unsigned i = 1; i <= 10; i++) {
+ printf("round %u (used quota: %zu, time: %ld ms)\n",
+ i, alloc.consumed(), timer.elapsed_ms());
+
+ Array_of_slab_elements array(slab, i*100000, SLAB_SIZE);
+ printf(" allocation completed (used quota: %zu", alloc.consumed());
+ }
+
+ printf(" finished (used quota: %zu, time: %ld ms)\n",
+ alloc.consumed(), timer.elapsed_ms());
+
+ /*
+ * The slab keeps two empty blocks around. For the test, we also need to
+ * take the overhead of the two block allocations at the heap into
+ * account.
+ */
+ enum { HEAP_OVERHEAD = 36 };
+ if (alloc.consumed() > 2*(BLOCK_SIZE + HEAP_OVERHEAD)) {
+ PERR("slab failed to release empty slab blocks");
+ return -1;
+ }
+ }
+
+ /* validate slab destruction */
+ printf("destructed slab (used quota: %zu)\n", alloc.consumed());
+ if (alloc.consumed() > 0) {
+ PERR("slab failed to release all backing store");
+ return -2;
+ }
+
+ return 0;
+}
diff --git a/repos/base/src/test/slab/target.mk b/repos/base/src/test/slab/target.mk
new file mode 100644
index 0000000000..ca9d80fd3d
--- /dev/null
+++ b/repos/base/src/test/slab/target.mk
@@ -0,0 +1,3 @@
+TARGET = test-slab
+SRC_CC = main.cc
+LIBS = base