Massive changes for separate thread state management. · python/cpython@a027efa

GitHub

@@ -35,14 +35,13 @@ PERFORMANCE OF THIS SOFTWARE.

3535#include"Python.h"

36363737#ifndefWITH_THREAD

38-Error! TherestofPythonisnotcompiledwiththreadsupport.

39-Rerunconfigure, addinga--with-threadoption.

38+#error "Error! The rest of Python is not compiled with thread support."

39+#error "Rerun configure, adding a --with-thread option."

40+#error "Then run `make clean' followed by `make'."

4041#endif

41424243#include"thread.h"

434444-externint_PyThread_Started;

45-4645staticPyObject*ThreadError;

47464847@@ -192,52 +191,90 @@ static PyTypeObject Locktype = {

192191193192/* Module functions */

194193194+structbootstate {

195+PyInterpreterState*interp;

196+PyObject*func;

197+PyObject*args;

198+PyObject*keyw;

199+};

200+195201staticvoid

196-t_bootstrap(args_raw)

197-void*args_raw;

202+t_bootstrap(boot_raw)

203+void*boot_raw;

198204{

199-PyObject*args= (PyObject*) args_raw;

200-PyObject*func, *arg, *res;

201-202-_PyThread_Started++;

205+structbootstate*boot= (structbootstate*) boot_raw;

206+PyThreadState*alttstate, *tstate;

207+PyObject*res;

203208209+tstate=PyThreadState_New(boot->interp);

204210PyEval_RestoreThread((void*)NULL);

205-func=PyTuple_GetItem(args, 0);

206-arg=PyTuple_GetItem(args, 1);

207-res=PyEval_CallObject(func, arg);

208-Py_DECREF(args); /* Matches the INCREF(args) in thread_start_new_thread */

211+alttstate=PyThreadState_Swap(tstate);

212+res=PyEval_CallObjectWithKeywords(

213+boot->func, boot->args, boot->keyw);

214+Py_DECREF(boot->func);

215+Py_DECREF(boot->args);

216+Py_XDECREF(boot->keyw);

217+PyMem_DEL(boot_raw);

209218if (res==NULL) {

210219if (PyErr_Occurred() ==PyExc_SystemExit)

211220PyErr_Clear();

212221else {

213222fprintf(stderr, "Unhandled exception in thread:\n");

214-PyErr_Print();/* From pythonmain.c */

223+PyErr_Print();

215224 }

216225 }

217226else

218227Py_DECREF(res);

219- (void) PyEval_SaveThread(); /* Should always be NULL */

228+ (void) PyThreadState_Swap(alttstate);

229+ (void) PyEval_SaveThread();

230+PyThreadState_Delete(tstate);

220231exit_thread();

221232}

222233223234staticPyObject*

224-thread_start_new_thread(self, args)

235+thread_start_new_thread(self, fargs)

225236PyObject*self; /* Not used */

226-PyObject*args;

237+PyObject*fargs;

227238{

228-PyObject*func, *arg;

239+PyObject*func, *args=NULL, *keyw=NULL;

240+structbootstate*boot;

229241230-if (!PyArg_Parse(args, "(OO)", &func, &arg))

242+if (!PyArg_ParseTuple(fargs, "OO|O", &func, &args, &keyw))

243+returnNULL;

244+if (!PyCallable_Check(func)) {

245+PyErr_SetString(PyExc_TypeError,

246+"first arg must be callable");

231247returnNULL;

248+ }

249+if (!PyTuple_Check(args)) {

250+PyErr_SetString(PyExc_TypeError,

251+"optional 2nd arg must be a tuple");

252+returnNULL;

253+ }

254+if (keyw!=NULL&& !PyDict_Check(keyw)) {

255+PyErr_SetString(PyExc_TypeError,

256+"optional 3rd arg must be a dictionary");

257+returnNULL;

258+ }

259+boot=PyMem_NEW(structbootstate, 1);

260+if (boot==NULL)

261+returnPyErr_NoMemory();

262+boot->interp=PyThreadState_Get()->interpreter_state;

263+boot->func=func;

264+boot->args=args;

265+boot->keyw=keyw;

266+Py_INCREF(func);

232267Py_INCREF(args);

233-/* Initialize the interpreter's stack save/restore mechanism */

234-PyEval_InitThreads();

235-if (!start_new_thread(t_bootstrap, (void*) args)) {

236-Py_DECREF(args);

268+Py_XINCREF(keyw);

269+PyEval_InitThreads(); /* Start the interpreter's thread-awareness */

270+if (!start_new_thread(t_bootstrap, (void*) boot)) {

237271PyErr_SetString(ThreadError, "can't start new thread\n");

272+Py_DECREF(func);

273+Py_DECREF(args);

274+Py_XDECREF(keyw);

275+PyMem_DEL(boot);

238276returnNULL;

239277 }

240-/* Otherwise the DECREF(args) is done by t_bootstrap */

241278Py_INCREF(Py_None);

242279returnPy_None;

243280}

@@ -294,8 +331,8 @@ thread_get_ident(self, args)

294331}

295332296333staticPyMethodDefthread_methods[] = {

297- {"start_new_thread", (PyCFunction)thread_start_new_thread},

298- {"start_new", (PyCFunction)thread_start_new_thread},

334+ {"start_new_thread", (PyCFunction)thread_start_new_thread, 1},

335+ {"start_new", (PyCFunction)thread_start_new_thread, 1},

299336 {"allocate_lock", (PyCFunction)thread_allocate_lock},

300337 {"allocate", (PyCFunction)thread_allocate_lock},

301338 {"exit_thread", (PyCFunction)thread_exit_thread},