Skip to content

Commit

Permalink
Woho. Epic commit with hierarchical tasks, function calls, SPAWN inst…
Browse files Browse the repository at this point in the history
…ruction, task message passing, etc etc. Still WIP, but tests pass and main.c runs
  • Loading branch information
rsms committed Oct 21, 2012
1 parent 6b3b323 commit 74e10cf
Show file tree
Hide file tree
Showing 24 changed files with 529 additions and 322 deletions.
2 changes: 1 addition & 1 deletion Make.common
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ AR = ar
UpperCase = $(shell echo $(1) | tr a-z A-Z)

# Compiler and Linker flags for all targets
CFLAGS += -Wall -g -std=c99 -MMD -I$(INCLUDE_BUILD_PREFIX) \
CFLAGS += -Wall -g -std=c99 -I$(INCLUDE_BUILD_PREFIX) \
-arch $(TARGET_ARCH)
CXXFLAGS += -std=c++11 -fno-rtti
LDFLAGS += -arch $(TARGET_ARCH)
Expand Down
7 changes: 4 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
include Make.common
all: sol test
all: test

clean:
@$(MAKE) -C $(SRCROOT)/sol $@
@$(MAKE) -C $(SRCROOT)/test $@
Expand All @@ -11,8 +12,8 @@ sol: libev

libev:
@$(MAKE) -C $(SRCROOT)/deps/libev
@mkdir -p "$(BUILD_PREFIX)/libev"
ln -fs "$(SRCROOT)/deps/libev/.libs/libev.a" "$(BUILD_PREFIX)/libev"
@mkdir -p "$(LIB_BUILD_PREFIX)"
@ln -fs "$(SRCROOT)/deps/libev/.libs/libev.a" "$(LIB_BUILD_PREFIX)"

test:
@$(MAKE) -C $(SRCROOT)/test $@
Expand Down
6 changes: 3 additions & 3 deletions sol/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ c_sources := main.c \
sched.c task.c func.c \
value.c

headers_pub := sol.h common.h common_target.h common_stdint.h \
headers_pub := sol.h common.h common_target.h common_stdint.h common_atomic.h \
debug.h log.h host.h tidmap.h msg.h \
vm.h sched.h runq.h task.h func.h arec.h instr.h \
value.h
Expand Down Expand Up @@ -39,9 +39,9 @@ headers_pub_export_dirs = $(call FileDirs,$(headers_pub_export))
main_program = $(BIN_BUILD_PREFIX)/$(project_id)

# Compiler and linker flags
c_flags := $(CFLAGS)
c_flags := $(CFLAGS) -MMD
cxx_flags := $(CXXFLAGS)
ld_flags := $(LDFLAGS) -L"$(BUILD_PREFIX)"/libev -lev
ld_flags := $(LDFLAGS) -L"$(LIB_BUILD_PREFIX)" -lev
xxld_flags := $(XXLDFLAGS)

# --- targets ---------------------------------------------------------------------
Expand Down
60 changes: 37 additions & 23 deletions sol/common.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#ifndef S_COMMON_H_
#define S_COMMON_H_
#define S_COMMON_H_INSIDE_
#define S_INTERNAL_

#define S_STR1(str) #str
#define S_STR(str) S_STR1(str)
Expand All @@ -14,6 +14,8 @@
#ifndef S_DEBUG
#define S_DEBUG 0
#endif
// Disable multiprocessing?
//#define S_WITHOUT_MP 0

#include <sol/common_target.h>

Expand All @@ -23,7 +25,26 @@
#define S_FILENAME ((strrchr(__FILE__, '/') ?: __FILE__ - 1) + 1)
#endif

#define S_countof(a) (sizeof(a)/sizeof(*(a)))
#define s_countof(a) (sizeof(a)/sizeof(*(a)))

// Assertion macros
#if !NDEBUG
#define SAssert(x) assert(x)
// Important: The following macros _always_ evaluate `x`, even when compiling
// w/ assertions disabled. The purpose is to allow wrapping like so:
// SAssertNil(somelibcfunc(dostuff))
//
#define SAssertTrue(x) SAssert((x) == true)
#define SAssertFalse(x) SAssert((x) == false)
#define SAssertNil(x) SAssert((x) == 0)
#define SAssertNotNil(x) SAssert((x) != 0)
#else
#define SAssert(x) ((void)0)
#define SAssertTrue(x) (x)
#define SAssertFalse(x) (x)
#define SAssertNil(x) (x)
#define SAssertNotNil(x) (x)
#endif

// Terminate process with status 70 (EX_SOFTWARE), writing `fmt` with optional
// arguments to stderr.
Expand Down Expand Up @@ -51,7 +72,9 @@
#else
#define S_ALWAYS_INLINE
#endif
#if __has_attribute(deprecated)
#if __has_attribute(unused)
// Attached to a function, means that the function is meant to be possibly
// unused. The compiler will not produce a warning for this function.
#define S_UNUSED __attribute__((unused))
#else
#define S_UNUSED
Expand All @@ -71,6 +94,13 @@
#else
#define S_PACKED
#endif
#if __has_attribute(aligned)
#define S_ALIGNED(bytes) __attribute__((aligned (bytes)))
#else
#warning "No align attribute available. Things might break"
#define S_ALIGNED
#endif

#if __has_builtin(__builtin_unreachable)
#define S_UNREACHABLE do { \
assert(!"Declared S_UNREACHABLE but was reached"); \
Expand All @@ -94,28 +124,10 @@
__typeof__ (b) _b = (b); \
_a < _b ? _a : _b; })


// type S_SYNC_SWAP(type *ptr, type value)
#if defined(__clang__)
// This is much more efficient than the below `_s_xchg` fallback.
#define S_SYNC_SWAP __sync_swap
#elif defined(__GNUC__) && (__GNUC__ >= 4)
static inline void* _s_xchg(void* volatile* ptr, void* value) {
void* oldval;
do {
oldval = *ptr;
} while (__sync_val_compare_and_swap(ptr, oldval, value) != oldval);
return oldval;
}
#define S_SYNC_SWAP(ptr, value) _s_xchg((void* volatile*)(ptr), (void*)(value))
#else
#error "Unsupported compiler: No atomic operations"
#endif


#include <sol/common_stdint.h> // .. include <std{io,int,def,bool}>
#include <assert.h>
#include <stdlib.h>
#include <stddef.h>
#include <errno.h>
#include <string.h>
#include <err.h>
Expand All @@ -124,5 +136,7 @@
#include <unistd.h>
#endif

#undef S_COMMON_H_INSIDE_
#include <sol/common_atomic.h>

#undef S_INTERNAL_
#endif // S_COMMON_H_
61 changes: 61 additions & 0 deletions sol/common_atomic.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#ifndef S_COMMON_ATOMIC_H_
#define S_COMMON_ATOMIC_H_
#ifndef S_INTERNAL_
#error "This file should not be included directly"
#endif

// Atomically swap integers or pointers in memory.
// E.g: int old_value = SAtomicSwap(&value, new_value);
// T SAtomicSwap(T *ptr, T value)
#if S_WITHOUT_SMP
#define SAtomicSwap(ptr, value) \
({ __typeof__ (value) oldval = *(ptr); \
*(ptr) = (value); \
oldval; })
#elif defined(__clang__)
// This is more efficient than the below fallback
#define SAtomicSwap __sync_swap
#elif defined(__GNUC__) && (__GNUC__ >= 4)
static inline void* S_UNUSED _SAtomicSwap(void* volatile* ptr, void* value) {
void* oldval;
do {
oldval = *ptr;
} while (__sync_val_compare_and_swap(ptr, oldval, value) != oldval);
return oldval;
}
#define SAtomicSwap(ptr, value) \
_SAtomicSwap((void* volatile*)(ptr), (void*)(value))
#else
#error "Unsupported compiler: Missing support for atomic operations"
#endif

// Atomically increment a 32-bit integer by N. There's no return value.
// void SAtomicSubAndFetch(T* operand, T delta)
#if S_WITHOUT_SMP
#define SAtomicAdd32(operand, delta) (*(operand) += (delta))
#elif S_TARGET_ARCH_X64 || S_TARGET_ARCH_X86
inline static void S_UNUSED SAtomicAdd32(int32_t* operand, int32_t delta) {
// From http://www.memoryhole.net/kyle/2007/05/atomic_incrementing.html
__asm__ __volatile__ (
"lock xaddl %1, %0\n" // add delta to operand
: // no output
: "m" (*operand), "r" (delta)
);
}
#elif defined(__clang__) || (defined(__GNUC__) && (__GNUC__ >= 4))
#define SAtomicAdd32 __sync_sub_and_fetch
#else
#error "Unsupported compiler: Missing support for atomic operations"
#endif

// Subtract `delta` from `operand` and return the resulting value of `operand`
// T SAtomicSubAndFetch(T* operand, T delta)
#if S_WITHOUT_SMP
#define SAtomicSubAndFetch(operand, delta) (*(operand) -= (delta))
#elif defined(__clang__) || (defined(__GNUC__) && (__GNUC__ >= 4))
#define SAtomicSubAndFetch __sync_sub_and_fetch
#else
#error "Unsupported compiler: Missing support for atomic operations"
#endif

#endif // S_COMMON_ATOMIC_H_
2 changes: 1 addition & 1 deletion sol/common_stdint.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#ifndef S_COMMON_H_INSIDE_
#ifndef S_INTERNAL_
#error "This file should not be included directly"
#endif

Expand Down
6 changes: 5 additions & 1 deletion sol/common_target.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#ifndef S_COMMON_H_INSIDE_
#ifndef S_COMMON_TARGET_H_
#define S_COMMON_TARGET_H_
#ifndef S_INTERNAL_
#error "This file should not be included directly"
#endif

Expand Down Expand Up @@ -82,3 +84,5 @@
#define S_TARGET_OS_UNKNOWN 1
#endif
//-- end S_TARGET_OS_*

#endif // S_COMMON_TARGET_H_
File renamed without changes.
6 changes: 3 additions & 3 deletions sol/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,9 @@ int main(int argc, const char** argv) {
SSched* sched = SSchedCreate();

// Schedule several tasks running the same program
//SSchedTask(sched, STaskCreate(b_fun, 0));
//SSchedTask(sched, STaskCreate(fun1, 0));
SSchedTask(sched, STaskCreate(fun2, 0));
//SSchedTask(sched, STaskCreate(b_fun, 0, 0));
//SSchedTask(sched, STaskCreate(fun1, 0, 0));
SSchedTask(sched, STaskCreate(fun2, 0, 0));

SSchedRun(&vm, sched);

Expand Down
7 changes: 5 additions & 2 deletions sol/msg.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,13 @@
// q->sentinel.next = 0;
// }

void SMsgEnqueue(SMsgQ* q, SMsg* m) {
// Based on https://groups.google.com/d/msg/lock-free/Vd9xuHrLggE/B9-URa3B37MJ

bool SMsgEnqueue(SMsgQ* q, SMsg* m) {
m->next = 0;
SMsg* prev = S_SYNC_SWAP(&q->head, m);
SMsg* prev = SAtomicSwap(&q->head, m);
prev->next = m;
return prev == &q->sentinel;
}

SMsg* SMsgDequeue(SMsgQ* q) {
Expand Down
25 changes: 15 additions & 10 deletions sol/msg.h
Original file line number Diff line number Diff line change
@@ -1,29 +1,34 @@
// Multiple Producer, Single Consumer lock-free (well, one CAS per "enqueue")
// message queue. Zero or more task running in any scheduler can send a message
// to any other task's inbox, which is a `SMsgQ`.
#ifndef S_MSG_H_
#define S_MSG_H_
#include <sol/common.h>
#include <sol/value.h>

// Multiple Producer, Single Consumer lock-free (well, one CAS per "enqueue")
// message queue. Zero or more task running in any scheduler can send a message
// to any other task's inbox, which is a `SMsgQ`.
// Based on https://groups.google.com/d/msg/lock-free/Vd9xuHrLggE/B9-URa3B37MJ
struct STask;

typedef struct SMsg {
struct SMsg* volatile next;
SValue value;
} SMsg;
// Size is 24 bytes (8-byte aligned with 8-byte pointers)
struct STask* sender;
} SMsg; // 32

typedef struct SMsgQ {
SMsg* volatile head;
uint8_t _pad; // cache line hack
SMsg* tail;
SMsg sentinel;
} SMsgQ;
// Size is 48 bytes (8-byte aligned with 8-byte pointers)
} SMsgQ; // 56

// Constant initializer. E.g. `q = S_MSGQ_INIT(q);`
#define S_MSGQ_INIT(q) (SMsgQ){&(q).sentinel, 0, &(q).sentinel, {0}}

#define S_MSGQ_INIT(q) {&(q).sentinel, &(q).sentinel, {0}}
// Put message `m` at end of queue `q`. Returns true if the queue was empty.
bool SMsgEnqueue(SMsgQ* q, SMsg* m);

void SMsgEnqueue(SMsgQ* q, SMsg* m);
// Get the message at the beginning of the queue. Returns 0 if there are no
// messages.
SMsg* SMsgDequeue(SMsgQ* q);

#endif // S_MSG_H_
Loading

0 comments on commit 74e10cf

Please sign in to comment.