Skip to content

Commit 43a1dfb

Browse files
committed
Use unsigned long long for thread ids
1 parent cf98e3d commit 43a1dfb

File tree

4 files changed

+66
-47
lines changed

4 files changed

+66
-47
lines changed

Include/internal/pycore_pythread.h

+6-3
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,8 @@ PyAPI_FUNC(PyLockStatus) PyThread_acquire_lock_timed_with_retries(
106106
PyThread_type_lock,
107107
PY_TIMEOUT_T microseconds);
108108

109+
PyAPI_FUNC(unsigned long long) PyThread_get_thread_ident_ex(void);
110+
109111
/* Thread joining APIs.
110112
*
111113
* These APIs have a strict contract:
@@ -117,9 +119,10 @@ PyAPI_FUNC(PyLockStatus) PyThread_acquire_lock_timed_with_retries(
117119
* PyThread_detach_thread, or calling them more than once (including
118120
* simultaneously), results in undefined behavior.
119121
*/
120-
PyAPI_FUNC(unsigned long) PyThread_start_joinable_thread(void (*func)(void *),
121-
void *arg,
122-
Py_uintptr_t* handle);
122+
PyAPI_FUNC(int) PyThread_start_joinable_thread(void (*func)(void *),
123+
void *arg,
124+
unsigned long long* ident,
125+
Py_uintptr_t* handle);
123126
/*
124127
* Join a thread started with `PyThread_start_joinable_thread`.
125128
* This function cannot be interrupted. It returns 0 on success,

Modules/_threadmodule.c

+21-19
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ get_thread_state(PyObject *module)
4444

4545
typedef struct {
4646
PyObject_HEAD
47-
unsigned long ident; // TODO ULL instead
47+
unsigned long long ident;
4848
Py_uintptr_t handle;
4949
char joinable;
5050
} ThreadHandleObject;
@@ -80,14 +80,14 @@ ThreadHandle_dealloc(ThreadHandleObject *self)
8080
static PyObject *
8181
ThreadHandle_repr(ThreadHandleObject *self)
8282
{
83-
return PyUnicode_FromFormat("<%s object: ident=%ul>",
83+
return PyUnicode_FromFormat("<%s object: ident=%llu>",
8484
Py_TYPE(self)->tp_name, self->ident);
8585
}
8686

8787
static PyObject *
8888
ThreadHandle_get_ident(ThreadHandleObject *self, void *ignored)
8989
{
90-
return PyLong_FromUnsignedLong(self->ident);
90+
return PyLong_FromUnsignedLongLong(self->ident);
9191
}
9292

9393
static PyObject *
@@ -115,7 +115,7 @@ ThreadHandle_join(ThreadHandleObject *self, void* ignored)
115115
PyErr_SetString(PyExc_ValueError, "the thread is not joinable");
116116
return NULL;
117117
}
118-
if (self->ident == PyThread_get_thread_ident()) {
118+
if (self->ident == PyThread_get_thread_ident_ex()) {
119119
// PyThread_join_thread() would deadlock or error out.
120120
PyErr_SetString(ThreadError, "Cannot join current thread");
121121
return NULL;
@@ -397,7 +397,7 @@ static PyType_Spec lock_type_spec = {
397397
typedef struct {
398398
PyObject_HEAD
399399
PyThread_type_lock rlock_lock;
400-
unsigned long rlock_owner;
400+
unsigned long long rlock_owner;
401401
unsigned long rlock_count;
402402
PyObject *in_weakreflist;
403403
} rlockobject;
@@ -434,13 +434,13 @@ static PyObject *
434434
rlock_acquire(rlockobject *self, PyObject *args, PyObject *kwds)
435435
{
436436
_PyTime_t timeout;
437-
unsigned long tid;
437+
unsigned long long tid;
438438
PyLockStatus r = PY_LOCK_ACQUIRED;
439439

440440
if (lock_acquire_parse_args(args, kwds, &timeout) < 0)
441441
return NULL;
442442

443-
tid = PyThread_get_thread_ident();
443+
tid = PyThread_get_thread_ident_ex();
444444
if (self->rlock_count > 0 && tid == self->rlock_owner) {
445445
unsigned long count = self->rlock_count + 1;
446446
if (count <= self->rlock_count) {
@@ -483,7 +483,7 @@ the lock is taken and its internal counter initialized to 1.");
483483
static PyObject *
484484
rlock_release(rlockobject *self, PyObject *Py_UNUSED(ignored))
485485
{
486-
unsigned long tid = PyThread_get_thread_ident();
486+
unsigned long long tid = PyThread_get_thread_ident_ex();
487487

488488
if (self->rlock_count == 0 || self->rlock_owner != tid) {
489489
PyErr_SetString(PyExc_RuntimeError,
@@ -567,7 +567,7 @@ For internal use by `threading.Condition`.");
567567
static PyObject *
568568
rlock_recursion_count(rlockobject *self, PyObject *Py_UNUSED(ignored))
569569
{
570-
unsigned long tid = PyThread_get_thread_ident();
570+
unsigned long long tid = PyThread_get_thread_ident_ex();
571571
return PyLong_FromUnsignedLong(
572572
self->rlock_owner == tid ? self->rlock_count : 0UL);
573573
}
@@ -580,7 +580,7 @@ For internal use by reentrancy checks.");
580580
static PyObject *
581581
rlock_is_owned(rlockobject *self, PyObject *Py_UNUSED(ignored))
582582
{
583-
unsigned long tid = PyThread_get_thread_ident();
583+
unsigned long long tid = PyThread_get_thread_ident_ex();
584584

585585
if (self->rlock_count > 0 && self->rlock_owner == tid) {
586586
Py_RETURN_TRUE;
@@ -1235,7 +1235,7 @@ static int
12351235
do_start_new_thread(thread_module_state* state,
12361236
PyObject *func, PyObject* args, PyObject* kwargs,
12371237
int joinable,
1238-
unsigned long* ident, Py_uintptr_t* handle)
1238+
unsigned long long* ident, Py_uintptr_t* handle)
12391239
{
12401240
PyInterpreterState *interp = _PyInterpreterState_GET();
12411241
if (!_PyInterpreterState_HasFeature(interp, Py_RTFLAGS_THREADS)) {
@@ -1269,13 +1269,15 @@ do_start_new_thread(thread_module_state* state,
12691269
boot->args = Py_NewRef(args);
12701270
boot->kwargs = Py_XNewRef(kwargs);
12711271

1272+
int err;
12721273
if (joinable) {
1273-
*ident = PyThread_start_joinable_thread(thread_run, (void*) boot, handle);
1274+
err = PyThread_start_joinable_thread(thread_run, (void*) boot, ident, handle);
12741275
} else {
12751276
*handle = 0;
12761277
*ident = PyThread_start_new_thread(thread_run, (void*) boot);
1278+
err = (*ident == PYTHREAD_INVALID_THREAD_ID);
12771279
}
1278-
if (*ident == PYTHREAD_INVALID_THREAD_ID) {
1280+
if (err) {
12791281
PyErr_SetString(ThreadError, "can't start new thread");
12801282
PyThreadState_Clear(boot->tstate);
12811283
thread_bootstate_free(boot, 1);
@@ -1314,13 +1316,13 @@ thread_PyThread_start_new_thread(PyObject *module, PyObject *fargs)
13141316
return NULL;
13151317
}
13161318

1317-
unsigned long ident = 0;
1319+
unsigned long long ident = 0;
13181320
Py_uintptr_t handle;
13191321
if (do_start_new_thread(state, func, args, kwargs, /*joinable=*/ 0,
13201322
&ident, &handle)) {
13211323
return NULL;
13221324
}
1323-
return PyLong_FromUnsignedLong(ident);
1325+
return PyLong_FromUnsignedLongLong(ident);
13241326
}
13251327

13261328
PyDoc_STRVAR(start_new_doc,
@@ -1440,12 +1442,12 @@ information about locks.");
14401442
static PyObject *
14411443
thread_get_ident(PyObject *self, PyObject *Py_UNUSED(ignored))
14421444
{
1443-
unsigned long ident = PyThread_get_thread_ident();
1445+
unsigned long long ident = PyThread_get_thread_ident_ex();
14441446
if (ident == PYTHREAD_INVALID_THREAD_ID) {
14451447
PyErr_SetString(ThreadError, "no current thread ident");
14461448
return NULL;
14471449
}
1448-
return PyLong_FromUnsignedLong(ident);
1450+
return PyLong_FromUnsignedLongLong(ident);
14491451
}
14501452

14511453
PyDoc_STRVAR(get_ident_doc,
@@ -1632,8 +1634,8 @@ thread_excepthook_file(PyObject *file, PyObject *exc_type, PyObject *exc_value,
16321634
Py_DECREF(name);
16331635
}
16341636
else {
1635-
unsigned long ident = PyThread_get_thread_ident();
1636-
PyObject *str = PyUnicode_FromFormat("%lu", ident);
1637+
unsigned long long ident = PyThread_get_thread_ident_ex();
1638+
PyObject *str = PyUnicode_FromFormat("%llu", ident);
16371639
if (str != NULL) {
16381640
if (PyFile_WriteObject(str, file, Py_PRINT_RAW) < 0) {
16391641
Py_DECREF(str);

Python/thread_nt.h

+21-11
Original file line numberDiff line numberDiff line change
@@ -182,8 +182,9 @@ bootstrap(void *call)
182182
return 0;
183183
}
184184

185-
unsigned long
186-
PyThread_start_joinable_thread(void (*func)(void *), void *arg, Py_uintptr_t* handle) {
185+
int
186+
PyThread_start_joinable_thread(void (*func)(void *), void *arg,
187+
unsigned long long* ident, Py_uintptr_t* handle) {
187188
HANDLE hThread;
188189
unsigned threadID;
189190
callobj *obj;
@@ -193,7 +194,7 @@ PyThread_start_joinable_thread(void (*func)(void *), void *arg, Py_uintptr_t* ha
193194

194195
obj = (callobj*)HeapAlloc(GetProcessHeap(), 0, sizeof(*obj));
195196
if (!obj)
196-
return PYTHREAD_INVALID_THREAD_ID;
197+
return -1;
197198
obj->func = func;
198199
obj->arg = arg;
199200
PyThreadState *tstate = _PyThreadState_GET();
@@ -207,20 +208,22 @@ PyThread_start_joinable_thread(void (*func)(void *), void *arg, Py_uintptr_t* ha
207208
* too many threads".
208209
*/
209210
HeapFree(GetProcessHeap(), 0, obj);
210-
return PYTHREAD_INVALID_THREAD_ID;
211+
return -1;
211212
}
213+
*ident = threadID;
212214
*handle = (Py_uintptr_t) hThread;
213-
return threadID;
215+
return 0;
214216
}
215217

216218
unsigned long
217219
PyThread_start_new_thread(void (*func)(void *), void *arg) {
218220
Py_uintptr_t handle;
219-
unsigned long threadID = PyThread_start_joinable_thread(func, arg, &handle);
220-
if (handle) {
221-
CloseHandle((HANDLE) handle);
221+
unsigned long long ident;
222+
if (PyThread_start_joinable_thread(func, arg, &ident, &handle)) {
223+
return PYTHREAD_INVALID_THREAD_ID;
222224
}
223-
return threadID;
225+
CloseHandle((HANDLE) handle);
226+
return ident;
224227
}
225228

226229
int
@@ -241,15 +244,22 @@ PyThread_detach_thread(Py_uintptr_t handle) {
241244
* Return the thread Id instead of a handle. The Id is said to uniquely identify the
242245
* thread in the system
243246
*/
244-
unsigned long
245-
PyThread_get_thread_ident(void)
247+
unsigned long long
248+
PyThread_get_thread_ident_ex(void)
246249
{
247250
if (!initialized)
248251
PyThread_init_thread();
249252

250253
return GetCurrentThreadId();
251254
}
252255

256+
unsigned long
257+
PyThread_get_thread_ident(void)
258+
{
259+
return (unsigned long) PyThread_get_thread_ident_ex();
260+
}
261+
262+
253263
#ifdef PY_HAVE_THREAD_NATIVE_ID
254264
/*
255265
* Return the native Thread ID (TID) of the calling thread.

Python/thread_pthread.h

+18-14
Original file line numberDiff line numberDiff line change
@@ -298,20 +298,18 @@ do_start_joinable_thread(void (*func)(void *), void *arg, pthread_t* out_id)
298298
return 0;
299299
}
300300

301-
unsigned long
302-
PyThread_start_joinable_thread(void (*func)(void *), void *arg, Py_uintptr_t* handle) {
301+
int
302+
PyThread_start_joinable_thread(void (*func)(void *), void *arg,
303+
unsigned long long* ident, Py_uintptr_t* handle) {
303304
pthread_t th = (pthread_t) 0;
304305
if (do_start_joinable_thread(func, arg, &th)) {
305-
return PYTHREAD_INVALID_THREAD_ID;
306+
return -1;
306307
}
307-
assert(th == (pthread_t) (unsigned long) th);
308-
assert(th == (pthread_t) (Py_uintptr_t) th);
308+
*ident = (unsigned long long) th;
309309
*handle = (Py_uintptr_t) th;
310-
#if SIZEOF_PTHREAD_T <= SIZEOF_LONG
311-
return (unsigned long) th;
312-
#else
313-
return (unsigned long) *(unsigned long *) &th;
314-
#endif
310+
assert(th == (pthread_t) *ident);
311+
assert(th == (pthread_t) *handle);
312+
return 0;
315313
}
316314

317315
unsigned long
@@ -345,14 +343,20 @@ PyThread_detach_thread(Py_uintptr_t th) {
345343
- The cast to unsigned long is inherently unsafe.
346344
- It is not clear that the 'volatile' (for AIX?) are any longer necessary.
347345
*/
348-
unsigned long
349-
PyThread_get_thread_ident(void)
350-
{
346+
unsigned long long
347+
PyThread_get_thread_ident_ex(void) {
351348
volatile pthread_t threadid;
352349
if (!initialized)
353350
PyThread_init_thread();
354351
threadid = pthread_self();
355-
return (unsigned long) threadid;
352+
assert(threadid == (pthread_t) (unsigned long long) threadid);
353+
return (unsigned long long) threadid;
354+
}
355+
356+
unsigned long
357+
PyThread_get_thread_ident(void)
358+
{
359+
return (unsigned long) PyThread_get_thread_ident_ex();
356360
}
357361

358362
#ifdef PY_HAVE_THREAD_NATIVE_ID

0 commit comments

Comments
 (0)