Skip to content

Commit

Permalink
[Fiber] Add x64 implementation on MacOS
Browse files Browse the repository at this point in the history
  • Loading branch information
JiayinCao committed Jan 15, 2023
1 parent b1b884d commit c0825d6
Show file tree
Hide file tree
Showing 7 changed files with 203 additions and 5 deletions.
2 changes: 1 addition & 1 deletion src/job/fiber_impl/fiber_impl_asm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

#include "../fiber.h"

#if defined(SORT_ARM64_TARGET) && defined(SORT_IN_MAC)
#if defined(SORT_IN_MAC)

static inline void RunFiber(Fiber* fiber){
if(fiber->m_target_func)
Expand Down
2 changes: 1 addition & 1 deletion src/job/fiber_impl/fiber_impl_asm_aarch64_shared.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
this program. If not, see <http://www.gnu.org/licenses/gpl-3.0.html>.
*/

// This file simply defines some macros to be shared by assembly language and cpp code
// This file simply defines some macros to be shared by assembly language and C code

#define FIBER_REG_X0 0x00
#define FIBER_REG_X1 0x08
Expand Down
44 changes: 44 additions & 0 deletions src/job/fiber_impl/fiber_impl_asm_x64.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
This file is a part of SORT(Simple Open Ray Tracing), an open-source cross
platform physically based renderer.
Copyright (c) 2011-2023 by Jiayin Cao - All rights reserved.
SORT is a free software written for educational purpose. Anyone can distribute
or modify it under the the terms of the GNU General Public License Version 3 as
published by the Free Software Foundation. However, there is NO warranty that
all components are functional in a perfect manner. Without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program. If not, see <http://www.gnu.org/licenses/gpl-3.0.html>.
*/

#include <stdint.h>
#include "core/define.h"

#if defined(SORT_X64_TARGET) && (defined(SORT_IN_MAC) || defined(SORT_IN_LINUX))

#include "fiber_impl_asm_x64.h"

// fiber entry function
static inline void fiber_entry(void (*target)(void*), void* arg) {
target(arg);
}

// setup a new fiber
void create_fiber(struct FiberContext* context,
void* stack,
uint32_t stackSize,
void (*target)(void*),
void* arg) {
uintptr_t* stack_top = (uintptr_t*)((uint8_t*)(stack) + stackSize);
context->rip = (uintptr_t)&fiber_entry;
context->rdi = (uintptr_t)target;
context->rsi = (uintptr_t)arg;
context->rsp = (uintptr_t)&stack_top[-3];
stack_top[-2] = 0; // No return target.
}

#endif
53 changes: 51 additions & 2 deletions src/job/fiber_impl/fiber_impl_asm_x64.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,56 @@
this program. If not, see <http://www.gnu.org/licenses/gpl-3.0.html>.
*/

#include "fiber_impl_asm_x64_shared.h"

struct FiberContext{
// type of each register, has to be 64 bits
typedef unsigned long long Register;

};
struct FiberContext {
// callee-saved registers
Register rbx;
Register rbp;
Register r12;
Register r13;
Register r14;
Register r15;

// parameter registers
Register rdi;
Register rsi;

// stack and instruction registers
Register rsp;
Register rip;
};

#if defined(__cplusplus)

#include <cstddef>

// X64's register should be 64 bits wide
static_assert(sizeof(Register) == 8);

#define CHECK_OFFSET(REGISTER, OFFSET) \
static_assert(offsetof(FiberContext, REGISTER) == OFFSET, "Incorrect register offset")

CHECK_OFFSET(rbx, FIBER_REG_RBX);
CHECK_OFFSET(rbp, FIBER_REG_RBP);
CHECK_OFFSET(r12, FIBER_REG_R12);
CHECK_OFFSET(r13, FIBER_REG_R13);
CHECK_OFFSET(r14, FIBER_REG_R14);
CHECK_OFFSET(r15, FIBER_REG_R15);
CHECK_OFFSET(rdi, FIBER_REG_RDI);
CHECK_OFFSET(rsi, FIBER_REG_RSI);
CHECK_OFFSET(rsp, FIBER_REG_RSP);
CHECK_OFFSET(rip, FIBER_REG_RIP);

extern "C" {
// @brief Low level function to switch fibers, this is implemented in assembly language
extern void switch_fiber(FiberContext* from, const FiberContext* to);

// @brief Create a brand new fiber
extern void create_fiber(FiberContext* context, void* stack, uint32_t stackSize, void (*target)(void*), void* arg);
}

#endif
68 changes: 68 additions & 0 deletions src/job/fiber_impl/fiber_impl_asm_x64.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
This file is a part of SORT(Simple Open Ray Tracing), an open-source cross
platform physically based renderer.
Copyright (c) 2011-2023 by Jiayin Cao - All rights reserved.
SORT is a free software written for educational purpose. Anyone can distribute
or modify it under the the terms of the GNU General Public License Version 3 as
published by the Free Software Foundation. However, there is NO warranty that
all components are functional in a perfect manner. Without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program. If not, see <http://www.gnu.org/licenses/gpl-3.0.html>.
*/


#if defined(__x86_64__)

#include "fiber_impl_asm_x64_shared.h"

// void marl_fiber_swap(marl_fiber_context* from, const marl_fiber_context* to)
// rdi: from
// rsi: to
.text
.global ASM_ENTRY_WRAPPER(switch_fiber)
.align 4
ASM_ENTRY_WRAPPER(switch_fiber):

// Save context 'from'

// Store callee-preserved registers
movq %rbx, FIBER_REG_RBX(%rdi)
movq %rbp, FIBER_REG_RBP(%rdi)
movq %r12, FIBER_REG_R12(%rdi)
movq %r13, FIBER_REG_R13(%rdi)
movq %r14, FIBER_REG_R14(%rdi)
movq %r15, FIBER_REG_R15(%rdi)

movq (%rsp), %rcx /* call stores the return address on the stack before jumping */
movq %rcx, FIBER_REG_RIP(%rdi)
leaq 8(%rsp), %rcx /* skip the pushed return address */
movq %rcx, FIBER_REG_RSP(%rdi)

// Load context 'to'
movq %rsi, %r8

// Load callee-preserved registers
movq FIBER_REG_RBX(%r8), %rbx
movq FIBER_REG_RBP(%r8), %rbp
movq FIBER_REG_R12(%r8), %r12
movq FIBER_REG_R13(%r8), %r13
movq FIBER_REG_R14(%r8), %r14
movq FIBER_REG_R15(%r8), %r15

// Load first two call parameters
movq FIBER_REG_RDI(%r8), %rdi
movq FIBER_REG_RSI(%r8), %rsi

// Load stack pointer
movq FIBER_REG_RSP(%r8), %rsp

// Load instruction pointer, and jump
movq FIBER_REG_RIP(%r8), %rcx
jmp *%rcx

#endif // defined(__x86_64__)
37 changes: 37 additions & 0 deletions src/job/fiber_impl/fiber_impl_asm_x64_shared.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
This file is a part of SORT(Simple Open Ray Tracing), an open-source cross
platform physically based renderer.
Copyright (c) 2011-2023 by Jiayin Cao - All rights reserved.
SORT is a free software written for educational purpose. Anyone can distribute
or modify it under the the terms of the GNU General Public License Version 3 as
published by the Free Software Foundation. However, there is NO warranty that
all components are functional in a perfect manner. Without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program. If not, see <http://www.gnu.org/licenses/gpl-3.0.html>.
*/

// This file simply defines some macros to be shared by assembly language and C code

#include "core/define.h"

#define FIBER_REG_RBX 0x00
#define FIBER_REG_RBP 0x08
#define FIBER_REG_R12 0x10
#define FIBER_REG_R13 0x18
#define FIBER_REG_R14 0x20
#define FIBER_REG_R15 0x28
#define FIBER_REG_RDI 0x30
#define FIBER_REG_RSI 0x38
#define FIBER_REG_RSP 0x40
#define FIBER_REG_RIP 0x48

#if defined(SORT_IN_MAC)
#define ASM_ENTRY_WRAPPER(x) _##x
#else
#define ASM_ENTRY_WRAPPER(x) x
#endif
2 changes: 1 addition & 1 deletion src/unittests/fiber.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ using namespace unittest;

// only Apple Silicon Mac has fiber implementation now
// next step is to support X64, Intel Mac and Ubuntu, they should be quite similar
#if defined(SORT_ARM64_TARGET) && defined(SORT_IN_MAC)
#if defined(SORT_IN_MAC)

// Convert the current thread to a fiber
TEST(Fiber, ConvertCurrentThreadToFiber) {
Expand Down

0 comments on commit c0825d6

Please sign in to comment.