Browse Source

add cops impl

Signed-off-by: Rain <rain.by.zhou@gmail.com>
main cops_v2
Rain 4 years ago
parent
commit
53ad16b79a
  1. 2
      .gitignore
  2. 3
      build.sh
  3. 28
      context.cpp
  4. 68
      context.h
  5. 26
      main.cpp
  6. 48
      switch_context.S

2
.gitignore

@ -1,6 +1,8 @@
# Prerequisites
*.d
cops
# Compiled Object files
*.slo
*.lo

3
build.sh

@ -0,0 +1,3 @@
#!/bin/bash
g++ -g -std=c++17 -I. *.cpp *.S -o cops

28
context.cpp

@ -0,0 +1,28 @@
#include <context.h>
#include <iostream>
namespace cops{
static coro_t def([](){});
coro_t* current = &def;
void main(coro_t* coro, context from) {
coro->next_->ctx_ = from;
coro->fn_();
coro->switch_out();
}
void coro_t::switch_out() {
current = next_;
context from = switch_context(next_, next_->ctx_);
next_ = static_cast<coro_t*>(from);
next_->ctx_ = from;
}
void coro_t::switch_in() {
next_ = current;
current = this;
ctx_ = switch_context(this, ctx_);
}
}

68
context.h

@ -0,0 +1,68 @@
#pragma once
#include <memory>
#include <functional>
#include <stdint.h>
namespace cops {
class coro_t;
}
using context = void*;
extern "C"
context switch_context(cops::coro_t* to, context ctx);
extern "C"
context make_context(context sp, void* entry);
namespace cops {
class stack_t {
public:
stack_t(size_t size = 64 * 1024) : size_(size) {
sp_ = new char[size_];
}
~stack_t() {
delete[] sp_;
}
void* sp() {
return sp_ + size_ - 1;
}
private:
char* sp_;
size_t size_;
};
class coro_t {
public:
using Fn = std::function<void(void)>;
explicit coro_t(Fn&& fn)
: fn_(std::forward<Fn>(fn)) {
}
~coro_t() {
}
void switch_out();
void switch_in();
public:
context ctx_;
coro_t* next_;
stack_t stack_;
Fn fn_;
};
extern coro_t* current;
void main(coro_t* coro, context ctx);
template <class Fn>
std::unique_ptr<coro_t> make_coro(Fn&& fn) {
auto coro = std::make_unique<coro_t>(std::forward<Fn>(fn));
coro->ctx_ = make_context(coro->stack_.sp(), (void*)main);
return coro;
}
} // cops

26
main.cpp

@ -0,0 +1,26 @@
#include <iostream>
#include <context.h>
int main() {
std::unique_ptr<cops::coro_t> coro;
std::unique_ptr<cops::coro_t> sub_coro;
coro = cops::make_coro([&sub_coro]() {
std::cout << "coro" << std::endl;
cops::current->switch_out();
sub_coro = cops::make_coro([]() {
std::cout << "sub_coro" << std::endl;
cops::current->switch_out();
std::cout << "sub_coro exit" << std::endl;
});
sub_coro->switch_in();
std::cout << "coro exit" << std::endl;
});
std::cout << "main" << std::endl;
coro->switch_in();
std::cout << "main" << std::endl;
coro->switch_in();
std::cout << "main" << std::endl;
sub_coro->switch_in();
std::cout << "exit" << std::endl;
return 0;
}

48
switch_context.S

@ -0,0 +1,48 @@
.file "switch_context.S"
.text
.globl switch_context
.type switch_context,@function
.align 16
switch_context:
leaq -56(%rsp), %rsp
movq %rdi, (%rsp) /* save suspended coro_t* */
movq %r12, 8(%rsp)
movq %r13, 16(%rsp)
movq %r14, 24(%rsp)
movq %r15, 32(%rsp)
movq %rbx, 40(%rsp)
movq %rbp, 48(%rsp)
movq %rsp, %rax /* return suspended context */
movq %rsi, %rsp /* restore context */
movq 56(%rsp), %r8 /* return point */
movq 8(%rsp), %r12
movq 16(%rsp), %r13
movq 24(%rsp), %r14
movq 32(%rsp), %r15
movq 40(%rsp), %rbx
movq 48(%rsp), %rbp
leaq 64(%rsp), %rsp
movq %rax, %rsi /* for main(coro_t*, context) 2rd argument */
jmp *%r8
.size switch_context,.-switch_context
.section .note.GNU-stack,"",%progbits
.text
.globl make_context
.type make_context,@function
.align 16
make_context:
andq $-16, %rdi /* 16 bytes align for movdqa */
leaq -56(%rdi), %rdi
movq %rsi, 56(%rdi) /* set entry */
movq %rdi, %rax /* return updated context */
retq
.size make_context,.-make_context
.section .note.GNU-stack,"",%progbits
Loading…
Cancel
Save