typedef signed long rint64;
typedef unsigned long ruint64;
typedef unsigned long rword;
+typedef unsigned long rsize_t;
+typedef signed long rssize_t;
typedef unsigned int ratomic;
/*
rboolean r_atomic_compare_and_exchange(volatile ratomic *ptr, ratomic oldval, ratomic newval);
ratomic r_atomic_exchange(volatile ratomic *ptr, ratomic val);
-ratomic r_atomic_add(volatile ratomic *ptr, ratomic val);
-ratomic r_atomic_sub(volatile ratomic *ptr, ratomic val);
+void r_atomic_add(volatile ratomic *ptr, ratomic val);
+void r_atomic_sub(volatile ratomic *ptr, ratomic val);
#ifdef __cplusplus
}
#include <stdlib.h>
#include <string.h>
+#include "rspinlock.h"
#include "rmem.h"
-long int g_allocmem = 0;
-long int g_maxmem = 0;
+static rspinlock g_lock = R_SPINLOCK_INIT;
+static long int g_allocmem = 0;
+static long int g_maxmem = 0;
+
+typedef struct _RMemAllocVTable {
+ rpointer (*malloc)(rsize_t size);
+ void (*free)(rpointer ptr);
+ rpointer (*realloc)(rpointer ptr, rsize_t size);
+} RMemAllocVTable;
+
+
+static rpointer r_std_malloc(rsize_t size)
+{
+ return malloc((size_t)size);
+}
+
+
+static void r_std_free(rpointer ptr)
+{
+ free((void*)ptr);
+}
+
+
+static rpointer r_std_realloc(rpointer ptr, rsize_t size)
+{
+ return realloc((void*)ptr, (size_t)size);
+}
+
+
+static rpointer r_dbg_malloc(rsize_t size)
+{
+ rword *mem = NULL;
+ size += sizeof(rword);
+ mem = (rword*)malloc((size_t)(size));
+ *((rword*)mem) = size;
+ r_spinlock_lock(&g_lock);
+ g_allocmem += size;
+ if (g_maxmem < g_allocmem)
+ g_maxmem = g_allocmem;
+ r_spinlock_unlock(&g_lock);
+ mem += 1;
+ return (void*)mem;
+}
+
+
+static void r_dbg_free(rpointer ptr)
+{
+ rword *mem = (void*)(((rword*)ptr) - 1);
+ rword size;
+ if (!ptr)
+ return;
+ size = *mem;
+ r_spinlock_lock(&g_lock);
+ g_allocmem -= size;
+ r_spinlock_unlock(&g_lock);
+ free((void*)mem);
+}
+
+
+static rpointer r_dbg_realloc(rpointer ptr, rsize_t size)
+{
+ rword *mem = (void*)(((rword*)ptr) - 1);
+ rword csize;
+ if (!ptr)
+ return r_malloc(size);
+ csize = *mem;
+ r_spinlock_lock(&g_lock);
+ g_allocmem -= csize;
+ r_spinlock_unlock(&g_lock);
+ size += sizeof(long);
+ mem = (rword*)realloc((void*)mem, (size_t)(size));
+ *mem = size;
+ r_spinlock_lock(&g_lock);
+ g_allocmem += size;
+ if (g_maxmem < g_allocmem)
+ g_maxmem = g_allocmem;
+ r_spinlock_unlock(&g_lock);
+ mem += 1;
+ return (void*)mem;
+}
+
+
+static RMemAllocVTable g_stdMemAlloc = {
+ r_std_malloc,
+ r_std_free,
+ r_std_realloc,
+};
+
+
+static RMemAllocVTable g_dbgMemAlloc = {
+ r_dbg_malloc,
+ r_dbg_free,
+ r_dbg_realloc,
+};
rpointer r_malloc(unsigned long size)
return memcpy(dest, src, (size_t)n);
}
-
-rboolean r_atomic_int_compare_and_exchange (volatile rint *atomic, rint oldval, rint newval)
-{
- rint result;
-
- __asm__ __volatile__ ("lock; cmpxchgl %2, %1"
- : "=a" (result), "=m" (*atomic)
- : "r" (newval), "m" (*atomic), "0" (oldval));
-
- return result == oldval;
-}
extern "C" {
#endif
+#define R_SPINLOCK_INIT 0
#define R_SPINLOCK_BUSY 1
typedef ratomic rspinlock;
ROBJECT_SRCDIR = $(SRCDIR)/robject
+RLIB_SRCDIR = $(SRCDIR)/rlib
TESTS_SRCDIR = $(SRCDIR)/tests
-INCLUDE = -I$(SRCDIR)/arch/$(OS)/$(ARCHDIR) -I$(ROBJECT_SRCDIR)
-LIBS = -L$(ROBJECT_SRCDIR)/build/$(OS)/$(ARCHDIR)/out -lrobject --static
+INCLUDE = -I$(SRCDIR)/arch/$(OS)/$(ARCHDIR) -I$(ROBJECT_SRCDIR) -I$(RLIB_SRCDIR)
+LIBS = -L$(ROBJECT_SRCDIR)/build/$(OS)/$(ARCHDIR)/out
+LIBS += -L$(RLIB_SRCDIR)/build/$(OS)/$(ARCHDIR)/out -lrlib -lpthread --static
TESTS = \
- $(OUTDIR)/robject-ver \
$(OUTDIR)/rlock-test \
all : $(OUTDIR) $(TESTS)
+#include <pthread.h>
#include <stdio.h>
+#include <stdlib.h>
+#include "rspinlock.h"
+#define NUM_THREADS 10
+#define NUM_ITERATIONS 100000
-int main(int argc, char *argv[])
-{
+static rspinlock g_lock;
+static ruint32 g_result;
+
+
+void *test_busy_work(void *t) {
+ ruint32 r;
+ ruint32 i;
+ long tid = (long)t;
+
+ printf("Thread %ld starting...\n", tid);
+ for (i = 0; i < NUM_ITERATIONS; i++) {
+ r_spinlock_lock(&g_lock);
+ r = g_result;
+ r = r + 1;
+ g_result = r;
+ r_spinlock_unlock(&g_lock);
+ }
+ printf("Thread %ld done. \n", tid);
+ pthread_exit((void*) t);
+}
+
+
+int main(int argc, char *argv[]) {
+ pthread_t thread[NUM_THREADS];
+ pthread_attr_t attr;
+ int rc;
+ long t;
+ void *status;
+
+ /* Initialize the global varibales */
+ r_spinlock_init(&g_lock);
+ g_result = 0;
+
+ /* Initialize and set thread detached attribute */
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
+
+ for (t = 0; t < NUM_THREADS; t++) {
+ printf("Main: creating thread %ld\n", t);
+ rc = pthread_create(&thread[t], &attr, test_busy_work, (void *) t);
+ if (rc) {
+ printf("ERROR; return code from pthread_create() is %d\n", rc);
+ exit(-1);
+ }
+ }
+
+ /* Free attribute and wait for the other threads */
+ pthread_attr_destroy(&attr);
+ for (t = 0; t < NUM_THREADS; t++) {
+ rc = pthread_join(thread[t], &status);
+ if (rc) {
+ printf("ERROR; return code from pthread_join() is %d\n", rc);
+ exit(-1);
+ }
+ printf("Main: completed join with thread %ld having a status of %ld\n",
+ t, (long) status);
+ }
+
+ printf("Main: program completed. Exiting. Expected Result = %d, Actual Result = %d\n",
+ NUM_ITERATIONS * NUM_THREADS, g_result);
+ if (g_result == NUM_ITERATIONS * NUM_THREADS)
+ printf("Test PASSED\n");
+ else
+ printf("Test FAILED\n");
+ pthread_exit(NULL);
+}
+
+int maine(int argc, char *argv[]) {
fprintf(stdout, "It works!\n");
return 0;
}