A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://github.com/python/cpython/commit/aa0aa0492c5fffe750a26d2ab13737a1a6d7d63c below:

Remove own implementation for thread-local storage (#2537) · python/cpython@aa0aa04 · GitHub

@@ -81,14 +81,14 @@ PyThread_init_thread(void)

81 81

or the size specified by the THREAD_STACK_SIZE macro. */

82 82

static size_t _pythread_stacksize = 0;

83 83 84 -

#ifdef _POSIX_THREADS

85 -

#define PYTHREAD_NAME "pthread"

86 -

#include "thread_pthread.h"

87 -

#endif

88 - 89 -

#ifdef NT_THREADS

90 -

#define PYTHREAD_NAME "nt"

91 -

#include "thread_nt.h"

84 +

#if defined(_POSIX_THREADS)

85 +

# define PYTHREAD_NAME "pthread"

86 +

# include "thread_pthread.h"

87 +

#elif defined(NT_THREADS)

88 +

# define PYTHREAD_NAME "nt"

89 +

# include "thread_nt.h"

90 +

#else

91 +

# error "Require native thread feature. See https://bugs.python.org/issue30832"

92 92

#endif

93 93 94 94

@@ -114,13 +114,7 @@ PyThread_set_stacksize(size_t size)

114 114

#endif

115 115

}

116 116 117 -

#ifndef Py_HAVE_NATIVE_TLS

118 -

/* If the platform has not supplied a platform specific

119 -

TLS implementation, provide our own.

120 117 121 -

This code stolen from "thread_sgi.h", where it was the only

122 -

implementation of an existing Python TLS API.

123 -

*/

124 118

/* ------------------------------------------------------------------------

125 119

Per-thread data ("key") support.

126 120

@@ -157,205 +151,6 @@ any of the other functions are called. There's also a hidden assumption

157 151

that calls to PyThread_create_key() are serialized externally.

158 152

------------------------------------------------------------------------ */

159 153 160 -

/* A singly-linked list of struct key objects remembers all the key->value

161 -

* associations. File static keyhead heads the list. keymutex is used

162 -

* to enforce exclusion internally.

163 -

*/

164 -

struct key {

165 -

/* Next record in the list, or NULL if this is the last record. */

166 -

struct key *next;

167 - 168 -

/* The thread id, according to PyThread_get_thread_ident(). */

169 -

unsigned long id;

170 - 171 -

/* The key and its associated value. */

172 -

int key;

173 -

void *value;

174 -

};

175 - 176 -

static struct key *keyhead = NULL;

177 -

static PyThread_type_lock keymutex = NULL;

178 -

static int nkeys = 0; /* PyThread_create_key() hands out nkeys+1 next */

179 - 180 -

/* Internal helper.

181 -

* If the current thread has a mapping for key, the appropriate struct key*

182 -

* is returned. NB: value is ignored in this case!

183 -

* If there is no mapping for key in the current thread, then:

184 -

* If value is NULL, NULL is returned.

185 -

* Else a mapping of key to value is created for the current thread,

186 -

* and a pointer to a new struct key* is returned; except that if

187 -

* malloc() can't find room for a new struct key*, NULL is returned.

188 -

* So when value==NULL, this acts like a pure lookup routine, and when

189 -

* value!=NULL, this acts like dict.setdefault(), returning an existing

190 -

* mapping if one exists, else creating a new mapping.

191 -

*

192 -

* Caution: this used to be too clever, trying to hold keymutex only

193 -

* around the "p->next = keyhead; keyhead = p" pair. That allowed

194 -

* another thread to mutate the list, via key deletion, concurrent with

195 -

* find_key() crawling over the list. Hilarity ensued. For example, when

196 -

* the for-loop here does "p = p->next", p could end up pointing at a

197 -

* record that PyThread_delete_key_value() was concurrently free()'ing.

198 -

* That could lead to anything, from failing to find a key that exists, to

199 -

* segfaults. Now we lock the whole routine.

200 -

*/

201 -

static struct key *

202 -

find_key(int set_value, int key, void *value)

203 -

{

204 -

struct key *p, *prev_p;

205 -

unsigned long id = PyThread_get_thread_ident();

206 - 207 -

if (!keymutex)

208 -

return NULL;

209 -

PyThread_acquire_lock(keymutex, 1);

210 -

prev_p = NULL;

211 -

for (p = keyhead; p != NULL; p = p->next) {

212 -

if (p->id == id && p->key == key) {

213 -

if (set_value)

214 -

p->value = value;

215 -

goto Done;

216 -

}

217 -

/* Sanity check. These states should never happen but if

218 -

* they do we must abort. Otherwise we'll end up spinning

219 -

* in a tight loop with the lock held. A similar check is done

220 -

* in pystate.c tstate_delete_common(). */

221 -

if (p == prev_p)

222 -

Py_FatalError("tls find_key: small circular list(!)");

223 -

prev_p = p;

224 -

if (p->next == keyhead)

225 -

Py_FatalError("tls find_key: circular list(!)");

226 -

}

227 -

if (!set_value && value == NULL) {

228 -

assert(p == NULL);

229 -

goto Done;

230 -

}

231 -

p = (struct key *)PyMem_RawMalloc(sizeof(struct key));

232 -

if (p != NULL) {

233 -

p->id = id;

234 -

p->key = key;

235 -

p->value = value;

236 -

p->next = keyhead;

237 -

keyhead = p;

238 -

}

239 -

Done:

240 -

PyThread_release_lock(keymutex);

241 -

return p;

242 -

}

243 - 244 -

/* Return a new key. This must be called before any other functions in

245 -

* this family, and callers must arrange to serialize calls to this

246 -

* function. No violations are detected.

247 -

*/

248 -

int

249 -

PyThread_create_key(void)

250 -

{

251 -

/* All parts of this function are wrong if it's called by multiple

252 -

* threads simultaneously.

253 -

*/

254 -

if (keymutex == NULL)

255 -

keymutex = PyThread_allocate_lock();

256 -

return ++nkeys;

257 -

}

258 - 259 -

/* Forget the associations for key across *all* threads. */

260 -

void

261 -

PyThread_delete_key(int key)

262 -

{

263 -

struct key *p, **q;

264 - 265 -

PyThread_acquire_lock(keymutex, 1);

266 -

q = &keyhead;

267 -

while ((p = *q) != NULL) {

268 -

if (p->key == key) {

269 -

*q = p->next;

270 -

PyMem_RawFree((void *)p);

271 -

/* NB This does *not* free p->value! */

272 -

}

273 -

else

274 -

q = &p->next;

275 -

}

276 -

PyThread_release_lock(keymutex);

277 -

}

278 - 279 -

int

280 -

PyThread_set_key_value(int key, void *value)

281 -

{

282 -

struct key *p;

283 - 284 -

p = find_key(1, key, value);

285 -

if (p == NULL)

286 -

return -1;

287 -

else

288 -

return 0;

289 -

}

290 - 291 -

/* Retrieve the value associated with key in the current thread, or NULL

292 -

* if the current thread doesn't have an association for key.

293 -

*/

294 -

void *

295 -

PyThread_get_key_value(int key)

296 -

{

297 -

struct key *p = find_key(0, key, NULL);

298 - 299 -

if (p == NULL)

300 -

return NULL;

301 -

else

302 -

return p->value;

303 -

}

304 - 305 -

/* Forget the current thread's association for key, if any. */

306 -

void

307 -

PyThread_delete_key_value(int key)

308 -

{

309 -

unsigned long id = PyThread_get_thread_ident();

310 -

struct key *p, **q;

311 - 312 -

PyThread_acquire_lock(keymutex, 1);

313 -

q = &keyhead;

314 -

while ((p = *q) != NULL) {

315 -

if (p->key == key && p->id == id) {

316 -

*q = p->next;

317 -

PyMem_RawFree((void *)p);

318 -

/* NB This does *not* free p->value! */

319 -

break;

320 -

}

321 -

else

322 -

q = &p->next;

323 -

}

324 -

PyThread_release_lock(keymutex);

325 -

}

326 - 327 -

/* Forget everything not associated with the current thread id.

328 -

* This function is called from PyOS_AfterFork_Child(). It is necessary

329 -

* because other thread ids which were in use at the time of the fork

330 -

* may be reused for new threads created in the forked process.

331 -

*/

332 -

void

333 -

PyThread_ReInitTLS(void)

334 -

{

335 -

unsigned long id = PyThread_get_thread_ident();

336 -

struct key *p, **q;

337 - 338 -

if (!keymutex)

339 -

return;

340 - 341 -

/* As with interpreter_lock in PyEval_ReInitThreads()

342 -

we just create a new lock without freeing the old one */

343 -

keymutex = PyThread_allocate_lock();

344 - 345 -

/* Delete all keys which do not match the current thread id */

346 -

q = &keyhead;

347 -

while ((p = *q) != NULL) {

348 -

if (p->id != id) {

349 -

*q = p->next;

350 -

PyMem_RawFree((void *)p);

351 -

/* NB This does *not* free p->value! */

352 -

}

353 -

else

354 -

q = &p->next;

355 -

}

356 -

}

357 - 358 -

#endif /* Py_HAVE_NATIVE_TLS */

359 154 360 155

PyDoc_STRVAR(threadinfo__doc__,

361 156

"sys.thread_info\n\


RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4