├── CMakeLists.txt ├── bin └── LIB && BIN ├── build.sh ├── include └── meng.h ├── libmeng.sln ├── libmeng.vcxproj ├── libmeng.vcxproj.filters ├── log.txt ├── readme.md ├── src ├── common.h ├── linux64 │ └── swapcontext.s ├── meng.cpp └── win32 │ └── swapcontext.asm └── test ├── CMakeLists.txt ├── test.cpp ├── test.vcxproj └── test.vcxproj.filters /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | CMAKE_MINIMUM_REQUIRED(VERSION 2.8) 2 | 3 | PROJECT(MENG) 4 | ENABLE_LANGUAGE(CXX ASM) 5 | SET(MENG_SRC_LIST ./src/meng.cpp ./src/linux64/swapcontext.s) 6 | INCLUDE_DIRECTORIES(./include) 7 | INCLUDE_DIRECTORIES(./src) 8 | MESSAGE(STATUS "This is cmdcontroller BINARY dir " ${MENG_BINARY_DIR}) 9 | MESSAGE(STATUS "This is cmdcontroller SOURCE dir " ${MENG_SOURCE_DIR}) 10 | MESSAGE(STATUS "This is cmdcontroller SOURCE file " ${MENG_SRC_LIST}) 11 | IF(REMOD) 12 | SET(CMAKE_CXX_FLAGS "-O3 -Wall -Werror -gdwarf-2 -m64 -DNDEBUG") 13 | MESSAGE("build release lib") 14 | ELSE() 15 | SET(CMAKE_CXX_FLAGS "-g3 -O0 -Wall -Werror -gdwarf-2 -m64 -D_DEBUG") 16 | MESSAGE("build debug lib") 17 | ENDIF() 18 | SET(LIBRARY_OUTPUT_PATH ${MENG_BINARY_DIR}/bin) 19 | SET(ASM_OPTIONS "-x assembler-with-cpp") 20 | SET(CMAKE_ASM_FLAGS "${CMAKE_CXX_FLAGS} ${ASM_OPTIONS}" ) 21 | ADD_LIBRARY(meng STATIC ${MENG_SRC_LIST}) 22 | -------------------------------------------------------------------------------- /bin/LIB && BIN: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/esrrhs/libmeng/8c284855fbbda8107193fe76e8e7704181b28b30/bin/LIB && BIN -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | BUILD_FLAG="" 4 | 5 | if [ $# == 1 ] && [ $1 == "release" ];then 6 | BUILD_FLAG=" -DREMOD=ON" 7 | fi 8 | 9 | #lib 10 | rm CMakeCache.txt -rf 11 | rm CMakeFiles -rf 12 | rm cmake_install.cmake -rf 13 | rm Makefile -rf 14 | cmake . $BUILD_FLAG 15 | make clean 16 | make -j5 17 | 18 | #test 19 | cd test 20 | rm CMakeCache.txt -rf 21 | rm CMakeFiles -rf 22 | rm cmake_install.cmake -rf 23 | rm Makefile -rf 24 | cmake . $BUILD_FLAG 25 | make clean 26 | make -j5 27 | cd .. 28 | 29 | echo "build ok" 30 | -------------------------------------------------------------------------------- /include/meng.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/esrrhs/libmeng/8c284855fbbda8107193fe76e8e7704181b28b30/include/meng.h -------------------------------------------------------------------------------- /libmeng.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2013 4 | VisualStudioVersion = 12.0.21005.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test", "test\test.vcxproj", "{2B295A0E-C608-4B6E-AC3D-9232BA59DC07}" 7 | ProjectSection(ProjectDependencies) = postProject 8 | {51F12481-ED12-4D40-BCB1-8F8A37E9B801} = {51F12481-ED12-4D40-BCB1-8F8A37E9B801} 9 | EndProjectSection 10 | EndProject 11 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libmeng", "libmeng.vcxproj", "{51F12481-ED12-4D40-BCB1-8F8A37E9B801}" 12 | EndProject 13 | Global 14 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 15 | Debug|Win32 = Debug|Win32 16 | Release|Win32 = Release|Win32 17 | EndGlobalSection 18 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 19 | {2B295A0E-C608-4B6E-AC3D-9232BA59DC07}.Debug|Win32.ActiveCfg = Debug|Win32 20 | {2B295A0E-C608-4B6E-AC3D-9232BA59DC07}.Debug|Win32.Build.0 = Debug|Win32 21 | {2B295A0E-C608-4B6E-AC3D-9232BA59DC07}.Release|Win32.ActiveCfg = Release|Win32 22 | {2B295A0E-C608-4B6E-AC3D-9232BA59DC07}.Release|Win32.Build.0 = Release|Win32 23 | {51F12481-ED12-4D40-BCB1-8F8A37E9B801}.Debug|Win32.ActiveCfg = Debug|Win32 24 | {51F12481-ED12-4D40-BCB1-8F8A37E9B801}.Debug|Win32.Build.0 = Debug|Win32 25 | {51F12481-ED12-4D40-BCB1-8F8A37E9B801}.Release|Win32.ActiveCfg = Release|Win32 26 | {51F12481-ED12-4D40-BCB1-8F8A37E9B801}.Release|Win32.Build.0 = Release|Win32 27 | EndGlobalSection 28 | GlobalSection(SolutionProperties) = preSolution 29 | HideSolutionNode = FALSE 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /libmeng.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {51F12481-ED12-4D40-BCB1-8F8A37E9B801} 15 | Win32Proj 16 | libmeng 17 | 18 | 19 | 20 | StaticLibrary 21 | true 22 | MultiByte 23 | v120 24 | MultiByte 25 | 26 | 27 | StaticLibrary 28 | false 29 | true 30 | MultiByte 31 | v120 32 | true 33 | MultiByte 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | true 48 | ./bin 49 | $(ProjectName)_d 50 | 51 | 52 | false 53 | ./bin 54 | 55 | 56 | 57 | 58 | 59 | Level3 60 | Disabled 61 | WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) 62 | ./include;%(AdditionalIncludeDirectories) 63 | 64 | 65 | Console 66 | true 67 | 68 | 69 | 70 | 71 | Level3 72 | 73 | 74 | MaxSpeed 75 | true 76 | true 77 | WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) 78 | ./include;%(AdditionalIncludeDirectories) 79 | 80 | 81 | Console 82 | true 83 | true 84 | true 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | Document 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | -------------------------------------------------------------------------------- /libmeng.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /log.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/esrrhs/libmeng/8c284855fbbda8107193fe76e8e7704181b28b30/log.txt -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # libmeng # 2 | **libmeng**是一个跨平台的轻量级协程库,可以轻松组建协程、RPC 3 | 4 | # 特性 # 5 | * 支持win32、linux64 6 | * 支持协程中创建协程 7 | * 支持信号处理 8 | * 支持自定义参数 9 | * 支持栈溢出检测 10 | 11 | # API说明 # 12 | ### meng_create ### 13 | 创建协程对象,用来保存参数及栈信息,参数分别为:入口函数、栈大小、参数地址、参数大小 14 | ### meng_run ### 15 | 执行一个协程,直到调用meng_yield或者函数执行完 16 | ### meng_yield ### 17 | 释放执行权,跳转到meng_run的地方 18 | ### meng_end ### 19 | 判断一个协程是否结束 20 | ### meng_delete ### 21 | 释放协程对象 22 | 23 | # 示例 # 24 | 25 | ``` 26 | #!c++ 27 | 28 | 29 | // 协程入口 30 | void func(meng * m, void * arg, size_t argsize) 31 | { 32 | for (int i = 0; i < LOOP_NUM; i++) 33 | { 34 | printf("func %d %d\n", *(int*)arg, i); 35 | meng_yield(m); 36 | } 37 | } 38 | 39 | int main(int argc, const char * argv[]) 40 | { 41 | // 创建两个协程,指定函数入口、堆栈大小及参数 42 | int arg1 = 1; 43 | int arg2 = 2; 44 | meng * m1 = meng_create(func, 8 * 1024, &arg1, sizeof(arg1)); 45 | meng * m2 = meng_create(func, 8 * 1024, &arg2, sizeof(arg2)); 46 | 47 | // 循环执行两个协程 48 | while (!meng_end(m1) || !meng_end(m2)) 49 | { 50 | meng_run(m1); 51 | meng_run(m2); 52 | } 53 | 54 | // 销毁 55 | meng_delete(m1); 56 | meng_delete(m2); 57 | 58 | return 0; 59 | } 60 | ``` 61 | -------------------------------------------------------------------------------- /src/common.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "meng.h" 4 | 5 | #define MMALLOC(x) malloc(x) 6 | #define MFREE(x) free(x) 7 | 8 | enum meng_status 9 | { 10 | ms_start, 11 | ms_end, 12 | }; 13 | 14 | struct meng 15 | { 16 | meng_main func; 17 | meng_status status; 18 | char * father_context; 19 | char * last_context; 20 | char * stack; 21 | size_t stacksize; 22 | void * arg; 23 | int magic; 24 | }; 25 | 26 | // save old, load new 27 | extern "C" void swap_context(char * old_context, char * new_context); 28 | 29 | // ini 30 | extern "C" void ini_context(char * context); 31 | 32 | // get meng pointer 33 | extern "C" meng * get_meng(); 34 | 35 | #ifdef WIN32 36 | #define CONTEXT_SIZE (84) 37 | #define CONTEXT_RIP_POS (32) 38 | #define CONTEXT_RBP_POS (28) 39 | #define CONTEXT_RSP_POS (24) 40 | #define CONTEXT_RDI_POS (20) 41 | #define CONTEXT_RSI_POS (16) 42 | #define CONTEXT_RDX_POS (12) 43 | #else 44 | #define CONTEXT_SIZE (264) 45 | #define CONTEXT_RIP_POS (64) 46 | #define CONTEXT_RBP_POS (56) 47 | #define CONTEXT_RSP_POS (48) 48 | #define CONTEXT_RDI_POS (40) 49 | #define CONTEXT_RSI_POS (32) 50 | #define CONTEXT_RDX_POS (24) 51 | #endif 52 | -------------------------------------------------------------------------------- /src/linux64/swapcontext.s: -------------------------------------------------------------------------------- 1 | 2 | .globl swap_context 3 | swap_context: 4 | 5 | /* rdi, rsi */ 6 | 7 | /* save */ 8 | mov %RAX, (%rdi) 9 | mov %RBX, 8(%rdi) 10 | mov %RCX, 16(%rdi) 11 | mov %RDX, 24(%rdi) 12 | mov %RSI, 32(%rdi) 13 | mov %RDI, 40(%rdi) 14 | 15 | /* RSP */ 16 | lea 8(%rsp), %RCX 17 | mov %RCX, 48(%rdi) 18 | 19 | mov %RBP, 56(%rdi) 20 | 21 | /* EIP */ 22 | mov (%rsp), %RCX 23 | mov %RCX, 64(%rdi) 24 | 25 | mov %r8, 72(%rdi) 26 | mov %r9, 80(%rdi) 27 | mov %r10, 88(%rdi) 28 | mov %r11, 96(%rdi) 29 | mov %r12, 104(%rdi) 30 | mov %r13, 112(%rdi) 31 | mov %r14, 120(%rdi) 32 | mov %r15, 128(%rdi) 33 | 34 | movups %xmm0, 136(%rdi) 35 | movups %xmm1, 152(%rdi) 36 | movups %xmm2, 168(%rdi) 37 | movups %xmm3, 184(%rdi) 38 | movups %xmm4, 200(%rdi) 39 | movups %xmm5, 216(%rdi) 40 | movups %xmm6, 232(%rdi) 41 | movups %xmm7, 248(%rdi) 42 | 43 | /* load */ 44 | mov (%rsi), %RAX 45 | mov 8(%rsi), %RBX 46 | mov 16(%rsi), %RCX 47 | mov 24(%rsi), %RDX 48 | mov 40(%rsi), %RDI 49 | mov 48(%rsi), %RSP 50 | mov 56(%rsi), %RBP 51 | 52 | mov 72(%rsi), %r8 53 | mov 80(%rsi), %r9 54 | mov 88(%rsi), %r10 55 | mov 96(%rsi), %r11 56 | mov 104(%rsi), %r12 57 | mov 112(%rsi), %r13 58 | mov 120(%rsi), %r14 59 | mov 128(%rsi), %r15 60 | 61 | movups 136(%rdi), %xmm0 62 | movups 152(%rdi), %xmm1 63 | movups 168(%rdi), %xmm2 64 | movups 184(%rdi), %xmm3 65 | movups 200(%rdi), %xmm4 66 | movups 216(%rdi), %xmm5 67 | movups 232(%rdi), %xmm6 68 | movups 248(%rdi), %xmm7 69 | 70 | push 64(%rsi) 71 | mov 32(%rsi), %RSI 72 | 73 | ret 74 | 75 | .globl ini_context 76 | ini_context: 77 | 78 | ret 79 | 80 | .globl get_meng 81 | get_meng: 82 | 83 | mov 8(%rbp), %rax 84 | ret 85 | 86 | -------------------------------------------------------------------------------- /src/meng.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/esrrhs/libmeng/8c284855fbbda8107193fe76e8e7704181b28b30/src/meng.cpp -------------------------------------------------------------------------------- /src/win32/swapcontext.asm: -------------------------------------------------------------------------------- 1 | .model FLAT, C 2 | 3 | .code 4 | 5 | swap_context PROC 6 | 7 | ; eax father_context dword ptr [esp+4] 8 | ; ecx last_context dword ptr [esp+8] 9 | 10 | push EAX 11 | mov EAX, dword ptr [esp+8] 12 | 13 | ; save 14 | mov dword ptr [eax+4], EBX 15 | mov dword ptr [eax+8], ECX 16 | mov dword ptr [eax+12], EDX 17 | mov dword ptr [eax+16], ESI 18 | mov dword ptr [eax+20], EDI 19 | 20 | ;; ESP 21 | lea ECX, [esp] + 8 22 | mov dword ptr [eax+24], ECX 23 | 24 | mov dword ptr [eax+28], EBP 25 | 26 | ;; EIP 27 | mov ECX, dword ptr [esp + 4] 28 | mov dword ptr [eax+32], ECX 29 | 30 | mov word ptr [eax+36], SS 31 | mov word ptr [eax+40], ES 32 | mov word ptr [eax+44], DS 33 | mov word ptr [eax+48], FS 34 | 35 | ;; SSE 36 | movss dword ptr [eax+52], XMM0 37 | movss dword ptr [eax+56], XMM1 38 | movss dword ptr [eax+60], XMM2 39 | movss dword ptr [eax+64], XMM3 40 | movss dword ptr [eax+68], XMM4 41 | movss dword ptr [eax+72], XMM5 42 | movss dword ptr [eax+76], XMM6 43 | movss dword ptr [eax+80], XMM7 44 | 45 | mov ECX, EAX 46 | pop EAX 47 | mov dword ptr [ECX+0], EAX 48 | 49 | mov ECX, dword ptr [esp+8] 50 | 51 | ; load 52 | mov EAX, dword ptr [ecx+0] 53 | mov EBX, dword ptr [ecx+4] 54 | mov EDX, dword ptr [ecx+12] 55 | mov ESI, dword ptr [ecx+16] 56 | mov EDI, dword ptr [ecx+20] 57 | mov ESP, dword ptr [ecx+24] 58 | mov EBP, dword ptr [ecx+28] 59 | 60 | mov FS, word ptr [ecx+48] 61 | mov ES, word ptr [ecx+40] 62 | mov DS, word ptr [ecx+44] 63 | mov SS, word ptr [ecx+36] 64 | 65 | ;; SSE 66 | movss XMM0, dword ptr [ecx+52] 67 | movss XMM1, dword ptr [ecx+56] 68 | movss XMM2, dword ptr [ecx+60] 69 | movss XMM3, dword ptr [ecx+64] 70 | movss XMM4, dword ptr [ecx+68] 71 | movss XMM5, dword ptr [ecx+72] 72 | movss XMM6, dword ptr [ecx+76] 73 | movss XMM7, dword ptr [ecx+80] 74 | 75 | push dword ptr [ecx+32] 76 | mov ECX, dword ptr [ecx+8] 77 | 78 | ret 79 | 80 | swap_context ENDP 81 | 82 | ini_context PROC 83 | 84 | ; ecx context 85 | 86 | mov ECX, dword ptr [esp+4] 87 | 88 | mov word ptr [ecx+36], SS 89 | mov word ptr [ecx+40], ES 90 | mov word ptr [ecx+44], DS 91 | mov word ptr [ecx+48], FS 92 | 93 | ret 94 | 95 | ini_context ENDP 96 | 97 | get_meng PROC 98 | 99 | mov eax, dword ptr [ebp+4] 100 | 101 | ret 102 | 103 | get_meng ENDP 104 | 105 | end 106 | -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | CMAKE_MINIMUM_REQUIRED(VERSION 2.8) 2 | 3 | PROJECT(TEST) 4 | AUX_SOURCE_DIRECTORY(./ TEST_SRC_LIST) 5 | INCLUDE_DIRECTORIES(./) 6 | INCLUDE_DIRECTORIES(../include) 7 | MESSAGE(STATUS "This is cmdcontroller BINARY dir " ${TEST_BINARY_DIR}) 8 | MESSAGE(STATUS "This is cmdcontroller SOURCE dir " ${TEST_SOURCE_DIR}) 9 | MESSAGE(STATUS "This is cmdcontroller SOURCE file " ${TEST_SRC_LIST}) 10 | LINK_DIRECTORIES(${TEST_SOURCE_DIR}/../bin/) 11 | IF(REMOD) 12 | SET(CMAKE_CXX_FLAGS "-O3 -Wall -Werror -gdwarf-2 -m64 -DNDEBUG") 13 | MESSAGE("build release test") 14 | ELSE() 15 | SET(CMAKE_CXX_FLAGS "-g3 -O0 -Wall -Werror -gdwarf-2 -m64 -D_DEBUG") 16 | MESSAGE("build debug test") 17 | ENDIF() 18 | SET(EXECUTABLE_OUTPUT_PATH ${TEST_BINARY_DIR}/../bin) 19 | ADD_EXECUTABLE(test ${TEST_SRC_LIST}) 20 | TARGET_LINK_LIBRARIES(test meng profiler) 21 | -------------------------------------------------------------------------------- /test/test.cpp: -------------------------------------------------------------------------------- 1 | #include "../include/meng.h" 2 | #include 3 | #include 4 | #include 5 | 6 | #ifndef WIN32 7 | #include "gperftools/profiler.h" 8 | #endif 9 | 10 | #ifndef _DEBUG 11 | #define LOOP_NUM 10000000 12 | #else 13 | #define LOOP_NUM 10 14 | #endif 15 | 16 | void func(meng * m, void * arg, size_t argsize) 17 | { 18 | for (int i = 0; i < LOOP_NUM; i++) 19 | { 20 | #ifdef _DEBUG 21 | printf("func %d %d\n", *(int*)arg, i); 22 | #endif 23 | meng_yield(m); 24 | } 25 | } 26 | 27 | int main(int argc, const char * argv[]) 28 | { 29 | int arg1 = 1; 30 | int arg2 = 2; 31 | meng * m1 = meng_create(func, 8 * 1024, &arg1, sizeof(arg1)); 32 | meng * m2 = meng_create(func, 8 * 1024, &arg2, sizeof(arg2)); 33 | 34 | unsigned int begin,end; 35 | 36 | begin = time(0); 37 | 38 | #ifndef WIN32 39 | #ifndef _DEBUG 40 | ProfilerStart("meng.prof"); 41 | #endif 42 | #endif 43 | 44 | while (!meng_end(m1) || !meng_end(m2)) 45 | { 46 | meng_run(m1); 47 | meng_run(m2); 48 | } 49 | 50 | #ifndef WIN32 51 | #ifndef _DEBUG 52 | ProfilerStop(); 53 | #endif 54 | #endif 55 | 56 | end = time(0); 57 | 58 | meng_delete(m1); 59 | meng_delete(m2); 60 | 61 | printf("use %d\n", end - begin); 62 | char c; 63 | std::cin >> c; 64 | 65 | return 0; 66 | } 67 | 68 | -------------------------------------------------------------------------------- /test/test.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {2B295A0E-C608-4B6E-AC3D-9232BA59DC07} 15 | Win32Proj 16 | test 17 | 18 | 19 | 20 | Application 21 | true 22 | v120 23 | MultiByte 24 | 25 | 26 | Application 27 | false 28 | v120 29 | true 30 | MultiByte 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | true 44 | ../bin 45 | $(ProjectName)_d 46 | 47 | 48 | false 49 | ../bin 50 | 51 | 52 | 53 | 54 | 55 | Level3 56 | Disabled 57 | WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) 58 | 59 | 60 | Console 61 | true 62 | ../bin/libmeng_d.lib;%(AdditionalDependencies) 63 | 64 | 65 | 66 | 67 | Level3 68 | 69 | 70 | MaxSpeed 71 | true 72 | true 73 | WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) 74 | 75 | 76 | Console 77 | true 78 | true 79 | true 80 | ../bin/libmeng.lib;%(AdditionalDependencies) 81 | /SAFESEH:NO %(AdditionalOptions) 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /test/test.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | --------------------------------------------------------------------------------