tests: support building Linux tests in-tree
authorBarret Rhoden <brho@cs.berkeley.edu>
Mon, 8 Jun 2020 23:15:03 +0000 (19:15 -0400)
committerBarret Rhoden <brho@cs.berkeley.edu>
Tue, 9 Jun 2020 17:10:39 +0000 (13:10 -0400)
Previously, you had to manually invoke gcc to build the tests.  Now,
anytime you make tests, you'll also get the Linux version.  The tests
that are built for both OSes are specified manually in the Makefile.

This will also build any Linux modules in tests/linux/modules/.  You'll
need to provide LINUX_KDIR, e.g. in your Makelocal.  This is for tests
that need kernel support, such as the upcoming lock_test mcs-kernel mode.

You can also build these programs directly by cd-ing into tests/linux
and running Make.  This won't use any of the top-level Makefile
features (including Makelocal settings).  It's convenient if you don't
want to build Akaros (toolchain recompile, etc.).

Either way, the test binaries will appear in tests/linux/obj/.  The
top-level obj/ is just for Akaros's build output.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
16 files changed:
Makefile
Makelocal.template
tests/Makefile
tests/interference.c
tests/linux-lock-hacks.h [deleted file]
tests/linux/Makefile [new file with mode: 0644]
tests/linux/linux-lock-hacks.h [new file with mode: 0644]
tests/linux/misc-compat.h [new file with mode: 0644]
tests/linux/modules/.gitignore [new file with mode: 0644]
tests/linux/modules/Kbuild [new file with mode: 0644]
tests/lock_test.c
tests/misc-compat.h [deleted file]
tests/pthread_switch.c
tests/pthread_test.c
user/benchutil/measure.c
user/pthread/pthread.h

index 70766a6..6b3f1dc 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -195,8 +195,9 @@ HOSTCXX      = g++
 HOSTCFLAGS   = -Wall -Wno-char-subscripts -Wmissing-prototypes \
                -Wstrict-prototypes -O2 -fomit-frame-pointer
 HOSTCXXFLAGS = -O2
+HOSTLD       = ld
 
-export CONFIG_SHELL HOSTCC HOSTCXX HOSTCFLAGS HOSTCXXFLAGS
+export CONFIG_SHELL HOSTCC HOSTCXX HOSTCFLAGS HOSTCXXFLAGS HOSTLD
 
 # Beautify output
 # ---------------------------------------------------------------------------
index 098cf93..e9c4897 100644 (file)
@@ -8,6 +8,13 @@
 #CFLAGS_TESTS += -fno-optimize-sibling-calls
 export CFLAGS_USER CFLAGS_TESTS
 
+# For building linux modules, used by some tests on linux, set LINUX_KDIR
+#LINUX_KDIR := /path/to/linux/source
+export LINUX_KDIR
+# You can change the CC too, used for Linux apps and modules.
+# (and Kbuild, a little).  Default is just gcc.
+#HOSTCC := gcc-8
+
 # The default is num_cpus.  Use whatever you want.
 # MAKE_JOBS := 100
 
index b8c4095..d7f46f1 100644 (file)
@@ -24,6 +24,8 @@ TESTS_EXECS_CPP  = $(patsubst $(TESTS_DIR)/%.cc, \
                               $(OBJDIR)/$(TESTS_DIR)/%, \
                               $(TESTS_SRCS_CPP))
 
+export TESTS_DIR OBJDIR
+
 include $(TESTS_DIR)/openmp/Makefrag
 include $(TESTS_DIR)/vmm/Makefrag
 include $(TESTS_DIR)/dune/Makefrag
@@ -48,7 +50,7 @@ $(OBJDIR)/$(TESTS_DIR)/%: $(TESTS_LDDEPENDS_CPP)
        $(Q)$(CPP) $(TESTS_CXXFLAGS) -o $@ $< $(TESTS_LDLIBS)
 
 all: $(TESTS_EXECS)
-       @:
+       @cd $(TESTS_DIR)/linux && $(MAKE)
 
 install: $(TESTS_EXECS)
        @mkdir -p $(FIRST_KFS_PATH)/bin
@@ -60,5 +62,6 @@ uninstall:
 clean:
        @echo + clean [TESTS]
        @rm -rf $(OBJDIR)/tests/
+       @cd $(TESTS_DIR)/linux && $(MAKE) clean
 
 .PHONY: $(PHONY)
index 8196ff7..bcc303d 100644 (file)
@@ -22,31 +22,10 @@ static void os_init(void)
 
 #else
 
-/* Build on linux from $AKAROS_ROOT:
- * gcc -static --std=gnu99 tests/interference.c -o lin-interference
- */
-
 #include <stdio.h>
 #include "../user/parlib/include/parlib/tsc-compat.h"
-#include "misc-compat.h"
-
-struct sample_stats {
-       int (*get_sample)(void **data, int i, int j, uint64_t *sample);
-       uint64_t                avg_time;
-       uint64_t                var_time;
-       uint64_t                max_time;
-       uint64_t                min_time;
-       unsigned int            lat_50;
-       unsigned int            lat_75;
-       unsigned int            lat_90;
-       unsigned int            lat_99;
-       uint64_t                total_samples;
-};
-
-void compute_stats(void **data, int nr_i, int nr_j, struct sample_stats *stats)
-{
-       /* TODO: could try to link against benchutil. */
-}
+#include "../user/benchutil/include/benchutil/measure.h"
+#include "linux/misc-compat.h"
 
 static void os_init(void)
 {
diff --git a/tests/linux-lock-hacks.h b/tests/linux-lock-hacks.h
deleted file mode 100644 (file)
index 8596443..0000000
+++ /dev/null
@@ -1,163 +0,0 @@
-/* basic locking code that compiles on linux.  #included directly into
- * lock_test.  It's a .h so that make tests doesn't build it. */
-
-#define ARCH_CL_SIZE 64
-#define SPINLOCK_INITIALIZER {FALSE}
-
-typedef struct {
-       bool locked;
-} spinlock_t;
-
-void __attribute__((noinline)) spinlock_init(spinlock_t *lock)
-{
-       lock->locked = FALSE;
-}
-
-/* Returns TRUE if we grabbed the lock */
-bool __attribute__((noinline)) spinlock_trylock(spinlock_t *lock)
-{
-       if (lock->locked)
-               return FALSE;
-       return !__sync_lock_test_and_set(&lock->locked, TRUE);
-}
-
-void __attribute__((noinline)) spinlock_lock(spinlock_t *lock) 
-{
-       while (!spinlock_trylock(lock))
-               cpu_relax();
-}
-
-void __attribute__((noinline)) spinlock_unlock(spinlock_t *lock) 
-{
-       __sync_lock_release(&lock->locked, FALSE);
-}
-
-#define MCS_LOCK_INIT {0}
-#define MCS_QNODE_INIT {0, 0}
-
-typedef struct mcs_lock_qnode
-{
-       struct mcs_lock_qnode *next;
-       int locked;
-}__attribute__((aligned(ARCH_CL_SIZE))) mcs_lock_qnode_t;
-
-/* included for the dummy init in lock_thread */
-struct mcs_pdro_qnode
-{
-       struct mcs_pdro_qnode *next;
-       int locked;
-       uint32_t vcoreid;
-}__attribute__((aligned(ARCH_CL_SIZE)));
-
-#define MCSPDRO_QNODE_INIT {0, 0, 0}
-#define mcs_pdr_init(args...) {}
-
-typedef struct mcs_lock
-{
-       mcs_lock_qnode_t *lock;
-} mcs_lock_t;
-
-void __attribute__((noinline)) mcs_lock_init(struct mcs_lock *lock)
-{
-       memset(lock, 0, sizeof(mcs_lock_t));
-}
-
-static inline mcs_lock_qnode_t *mcs_qnode_swap(mcs_lock_qnode_t **addr,
-                                               mcs_lock_qnode_t *val)
-{
-       return (mcs_lock_qnode_t*) __sync_lock_test_and_set((void**)addr, val);
-}
-
-void __attribute__((noinline))
-mcs_lock_lock(struct mcs_lock *lock, struct mcs_lock_qnode *qnode)
-{
-       qnode->next = 0;
-       cmb();  /* swap provides a CPU mb() */
-       mcs_lock_qnode_t *predecessor = mcs_qnode_swap(&lock->lock, qnode);
-       if (predecessor) {
-               qnode->locked = 1;
-               wmb();
-               predecessor->next = qnode;
-               /* no need for a wrmb(), since this will only get unlocked
-                * after they read our previous write */
-               while (qnode->locked)
-                       cpu_relax();
-       }
-       cmb();  /* just need a cmb, the swap handles the CPU wmb/wrmb() */
-}
-
-void __attribute__((noinline))
-mcs_lock_unlock(struct mcs_lock *lock, struct mcs_lock_qnode *qnode)
-{
-       /* Check if someone is already waiting on us to unlock */
-       if (qnode->next == 0) {
-               cmb(); /* no need for CPU mbs, since there's an atomic_swap() */
-               /* Unlock it */
-               mcs_lock_qnode_t *old_tail = mcs_qnode_swap(&lock->lock,0);
-               /* no one else was already waiting, so we successfully unlocked
-                * and can return */
-               if (old_tail == qnode)
-                       return;
-               /* someone else was already waiting on the lock (last one on
-                * the list), and we accidentally took them off.  Try and put
-                * it back. */
-               mcs_lock_qnode_t *usurper = mcs_qnode_swap(&lock->lock,
-                                                          old_tail);
-               /* since someone else was waiting, they should have made
-                * themselves our next.  spin (very briefly!) til it happens.
-                * */
-               while (qnode->next == 0)
-                       cpu_relax();
-               if (usurper) {
-                       /* an usurper is someone who snuck in before we could
-                        * put the old tail back.  They now have the lock.
-                        * Let's put whoever is supposed to be next as their
-                        * next one. */
-                       usurper->next = qnode->next;
-               } else {
-                       /* No usurper meant we put things back correctly, so we
-                        * should just pass the lock / unlock whoever is next */
-                       qnode->next->locked = 0;
-               }
-       } else {
-               /* mb()s necessary since we didn't call an atomic_swap() */
-               /* need to make sure any previous writes don't pass unlocking */
-               wmb();
-               /* need to make sure any reads happen before the unlocking */
-               rwmb();
-               /* simply unlock whoever is next */
-               qnode->next->locked = 0;
-       }
-}
-
-/* CAS style mcs locks, kept around til we use them.  We're using the
- * usurper-style, since RISCV doesn't have a real CAS (yet?). */
-void __attribute__((noinline))
-mcs_lock_unlock_cas(struct mcs_lock *lock, struct mcs_lock_qnode *qnode)
-{
-       /* Check if someone is already waiting on us to unlock */
-       if (qnode->next == 0) {
-               cmb();  /* no need for CPU mbs, since there's an atomic_cas() */
-               /* If we're still the lock, just swap it with 0 (unlock) and
-                * return */
-               if (__sync_bool_compare_and_swap((void**)&lock->lock, qnode, 0))
-                       return;
-               /* We failed, someone is there and we are some (maybe a
-                * different) thread's pred.  Since someone else was waiting,
-                * they should have made themselves our next.  Spin (very
-                * briefly!) til it happens. */
-               while (qnode->next == 0)
-                       cpu_relax();
-               /* Alpha wants a read_barrier_depends() here */
-               /* Now that we have a next, unlock them */
-               qnode->next->locked = 0;
-       } else {
-               /* mb()s necessary since we didn't call an atomic_swap() */
-               /* need to make sure any previous writes don't pass unlocking */
-               wmb();
-               /* need to make sure any reads happen before the unlocking */
-               rwmb();
-               /* simply unlock whoever is next */
-               qnode->next->locked = 0;
-       }
-}
diff --git a/tests/linux/Makefile b/tests/linux/Makefile
new file mode 100644 (file)
index 0000000..c8f1e59
--- /dev/null
@@ -0,0 +1,84 @@
+# Builds certain tests for Linux
+#
+# Customize your settings in your Makelocal
+# - LINUX_KDIR: linux source for the module (/path/to/linux/source)
+#
+# You should be able to build the Linux programs without building Akaros by
+# running make in this directory.  Set LINUX_KDIR in your environment.  Fun!
+
+# Default compiler/tools come from the top-level Makefile.  They can be
+# overridden.  Also these are used if we were called directly instead of from
+# the top-level makefile.
+HOSTCC ?= gcc
+HOSTCFLAGS ?= -Wall -Wno-char-subscripts -Wmissing-prototypes \
+              -Wstrict-prototypes -O2 -fomit-frame-pointer
+HOSTLD ?= ld
+
+
+USERDIR = ../../user
+# override to our local obj/
+OBJDIR = obj
+
+ifeq ($(TESTS_DIR),)
+# independent build, from this directory
+Q = @
+endif
+# override, regardless
+TESTS_DIR = ..
+
+# defined below
+all:
+
+ifeq ($(LINUX_KDIR),)
+
+mods:
+       $(Q)echo LINUX_KDIR is unset.  Set it, Makelocal or env, for Linux mods
+
+mods_clean:
+       @:
+
+else
+
+mods:
+       @cd modules && $(MAKE) -C $(LINUX_KDIR) CC=$(HOSTCC) LD=$(HOSTLD) M=$$PWD modules
+
+mods_clean:
+       @cd modules && $(MAKE) -C $(LINUX_KDIR) M=$$PWD clean
+
+endif
+
+clean: mods_clean
+       @rm -rf $(OBJDIR) .*cmd
+
+# Programs in this directory (if any)
+tests_srcs_c := $(wildcard *.c)
+tests_lddepends_c := %.c
+tests_execs_c   = $(patsubst %.c, $(OBJDIR)/%, $(tests_srcs_c))
+
+# Select programs from tests/
+# All programs we build end up in obj/tests/linux/, even the ones from tests/
+sel_progs = lock_test.c interference.c pthread_test.c
+
+sel_progs_srcs_c = $(patsubst %c,$(TESTS_DIR)/%c, $(sel_progs))
+sel_progs_lddepends_c := $(TESTS_DIR)/%.c
+sel_progs_execs_c = $(patsubst %.c, $(OBJDIR)/%, $(sel_progs))
+
+progs = $(tests_execs_c) $(sel_progs_execs_c)
+
+tests_c_deps := $(USERDIR)/benchutil/measure.c
+tests_ldlibs := -lpthread -lm
+
+$(OBJDIR)/%: $(tests_lddepends_c)
+       @echo + cc [LINUX_TESTS] $<
+       @mkdir -p $(@D)
+       $(Q)$(HOSTCC) -static -O2 $< $(tests_c_deps) -o $@ $(tests_ldlibs)
+
+$(OBJDIR)/%: $(sel_progs_lddepends_c)
+       @echo + cc [LINUX_TESTS] $<
+       @mkdir -p $(@D)
+       $(Q)$(HOSTCC) -static -O2 $< $(tests_c_deps) -o $@ $(tests_ldlibs)
+
+all: mods $(progs)
+       @:
+
+.PHONY: $(all mods clean)
diff --git a/tests/linux/linux-lock-hacks.h b/tests/linux/linux-lock-hacks.h
new file mode 100644 (file)
index 0000000..6da938b
--- /dev/null
@@ -0,0 +1,163 @@
+/* basic locking code that compiles on linux.  #included directly into
+ * lock_test.  It's a .h so that make tests doesn't build it. */
+
+#define ARCH_CL_SIZE 64
+#define SPINLOCK_INITIALIZER {FALSE}
+
+typedef struct {
+       bool locked;
+} spinlock_t;
+
+void __attribute__((noinline)) spinlock_init(spinlock_t *lock)
+{
+       lock->locked = FALSE;
+}
+
+/* Returns TRUE if we grabbed the lock */
+bool __attribute__((noinline)) spinlock_trylock(spinlock_t *lock)
+{
+       if (lock->locked)
+               return FALSE;
+       return !__sync_lock_test_and_set(&lock->locked, TRUE);
+}
+
+void __attribute__((noinline)) spinlock_lock(spinlock_t *lock)
+{
+       while (!spinlock_trylock(lock))
+               cpu_relax();
+}
+
+void __attribute__((noinline)) spinlock_unlock(spinlock_t *lock)
+{
+       __sync_lock_release(&lock->locked, FALSE);
+}
+
+#define MCS_LOCK_INIT {0}
+#define MCS_QNODE_INIT {0, 0}
+
+typedef struct mcs_lock_qnode
+{
+       struct mcs_lock_qnode *next;
+       int locked;
+}__attribute__((aligned(ARCH_CL_SIZE))) mcs_lock_qnode_t;
+
+/* included for the dummy init in lock_thread */
+struct mcs_pdro_qnode
+{
+       struct mcs_pdro_qnode *next;
+       int locked;
+       uint32_t vcoreid;
+}__attribute__((aligned(ARCH_CL_SIZE)));
+
+#define MCSPDRO_QNODE_INIT {0, 0, 0}
+#define mcs_pdr_init(args...) {}
+
+typedef struct mcs_lock
+{
+       mcs_lock_qnode_t *lock;
+} mcs_lock_t;
+
+void __attribute__((noinline)) mcs_lock_init(struct mcs_lock *lock)
+{
+       memset(lock, 0, sizeof(mcs_lock_t));
+}
+
+static inline mcs_lock_qnode_t *mcs_qnode_swap(mcs_lock_qnode_t **addr,
+                                               mcs_lock_qnode_t *val)
+{
+       return (mcs_lock_qnode_t*) __sync_lock_test_and_set((void**)addr, val);
+}
+
+void __attribute__((noinline))
+mcs_lock_lock(struct mcs_lock *lock, struct mcs_lock_qnode *qnode)
+{
+       qnode->next = 0;
+       cmb();  /* swap provides a CPU mb() */
+       mcs_lock_qnode_t *predecessor = mcs_qnode_swap(&lock->lock, qnode);
+       if (predecessor) {
+               qnode->locked = 1;
+               wmb();
+               predecessor->next = qnode;
+               /* no need for a wrmb(), since this will only get unlocked
+                * after they read our previous write */
+               while (qnode->locked)
+                       cpu_relax();
+       }
+       cmb();  /* just need a cmb, the swap handles the CPU wmb/wrmb() */
+}
+
+void __attribute__((noinline))
+mcs_lock_unlock(struct mcs_lock *lock, struct mcs_lock_qnode *qnode)
+{
+       /* Check if someone is already waiting on us to unlock */
+       if (qnode->next == 0) {
+               cmb(); /* no need for CPU mbs, since there's an atomic_swap() */
+               /* Unlock it */
+               mcs_lock_qnode_t *old_tail = mcs_qnode_swap(&lock->lock,0);
+               /* no one else was already waiting, so we successfully unlocked
+                * and can return */
+               if (old_tail == qnode)
+                       return;
+               /* someone else was already waiting on the lock (last one on
+                * the list), and we accidentally took them off.  Try and put
+                * it back. */
+               mcs_lock_qnode_t *usurper = mcs_qnode_swap(&lock->lock,
+                                                          old_tail);
+               /* since someone else was waiting, they should have made
+                * themselves our next.  spin (very briefly!) til it happens.
+                * */
+               while (qnode->next == 0)
+                       cpu_relax();
+               if (usurper) {
+                       /* an usurper is someone who snuck in before we could
+                        * put the old tail back.  They now have the lock.
+                        * Let's put whoever is supposed to be next as their
+                        * next one. */
+                       usurper->next = qnode->next;
+               } else {
+                       /* No usurper meant we put things back correctly, so we
+                        * should just pass the lock / unlock whoever is next */
+                       qnode->next->locked = 0;
+               }
+       } else {
+               /* mb()s necessary since we didn't call an atomic_swap() */
+               /* need to make sure any previous writes don't pass unlocking */
+               wmb();
+               /* need to make sure any reads happen before the unlocking */
+               rwmb();
+               /* simply unlock whoever is next */
+               qnode->next->locked = 0;
+       }
+}
+
+/* CAS style mcs locks, kept around til we use them.  We're using the
+ * usurper-style, since RISCV doesn't have a real CAS (yet?). */
+void __attribute__((noinline))
+mcs_lock_unlock_cas(struct mcs_lock *lock, struct mcs_lock_qnode *qnode)
+{
+       /* Check if someone is already waiting on us to unlock */
+       if (qnode->next == 0) {
+               cmb();  /* no need for CPU mbs, since there's an atomic_cas() */
+               /* If we're still the lock, just swap it with 0 (unlock) and
+                * return */
+               if (__sync_bool_compare_and_swap((void**)&lock->lock, qnode, 0))
+                       return;
+               /* We failed, someone is there and we are some (maybe a
+                * different) thread's pred.  Since someone else was waiting,
+                * they should have made themselves our next.  Spin (very
+                * briefly!) til it happens. */
+               while (qnode->next == 0)
+                       cpu_relax();
+               /* Alpha wants a read_barrier_depends() here */
+               /* Now that we have a next, unlock them */
+               qnode->next->locked = 0;
+       } else {
+               /* mb()s necessary since we didn't call an atomic_swap() */
+               /* need to make sure any previous writes don't pass unlocking */
+               wmb();
+               /* need to make sure any reads happen before the unlocking */
+               rwmb();
+               /* simply unlock whoever is next */
+               qnode->next->locked = 0;
+       }
+}
diff --git a/tests/linux/misc-compat.h b/tests/linux/misc-compat.h
new file mode 100644 (file)
index 0000000..e6832e4
--- /dev/null
@@ -0,0 +1,71 @@
+#pragma once
+
+/* All of these should be in other Akaros headers */
+#ifndef __akaros__
+
+#include <stdbool.h>
+#ifndef TRUE
+#define TRUE   1
+#endif
+
+#ifndef FALSE
+#define FALSE  0
+#endif
+
+#include <sys/param.h> /* MIN/MAX */
+#include <unistd.h>
+
+/* not quite, since akaros udelay is a busy wait */
+#define udelay(usec) usleep(usec)
+#define ndelay(nsec)                                                           \
+{                                                                              \
+       struct timespec ts = {0, 0};                                           \
+       ts.tv_nsec = (nsec);                                                   \
+       nanosleep(&ts, 0);                                                     \
+}
+
+/* not quite a normal relax, which also pauses, but this works for all archs */
+static inline void cpu_relax(void)
+{
+       asm volatile("" : : : "memory");
+}
+
+#define pthread_id() (pthread_self())
+
+#define vcore_id() (-1)
+
+#define num_vcores() ((int)sysconf(_SC_NPROCESSORS_ONLN))
+
+#define ACCESS_ONCE(x) (*(volatile typeof(x) *)&(x))
+
+typedef void* atomic_t;
+
+static void uth_disable_notifs(void)
+{
+}
+
+static void uth_enable_notifs(void)
+{
+}
+
+static int get_pcoreid(void)
+{
+       return -1;
+}
+
+#define printd(args...) {}
+
+#define COUNT_OF(x) (sizeof((x))/sizeof((x)[0]))
+
+#ifdef __x86_64__
+
+#define mb() ({ asm volatile("mfence" ::: "memory"); })
+#define cmb() ({ asm volatile("" ::: "memory"); })
+#define rmb() cmb()
+#define wmb() cmb()
+#define wrmb() mb()
+#define rwmb() cmb()
+
+#endif /* __x86_64__ */
+
+#endif /* __ros__ */
diff --git a/tests/linux/modules/.gitignore b/tests/linux/modules/.gitignore
new file mode 100644 (file)
index 0000000..1a86f5e
--- /dev/null
@@ -0,0 +1,6 @@
+.cache.mk
+.tmp_versions/
+Module.symvers
+*.ko
+*.mod.c
+modules.order
diff --git a/tests/linux/modules/Kbuild b/tests/linux/modules/Kbuild
new file mode 100644 (file)
index 0000000..4517f23
--- /dev/null
@@ -0,0 +1 @@
+obj-m += mcs.o
index e1a985d..a02d7fb 100644 (file)
@@ -3,10 +3,7 @@
  * See LICENSE for details.
  *
  * lock_test: microbenchmark to measure different styles of spinlocks.
- *
- * to build on linux: (hacky)
- * $ gcc -O2 -std=gnu99 -fno-stack-protector -g tests/lock_test.c -lpthread \
- *    -lm -o linux_lock_test */
+ */
 
 #define _GNU_SOURCE /* pthread_yield */
 
 #else
 
 #include "../user/parlib/include/parlib/tsc-compat.h"
-#include "misc-compat.h"
-#include "linux-lock-hacks.h" /* TODO: have a build system and lib / C file */
-
 #include "../user/benchutil/include/benchutil/measure.h"
-#include "../user/benchutil/measure.c"
+#include "linux/misc-compat.h"
+#include "linux/linux-lock-hacks.h"
 
 static void os_prep_work(pthread_t *worker_threads, int nr_threads)
 {
diff --git a/tests/misc-compat.h b/tests/misc-compat.h
deleted file mode 100644 (file)
index 08f472f..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-#pragma once
-
-#ifdef __ros__
-
-#include <parlib/timing.h>
-
-#define pthread_id() (pthread_self()->id)
-
-#else
-
-#include <stdbool.h>
-#ifndef TRUE
-#define TRUE   1
-#endif
-
-#ifndef FALSE
-#define FALSE  0
-#endif
-
-#include <sys/param.h> /* MIN/MAX */
-#include <unistd.h>
-
-/* not quite, since akaros udelay is a busy wait */
-#define udelay(usec) usleep(usec)
-#define ndelay(nsec)                                                           \
-{                                                                              \
-       struct timespec ts = {0, 0};                                           \
-       ts.tv_nsec = (nsec);                                                   \
-       nanosleep(&ts, 0);                                                     \
-}
-
-/* not quite a normal relax, which also pauses, but this works for all archs */
-static inline void cpu_relax(void)
-{
-       asm volatile("" : : : "memory");
-}
-
-#define pthread_id() (pthread_self())
-
-#define vcore_id() (-1)
-
-#define num_vcores() ((int)sysconf(_SC_NPROCESSORS_ONLN))
-
-#define ACCESS_ONCE(x) (*(volatile typeof(x) *)&(x))
-
-typedef void* atomic_t;
-
-static void uth_disable_notifs(void)
-{
-}
-
-static void uth_enable_notifs(void)
-{
-}
-
-static int get_pcoreid(void)
-{
-       return -1;
-}
-
-#define printd(args...) {}
-
-#define COUNT_OF(x) (sizeof((x))/sizeof((x)[0]))
-
-#ifdef __x86_64__
-
-#define mb() ({ asm volatile("mfence" ::: "memory"); })
-#define cmb() ({ asm volatile("" ::: "memory"); })
-#define rmb() cmb()
-#define wmb() cmb()
-#define wrmb() mb()
-#define rwmb() cmb()
-
-#endif /* __x86_64__ */
-
-#endif /* __ros__ */
index d5bb46b..7ef0e74 100644 (file)
@@ -10,7 +10,6 @@
 #include <stdlib.h>
 #include <unistd.h>
 #include <sys/time.h>
-#include "misc-compat.h"
 
 pthread_t th1, th2;
 int nr_switch_loops = 100;
index e7f568d..0d2b3e0 100644 (file)
@@ -4,9 +4,6 @@
  *
  * Basic test for pthreading.  Spawns a bunch of threads that yield.
  *
- * To build on linux, cd into tests and run:
- * $ gcc -O2 -std=gnu99 -fno-stack-protector -g pthread_test.c -lpthread
- *
  * Make sure you run it with taskset to fix the number of vcores/cpus. */
 
 #define _GNU_SOURCE /* for pth_yield on linux */
 #include <stdlib.h>
 #include <unistd.h>
 #include <sys/time.h>
-#include "misc-compat.h" /* OS dependent #incs */
+
+#ifndef __akaros__
+#include "linux/misc-compat.h"
+#endif
 
 /* These are here just to have the compiler test the _INITIALIZERS */
 pthread_cond_t dummy_cond = PTHREAD_COND_INITIALIZER;
index 299024b..d57459f 100644 (file)
@@ -17,8 +17,7 @@
  #include <parlib/tsc-compat.h>
  #include <benchutil/measure.h>
 #else
- /* you'll need to do find this manually on linux */
- #include "measure.h"
+ #include "include/benchutil/measure.h"
 #endif /* __ros__ */
 
 /* Basic stats computation and printing.
index d85742e..88b3380 100644 (file)
@@ -49,6 +49,7 @@ struct pthread_tcb {
        struct pthread_cleanup_stack cr_stack;
 };
 typedef struct pthread_tcb* pthread_t;
+#define pthread_id() (pthread_self()->id)
 TAILQ_HEAD(pthread_queue, pthread_tcb);
 
 /* Per-vcore data structures to manage syscalls.  The ev_q is where we tell the