Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commita027efa

Browse files
committed
Massive changes for separate thread state management.
All per-thread globals are moved into a struct which is manipulatedseparately.
1 parent73237c5 commita027efa

File tree

15 files changed

+864
-261
lines changed

15 files changed

+864
-261
lines changed

‎Include/Python.h‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,8 @@ PERFORMANCE OF THIS SOFTWARE.
9595
#include"import.h"
9696
#include"bltinmodule.h"
9797

98+
#include"pystate.h"
99+
98100
#include"abstract.h"
99101

100102
#definePyArg_GetInt(v,a)PyArg_Parse((v), "i", (a))

‎Include/frameobject.h‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ typedef struct _frame {
5252
PyObject*f_locals;/* local symbol table (PyDictObject) */
5353
PyObject**f_valuestack;/* points after the last local */
5454
PyObject*f_trace;/* Trace function */
55+
PyObject*f_exc_type,*f_exc_value,*f_exc_traceback;
56+
PyThreadState*f_tstate;
5557
intf_lasti;/* Last instruction if called */
5658
intf_lineno;/* Current line number */
5759
intf_restricted;/* Flag set if restricted operations
@@ -71,7 +73,7 @@ extern DL_IMPORT(PyTypeObject) PyFrame_Type;
7173
#definePyFrame_Check(op) ((op)->ob_type == &PyFrame_Type)
7274

7375
PyFrameObject*PyFrame_New
74-
Py_PROTO((PyFrameObject*,PyCodeObject*,
76+
Py_PROTO((PyThreadState*,PyCodeObject*,
7577
PyObject*,PyObject*));
7678

7779

‎Include/pystate.h‎

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
#ifndefPy_PYSTATE_H
2+
#definePy_PYSTATE_H
3+
#ifdef__cplusplus
4+
extern"C" {
5+
#endif
6+
7+
/***********************************************************
8+
Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
9+
The Netherlands.
10+
11+
All Rights Reserved
12+
13+
Permission to use, copy, modify, and distribute this software and its
14+
documentation for any purpose and without fee is hereby granted,
15+
provided that the above copyright notice appear in all copies and that
16+
both that copyright notice and this permission notice appear in
17+
supporting documentation, and that the names of Stichting Mathematisch
18+
Centrum or CWI or Corporation for National Research Initiatives or
19+
CNRI not be used in advertising or publicity pertaining to
20+
distribution of the software without specific, written prior
21+
permission.
22+
23+
While CWI is the initial source for this software, a modified version
24+
is made available by the Corporation for National Research Initiatives
25+
(CNRI) at the Internet address ftp://ftp.python.org.
26+
27+
STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
28+
REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
29+
MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
30+
CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
31+
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
32+
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
33+
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
34+
PERFORMANCE OF THIS SOFTWARE.
35+
36+
******************************************************************/
37+
38+
/* Thread and interpreter state structures and their interfaces */
39+
40+
41+
/* State shared between threads */
42+
43+
#defineNEXITFUNCS 32
44+
45+
typedefstruct_is {
46+
47+
PyObject*import_modules;
48+
PyObject*sysdict;
49+
50+
intnthreads;
51+
52+
void (*exitfuncs[NEXITFUNCS])();
53+
intnexitfuncs;
54+
55+
}PyInterpreterState;
56+
57+
58+
/* State unique per thread */
59+
60+
struct_frame;/* Avoid including frameobject.h */
61+
62+
typedefstruct_ts {
63+
64+
PyInterpreterState*interpreter_state;
65+
66+
struct_frame*frame;
67+
intrecursion_depth;
68+
intticker;
69+
inttracing;
70+
71+
PyObject*sys_profilefunc;
72+
PyObject*sys_tracefunc;
73+
intsys_checkinterval;
74+
75+
PyObject*curexc_type;
76+
PyObject*curexc_value;
77+
PyObject*curexc_traceback;
78+
79+
PyObject*exc_type;
80+
PyObject*exc_value;
81+
PyObject*exc_traceback;
82+
83+
/* XXX Other state that should be here:
84+
- signal handlers
85+
- low-level "pending calls"
86+
Problem with both is that they may be referenced from
87+
interrupt handlers where there is no clear concept of a
88+
"current thread"???
89+
*/
90+
91+
}PyThreadState;
92+
93+
94+
PyInterpreterState*PyInterpreterState_New(void);
95+
voidPyInterpreterState_Delete(PyInterpreterState*);
96+
97+
PyThreadState*PyThreadState_New(PyInterpreterState*);
98+
voidPyThreadState_Delete(PyThreadState*);
99+
100+
PyThreadState*PyThreadState_Get(void);
101+
PyThreadState*PyThreadState_Swap(PyThreadState*);
102+
103+
/* Some background.
104+
105+
There are lots of issues here.
106+
107+
First, we can build Python without threads, with threads, or (when
108+
Greg Stein's mods are out of beta, on some platforms) with free
109+
threading.
110+
111+
Next, assuming some form of threading is used, there can be several
112+
kinds of threads. Python code can create threads with the thread
113+
module. C code can create threads with the interface defined in
114+
python's "thread.h". Or C code can create threads directly with
115+
the OS threads interface (e.g. Solaris threads, SGI threads or
116+
pthreads, whatever is being used, as long as it's the same that
117+
Python is configured for).
118+
119+
Next, let's discuss sharing of interpreter state between threads.
120+
The exception state (sys.exc_* currently) should never be shared
121+
between threads, because it is stack frame specific. The contents
122+
of the sys module, in particular sys.modules and sys.path, are
123+
generally shared between threads. But occasionally it is useful to
124+
have separate module collections, e.g. when threads originate in C
125+
code and are used to execute unrelated Python scripts.
126+
(Traditionally, one would use separate processes for this, but
127+
there are lots of reasons why threads are attractive.)
128+
129+
*/
130+
131+
#ifdef__cplusplus
132+
}
133+
#endif
134+
#endif/* !Py_PYSTATE_H */

‎Include/pythread.h‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ extern "C" {
3535
#defineup_sema PyThread_up_sema
3636
#defineexit_prog PyThread_exit_prog
3737
#define_exit_prog PyThread__exit_prog
38+
#definecreate_key PyThread_create_key
39+
#definedelete_key PyThread_delete_key
40+
#defineget_key_value PyThread_get_key_value
41+
#defineset_key_value PyThread_set_key_value
3842

3943

4044
voidinit_threadPy_PROTO((void));
@@ -62,6 +66,11 @@ void exit_prog Py_PROTO((int));
6266
void_exit_progPy_PROTO((int));
6367
#endif
6468

69+
intcreate_keyPy_PROTO((void));
70+
voiddelete_keyPy_PROTO((int));
71+
intset_key_valuePy_PROTO((int,void*));
72+
void*get_key_valuePy_PROTO((int));
73+
6574
#ifdef__cplusplus
6675
}
6776
#endif

‎Include/thread.h‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ extern "C" {
3535
#defineup_sema PyThread_up_sema
3636
#defineexit_prog PyThread_exit_prog
3737
#define_exit_prog PyThread__exit_prog
38+
#definecreate_key PyThread_create_key
39+
#definedelete_key PyThread_delete_key
40+
#defineget_key_value PyThread_get_key_value
41+
#defineset_key_value PyThread_set_key_value
3842

3943

4044
voidinit_threadPy_PROTO((void));
@@ -62,6 +66,11 @@ void exit_prog Py_PROTO((int));
6266
void_exit_progPy_PROTO((int));
6367
#endif
6468

69+
intcreate_keyPy_PROTO((void));
70+
voiddelete_keyPy_PROTO((int));
71+
intset_key_valuePy_PROTO((int,void*));
72+
void*get_key_valuePy_PROTO((int));
73+
6574
#ifdef__cplusplus
6675
}
6776
#endif

‎Modules/threadmodule.c‎

Lines changed: 64 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,13 @@ PERFORMANCE OF THIS SOFTWARE.
3535
#include"Python.h"
3636

3737
#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
4142

4243
#include"thread.h"
4344

44-
externint_PyThread_Started;
45-
4645
staticPyObject*ThreadError;
4746

4847

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

193192
/* Module functions */
194193

194+
structbootstate {
195+
PyInterpreterState*interp;
196+
PyObject*func;
197+
PyObject*args;
198+
PyObject*keyw;
199+
};
200+
195201
staticvoid
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;
203208

209+
tstate=PyThreadState_New(boot->interp);
204210
PyEval_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);
209218
if (res==NULL) {
210219
if (PyErr_Occurred()==PyExc_SystemExit)
211220
PyErr_Clear();
212221
else {
213222
fprintf(stderr,"Unhandled exception in thread:\n");
214-
PyErr_Print();/* From pythonmain.c */
223+
PyErr_Print();
215224
}
216225
}
217226
else
218227
Py_DECREF(res);
219-
(void)PyEval_SaveThread();/* Should always be NULL */
228+
(void)PyThreadState_Swap(alttstate);
229+
(void)PyEval_SaveThread();
230+
PyThreadState_Delete(tstate);
220231
exit_thread();
221232
}
222233

223234
staticPyObject*
224-
thread_start_new_thread(self,args)
235+
thread_start_new_thread(self,fargs)
225236
PyObject*self;/* Not used */
226-
PyObject*args;
237+
PyObject*fargs;
227238
{
228-
PyObject*func,*arg;
239+
PyObject*func,*args=NULL,*keyw=NULL;
240+
structbootstate*boot;
229241

230-
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");
231247
returnNULL;
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);
232267
Py_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)) {
237271
PyErr_SetString(ThreadError,"can't start new thread\n");
272+
Py_DECREF(func);
273+
Py_DECREF(args);
274+
Py_XDECREF(keyw);
275+
PyMem_DEL(boot);
238276
returnNULL;
239277
}
240-
/* Otherwise the DECREF(args) is done by t_bootstrap */
241278
Py_INCREF(Py_None);
242279
returnPy_None;
243280
}
@@ -294,8 +331,8 @@ thread_get_ident(self, args)
294331
}
295332

296333
staticPyMethodDefthread_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},

‎Objects/frameobject.c‎

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ static struct memberlist frame_memberlist[] = {
5050
{"f_lineno",T_INT,OFF(f_lineno),RO},
5151
{"f_restricted",T_INT,OFF(f_restricted),RO},
5252
{"f_trace",T_OBJECT,OFF(f_trace)},
53+
{"f_exc_type",T_OBJECT,OFF(f_exc_type)},
54+
{"f_exc_value",T_OBJECT,OFF(f_exc_value)},
55+
{"f_exc_traceback",T_OBJECT,OFF(f_exc_traceback)},
5356
{NULL}/* Sentinel */
5457
};
5558

@@ -112,6 +115,9 @@ frame_dealloc(f)
112115
Py_XDECREF(f->f_globals);
113116
Py_XDECREF(f->f_locals);
114117
Py_XDECREF(f->f_trace);
118+
Py_XDECREF(f->f_exc_type);
119+
Py_XDECREF(f->f_exc_value);
120+
Py_XDECREF(f->f_exc_traceback);
115121
f->f_back=free_list;
116122
free_list=f;
117123
}
@@ -134,12 +140,13 @@ PyTypeObject PyFrame_Type = {
134140
};
135141

136142
PyFrameObject*
137-
PyFrame_New(back,code,globals,locals)
138-
PyFrameObject*back;
143+
PyFrame_New(tstate,code,globals,locals)
144+
PyThreadState*tstate;
139145
PyCodeObject*code;
140146
PyObject*globals;
141147
PyObject*locals;
142148
{
149+
PyFrameObject*back=tstate->frame;
143150
staticPyObject*builtin_object;
144151
PyFrameObject*f;
145152
PyObject*builtins;
@@ -214,6 +221,10 @@ PyFrame_New(back, code, globals, locals)
214221
}
215222
f->f_locals=locals;
216223
f->f_trace=NULL;
224+
f->f_exc_type=f->f_exc_value=f->f_exc_traceback=NULL;
225+
f->f_tstate=PyThreadState_Get();
226+
if (f->f_tstate==NULL)
227+
Py_FatalError("can't create new frame without thread");
217228

218229
f->f_lasti=0;
219230
f->f_lineno=code->co_firstlineno;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp