]> git.proxmox.com Git - mirror_edk2.git/blame - AppPkg/Applications/Python/Python-2.7.2/Python/thread_pth.h
EmbeddedPkg: Extend NvVarStoreFormattedLib LIBRARY_CLASS
[mirror_edk2.git] / AppPkg / Applications / Python / Python-2.7.2 / Python / thread_pth.h
CommitLineData
4710c53d 1\r
2/* GNU pth threads interface\r
3 http://www.gnu.org/software/pth\r
4 2000-05-03 Andy Dustman <andy@dustman.net>\r
5\r
6 Adapted from Posix threads interface\r
7 12 May 1997 -- david arnold <davida@pobox.com>\r
8 */\r
9\r
10#include <stdlib.h>\r
11#include <string.h>\r
12#include <pth.h>\r
13\r
14/* A pth mutex isn't sufficient to model the Python lock type\r
15 * because pth mutexes can be acquired multiple times by the\r
16 * same thread.\r
17 *\r
18 * The pth_lock struct implements a Python lock as a "locked?" bit\r
19 * and a <condition, mutex> pair. In general, if the bit can be acquired\r
20 * instantly, it is, else the pair is used to block the thread until the\r
21 * bit is cleared.\r
22 */\r
23\r
24typedef struct {\r
25 char locked; /* 0=unlocked, 1=locked */\r
26 /* a <cond, mutex> pair to handle an acquire of a locked lock */\r
27 pth_cond_t lock_released;\r
28 pth_mutex_t mut;\r
29} pth_lock;\r
30\r
31#define CHECK_STATUS(name) if (status == -1) { printf("%d ", status); perror(name); error = 1; }\r
32\r
33pth_attr_t PyThread_attr;\r
34\r
35/*\r
36 * Initialization.\r
37 */\r
38\r
39static void PyThread__init_thread(void)\r
40{\r
41 pth_init();\r
42 PyThread_attr = pth_attr_new();\r
43 pth_attr_set(PyThread_attr, PTH_ATTR_STACK_SIZE, 1<<18);\r
44 pth_attr_set(PyThread_attr, PTH_ATTR_JOINABLE, FALSE);\r
45}\r
46\r
47/*\r
48 * Thread support.\r
49 */\r
50\r
51\r
52long PyThread_start_new_thread(void (*func)(void *), void *arg)\r
53{\r
54 pth_t th;\r
55 dprintf(("PyThread_start_new_thread called\n"));\r
56 if (!initialized)\r
57 PyThread_init_thread();\r
58\r
59 th = pth_spawn(PyThread_attr,\r
60 (void* (*)(void *))func,\r
61 (void *)arg\r
62 );\r
63\r
64 return th;\r
65}\r
66\r
67long PyThread_get_thread_ident(void)\r
68{\r
69 volatile pth_t threadid;\r
70 if (!initialized)\r
71 PyThread_init_thread();\r
72 /* Jump through some hoops for Alpha OSF/1 */\r
73 threadid = pth_self();\r
74 return (long) *(long *) &threadid;\r
75}\r
76\r
77void PyThread_exit_thread(void)\r
78{\r
79 dprintf(("PyThread_exit_thread called\n"));\r
80 if (!initialized) {\r
81 exit(0);\r
82 }\r
83}\r
84\r
85/*\r
86 * Lock support.\r
87 */\r
88PyThread_type_lock PyThread_allocate_lock(void)\r
89{\r
90 pth_lock *lock;\r
91 int status, error = 0;\r
92\r
93 dprintf(("PyThread_allocate_lock called\n"));\r
94 if (!initialized)\r
95 PyThread_init_thread();\r
96\r
97 lock = (pth_lock *) malloc(sizeof(pth_lock));\r
98 memset((void *)lock, '\0', sizeof(pth_lock));\r
99 if (lock) {\r
100 lock->locked = 0;\r
101 status = pth_mutex_init(&lock->mut);\r
102 CHECK_STATUS("pth_mutex_init");\r
103 status = pth_cond_init(&lock->lock_released);\r
104 CHECK_STATUS("pth_cond_init");\r
105 if (error) {\r
106 free((void *)lock);\r
107 lock = NULL;\r
108 }\r
109 }\r
110 dprintf(("PyThread_allocate_lock() -> %p\n", lock));\r
111 return (PyThread_type_lock) lock;\r
112}\r
113\r
114void PyThread_free_lock(PyThread_type_lock lock)\r
115{\r
116 pth_lock *thelock = (pth_lock *)lock;\r
117\r
118 dprintf(("PyThread_free_lock(%p) called\n", lock));\r
119\r
120 free((void *)thelock);\r
121}\r
122\r
123int PyThread_acquire_lock(PyThread_type_lock lock, int waitflag)\r
124{\r
125 int success;\r
126 pth_lock *thelock = (pth_lock *)lock;\r
127 int status, error = 0;\r
128\r
129 dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag));\r
130\r
131 status = pth_mutex_acquire(&thelock->mut, !waitflag, NULL);\r
132 CHECK_STATUS("pth_mutex_acquire[1]");\r
133 success = thelock->locked == 0;\r
134 if (success) thelock->locked = 1;\r
135 status = pth_mutex_release( &thelock->mut );\r
136 CHECK_STATUS("pth_mutex_release[1]");\r
137\r
138 if ( !success && waitflag ) {\r
139 /* continue trying until we get the lock */\r
140\r
141 /* mut must be locked by me -- part of the condition\r
142 * protocol */\r
143 status = pth_mutex_acquire( &thelock->mut, !waitflag, NULL );\r
144 CHECK_STATUS("pth_mutex_acquire[2]");\r
145 while ( thelock->locked ) {\r
146 status = pth_cond_await(&thelock->lock_released,\r
147 &thelock->mut, NULL);\r
148 CHECK_STATUS("pth_cond_await");\r
149 }\r
150 thelock->locked = 1;\r
151 status = pth_mutex_release( &thelock->mut );\r
152 CHECK_STATUS("pth_mutex_release[2]");\r
153 success = 1;\r
154 }\r
155 if (error) success = 0;\r
156 dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success));\r
157 return success;\r
158}\r
159\r
160void PyThread_release_lock(PyThread_type_lock lock)\r
161{\r
162 pth_lock *thelock = (pth_lock *)lock;\r
163 int status, error = 0;\r
164\r
165 dprintf(("PyThread_release_lock(%p) called\n", lock));\r
166\r
167 status = pth_mutex_acquire( &thelock->mut, 0, NULL );\r
168 CHECK_STATUS("pth_mutex_acquire[3]");\r
169\r
170 thelock->locked = 0;\r
171\r
172 status = pth_mutex_release( &thelock->mut );\r
173 CHECK_STATUS("pth_mutex_release[3]");\r
174\r
175 /* wake up someone (anyone, if any) waiting on the lock */\r
176 status = pth_cond_notify( &thelock->lock_released, 0 );\r
177 CHECK_STATUS("pth_cond_notify");\r
178}\r