Repository URL to install this package:
|
Version:
2.0.17 ▾
|
/* uGreen -> uWSGI green threads */
#include <uwsgi.h>
#ifdef __UCLIBC__
struct uwsgi_plugin ugreen_plugin = {
.name = "ugreen",
};
#else
#ifdef __APPLE__
#define _XOPEN_SOURCE
#endif
#include <ucontext.h>
struct uwsgi_ugreen {
int ugreen;
int stackpages;
ucontext_t main;
ucontext_t *contexts;
size_t u_stack_size;
} ug;
#define UGREEN_DEFAULT_STACKSIZE 256*1024
extern struct uwsgi_server uwsgi;
static struct uwsgi_option ugreen_options[] = {
{"ugreen", no_argument, 0, "enable ugreen coroutine subsystem", uwsgi_opt_true, &ug.ugreen, 0},
{"ugreen-stacksize", required_argument, 0, "set ugreen stack size in pages", uwsgi_opt_set_int, &ug.stackpages, 0},
{ 0, 0, 0, 0, 0, 0, 0 }
};
static void u_green_schedule_to_req() {
int id = uwsgi.wsgi_req->async_id;
uint8_t modifier1 = uwsgi.wsgi_req->uh->modifier1;
// first round ?
if (!uwsgi.wsgi_req->suspended) {
ug.contexts[id].uc_link = &ug.main;
makecontext(&ug.contexts[id], async_schedule_to_req_green, 0);
uwsgi.wsgi_req->suspended = 1;
}
// call it in the main core
if (uwsgi.p[modifier1]->suspend) {
uwsgi.p[modifier1]->suspend(NULL);
}
// save the main stack and switch to the core
swapcontext(&ug.main, &ug.contexts[id] );
// call it in the main core
if (uwsgi.p[modifier1]->resume) {
uwsgi.p[modifier1]->resume(NULL);
}
}
static void u_green_schedule_to_main(struct wsgi_request *wsgi_req) {
if (uwsgi.p[wsgi_req->uh->modifier1]->suspend) {
uwsgi.p[wsgi_req->uh->modifier1]->suspend(wsgi_req);
}
// back to main
swapcontext(&ug.contexts[wsgi_req->async_id], &ug.main);
// back to core
if (uwsgi.p[wsgi_req->uh->modifier1]->resume) {
uwsgi.p[wsgi_req->uh->modifier1]->resume(wsgi_req);
}
uwsgi.wsgi_req = wsgi_req;
}
static int u_green_init() {
static int i;
if (!ug.ugreen) {
return 0;
}
ug.u_stack_size = UGREEN_DEFAULT_STACKSIZE;
if (ug.stackpages > 0) {
ug.u_stack_size = ug.stackpages * uwsgi.page_size;
}
uwsgi_log("initializing %d uGreen threads with stack size of %lu (%lu KB)\n", uwsgi.async, (unsigned long) ug.u_stack_size, (unsigned long) ug.u_stack_size/1024);
ug.contexts = uwsgi_malloc( sizeof(ucontext_t) * uwsgi.async);
for(i=0;i<uwsgi.async;i++) {
getcontext(&ug.contexts[i]);
ug.contexts[i].uc_stack.ss_sp = mmap(NULL, ug.u_stack_size + (uwsgi.page_size*2) , PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_PRIVATE, -1, 0) + uwsgi.page_size;
if (ug.contexts[i].uc_stack.ss_sp == MAP_FAILED) {
uwsgi_error("mmap()");
exit(1);
}
// set guard pages for stack
if (mprotect(ug.contexts[i].uc_stack.ss_sp - uwsgi.page_size, uwsgi.page_size, PROT_NONE)) {
uwsgi_error("mprotect()");
exit(1);
}
if (mprotect(ug.contexts[i].uc_stack.ss_sp + ug.u_stack_size, uwsgi.page_size, PROT_NONE)) {
uwsgi_error("mprotect()");
exit(1);
}
ug.contexts[i].uc_stack.ss_size = ug.u_stack_size;
}
uwsgi.schedule_to_main = u_green_schedule_to_main;
uwsgi.schedule_to_req = u_green_schedule_to_req;
return 0;
}
struct uwsgi_plugin ugreen_plugin = {
.name = "ugreen",
.init = u_green_init,
.options = ugreen_options,
};
#endif