├── 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 |
--------------------------------------------------------------------------------