History

add hg and python

cinap_lenrek committed 15 years ago

Commit 4bb9e221 parent 987265c3706 files · +1228772 −-233Browse files

Showing the changes to sys/src/cmd/python/Python/thread.c (1 of 3706 files). Show all

Unified · Split

sys/src/cmd/python/Python/thread.c+384−0
@@ -0,0 +1,384 @@
1+
2+/* Thread package.
3+ This is intended to be usable independently from Python.
4+ The implementation for system foobar is in a file thread_foobar.h
5+ which is included by this file dependent on config settings.
6+ Stuff shared by all thread_*.h files is collected here. */
7+
8+#include "Python.h"
9+
10+
11+#ifndef _POSIX_THREADS
12+/* This means pthreads are not implemented in libc headers, hence the macro
13+ not present in unistd.h. But they still can be implemented as an external
14+ library (e.g. gnu pth in pthread emulation) */
15+# ifdef HAVE_PTHREAD_H
16+# include <pthread.h> /* _POSIX_THREADS */
17+# endif
18+#endif
19+
20+#ifndef DONT_HAVE_STDIO_H
21+#include <stdio.h>
22+#endif
23+
24+#include <stdlib.h>
25+
26+#ifdef __sgi
27+#ifndef HAVE_PTHREAD_H /* XXX Need to check in configure.in */
28+#undef _POSIX_THREADS
29+#endif
30+#endif
31+
32+#include "pythread.h"
33+
34+#ifndef _POSIX_THREADS
35+
36+#ifdef __sgi
37+#define SGI_THREADS
38+#endif
39+
40+#ifdef HAVE_THREAD_H
41+#define SOLARIS_THREADS
42+#endif
43+
44+#if defined(sun) && !defined(SOLARIS_THREADS)
45+#define SUN_LWP
46+#endif
47+
48+/* Check if we're running on HP-UX and _SC_THREADS is defined. If so, then
49+ enough of the Posix threads package is implimented to support python
50+ threads.
51+
52+ This is valid for HP-UX 11.23 running on an ia64 system. If needed, add
53+ a check of __ia64 to verify that we're running on a ia64 system instead
54+ of a pa-risc system.
55+*/
56+#ifdef __hpux
57+#ifdef _SC_THREADS
58+#define _POSIX_THREADS
59+#endif
60+#endif
61+
62+#endif /* _POSIX_THREADS */
63+
64+
65+#ifdef Py_DEBUG
66+static int thread_debug = 0;
67+#define dprintf(args) (void)((thread_debug & 1) && printf args)
68+#define d2printf(args) ((thread_debug & 8) && printf args)
69+#else
70+#define dprintf(args)
71+#define d2printf(args)
72+#endif
73+
74+static int initialized;
75+
76+static void PyThread__init_thread(void); /* Forward */
77+
78+void
79+PyThread_init_thread(void)
80+{
81+#ifdef Py_DEBUG
82+ char *p = getenv("THREADDEBUG");
83+
84+ if (p) {
85+ if (*p)
86+ thread_debug = atoi(p);
87+ else
88+ thread_debug = 1;
89+ }
90+#endif /* Py_DEBUG */
91+ if (initialized)
92+ return;
93+ initialized = 1;
94+ dprintf(("PyThread_init_thread called\n"));
95+ PyThread__init_thread();
96+}
97+
98+/* Support for runtime thread stack size tuning.
99+ A value of 0 means using the platform's default stack size
100+ or the size specified by the THREAD_STACK_SIZE macro. */
101+static size_t _pythread_stacksize = 0;
102+
103+#ifdef SGI_THREADS
104+#include "thread_sgi.h"
105+#endif
106+
107+#ifdef SOLARIS_THREADS
108+#include "thread_solaris.h"
109+#endif
110+
111+#ifdef SUN_LWP
112+#include "thread_lwp.h"
113+#endif
114+
115+#ifdef HAVE_PTH
116+#include "thread_pth.h"
117+#undef _POSIX_THREADS
118+#endif
119+
120+#ifdef _POSIX_THREADS
121+#include "thread_pthread.h"
122+#endif
123+
124+#ifdef C_THREADS
125+#include "thread_cthread.h"
126+#endif
127+
128+#ifdef NT_THREADS
129+#include "thread_nt.h"
130+#endif
131+
132+#ifdef OS2_THREADS
133+#include "thread_os2.h"
134+#endif
135+
136+#ifdef BEOS_THREADS
137+#include "thread_beos.h"
138+#endif
139+
140+#ifdef WINCE_THREADS
141+#include "thread_wince.h"
142+#endif
143+
144+#ifdef PLAN9_THREADS
145+#include "thread_plan9.h"
146+#endif
147+
148+#ifdef ATHEOS_THREADS
149+#include "thread_atheos.h"
150+#endif
151+
152+/*
153+#ifdef FOOBAR_THREADS
154+#include "thread_foobar.h"
155+#endif
156+*/
157+
158+/* return the current thread stack size */
159+size_t
160+PyThread_get_stacksize(void)
161+{
162+ return _pythread_stacksize;
163+}
164+
165+/* Only platforms defining a THREAD_SET_STACKSIZE() macro
166+ in thread_<platform>.h support changing the stack size.
167+ Return 0 if stack size is valid,
168+ -1 if stack size value is invalid,
169+ -2 if setting stack size is not supported. */
170+int
171+PyThread_set_stacksize(size_t size)
172+{
173+#if defined(THREAD_SET_STACKSIZE)
174+ return THREAD_SET_STACKSIZE(size);
175+#else
176+ return -2;
177+#endif
178+}
179+
180+#ifndef Py_HAVE_NATIVE_TLS
181+/* If the platform has not supplied a platform specific
182+ TLS implementation, provide our own.
183+
184+ This code stolen from "thread_sgi.h", where it was the only
185+ implementation of an existing Python TLS API.
186+*/
187+/* ------------------------------------------------------------------------
188+Per-thread data ("key") support.
189+
190+Use PyThread_create_key() to create a new key. This is typically shared
191+across threads.
192+
193+Use PyThread_set_key_value(thekey, value) to associate void* value with
194+thekey in the current thread. Each thread has a distinct mapping of thekey
195+to a void* value. Caution: if the current thread already has a mapping
196+for thekey, value is ignored.
197+
198+Use PyThread_get_key_value(thekey) to retrieve the void* value associated
199+with thekey in the current thread. This returns NULL if no value is
200+associated with thekey in the current thread.
201+
202+Use PyThread_delete_key_value(thekey) to forget the current thread's associated
203+value for thekey. PyThread_delete_key(thekey) forgets the values associated
204+with thekey across *all* threads.
205+
206+While some of these functions have error-return values, none set any
207+Python exception.
208+
209+None of the functions does memory management on behalf of the void* values.
210+You need to allocate and deallocate them yourself. If the void* values
211+happen to be PyObject*, these functions don't do refcount operations on
212+them either.
213+
214+The GIL does not need to be held when calling these functions; they supply
215+their own locking. This isn't true of PyThread_create_key(), though (see
216+next paragraph).
217+
218+There's a hidden assumption that PyThread_create_key() will be called before
219+any of the other functions are called. There's also a hidden assumption
220+that calls to PyThread_create_key() are serialized externally.
221+------------------------------------------------------------------------ */
222+
223+/* A singly-linked list of struct key objects remembers all the key->value
224+ * associations. File static keyhead heads the list. keymutex is used
225+ * to enforce exclusion internally.
226+ */
227+struct key {
228+ /* Next record in the list, or NULL if this is the last record. */
229+ struct key *next;
230+
231+ /* The thread id, according to PyThread_get_thread_ident(). */
232+ long id;
233+
234+ /* The key and its associated value. */
235+ int key;
236+ void *value;
237+};
238+
239+static struct key *keyhead = NULL;
240+static PyThread_type_lock keymutex = NULL;
241+static int nkeys = 0; /* PyThread_create_key() hands out nkeys+1 next */
242+
243+/* Internal helper.
244+ * If the current thread has a mapping for key, the appropriate struct key*
245+ * is returned. NB: value is ignored in this case!
246+ * If there is no mapping for key in the current thread, then:
247+ * If value is NULL, NULL is returned.
248+ * Else a mapping of key to value is created for the current thread,
249+ * and a pointer to a new struct key* is returned; except that if
250+ * malloc() can't find room for a new struct key*, NULL is returned.
251+ * So when value==NULL, this acts like a pure lookup routine, and when
252+ * value!=NULL, this acts like dict.setdefault(), returning an existing
253+ * mapping if one exists, else creating a new mapping.
254+ *
255+ * Caution: this used to be too clever, trying to hold keymutex only
256+ * around the "p->next = keyhead; keyhead = p" pair. That allowed
257+ * another thread to mutate the list, via key deletion, concurrent with
258+ * find_key() crawling over the list. Hilarity ensued. For example, when
259+ * the for-loop here does "p = p->next", p could end up pointing at a
260+ * record that PyThread_delete_key_value() was concurrently free()'ing.
261+ * That could lead to anything, from failing to find a key that exists, to
262+ * segfaults. Now we lock the whole routine.
263+ */
264+static struct key *
265+find_key(int key, void *value)
266+{
267+ struct key *p;
268+ long id = PyThread_get_thread_ident();
269+
270+ if (!keymutex)
271+ return NULL;
272+ PyThread_acquire_lock(keymutex, 1);
273+ for (p = keyhead; p != NULL; p = p->next) {
274+ if (p->id == id && p->key == key)
275+ goto Done;
276+ }
277+ if (value == NULL) {
278+ assert(p == NULL);
279+ goto Done;
280+ }
281+ p = (struct key *)malloc(sizeof(struct key));
282+ if (p != NULL) {
283+ p->id = id;
284+ p->key = key;
285+ p->value = value;
286+ p->next = keyhead;
287+ keyhead = p;
288+ }
289+ Done:
290+ PyThread_release_lock(keymutex);
291+ return p;
292+}
293+
294+/* Return a new key. This must be called before any other functions in
295+ * this family, and callers must arrange to serialize calls to this
296+ * function. No violations are detected.
297+ */
298+int
299+PyThread_create_key(void)
300+{
301+ /* All parts of this function are wrong if it's called by multiple
302+ * threads simultaneously.
303+ */
304+ if (keymutex == NULL)
305+ keymutex = PyThread_allocate_lock();
306+ return ++nkeys;
307+}
308+
309+/* Forget the associations for key across *all* threads. */
310+void
311+PyThread_delete_key(int key)
312+{
313+ struct key *p, **q;
314+
315+ PyThread_acquire_lock(keymutex, 1);
316+ q = &keyhead;
317+ while ((p = *q) != NULL) {
318+ if (p->key == key) {
319+ *q = p->next;
320+ free((void *)p);
321+ /* NB This does *not* free p->value! */
322+ }
323+ else
324+ q = &p->next;
325+ }
326+ PyThread_release_lock(keymutex);
327+}
328+
329+/* Confusing: If the current thread has an association for key,
330+ * value is ignored, and 0 is returned. Else an attempt is made to create
331+ * an association of key to value for the current thread. 0 is returned
332+ * if that succeeds, but -1 is returned if there's not enough memory
333+ * to create the association. value must not be NULL.
334+ */
335+int
336+PyThread_set_key_value(int key, void *value)
337+{
338+ struct key *p;
339+
340+ assert(value != NULL);
341+ p = find_key(key, value);
342+ if (p == NULL)
343+ return -1;
344+ else
345+ return 0;
346+}
347+
348+/* Retrieve the value associated with key in the current thread, or NULL
349+ * if the current thread doesn't have an association for key.
350+ */
351+void *
352+PyThread_get_key_value(int key)
353+{
354+ struct key *p = find_key(key, NULL);
355+
356+ if (p == NULL)
357+ return NULL;
358+ else
359+ return p->value;
360+}
361+
362+/* Forget the current thread's association for key, if any. */
363+void
364+PyThread_delete_key_value(int key)
365+{
366+ long id = PyThread_get_thread_ident();
367+ struct key *p, **q;
368+
369+ PyThread_acquire_lock(keymutex, 1);
370+ q = &keyhead;
371+ while ((p = *q) != NULL) {
372+ if (p->key == key && p->id == id) {
373+ *q = p->next;
374+ free((void *)p);
375+ /* NB This does *not* free p->value! */
376+ break;
377+ }
378+ else
379+ q = &p->next;
380+ }
381+ PyThread_release_lock(keymutex);
382+}
383+
384+#endif /* Py_HAVE_NATIVE_TLS */