bpo-6532: Make the thread id an unsigned integer. (#781)

* bpo-6532: Make the thread id an unsigned integer.

From C API side the type of results of PyThread_start_new_thread() and
PyThread_get_thread_ident(), the id parameter of
PyThreadState_SetAsyncExc(), and the thread_id field of PyThreadState
changed from "long" to "unsigned long".

* Restore a check in thread_get_ident().
diff --git a/Python/ceval.c b/Python/ceval.c
index fd60b73..e7ee772 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -148,7 +148,7 @@
 #include "pythread.h"
 
 static PyThread_type_lock pending_lock = 0; /* for pending calls */
-static long main_thread = 0;
+static unsigned long main_thread = 0;
 /* This single variable consolidates all requests to break out of the fast path
    in the eval loop. */
 static _Py_atomic_int eval_breaker = {0};
diff --git a/Python/import.c b/Python/import.c
index 0fc4d1d..17a320b 100644
--- a/Python/import.c
+++ b/Python/import.c
@@ -147,14 +147,14 @@
 #include "pythread.h"
 
 static PyThread_type_lock import_lock = 0;
-static long import_lock_thread = -1;
+static unsigned long import_lock_thread = PYTHREAD_INVALID_THREAD_ID;
 static int import_lock_level = 0;
 
 void
 _PyImport_AcquireLock(void)
 {
-    long me = PyThread_get_thread_ident();
-    if (me == -1)
+    unsigned long me = PyThread_get_thread_ident();
+    if (me == PYTHREAD_INVALID_THREAD_ID)
         return; /* Too bad */
     if (import_lock == NULL) {
         import_lock = PyThread_allocate_lock();
@@ -165,7 +165,8 @@
         import_lock_level++;
         return;
     }
-    if (import_lock_thread != -1 || !PyThread_acquire_lock(import_lock, 0))
+    if (import_lock_thread != PYTHREAD_INVALID_THREAD_ID ||
+        !PyThread_acquire_lock(import_lock, 0))
     {
         PyThreadState *tstate = PyEval_SaveThread();
         PyThread_acquire_lock(import_lock, 1);
@@ -179,15 +180,15 @@
 int
 _PyImport_ReleaseLock(void)
 {
-    long me = PyThread_get_thread_ident();
-    if (me == -1 || import_lock == NULL)
+    unsigned long me = PyThread_get_thread_ident();
+    if (me == PYTHREAD_INVALID_THREAD_ID || import_lock == NULL)
         return 0; /* Too bad */
     if (import_lock_thread != me)
         return -1;
     import_lock_level--;
     assert(import_lock_level >= 0);
     if (import_lock_level == 0) {
-        import_lock_thread = -1;
+        import_lock_thread = PYTHREAD_INVALID_THREAD_ID;
         PyThread_release_lock(import_lock);
     }
     return 1;
@@ -209,7 +210,7 @@
     }
     if (import_lock_level > 1) {
         /* Forked as a side effect of import */
-        long me = PyThread_get_thread_ident();
+        unsigned long me = PyThread_get_thread_ident();
         /* The following could fail if the lock is already held, but forking as
            a side-effect of an import is a) rare, b) nuts, and c) difficult to
            do thanks to the lock only being held when doing individual module
@@ -218,7 +219,7 @@
         import_lock_thread = me;
         import_lock_level--;
     } else {
-        import_lock_thread = -1;
+        import_lock_thread = PYTHREAD_INVALID_THREAD_ID;
         import_lock_level = 0;
     }
 }
@@ -238,7 +239,7 @@
 /*[clinic end generated code: output=8b89384b5e1963fc input=9b088f9b217d9bdf]*/
 {
 #ifdef WITH_THREAD
-    return PyBool_FromLong(import_lock_thread != -1);
+    return PyBool_FromLong(import_lock_thread != PYTHREAD_INVALID_THREAD_ID);
 #else
     Py_RETURN_FALSE;
 #endif
diff --git a/Python/pystate.c b/Python/pystate.c
index 65c244e..8e81707 100644
--- a/Python/pystate.c
+++ b/Python/pystate.c
@@ -580,7 +580,8 @@
    existing async exception.  This raises no exceptions. */
 
 int
-PyThreadState_SetAsyncExc(long id, PyObject *exc) {
+PyThreadState_SetAsyncExc(unsigned long id, PyObject *exc)
+{
     PyInterpreterState *interp = GET_INTERP_STATE();
     PyThreadState *p;
 
@@ -668,7 +669,7 @@
             struct _frame *frame = t->frame;
             if (frame == NULL)
                 continue;
-            id = PyLong_FromLong(t->thread_id);
+            id = PyLong_FromUnsignedLong(t->thread_id);
             if (id == NULL)
                 goto Fail;
             stat = PyDict_SetItem(result, id, (PyObject *)frame);
diff --git a/Python/thread.c b/Python/thread.c
index 63eeb1e..3a52e1e 100644
--- a/Python/thread.c
+++ b/Python/thread.c
@@ -172,7 +172,7 @@
     struct key *next;
 
     /* The thread id, according to PyThread_get_thread_ident(). */
-    long id;
+    unsigned long id;
 
     /* The key and its associated value. */
     int key;
@@ -208,7 +208,7 @@
 find_key(int set_value, int key, void *value)
 {
     struct key *p, *prev_p;
-    long id = PyThread_get_thread_ident();
+    unsigned long id = PyThread_get_thread_ident();
 
     if (!keymutex)
         return NULL;
@@ -312,7 +312,7 @@
 void
 PyThread_delete_key_value(int key)
 {
-    long id = PyThread_get_thread_ident();
+    unsigned long id = PyThread_get_thread_ident();
     struct key *p, **q;
 
     PyThread_acquire_lock(keymutex, 1);
@@ -338,7 +338,7 @@
 void
 PyThread_ReInitTLS(void)
 {
-    long id = PyThread_get_thread_ident();
+    unsigned long id = PyThread_get_thread_ident();
     struct key *p, **q;
 
     if (!keymutex)
diff --git a/Python/thread_foobar.h b/Python/thread_foobar.h
index ea96f9c..45cfd1b 100644
--- a/Python/thread_foobar.h
+++ b/Python/thread_foobar.h
@@ -9,7 +9,7 @@
 /*
  * Thread support.
  */
-long
+unsigned long
 PyThread_start_new_thread(void (*func)(void *), void *arg)
 {
     int success = 0;            /* init not needed when SOLARIS_THREADS and */
@@ -18,10 +18,10 @@
     dprintf(("PyThread_start_new_thread called\n"));
     if (!initialized)
         PyThread_init_thread();
-    return success < 0 ? -1 : 0;
+    return success < 0 ? PYTHREAD_INVALID_THREAD_ID : 0;
 }
 
-long
+unsigned long
 PyThread_get_thread_ident(void)
 {
     if (!initialized)
diff --git a/Python/thread_nt.h b/Python/thread_nt.h
index 74a6ee8..8158ff8 100644
--- a/Python/thread_nt.h
+++ b/Python/thread_nt.h
@@ -140,7 +140,7 @@
 }
 #endif /* _PY_USE_CV_LOCKS */
 
-long PyThread_get_thread_ident(void);
+unsigned long PyThread_get_thread_ident(void);
 
 /*
  * Initialization of the C package, should not be needed.
@@ -172,21 +172,21 @@
     return 0;
 }
 
-long
+unsigned long
 PyThread_start_new_thread(void (*func)(void *), void *arg)
 {
     HANDLE hThread;
     unsigned threadID;
     callobj *obj;
 
-    dprintf(("%ld: PyThread_start_new_thread called\n",
+    dprintf(("%lu: PyThread_start_new_thread called\n",
              PyThread_get_thread_ident()));
     if (!initialized)
         PyThread_init_thread();
 
     obj = (callobj*)HeapAlloc(GetProcessHeap(), 0, sizeof(*obj));
     if (!obj)
-        return -1;
+        return PYTHREAD_INVALID_THREAD_ID;
     obj->func = func;
     obj->arg = arg;
     hThread = (HANDLE)_beginthreadex(0,
@@ -199,24 +199,24 @@
          * too many threads".
          */
         int e = errno;
-        dprintf(("%ld: PyThread_start_new_thread failed, errno %d\n",
+        dprintf(("%lu: PyThread_start_new_thread failed, errno %d\n",
                  PyThread_get_thread_ident(), e));
         threadID = (unsigned)-1;
         HeapFree(GetProcessHeap(), 0, obj);
     }
     else {
-        dprintf(("%ld: PyThread_start_new_thread succeeded: %p\n",
+        dprintf(("%lu: PyThread_start_new_thread succeeded: %p\n",
                  PyThread_get_thread_ident(), (void*)hThread));
         CloseHandle(hThread);
     }
-    return (long) threadID;
+    return threadID;
 }
 
 /*
  * Return the thread Id instead of a handle. The Id is said to uniquely identify the
  * thread in the system
  */
-long
+unsigned long
 PyThread_get_thread_ident(void)
 {
     if (!initialized)
@@ -228,7 +228,7 @@
 void
 PyThread_exit_thread(void)
 {
-    dprintf(("%ld: PyThread_exit_thread called\n", PyThread_get_thread_ident()));
+    dprintf(("%lu: PyThread_exit_thread called\n", PyThread_get_thread_ident()));
     if (!initialized)
         exit(0);
     _endthreadex(0);
@@ -250,7 +250,7 @@
 
     aLock = AllocNonRecursiveMutex() ;
 
-    dprintf(("%ld: PyThread_allocate_lock() -> %p\n", PyThread_get_thread_ident(), aLock));
+    dprintf(("%lu: PyThread_allocate_lock() -> %p\n", PyThread_get_thread_ident(), aLock));
 
     return (PyThread_type_lock) aLock;
 }
@@ -258,7 +258,7 @@
 void
 PyThread_free_lock(PyThread_type_lock aLock)
 {
-    dprintf(("%ld: PyThread_free_lock(%p) called\n", PyThread_get_thread_ident(),aLock));
+    dprintf(("%lu: PyThread_free_lock(%p) called\n", PyThread_get_thread_ident(),aLock));
 
     FreeNonRecursiveMutex(aLock) ;
 }
@@ -289,7 +289,7 @@
     else
         milliseconds = INFINITE;
 
-    dprintf(("%ld: PyThread_acquire_lock_timed(%p, %lld) called\n",
+    dprintf(("%lu: PyThread_acquire_lock_timed(%p, %lld) called\n",
              PyThread_get_thread_ident(), aLock, microseconds));
 
     if (aLock && EnterNonRecursiveMutex((PNRMUTEX)aLock,
@@ -300,7 +300,7 @@
         success = PY_LOCK_FAILURE;
     }
 
-    dprintf(("%ld: PyThread_acquire_lock(%p, %lld) -> %d\n",
+    dprintf(("%lu: PyThread_acquire_lock(%p, %lld) -> %d\n",
              PyThread_get_thread_ident(), aLock, microseconds, success));
 
     return success;
@@ -314,10 +314,10 @@
 void
 PyThread_release_lock(PyThread_type_lock aLock)
 {
-    dprintf(("%ld: PyThread_release_lock(%p) called\n", PyThread_get_thread_ident(),aLock));
+    dprintf(("%lu: PyThread_release_lock(%p) called\n", PyThread_get_thread_ident(),aLock));
 
     if (!(aLock && LeaveNonRecursiveMutex((PNRMUTEX) aLock)))
-        dprintf(("%ld: Could not PyThread_release_lock(%p) error: %ld\n", PyThread_get_thread_ident(), aLock, GetLastError()));
+        dprintf(("%lu: Could not PyThread_release_lock(%p) error: %ld\n", PyThread_get_thread_ident(), aLock, GetLastError()));
 }
 
 /* minimum/maximum thread stack sizes supported */
diff --git a/Python/thread_pthread.h b/Python/thread_pthread.h
index ba7393f..b95840c 100644
--- a/Python/thread_pthread.h
+++ b/Python/thread_pthread.h
@@ -184,7 +184,7 @@
  */
 
 
-long
+unsigned long
 PyThread_start_new_thread(void (*func)(void *), void *arg)
 {
     pthread_t th;
@@ -202,7 +202,7 @@
 
 #if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED)
     if (pthread_attr_init(&attrs) != 0)
-        return -1;
+        return PYTHREAD_INVALID_THREAD_ID;
 #endif
 #if defined(THREAD_STACK_SIZE)
     tss = (_pythread_stacksize != 0) ? _pythread_stacksize
@@ -210,7 +210,7 @@
     if (tss != 0) {
         if (pthread_attr_setstacksize(&attrs, tss) != 0) {
             pthread_attr_destroy(&attrs);
-            return -1;
+            return PYTHREAD_INVALID_THREAD_ID;
         }
     }
 #endif
@@ -232,31 +232,31 @@
     pthread_attr_destroy(&attrs);
 #endif
     if (status != 0)
-        return -1;
+        return PYTHREAD_INVALID_THREAD_ID;
 
     pthread_detach(th);
 
 #if SIZEOF_PTHREAD_T <= SIZEOF_LONG
-    return (long) th;
+    return (unsigned long) th;
 #else
-    return (long) *(long *) &th;
+    return (unsigned long) *(unsigned long *) &th;
 #endif
 }
 
 /* XXX This implementation is considered (to quote Tim Peters) "inherently
    hosed" because:
      - It does not guarantee the promise that a non-zero integer is returned.
-     - The cast to long is inherently unsafe.
+     - The cast to unsigned long is inherently unsafe.
      - It is not clear that the 'volatile' (for AIX?) are any longer necessary.
 */
-long
+unsigned long
 PyThread_get_thread_ident(void)
 {
     volatile pthread_t threadid;
     if (!initialized)
         PyThread_init_thread();
     threadid = pthread_self();
-    return (long) threadid;
+    return (unsigned long) threadid;
 }
 
 void
diff --git a/Python/traceback.c b/Python/traceback.c
index 9f8c568..b52385e 100644
--- a/Python/traceback.c
+++ b/Python/traceback.c
@@ -731,7 +731,7 @@
     else
         PUTS(fd, "Thread 0x");
     _Py_DumpHexadecimal(fd,
-                        (unsigned long)tstate->thread_id,
+                        tstate->thread_id,
                         sizeof(unsigned long) * 2);
     PUTS(fd, " (most recent call first):\n");
 }