[Stackless] Python, C, context-switching

Lars Immisch lars at ibp.de
Tue Oct 5 11:28:26 CEST 2004


Hi Joël,

>>Does your SWIG glue code that invokes the callbacks acquire and release
>>the Global Interpreter lock?
> 
> Yes the global interpreter lock is used, this is my glue code:
> void execute() {
>     Py_BEGIN_ALLOW_THREADS;
>     m_callback->run ();
>     Py_END_ALLOW_THREADS;
> }
> 
> the run method is like that:
> void run () {
>  PyObject * pyres;
>      pyres = PyObject_CallObject(callable, NULL);
>      Py_XDECREF(pyres);
> }
> 
> I've check the value of the "callable" parameters and it is not null.
> 
> Any idea ?

You got it backwards ;-)

The GIL must be locked before you enter the Python code.

Py_BEGIN_ALLOW_THREADS is a macro that creates a block in which a 
PyThreadState *tstate is locally stored.

If you are single-threaded (OS-thread-wise) or otherwise know in which 
thread context the callback will be called, you can store the tstate in 
thread local storage.

You might use a SWIG macro like:

%define NONBLOCKING(name)
%exception name {
     PyThreadState *tstate = PyEval_SaveThread();
%#ifdef WIN32
     TlsSetValue(tlsindex, tstate);
%#else
     pthread_setspecific(tlsindex, tstate);
%#endif
     $function
     PyEval_RestoreThread(tstate);
}
%enddef

(Be warned: of the top off my head - might not compile)

Let's assume run will be called in the thread context of execute, then 
you'd say:

NONBLOCKING(execute)

In the run wrapper, you'd do:

void run () {
     PyThreadState *tstate = 0;

#ifdef WIN32
     tstate = (PyThreadState*)TlsGetValue(tlsindex);
#else
     tstate = (PyThreadState*)pthread_getspecific(tlsindex);
#endif

     PyEval_AcquireThread(tstate);

     PyObject * pyres;
     pyres = PyObject_CallObject(callable, NULL);
     Py_XDECREF(pyres);

     PyEval_ReleaseThread(tstate);
}

Now all that is left to do is to create the thread local storage key in 
your SWIG initialization section, like so:

#ifdef WIN32
DWORD tlsindex;
#else
pthread_key_t tlsindex;
#endif

%init %{
#ifdef WIN32
     tlsindex = TlsAlloc();
#else
     pthread_key_create(&tlsindex, NULL);
#endif
%}

I have described the procedure once in:

http://mailman.cs.uchicago.edu/pipermail/swig/2003-June/007739.html

I think I should write a chapter for the SWIG docs. The question comes 
up fairly often.

- Lars

_______________________________________________
Stackless mailing list
Stackless at stackless.com
http://www.stackless.com/mailman/listinfo/stackless



More information about the Stackless mailing list