2017-06-09 23:54:20 +00:00
|
|
|
/*
|
|
|
|
libco.amd64 (2016-09-14)
|
|
|
|
author: byuu
|
|
|
|
license: public domain
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define LIBCO_C
|
|
|
|
#include "libco.h"
|
|
|
|
|
|
|
|
#include <assert.h>
|
|
|
|
#include <stdlib.h>
|
2017-06-10 22:20:58 +00:00
|
|
|
#include <string.h>
|
2017-06-09 23:54:20 +00:00
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
extern "C" {
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static long long co_active_buffer[64];
|
|
|
|
static cothread_t co_active_handle = 0;
|
|
|
|
|
2017-06-10 23:51:59 +00:00
|
|
|
static void* smalloc(size_t size)
|
|
|
|
{
|
|
|
|
char* ret = malloc(size + 16);
|
|
|
|
if (ret)
|
|
|
|
{
|
|
|
|
*(size_t*)ret = size;
|
|
|
|
return ret + 16;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void sfree(void* ptr)
|
|
|
|
{
|
|
|
|
char* original = (char*)ptr - 16;
|
|
|
|
size_t size = *(size_t*)original + 16;
|
|
|
|
memset(original, 0, size);
|
|
|
|
free(original);
|
|
|
|
}
|
|
|
|
|
2017-06-09 23:54:20 +00:00
|
|
|
extern void co_swap(cothread_t, cothread_t);
|
|
|
|
|
|
|
|
static void crash() {
|
|
|
|
assert(0); /* called only if cothread_t entrypoint returns */
|
2017-06-10 22:20:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void co_clean() {
|
|
|
|
memset(co_active_buffer, 0, sizeof(co_active_buffer));
|
2017-06-09 23:54:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
cothread_t co_active() {
|
|
|
|
if(!co_active_handle) co_active_handle = &co_active_buffer;
|
|
|
|
return co_active_handle;
|
|
|
|
}
|
|
|
|
|
|
|
|
cothread_t co_create(unsigned int size, void (*entrypoint)(void)) {
|
|
|
|
cothread_t handle;
|
|
|
|
if(!co_active_handle) co_active_handle = &co_active_buffer;
|
|
|
|
size += 512; /* allocate additional space for storage */
|
|
|
|
size &= ~15; /* align stack to 16-byte boundary */
|
|
|
|
|
2017-06-10 23:51:59 +00:00
|
|
|
if(handle = (cothread_t)smalloc(size)) {
|
2017-06-09 23:54:20 +00:00
|
|
|
long long *p = (long long*)((char*)handle + size); /* seek to top of stack */
|
|
|
|
*--p = (long long)crash; /* crash if entrypoint returns */
|
|
|
|
*--p = (long long)entrypoint; /* start of function */
|
|
|
|
*(long long*)handle = (long long)p; /* stack pointer */
|
|
|
|
}
|
|
|
|
|
|
|
|
return handle;
|
|
|
|
}
|
|
|
|
|
|
|
|
void co_delete(cothread_t handle) {
|
2017-06-10 23:51:59 +00:00
|
|
|
sfree(handle);
|
2017-06-09 23:54:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void co_switch(cothread_t handle) {
|
|
|
|
register cothread_t co_previous_handle = co_active_handle;
|
|
|
|
co_swap(co_active_handle = handle, co_previous_handle);
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
}
|
|
|
|
#endif
|