init push

This commit is contained in:
oceanbase-admin
2021-05-31 22:56:52 +08:00
commit cea7de1475
7020 changed files with 5689869 additions and 0 deletions

3
deps/easy/src/thread/CMakeLists.txt vendored Normal file
View File

@ -0,0 +1,3 @@
easy_add_objects(thread
easy_uthread.c
)

259
deps/easy/src/thread/easy_uthread.c vendored Normal file
View File

@ -0,0 +1,259 @@
/**
* Copyright (c) 2021 OceanBase
* OceanBase CE is licensed under Mulan PubL v2.
* You can use this software according to the terms and conditions of the Mulan PubL v2.
* You may obtain a copy of Mulan PubL v2 at:
* http://license.coscl.org.cn/MulanPubL-2.0
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PubL v2 for more details.
*/
#include "easy_atomic.h"
#include "thread/easy_uthread.h"
#include <signal.h>
__thread easy_uthread_control_t* easy_uthread_var = NULL;
static easy_uthread_t* easy_uthread_alloc(easy_uthread_start_pt* fn, void* args, int stack_size);
static void easy_uthread_start(uint32_t y, uint32_t x);
static void easy_uthread_context_switch(ucontext_t* from, ucontext_t* to);
void easy_uthread_init(easy_uthread_control_t* control)
{
if (easy_uthread_var == NULL) {
easy_uthread_var = control;
memset(easy_uthread_var, 0, sizeof(easy_uthread_control_t));
easy_list_init(&easy_uthread_var->runqueue);
easy_list_init(&easy_uthread_var->thread_list);
}
}
void easy_uthread_destroy()
{
easy_uthread_t *t, *t2;
if (!easy_uthread_var)
return;
easy_list_for_each_entry_safe(t, t2, &easy_uthread_var->thread_list, thread_list_node)
{
easy_pool_destroy(t->pool);
}
easy_uthread_var = NULL;
}
void easy_uthread_stop()
{
if (easy_uthread_var) {
easy_uthread_var->stoped = 1;
}
}
easy_uthread_t* easy_uthread_create(easy_uthread_start_pt* start_routine, void* args, int stack_size)
{
easy_uthread_t* t;
if (!easy_uthread_var)
return NULL;
if ((t = easy_uthread_alloc(start_routine, args, stack_size)) == NULL)
return NULL;
easy_uthread_var->thread_count++;
easy_list_add_tail(&t->thread_list_node, &easy_uthread_var->thread_list);
easy_uthread_ready(t);
return t;
}
void easy_uthread_exit(int val)
{
easy_uthread_var->exit_value = val;
easy_uthread_var->running->exiting = 1;
easy_uthread_switch();
}
void easy_uthread_switch()
{
easy_uthread_var->running->errcode = 0;
easy_uthread_needstack(0);
easy_uthread_context_switch(&easy_uthread_var->running->context, &easy_uthread_var->context);
}
easy_uthread_t* easy_uthread_current()
{
return (easy_uthread_var ? easy_uthread_var->running : NULL);
}
int easy_uthread_get_errcode()
{
if (easy_uthread_var && easy_uthread_var->running)
return easy_uthread_var->running->errcode;
else
return 0;
}
void easy_uthread_set_errcode(easy_uthread_t* t, int errcode)
{
t->errcode = (errcode & 0xff);
}
void easy_uthread_needstack(int n)
{
easy_uthread_t* t;
t = easy_uthread_var->running;
if ((char*)&t <= (char*)t->stk || (char*)&t - (char*)t->stk < 256 + n) {
fprintf(stderr, "uthread stack overflow: &t=%p tstk=%p n=%d\n", &t, t->stk, 256 + n);
abort();
}
}
void easy_uthread_ready(easy_uthread_t* t)
{
if (t) {
t->ready = 1;
easy_list_add_tail(&t->runqueue_node, &easy_uthread_var->runqueue);
}
}
int easy_uthread_yield()
{
int n;
n = easy_uthread_var->nswitch;
easy_uthread_ready(easy_uthread_var->running);
easy_uthread_switch();
return easy_uthread_var->nswitch - n - 1;
}
int easy_uthread_scheduler()
{
easy_uthread_t* t;
while (easy_uthread_var->stoped == 0) {
if (easy_uthread_var->thread_count == 0) {
break;
}
if (easy_list_empty(&easy_uthread_var->runqueue)) {
fprintf(stderr, "no runnable user thread! (%d)\n", easy_uthread_var->thread_count);
easy_uthread_var->exit_value = 1;
break;
}
// first entry
t = easy_list_entry(easy_uthread_var->runqueue.next, easy_uthread_t, runqueue_node);
easy_list_del(&t->runqueue_node);
t->ready = 0;
easy_uthread_var->running = t;
easy_uthread_var->nswitch++;
easy_uthread_context_switch(&easy_uthread_var->context, &t->context);
easy_uthread_var->running = NULL;
if (t->exiting) {
easy_list_del(&t->thread_list_node);
easy_uthread_var->thread_count--;
easy_pool_destroy(t->pool);
}
}
return easy_uthread_var->exit_value;
}
void easy_uthread_print(int sig)
{
easy_uthread_t* t;
char* extra;
fprintf(stderr, "uthread list:\n");
easy_list_for_each_entry(t, &easy_uthread_var->thread_list, thread_list_node)
{
if (t == easy_uthread_var->running)
extra = " (running)";
else if (t->ready)
extra = " (ready)";
else
extra = "";
fprintf(stderr, "%6d %s\n", t->id, extra);
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
static easy_uthread_t* easy_uthread_alloc(easy_uthread_start_pt* fn, void* args, int stack_size)
{
easy_uthread_t* t;
easy_pool_t* pool;
int size;
sigset_t zero;
uint32_t x, y;
uint64_t z;
size = sizeof(easy_uthread_t) + stack_size;
if ((pool = easy_pool_create(size)) == NULL)
return NULL;
if ((t = (easy_uthread_t*)easy_pool_alloc(pool, size)) == NULL)
goto error_exit;
memset(t, 0, sizeof(easy_uthread_t));
t->pool = pool;
t->stk = (unsigned char*)(t + 1);
t->stksize = stack_size;
t->id = ++easy_uthread_var->gid;
t->startfn = fn;
t->startargs = args;
/* do a reasonable initialization */
memset(&t->context, 0, sizeof(t->context));
sigemptyset(&zero);
sigprocmask(SIG_BLOCK, &zero, &t->context.uc_sigmask);
/* must initialize with current context */
if (getcontext(&t->context) < 0)
goto error_exit;
/* call makecontext to do the real work. */
t->context.uc_stack.ss_sp = t->stk;
t->context.uc_stack.ss_size = t->stksize;
z = (unsigned long)t;
y = (uint32_t)z;
x = (uint32_t)(z >> 32);
makecontext(&t->context, (void (*)())easy_uthread_start, 2, y, x);
return t;
error_exit:
if (pool)
easy_pool_destroy(pool);
return NULL;
}
static void easy_uthread_start(uint32_t y, uint32_t x)
{
uint64_t z;
z = x;
z <<= 32;
z |= y;
easy_uthread_t* t = (easy_uthread_t*)(long)z;
t->startfn(t->startargs);
easy_uthread_exit(0);
}
static void easy_uthread_context_switch(ucontext_t* from, ucontext_t* to)
{
if (swapcontext(from, to) < 0) {
fprintf(stderr, "swapcontext failed.\n");
abort();
}
}

102
deps/easy/src/thread/easy_uthread.h vendored Normal file
View File

@ -0,0 +1,102 @@
/**
* Copyright (c) 2021 OceanBase
* OceanBase CE is licensed under Mulan PubL v2.
* You can use this software according to the terms and conditions of the Mulan PubL v2.
* You may obtain a copy of Mulan PubL v2 at:
* http://license.coscl.org.cn/MulanPubL-2.0
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PubL v2 for more details.
*/
#ifndef EASY_UTHREAD_H
#define EASY_UTHREAD_H
#include "util/easy_pool.h"
#include "easy_list.h"
#include <ucontext.h>
EASY_CPP_START
#define EASY_UTHREAD_STACK (65536 - sizeof(easy_pool_t))
typedef void(easy_uthread_start_pt)(void* args);
typedef struct easy_uthread_t easy_uthread_t;
typedef struct easy_uthread_control_t easy_uthread_control_t;
struct easy_uthread_t {
easy_list_t runqueue_node;
easy_list_t thread_list_node;
easy_pool_t* pool;
easy_uthread_start_pt* startfn;
void* startargs;
uint32_t id;
int8_t exiting;
int8_t ready;
int8_t errcode;
uint32_t stksize;
unsigned char* stk;
ucontext_t context;
};
struct easy_uthread_control_t {
int gid;
int nswitch;
int16_t stoped;
int16_t thread_count;
int exit_value;
easy_list_t runqueue;
easy_list_t thread_list;
easy_uthread_t* running;
ucontext_t context;
};
void easy_uthread_init(easy_uthread_control_t* control);
void easy_uthread_destroy();
easy_uthread_t* easy_uthread_create(easy_uthread_start_pt* start, void* args, int stack_size);
easy_uthread_t* easy_uthread_current();
int easy_uthread_yield();
int easy_uthread_scheduler();
void easy_uthread_stop();
void easy_uthread_ready(easy_uthread_t* t);
void easy_uthread_switch();
void easy_uthread_needstack(int n);
void easy_uthread_ready(easy_uthread_t* t);
void easy_uthread_print(int sig);
int easy_uthread_get_errcode();
void easy_uthread_set_errcode(easy_uthread_t* t, int errcode);
//////////////////////
#define EASY_UTHREAD_RUN_MAIN(main_name) \
static int easy_uthread_stacksize = 0; \
static int easy_uthread_argc; \
static char** easy_uthread_argv; \
static void easy_uthread_mainstart(void* v) \
{ \
main_name(easy_uthread_argc, easy_uthread_argv); \
} \
int main(int argc, char** argv) \
{ \
int ret; \
struct sigaction sa, osa; \
easy_uthread_control_t control; \
memset(&sa, 0, sizeof sa); \
sa.sa_handler = easy_uthread_print; \
sa.sa_flags = SA_RESTART; \
sigaction(SIGQUIT, &sa, &osa); \
easy_uthread_argc = argc; \
easy_uthread_argv = argv; \
if (easy_uthread_stacksize == 0) \
easy_uthread_stacksize = 256 * 1024; \
easy_uthread_init(&control); \
easy_uthread_create(easy_uthread_mainstart, NULL, easy_uthread_stacksize); \
ret = easy_uthread_scheduler(); \
easy_uthread_destroy(); \
return ret; \
}
EASY_CPP_END
#endif