From 222b364df032461dd50be4f958edd2b9e32dfb70 Mon Sep 17 00:00:00 2001 From: yhy Date: Sun, 15 Dec 2024 21:49:26 +0800 Subject: [PATCH] =?UTF-8?q?=E9=A1=B9=E7=9B=AE=E7=BB=93=E6=9E=84=E5=8F=8A?= =?UTF-8?q?=E5=87=A0=E4=B8=AA=E6=96=87=E4=BB=B6=E5=88=9D=E6=AD=A5=E7=BC=96?= =?UTF-8?q?=E5=86=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 4 ++++ CMakeLists.txt | 31 +++++++++++++++++++++++++ includes/coroutine/coctx.h | 33 ++++++++++++++++++++++++++ includes/coroutine/coroutine.hpp | 28 ++++++++++++++++++++++ includes/log/logger.h | 18 ++++++++++++++ src/coroutine/coctx_swap.S | 40 ++++++++++++++++++++++++++++++++ test/asmtest/main.cc | 15 ++++++++++++ test/asmtest/swap.S | 7 ++++++ test/logtest/main.cc | 16 +++++++++++++ 9 files changed, 192 insertions(+) create mode 100644 .gitignore create mode 100644 CMakeLists.txt create mode 100644 includes/coroutine/coctx.h create mode 100644 includes/coroutine/coroutine.hpp create mode 100644 includes/log/logger.h create mode 100644 src/coroutine/coctx_swap.S create mode 100644 test/asmtest/main.cc create mode 100644 test/asmtest/swap.S create mode 100644 test/logtest/main.cc diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7382536 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +bin/ +build/ +lib/ +core.* \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..059729c --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,31 @@ +cmake_minimum_required(VERSION 3.0) + +project(tinyrpc) + +enable_language(CXX ASM) + +add_compile_options(-g -Wall -std=c++11) + +include_directories(includes/coroutine) +include_directories(includes/log) + +aux_source_directory(${CMAKE_SOURCE_DIR}/src/coroutine SRC_LIST) + +# set(ASM_FILES ${CMAKE_SOURCE_DIR}/src/swap.S) + +set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/bin) +set(LIBRARY_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/lib) + + +add_library(tinyrpc + ${SRC_LIST} + # ${ASM_FILES} + +) +aux_source_directory(${CMAKE_SOURCE_DIR}/test/logtest TEST_SRC_LIST) + +add_executable(test_tinyrpc + ${TEST_SRC_LIST} + +) + diff --git a/includes/coroutine/coctx.h b/includes/coroutine/coctx.h new file mode 100644 index 0000000..15d0706 --- /dev/null +++ b/includes/coroutine/coctx.h @@ -0,0 +1,33 @@ +#pragma once + +namespace tinyrpc { + enum class reg : unsigned int { // https://wiki.osdev.org/System_V_ABI + kRBP = 6, // 栈底指针 + kRDI = 7, // rdi,调用函数时的第一个参数 + kRSI = 8, // rsi, 调用函数时的第二个参数 这两个是 根据调用约定确定的 + kRETAddr = 9, // 下一个要执行的命令地址,它将被分配给 rip + kRSP = 13, // 堆栈顶部指针 + /* + + High memory + ----------------- + | 调用者的 rbp | <- 被调用函数栈帧的起点 + ----------------- + | 返回地址 (rip) | <- 存储调用函数后的下一条指令地址 + ----------------- + | 局部变量 | + ----------------- + Low memory + */ + }; + + struct coctx { // Coroutine Context + void* regs[14]{}; // 初始化为 0 + }; + + // 将当前寄存器的状态保存到第一个上下文中,然后从第二个上下文中取出寄存器的状态并将其分配给寄存器。 + extern "C" void coctx_swap(coctx *, coctx *) asm("coctx_swap"); + + + +} \ No newline at end of file diff --git a/includes/coroutine/coroutine.hpp b/includes/coroutine/coroutine.hpp new file mode 100644 index 0000000..e786f09 --- /dev/null +++ b/includes/coroutine/coroutine.hpp @@ -0,0 +1,28 @@ +#pragma once +#include "coctx.h" +#include +namespace tinyrpc { + + + class Coroutine { + private: + Coroutine(); + public: + Coroutine(std::size_t stack_size, void* stack_sp); + Coroutine(std::size_t stack_size, void* stack_sp, std::function cb); + + int getCorID() const {return m_cor_id;} + + private: + coctx m_ctx {}; // 这个协程的上下文信息 + int m_cor_id {0}; // 这个协程的 id + char* m_stack_sp {nullptr}; // 这个协程的栈空间指针 + std::size_t m_stack_size {0}; + bool m_is_in_cofunc {true}; // 调用 CoFunction 时为真,CoFunction 完成时为假。 + std::function m_callback {}; + + + }; + + +} \ No newline at end of file diff --git a/includes/log/logger.h b/includes/log/logger.h new file mode 100644 index 0000000..02d61f3 --- /dev/null +++ b/includes/log/logger.h @@ -0,0 +1,18 @@ +#pragma once +#include +#include + +// #define LOGGER (std::cout << __FILE__ << ":" << __LINE__) + +struct logger { + logger() = default; + + template + std::ostream& operator <<(T msg) { + return std::cout << __FILE__ << ":" << __LINE__ << " " << msg; + } + + ~logger() { + std::cout << std::endl; + } +}; \ No newline at end of file diff --git a/src/coroutine/coctx_swap.S b/src/coroutine/coctx_swap.S new file mode 100644 index 0000000..db7016d --- /dev/null +++ b/src/coroutine/coctx_swap.S @@ -0,0 +1,40 @@ +.globl coctx_swap +coctx_swap: + leaq (%rsp),%rax + movq %rax, 104(%rdi) + movq %rbx, 96(%rdi) + movq %rcx, 88(%rdi) + movq %rdx, 80(%rdi) + movq 0(%rax), %rax + movq %rax, 72(%rdi) + movq %rsi, 64(%rdi) + movq %rdi, 56(%rdi) + movq %rbp, 48(%rdi) + movq %r8, 40(%rdi) + movq %r9, 32(%rdi) + movq %r12, 24(%rdi) + movq %r13, 16(%rdi) + movq %r14, 8(%rdi) + movq %r15, (%rdi) + xorq %rax, %rax + + movq 48(%rsi), %rbp + movq 104(%rsi), %rsp + movq (%rsi), %r15 + movq 8(%rsi), %r14 + movq 16(%rsi), %r13 + movq 24(%rsi), %r12 + movq 32(%rsi), %r9 + movq 40(%rsi), %r8 + movq 56(%rsi), %rdi + movq 80(%rsi), %rdx + movq 88(%rsi), %rcx + movq 96(%rsi), %rbx + leaq 8(%rsp), %rsp # 把调用这个函数时主调函数压栈的返回地址弹出 + pushq 72(%rsi) # 把我们要恢复的返回地址压栈 + movq 64(%rsi), %rsi + ret + + +# https://zhuanlan.zhihu.com/p/27409164 +# https://blog.csdn.net/m0_47696151/article/details/121324729 \ No newline at end of file diff --git a/test/asmtest/main.cc b/test/asmtest/main.cc new file mode 100644 index 0000000..4625d06 --- /dev/null +++ b/test/asmtest/main.cc @@ -0,0 +1,15 @@ +#include +using namespace std; + + +extern "C" void asm_swap(void *a, void *b) asm("asm_swap"); + + +int main() { + long a = 1, b = 2; + cout << "a = " << a << ", b = " << b << endl; + asm_swap(&a, &b); + cout << "a = " << a << ", b = " << b << endl; + return 0; + +} \ No newline at end of file diff --git a/test/asmtest/swap.S b/test/asmtest/swap.S new file mode 100644 index 0000000..0587e1c --- /dev/null +++ b/test/asmtest/swap.S @@ -0,0 +1,7 @@ +.global asm_swap # 声明 swap 为全局符号,使得该符号可以被其他文件或模块引用。 +asm_swap: # 表明后续的指令是该函数的实现。 + movq (%rdi), %rax # 实现 swap 逻辑 + movq (%rsi), %rbx + movq %rax, (%rsi) + movq %rbx, (%rdi) + ret # 它将控制权返回给调用者 \ No newline at end of file diff --git a/test/logtest/main.cc b/test/logtest/main.cc new file mode 100644 index 0000000..4303ac5 --- /dev/null +++ b/test/logtest/main.cc @@ -0,0 +1,16 @@ +#include +#include "logger.h" +using namespace std; + + +// extern "C" void asm_swap(void *a, void *b) asm("asm_swap"); + + +int main() { + // long a = 1, b = 2; + // cout << "a = " << a << ", b = " << b << endl; + // asm_swap(&a, &b); + // cout << "a = " << a << ", b = " << b << endl; + // return 0; + logger() << "test"; +} \ No newline at end of file