ugreen support

This commit is contained in:
roberto@sirius
2010-03-28 18:18:23 +02:00
parent 0416914951
commit 314df1d809
13 changed files with 328 additions and 85 deletions
+9
View File
@@ -265,6 +265,15 @@ struct wsgi_request *find_first_available_wsgi_req(struct uwsgi_server *uwsgi) {
return NULL ;
}
struct wsgi_request *find_wsgi_req_by_id(struct uwsgi_server *uwsgi, int async_id) {
uint8_t *ptr = (uint8_t *) uwsgi->wsgi_requests ;
ptr += (sizeof(struct wsgi_request)+(uwsgi->buffer_size-1)) * async_id ;
return (struct wsgi_request *) ptr ;
}
struct wsgi_request *find_wsgi_req_by_fd(struct uwsgi_server *uwsgi, int fd, int etype) {
struct wsgi_request* wsgi_req = uwsgi->wsgi_requests ;
+3 -33
View File
@@ -8,12 +8,9 @@ int manage_python_response(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi
ssize_t sf_len = 0 ;
#endif
//fprintf(stderr,"managing response of tasklet %d on %p %s %d\n", wsgi_req->async_id, wsgi_req, ( (PyObject *) wsgi_req->async_result)->ob_type->tp_name, PyList_Size(wsgi_req->async_result));
fprintf(stderr,"managing request\n");
//fprintf(stderr,"managing request for %d %p\n", wsgi_req->async_id, wsgi_req);
// return or yield ?
if (PyString_Check((PyObject *)wsgi_req->async_result)) {
//fprintf(stderr,"DOH !!!\n");
if ((wsize = write(wsgi_req->poll.fd, PyString_AsString(wsgi_req->async_result), PyString_Size(wsgi_req->async_result))) < 0) {
perror("write()");
goto clear;
@@ -52,45 +49,29 @@ int manage_python_response(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi
// ok its a yield
if (!wsgi_req->async_placeholder) {
//fprintf(stderr,"getting placeholder %d\n", wsgi_req->async_id);
wsgi_req->async_placeholder = PyObject_GetIter(wsgi_req->async_result);
if (!wsgi_req->async_placeholder) {
goto clear2;
}
Py_DECREF((PyObject *)wsgi_req->async_result);
#ifdef UWSGI_ASYNC
if (uwsgi->async > 1 && !uwsgi->stackless) {
if (uwsgi->async > 1) {
return UWSGI_AGAIN;
}
#endif
}
//fprintf(stderr,"running yield %d %p\n", wsgi_req->async_id, wsgi_req);
/*
boh = wsgi_req->async_placeholder; boh2 = wsgi_req->async_result ;
fprintf(stderr,"placeholder refcnt %d: %d\n", wsgi_req->async_switches, boh->ob_refcnt);
*/
fprintf(stderr,"placeholder: %p\n", wsgi_req->async_placeholder) ;
pychunk = PyIter_Next(wsgi_req->async_placeholder) ;
/*
boh = wsgi_req->async_placeholder; boh2 = wsgi_req->async_result ;
fprintf(stderr,"AFTER NEXT %d/%d\n", boh->ob_refcnt, boh2->ob_refcnt);
*/
if (!pychunk) {
if (PyErr_Occurred()) PyErr_Print();
goto clear;
}
fprintf(stderr,"checking pychunk\n");
//fprintf(stderr,"ob type %s\n", pychunk->ob_type->tp_name);
if (PyString_Check(pychunk)) {
if ((wsize = write(wsgi_req->poll.fd, PyString_AsString(pychunk), PyString_Size(pychunk))) < 0) {
perror("write()");
@@ -112,22 +93,12 @@ int manage_python_response(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi
#endif
Py_DECREF(pychunk);
//Py_DECREF(wsgi_req->async_placeholder);
//Py_DECREF(wsgi_req->async_result);
/*
boh = wsgi_req->async_placeholder; boh2 = wsgi_req->async_result ;
fprintf(stderr,"AFTER CHUNK %d/%d\n", boh->ob_refcnt, boh2->ob_refcnt);
*/
return UWSGI_AGAIN ;
clear:
fprintf(stderr,"clearing request\n");
if (wsgi_req->sendfile_fd != -1) {
Py_DECREF(wsgi_req->async_sendfile);
Py_DECREF((PyObject *)wsgi_req->async_sendfile);
}
//fprintf(stderr,"finito\n");
if (wsgi_req->async_environ) {
PyDict_Clear(wsgi_req->async_environ);
}
@@ -138,7 +109,6 @@ clear:
Py_XDECREF((PyObject *)wsgi_req->async_placeholder);
clear2:
Py_DECREF((PyObject *)wsgi_req->async_result);
//fprintf(stderr,"RESULT REFCNT: %d\n", ((PyObject *) wsgi_req->async_result)->ob_refcnt);
PyErr_Clear();
return UWSGI_OK;
}
+7 -5
View File
@@ -6,16 +6,18 @@ extern struct uwsgi_server uwsgi;
PyObject *py_uwsgi_sendfile(PyObject * self, PyObject * args) {
if (!PyArg_ParseTuple(args, "Oi:uwsgi_sendfile", &uwsgi.wsgi_req->async_sendfile, &uwsgi.wsgi_req->sendfile_fd_chunk)) {
struct wsgi_request *wsgi_req = current_wsgi_req(&uwsgi);
if (!PyArg_ParseTuple(args, "Oi:uwsgi_sendfile", &wsgi_req->async_sendfile, &wsgi_req->sendfile_fd_chunk)) {
return NULL;
}
#ifdef PYTHREE
uwsgi.wsgi_req->sendfile_fd = PyObject_AsFileDescriptor(uwsgi.wsgi_req->async_sendfile);
wsgi_req->sendfile_fd = PyObject_AsFileDescriptor(wsgi_req->async_sendfile);
#else
if (PyFile_Check((PyObject *)uwsgi.wsgi_req->async_sendfile)) {
Py_INCREF(uwsgi.wsgi_req->async_sendfile);
uwsgi.wsgi_req->sendfile_fd = PyObject_AsFileDescriptor(uwsgi.wsgi_req->async_sendfile);
if (PyFile_Check((PyObject *)wsgi_req->async_sendfile)) {
Py_INCREF((PyObject *)wsgi_req->async_sendfile);
wsgi_req->sendfile_fd = PyObject_AsFileDescriptor(wsgi_req->async_sendfile);
}
#endif
+1 -3
View File
@@ -1,6 +1,4 @@
import stackless
def application(env, start_response):
print env
start_response('200 Ok', [('Content-type', 'text/plain')])
return "hello world"
yield "hello world"
+6 -6
View File
@@ -30,11 +30,8 @@ PyObject *py_uwsgi_stackless_worker(PyObject * self, PyObject * args) {
for(;;) {
// wait for request
fprintf(stderr,"tasklet %d is waiting on %p\n", async_id, wsgi_req);
zero = PyChannel_Receive(uwsgi.workers_channel);
fprintf(stderr,"tasket %d start\n", async_id);
wsgi_req_setup(wsgi_req, async_id);
if (wsgi_req_accept(uwsgi.serverfd, wsgi_req)) {
@@ -47,7 +44,6 @@ PyObject *py_uwsgi_stackless_worker(PyObject * self, PyObject * args) {
uwsgi_close_request(&uwsgi, wsgi_req);
fprintf(stderr,"tasket %d ended\n", async_id);
}
@@ -90,7 +86,7 @@ void stackless_init(struct uwsgi_server *uwsgi) {
wsgi_req->async_id = i ;
PyTasklet_Setup(wsgi_req->tasklet, PyTuple_New(0), NULL);
PyTasklet_Run(wsgi_req->tasklet);
//PyTasklet_Run(wsgi_req->tasklet);
wsgi_req = next_wsgi_req(uwsgi, wsgi_req) ;
}
@@ -124,10 +120,14 @@ void stackless_loop(struct uwsgi_server *uwsgi) {
}
/*
if (PyStackless_GetRunCount() > 0) {
PyStackless_Schedule(Py_None, 0);
}
//PyStackless_RunWatchdogEx( 10, PY_WATCHDOG_TOTALTIMEOUT);
*/
PyStackless_RunWatchdogEx( 10, PY_WATCHDOG_TOTALTIMEOUT);
//int_tasklet = (PyTaskletObject *) PyStackless_RunWatchdog( 1000 );
/*
fprintf(stderr,"done watchdog %p\n", int_tasklet);
+15
View File
@@ -0,0 +1,15 @@
import uwsgi
import time
def application(env, start_response):
counter = 0
start_response( '200 OK', [ ('Content-Type','text/html') ])
start_time = time.time()
for i in range(1,100000):
uwsgi.green_schedule()
# print every 100
if i % 100 == 0:
yield "<h1>%d</h1>\n" % i
counter = counter + i
yield "<h1>%d cycles after %d</h1>\n" % (counter, time.time() - start_time)
+232
View File
@@ -0,0 +1,232 @@
#ifdef UWSGI_UGREEN
#include "uwsgi.h"
#define GREEN_STACK_SIZE 128 * 1024
extern struct uwsgi_server uwsgi;
static int green_blocking(struct uwsgi_server *uwsgi) {
struct wsgi_request* wsgi_req = uwsgi->wsgi_requests ;
int i ;
for(i=0;i<uwsgi->async;i++) {
if (wsgi_req->async_status != UWSGI_ACCEPTING) {
return 0 ;
}
wsgi_req = next_wsgi_req(uwsgi, wsgi_req) ;
}
return -1 ;
}
static void u_green_schedule_to_main(struct uwsgi_server *uwsgi, int async_id) {
int py_current_recursion_depth;
struct _frame* py_current_frame;
PyThreadState* tstate = PyThreadState_GET();
py_current_recursion_depth = tstate->recursion_depth;
py_current_frame = tstate->frame;
swapcontext(uwsgi->green_contexts[async_id], &uwsgi->greenmain);
tstate = PyThreadState_GET();
tstate->recursion_depth = py_current_recursion_depth;
tstate->frame = py_current_frame ;
}
static void u_green_schedule_to_req(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
int py_current_recursion_depth;
struct _frame* py_current_frame;
PyThreadState* tstate = PyThreadState_GET();
py_current_recursion_depth = tstate->recursion_depth;
py_current_frame = tstate->frame;
uwsgi->wsgi_req = wsgi_req;
wsgi_req->async_switches++;
swapcontext(&uwsgi->greenmain, uwsgi->green_contexts[wsgi_req->async_id] );
tstate = PyThreadState_GET();
tstate->recursion_depth = py_current_recursion_depth;
tstate->frame = py_current_frame ;
}
PyObject *py_uwsgi_green_schedule(PyObject * self, PyObject * args) {
struct wsgi_request *wsgi_req = current_wsgi_req(&uwsgi);
/*
int py_current_recursion_depth;
struct _frame* py_current_frame;
PyThreadState* tstate = PyThreadState_GET();
py_current_recursion_depth = tstate->recursion_depth;
py_current_frame = tstate->frame;
*/
u_green_schedule_to_main(&uwsgi, wsgi_req->async_id);
/*
tstate = PyThreadState_GET();
tstate->recursion_depth = py_current_recursion_depth;
tstate->frame = py_current_frame ;
*/
Py_INCREF(Py_True);
return Py_True;
}
PyMethodDef uwsgi_green_methods[] = {
{"green_schedule", py_uwsgi_green_schedule, METH_VARARGS, ""},
{ NULL, NULL }
};
static struct wsgi_request *find_first_accepting_wsgi_req(struct uwsgi_server *uwsgi) {
struct wsgi_request* wsgi_req = uwsgi->wsgi_requests ;
int i ;
for(i=0;i<uwsgi->async;i++) {
if (wsgi_req->async_status == UWSGI_ACCEPTING) {
return wsgi_req ;
}
wsgi_req = next_wsgi_req(uwsgi, wsgi_req) ;
}
return NULL ;
}
static void u_green_request(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req, int async_id) {
for(;;) {
wsgi_req_setup(wsgi_req, async_id);
wsgi_req->async_status = UWSGI_ACCEPTING;
u_green_schedule_to_main(uwsgi, async_id);
if (wsgi_req_accept(uwsgi->serverfd, wsgi_req)) {
continue;
}
wsgi_req->async_status = UWSGI_OK;
u_green_schedule_to_main(uwsgi, async_id);
if (wsgi_req_recv(wsgi_req)) {
continue;
}
while(wsgi_req->async_status == UWSGI_AGAIN) {
u_green_schedule_to_main(uwsgi, async_id);
wsgi_req->async_status = (*uwsgi->shared->hooks[wsgi_req->modifier]) (uwsgi, wsgi_req);
}
u_green_schedule_to_main(uwsgi, async_id);
uwsgi_close_request(uwsgi, wsgi_req);
}
}
void u_green_loop(struct uwsgi_server *uwsgi) {
struct wsgi_request *wsgi_req = uwsgi->wsgi_requests ;
int i, current = 0 ;
PyMethodDef *uwsgi_function;
fprintf(stderr,"initializing %d green threads with stack size of %lu (%lu KB)\n", uwsgi->async, (unsigned long) GREEN_STACK_SIZE, (unsigned long) GREEN_STACK_SIZE/1024);
uwsgi->green_stacks = malloc( sizeof(char*) * uwsgi->async);
if (!uwsgi->green_stacks) {
perror("malloc()\n");
exit(1);
}
for(i=0;i<uwsgi->async;i++) {
//uwsgi->green_stacks[i] = malloc( 4096 * 256 );
uwsgi->green_stacks[i] = mmap(NULL, GREEN_STACK_SIZE , PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANONYMOUS | MAP_PRIVATE | MAP_GROWSDOWN, -1, 0);
if (!uwsgi->green_stacks[i]) {
perror("mmap()");
exit(1);
}
}
uwsgi->green_contexts = malloc( sizeof(ucontext_t*) * uwsgi->async);
if (!uwsgi->green_contexts) {
perror("malloc()\n");
exit(1);
}
for(i=0;i<uwsgi->async;i++) {
uwsgi->green_contexts[i] = malloc( sizeof(ucontext_t) );
if (!uwsgi->green_contexts[i]) {
perror("malloc()");
exit(1);
}
getcontext(uwsgi->green_contexts[i]);
uwsgi->green_contexts[i]->uc_stack.ss_sp = uwsgi->green_stacks[i];
uwsgi->green_contexts[i]->uc_stack.ss_size = GREEN_STACK_SIZE ;
uwsgi->green_contexts[i]->uc_link = NULL;
makecontext(uwsgi->green_contexts[i], (void (*) (void)) &u_green_request, 3, uwsgi, wsgi_req, i);
wsgi_req->async_status = UWSGI_ACCEPTING;
wsgi_req->async_id = i;
wsgi_req = next_wsgi_req(uwsgi, wsgi_req) ;
}
for (uwsgi_function = uwsgi_green_methods; uwsgi_function->ml_name != NULL; uwsgi_function++) {
PyObject *func = PyCFunction_New(uwsgi_function, NULL);
PyDict_SetItemString(uwsgi->embedded_dict, uwsgi_function->ml_name, func);
Py_DECREF(func);
}
for(;;) {
uwsgi->async_running = green_blocking(uwsgi) ;
uwsgi->async_nevents = async_wait(uwsgi->async_queue, uwsgi->async_events, uwsgi->async, uwsgi->async_running, 0);
if (uwsgi->async_nevents < 0) {
continue;
}
if (i > 0) {
wsgi_req = find_first_accepting_wsgi_req(uwsgi);
if (!wsgi_req) goto cycle;
}
for(i=0; i<uwsgi->async_nevents;i++) {
if (uwsgi->async_events[i].ASYNC_FD == uwsgi->serverfd) {
u_green_schedule_to_req(uwsgi, wsgi_req);
}
}
cycle:
wsgi_req = find_wsgi_req_by_id(uwsgi, current) ;
if (wsgi_req->async_status != UWSGI_ACCEPTING) {
u_green_schedule_to_req(uwsgi, wsgi_req);
}
current++;
if (current >= uwsgi->async) current = 0;
}
// never here
}
#endif
+15 -1
View File
@@ -281,7 +281,7 @@ int wsgi_req_accept(int fd, struct wsgi_request *wsgi_req) {
wsgi_req->poll.fd = accept(fd, (struct sockaddr *) &wsgi_req->c_addr, (socklen_t *) &wsgi_req->c_len);
if (uwsgi.wsgi_req->poll.fd < 0) {
if (wsgi_req->poll.fd < 0) {
perror("accept()");
return -1;
}
@@ -289,3 +289,17 @@ int wsgi_req_accept(int fd, struct wsgi_request *wsgi_req) {
return 0;
}
struct wsgi_request *current_wsgi_req(struct uwsgi_server *uwsgi) {
struct wsgi_request *wsgi_req = uwsgi->wsgi_req;
#ifdef UWSGI_STACKLESS
if (uwsgi->stackless && uwsgi->async >1) {
PyThreadState *ts = PyThreadState_GET();
wsgi_req = find_request_by_tasklet(ts->st.current);
}
#endif
return wsgi_req;
}
+8
View File
@@ -354,6 +354,9 @@ int main(int argc, char *argv[], char *envp[]) {
#endif
#ifdef UWSGI_STACKLESS
{"stackless", no_argument, &uwsgi.stackless, 1},
#endif
#ifdef UWSGI_UGREEN
{"ugreen", no_argument, &uwsgi.ugreen, 1},
#endif
{"version", no_argument, 0, LONG_ARGS_VERSION},
{0, 0, 0, 0}
@@ -1317,6 +1320,11 @@ int main(int argc, char *argv[], char *envp[]) {
uwsgi.async_running = -1 ;
#endif
#ifdef UWSGI_UGREEN
if (uwsgi.ugreen) {
u_green_loop(&uwsgi);
}
#endif
#ifdef UWSGI_STACKLESS
if (uwsgi.stackless) {
+19
View File
@@ -16,6 +16,10 @@
#include <netinet/sctp.h>
#endif
#ifdef UWSGI_UGREEN
#include <ucontext.h>
#endif
#include <arpa/inet.h>
#include <sys/mman.h>
#include <sys/file.h>
@@ -124,6 +128,7 @@ PyAPI_FUNC(PyObject *) PyMarshal_ReadObjectFromString(char *, Py_ssize_t);
#define UWSGI_OK 0
#define UWSGI_AGAIN 1
#define UWSGI_ACCEPTING 2
#define UWSGI_CLEAR_STATUS uwsgi.workers[uwsgi.mywid].status = 0
@@ -402,6 +407,13 @@ struct uwsgi_server {
int stackless;
#ifdef UWSGI_UGREEN
int ugreen;
ucontext_t greenmain;
ucontext_t **green_contexts;
char **green_stacks;
#endif
#ifdef __linux__
struct epoll_event *async_events;
#elif defined(__sun__)
@@ -681,6 +693,7 @@ struct http_status_codes {
struct wsgi_request *async_loop(struct uwsgi_server *);
struct wsgi_request *find_first_available_wsgi_req(struct uwsgi_server *);
struct wsgi_request *find_wsgi_req_by_fd(struct uwsgi_server *, int, int);
struct wsgi_request *find_wsgi_req_by_id(struct uwsgi_server *, int);
struct wsgi_request *next_wsgi_req(struct uwsgi_server *, struct wsgi_request *);
@@ -757,3 +770,9 @@ void uwsgi_close_request(struct uwsgi_server *, struct wsgi_request *) ;
void wsgi_req_setup(struct wsgi_request *, int);
int wsgi_req_recv(struct wsgi_request *);
int wsgi_req_accept(int, struct wsgi_request *);
#ifdef UWSGI_UGREEN
void u_green_loop(struct uwsgi_server *);
#endif
struct wsgi_request *current_wsgi_req(struct uwsgi_server *);
+7 -1
View File
@@ -8,13 +8,14 @@ SPOOLER=True
EMBEDDED=True
UDP=True
MULTICAST=True
THREADING=True
THREADING=False
SENDFILE=True
PROFILER=False
NAGIOS=True
PROXY=True
MINTERPRETERS=True
ASYNC=True
UGREEN=True
STACKLESS=False
PLUGINS = []
UWSGI_BIN_NAME = 'uwsgi'
@@ -153,6 +154,11 @@ def parse_vars():
cflags.append("-DUWSGI_PROXY")
gcc_list.append('proxy')
if UGREEN:
depends_on("UGREEN", ['ASYNC'])
cflags.append("-DUWSGI_UGREEN")
gcc_list.append('ugreen')
if SNMP:
depends_on("SNMP", ['UDP'])
cflags.append("-DUWSGI_SNMP")
+5 -28
View File
@@ -7,14 +7,7 @@ PyObject *py_uwsgi_write(PyObject * self, PyObject * args) {
char *content;
int len;
struct wsgi_request *wsgi_req = uwsgi.wsgi_req;
#ifdef UWSGI_STACKLESS
if (uwsgi.stackless) {
PyThreadState *ts = PyThreadState_GET();
wsgi_req = find_request_by_tasklet(ts->st.current);
}
#endif
struct wsgi_request *wsgi_req = current_wsgi_req(&uwsgi);
data = PyTuple_GetItem(args, 0);
if (PyString_Check(data)) {
@@ -41,15 +34,7 @@ PyObject *py_uwsgi_write(PyObject * self, PyObject * args) {
PyObject *py_eventfd_read(PyObject * self, PyObject * args) {
int fd, timeout;
struct wsgi_request *wsgi_req = uwsgi.wsgi_req;
#ifdef UWSGI_STACKLESS
if (uwsgi.stackless) {
PyThreadState *ts = PyThreadState_GET();
wsgi_req = find_request_by_tasklet(ts->st.current);
}
#endif
struct wsgi_request *wsgi_req = current_wsgi_req(&uwsgi);
if (!PyArg_ParseTuple(args, "i|i", &fd, &timeout)) {
return NULL;
@@ -68,14 +53,7 @@ PyObject *py_eventfd_read(PyObject * self, PyObject * args) {
PyObject *py_eventfd_write(PyObject * self, PyObject * args) {
int fd, timeout;
struct wsgi_request *wsgi_req = uwsgi.wsgi_req;
#ifdef UWSGI_STACKLESS
if (uwsgi.stackless) {
PyThreadState *ts = PyThreadState_GET();
wsgi_req = find_request_by_tasklet(ts->st.current);
}
#endif
struct wsgi_request *wsgi_req = current_wsgi_req(&uwsgi);
if (!PyArg_ParseTuple(args, "i|i", &fd, &timeout)) {
return NULL;
@@ -103,8 +81,6 @@ int uwsgi_request_wsgi(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req
struct uwsgi_app *wi ;
fprintf(stderr,"starting\n");
#ifdef UWSGI_ASYNC
if (wsgi_req->async_status == UWSGI_AGAIN) {
// get rid of timeout
@@ -204,6 +180,7 @@ int uwsgi_request_wsgi(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req
Py_INCREF((PyObject *)wsgi_req->async_environ);
for (i = 0; i < wsgi_req->var_cnt; i += 2) {
//fprintf(stderr,"%.*s: %.*s\n", wsgi_req->hvec[i].iov_len, wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i+1].iov_len, wsgi_req->hvec[i+1].iov_base);
pydictkey = PyString_FromStringAndSize(wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len);
@@ -303,6 +280,7 @@ int uwsgi_request_wsgi(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req
else {
#endif
PyTuple_SetItem(wsgi_req->async_args, 0, wsgi_req->async_environ);
wsgi_req->async_result = python_call(wi->wsgi_callable, wsgi_req->async_args);
@@ -313,7 +291,6 @@ int uwsgi_request_wsgi(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req
if (wsgi_req->async_result) {
fprintf(stderr,"looping\n");
while ( manage_python_response(uwsgi, wsgi_req) != UWSGI_OK) {
#ifdef UWSGI_ASYNC
+1 -8
View File
@@ -11,14 +11,7 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
PyObject *h_key, *h_value;
int i, j;
struct wsgi_request *wsgi_req = uwsgi.wsgi_req;
#ifdef UWSGI_STACKLESS
if (uwsgi.stackless) {
PyThreadState *ts = PyThreadState_GET();
wsgi_req = find_request_by_tasklet(ts->st.current);
}
#endif
struct wsgi_request *wsgi_req = current_wsgi_req(&uwsgi);
#ifndef UNBIT
int base = 0;