diff --git a/plugins/greenlet/greenlet.c b/plugins/greenlet/greenlet.c index ff48aab3..7aa5903a 100644 --- a/plugins/greenlet/greenlet.c +++ b/plugins/greenlet/greenlet.c @@ -2,6 +2,7 @@ #include extern struct uwsgi_server uwsgi; +extern struct uwsgi_python up; struct ugreenlet { int enabled; @@ -10,15 +11,22 @@ struct ugreenlet { PyGreenlet **gl; } ugl; -struct uwsgi_option greenlet_options[] = { +static struct uwsgi_option greenlet_options[] = { {"greenlet", no_argument, 0, "enable greenlet as suspend engine", uwsgi_opt_true, &ugl.enabled, 0}, { 0, 0, 0, 0, 0, 0, 0 } }; -PyObject *py_uwsgi_greenlet_request(PyObject * self, PyObject *args) { +static void gil_greenlet_get() { + pthread_setspecific(up.upt_gil_key, (void *) PyGILState_Ensure()); +} - uwsgi.wsgi_req->async_status = uwsgi.p[uwsgi.wsgi_req->uh->modifier1]->request(uwsgi.wsgi_req); - uwsgi.wsgi_req->suspended = 0; +static void gil_greenlet_release() { + PyGILState_Release((PyGILState_STATE) pthread_getspecific(up.upt_gil_key)); +} + +static PyObject *py_uwsgi_greenlet_request(PyObject * self, PyObject *args) { + + async_schedule_to_req_green(); Py_DECREF(ugl.gl[uwsgi.wsgi_req->async_id]); @@ -28,45 +36,66 @@ PyObject *py_uwsgi_greenlet_request(PyObject * self, PyObject *args) { PyMethodDef uwsgi_greenlet_request_method[] = {{"uwsgi_greenlet_request", py_uwsgi_greenlet_request, METH_VARARGS, ""}}; -static inline void greenlet_schedule_to_req() { +static void greenlet_schedule_to_req() { int id = uwsgi.wsgi_req->async_id; + uint8_t modifier1 = uwsgi.wsgi_req->uh->modifier1; + + // ensure gil + UWSGI_GET_GIL if (!uwsgi.wsgi_req->suspended) { ugl.gl[id] = PyGreenlet_New(ugl.callable, NULL); uwsgi.wsgi_req->suspended = 1; } + // call it in the main core + if (uwsgi.p[modifier1]->suspend) { + uwsgi.p[modifier1]->suspend(NULL); + } + PyGreenlet_Switch(ugl.gl[id], NULL, NULL); - if (uwsgi.wsgi_req->suspended) { - uwsgi.wsgi_req->async_status = UWSGI_AGAIN; - } + if (uwsgi.p[modifier1]->resume) { + uwsgi.p[modifier1]->resume(NULL); + } + } -static inline void greenlet_schedule_to_main(struct wsgi_request *wsgi_req) { +static void greenlet_schedule_to_main(struct wsgi_request *wsgi_req) { + // ensure gil + UWSGI_GET_GIL + + if (uwsgi.p[wsgi_req->uh->modifier1]->suspend) { + uwsgi.p[wsgi_req->uh->modifier1]->suspend(wsgi_req); + } PyGreenlet_Switch(ugl.main, NULL, NULL); + if (uwsgi.p[wsgi_req->uh->modifier1]->resume) { + uwsgi.p[wsgi_req->uh->modifier1]->resume(wsgi_req); + } uwsgi.wsgi_req = wsgi_req; } -static int greenlet_init() { - return 0; -} - static void greenlet_init_apps(void) { - if (!ugl.enabled) { - return; - } + if (!ugl.enabled) return; if (uwsgi.async <= 1) { - uwsgi_log("the greenlet loop engine requires async mode\n"); + uwsgi_log("the greenlet suspend engine requires async mode\n"); exit(1); } + if (uwsgi.has_threads) { + up.gil_get = gil_greenlet_get; + up.gil_release = gil_greenlet_release; + } + + // blindy call it as the stackless gil engine is already set + UWSGI_GET_GIL + PyGreenlet_Import(); @@ -77,15 +106,11 @@ static void greenlet_init_apps(void) { uwsgi.schedule_to_main = greenlet_schedule_to_main; uwsgi.schedule_to_req = greenlet_schedule_to_req; - - return; - } struct uwsgi_plugin greenlet_plugin = { .name = "greenlet", - .init = greenlet_init, .init_apps = greenlet_init_apps, .options = greenlet_options, }; diff --git a/plugins/python/wsgi_handlers.c b/plugins/python/wsgi_handlers.c index 1fc870ba..c2b331c8 100644 --- a/plugins/python/wsgi_handlers.c +++ b/plugins/python/wsgi_handlers.c @@ -293,8 +293,9 @@ int uwsgi_request_wsgi(struct wsgi_request *wsgi_req) { struct uwsgi_app *wi; - if (wsgi_req->async_status == UWSGI_AGAIN) { + if (wsgi_req->async_force_again) { wi = &uwsgi_apps[wsgi_req->app_id]; + wsgi_req->async_force_again = 0; UWSGI_GET_GIL // get rid of timeout if (wsgi_req->async_timed_out) { @@ -388,6 +389,7 @@ int uwsgi_request_wsgi(struct wsgi_request *wsgi_req) { while (wi->response_subhandler(wsgi_req) != UWSGI_OK) { if (uwsgi.async > 1) { UWSGI_RELEASE_GIL + wsgi_req->async_force_again = 1; return UWSGI_AGAIN; } else { diff --git a/plugins/stackless/stackless.c b/plugins/stackless/stackless.c index 498d0e98..ee81a447 100644 --- a/plugins/stackless/stackless.c +++ b/plugins/stackless/stackless.c @@ -84,6 +84,11 @@ static void stackless_init_apps(void) { if (!usl.enabled) return; + if (uwsgi.async <= 1) { + uwsgi_log("the stackless suspend engine requires async mode\n"); + exit(1); + } + if (uwsgi.has_threads) { up.gil_get = gil_stackless_get; up.gil_release = gil_stackless_release;