From 856fd8b00fd81de165f9c84596ac7b5fa6e5070b Mon Sep 17 00:00:00 2001 From: "roberto@fiorenzo" Date: Tue, 16 Nov 2010 10:06:19 +0100 Subject: [PATCH] towards a better uGreen (with ruby support) --- config.ru | 6 ++++++ plugins/python/uwsgi_pymodule.c | 17 +++++++++++++++++ plugins/rack/rack_plugin.c | 21 ++++++++++++++++----- plugins/ugreen/ugreen.c | 20 ++++++++++---------- uwsgi.h | 3 +++ 5 files changed, 52 insertions(+), 15 deletions(-) diff --git a/config.ru b/config.ru index d5868be0..88cd1ed8 100644 --- a/config.ru +++ b/config.ru @@ -2,6 +2,12 @@ require 'sinatra' get '/hi' do + + for i in 1..10 + puts "ruby" + #UWSGI.suspend() + end + "Hello World!" end diff --git a/plugins/python/uwsgi_pymodule.c b/plugins/python/uwsgi_pymodule.c index c9a0bb9e..3a5e7481 100644 --- a/plugins/python/uwsgi_pymodule.c +++ b/plugins/python/uwsgi_pymodule.c @@ -1150,6 +1150,19 @@ clear: }; #endif + +PyObject *py_uwsgi_suspend(PyObject * self, PyObject * args) { + + struct wsgi_request *wsgi_req = current_wsgi_req(); + + uwsgi.schedule_to_main(wsgi_req); + + Py_INCREF(Py_True); + return Py_True; + +} + + static PyMethodDef uwsgi_advanced_methods[] = { {"send_uwsgi_message", py_uwsgi_send_message, METH_VARARGS, ""}, {"send_multi_uwsgi_message", py_uwsgi_send_multi_message, METH_VARARGS, ""}, @@ -1183,9 +1196,13 @@ clear: #endif #ifdef UWSGI_ASYNC {"async_sleep", py_uwsgi_async_sleep, METH_VARARGS, ""}, + + {"green_schedule", py_uwsgi_suspend, METH_VARARGS, ""}, + {"suspend", py_uwsgi_suspend, METH_VARARGS, ""}, #endif {"parsefile", py_uwsgi_parse_file, METH_VARARGS, ""}, //{"call_hook", py_uwsgi_call_hook, METH_VARARGS, ""}, + {NULL, NULL}, }; diff --git a/plugins/rack/rack_plugin.c b/plugins/rack/rack_plugin.c index 50cf8f47..2340c3c6 100644 --- a/plugins/rack/rack_plugin.c +++ b/plugins/rack/rack_plugin.c @@ -60,8 +60,6 @@ struct uwsgi_rack { pthread_mutex_t gvl; - rb_thread_t context; - } ur; struct option uwsgi_rack_options[] = { @@ -332,6 +330,16 @@ VALUE require_rails(VALUE arg) { VALUE init_rack_app(VALUE); +VALUE uwsgi_ruby_suspend(VALUE *arg) { + + struct wsgi_request *wsgi_req = current_wsgi_req(); + + uwsgi.schedule_to_main(wsgi_req); + + return Qtrue; + +} + int uwsgi_rack_init(){ struct http_status_codes *http_sc; @@ -365,6 +373,10 @@ int uwsgi_rack_init(){ //uwsgi_register_loop( (char *) "fiber", fiber_loop); #endif + VALUE rb_uwsgi_embedded = rb_define_module("UWSGI"); + rb_define_module_function(rb_uwsgi_embedded, "suspend", uwsgi_ruby_suspend, 0); + + if (ur.rack) { ur.dispatcher = rb_protect(init_rack_app, rb_str_new2(ur.rack), &error); if (error) { @@ -750,13 +762,11 @@ int uwsgi_rack_manage_options(int i, char *optarg) { void uwsgi_rack_suspend(struct wsgi_request *wsgi_req) { uwsgi_log("SUSPENDING RUBY\n"); - rb_thread_save_context(ur.context); } void uwsgi_rack_resume(struct wsgi_request *wsgi_req) { uwsgi_log("RESUMING RUBY\n"); - rb_thread_restore_context(ur.context, RESTORE_NORMAL); } void uwsgi_rack_enable_threads(void) { @@ -840,9 +850,10 @@ struct uwsgi_plugin rack_plugin = { .manage_xml = uwsgi_rack_xml, .magic = uwsgi_rack_magic, -#ifdef RUBY19 + .suspend = uwsgi_rack_suspend, .resume = uwsgi_rack_resume, +#ifdef RUBY19 #ifdef UWSGI_THREADING .enable_threads = uwsgi_rack_enable_threads, .init_thread = uwsgi_rack_init_thread, diff --git a/plugins/ugreen/ugreen.c b/plugins/ugreen/ugreen.c index c83c0d9a..b688d79a 100644 --- a/plugins/ugreen/ugreen.c +++ b/plugins/ugreen/ugreen.c @@ -80,9 +80,7 @@ static int u_green_blocking() { return -1; } -inline static void u_green_schedule_to_main(int async_id) { - - struct wsgi_request *wsgi_req = uwsgi.wsgi_requests[async_id]; +inline static void u_green_schedule_to_main(struct wsgi_request *wsgi_req) { if (wsgi_req->async_status != UWSGI_ACCEPTING) { if (uwsgi.p[wsgi_req->uh.modifier1]->suspend) { @@ -90,7 +88,7 @@ inline static void u_green_schedule_to_main(int async_id) { } } - swapcontext(ug.contexts[async_id], &ug.main); + swapcontext(ug.contexts[wsgi_req->async_id], &ug.main); if (wsgi_req->async_status != UWSGI_ACCEPTING) { if (uwsgi.p[wsgi_req->uh.modifier1]->resume) { @@ -133,7 +131,7 @@ void u_green_wait_for_fd(struct wsgi_request *wsgi_req, int fd, int etype, int t wsgi_req->async_waiting_fd_type = etype; wsgi_req->async_timeout = time(NULL) + timeout; - u_green_schedule_to_main(wsgi_req->async_id); + u_green_schedule_to_main(wsgi_req); async_del(uwsgi.async_queue, wsgi_req->async_waiting_fd, wsgi_req->async_waiting_fd_type); @@ -168,7 +166,7 @@ static void u_green_request(struct wsgi_request *wsgi_req, int async_id) { wsgi_req->async_status = UWSGI_ACCEPTING; - u_green_schedule_to_main(async_id); + u_green_schedule_to_main(wsgi_req); if (wsgi_req_accept(wsgi_req)) { continue; @@ -178,18 +176,18 @@ static void u_green_request(struct wsgi_request *wsgi_req, int async_id) { wsgi_req->async_status = UWSGI_OK; // check here - u_green_schedule_to_main(async_id); + //u_green_schedule_to_main(wsgi_req); if (wsgi_req_recv(wsgi_req)) { continue; } while(wsgi_req->async_status == UWSGI_AGAIN) { - u_green_schedule_to_main(async_id); + u_green_schedule_to_main(wsgi_req); wsgi_req->async_status = uwsgi.p[wsgi_req->uh.modifier1]->request(wsgi_req); } - u_green_schedule_to_main(async_id); + u_green_schedule_to_main(wsgi_req); uwsgi_close_request(wsgi_req); @@ -245,7 +243,7 @@ int u_green_init() { ug.contexts[i]->uc_stack.ss_size = ug.u_stack_size; ug.contexts[i]->uc_link = NULL; - makecontext(ug.contexts[i], u_green_request, 2, wsgi_req, i); + makecontext(ug.contexts[i], (void(*)(void)) u_green_request, 2, wsgi_req, i); wsgi_req->async_status = UWSGI_ACCEPTING; wsgi_req->async_id = i; uwsgi_log("wsgi_req %d %d %p\n", wsgi_req->async_id, wsgi_req->async_status, ug.contexts[i]); @@ -317,6 +315,8 @@ void u_green_loop() { wsgi_req->async_id = i; } + uwsgi.schedule_to_main = u_green_schedule_to_main; + uwsgi_log("FFAR: %p\n", find_first_accepting_wsgi_req()); while(uwsgi.workers[uwsgi.mywid].manage_next_request) { diff --git a/uwsgi.h b/uwsgi.h index eaad4d10..0991e59b 100644 --- a/uwsgi.h +++ b/uwsgi.h @@ -784,6 +784,9 @@ struct uwsgi_server { struct wsgi_request *(*current_wsgi_req) (void); + // usedby suspend/resume loops + void (*schedule_to_main) (struct wsgi_request *); + int close_on_exec; char *loop;