-
Notifications
You must be signed in to change notification settings - Fork 39
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Woho. Epic commit with hierarchical tasks, function calls, SPAWN inst…
…ruction, task message passing, etc etc. Still WIP, but tests pass and main.c runs
- Loading branch information
Showing
24 changed files
with
529 additions
and
322 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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_ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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_ |
Oops, something went wrong.