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/Lib/_dummy_thread.py b/Lib/_dummy_thread.py
index 36e5f38..a2cae54 100644
--- a/Lib/_dummy_thread.py
+++ b/Lib/_dummy_thread.py
@@ -69,7 +69,7 @@
     available, it is safe to assume that the current process is the
     only thread.  Thus a constant can be safely returned.
     """
-    return -1
+    return 1
 
 def allocate_lock():
     """Dummy implementation of _thread.allocate_lock()."""
diff --git a/Lib/test/test_dummy_thread.py b/Lib/test/test_dummy_thread.py
index bb4bfe7..0840be6 100644
--- a/Lib/test/test_dummy_thread.py
+++ b/Lib/test/test_dummy_thread.py
@@ -111,8 +111,7 @@
     def test_ident(self):
         self.assertIsInstance(_thread.get_ident(), int,
                               "_thread.get_ident() returned a non-integer")
-        self.assertNotEqual(_thread.get_ident(), 0,
-                        "_thread.get_ident() returned 0")
+        self.assertGreater(_thread.get_ident(), 0)
 
     def test_LockType(self):
         self.assertIsInstance(_thread.allocate_lock(), _thread.LockType,
diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py
index e6d8e50..9aeb28a 100644
--- a/Lib/test/test_sys.py
+++ b/Lib/test/test_sys.py
@@ -393,6 +393,9 @@
         thread_id = thread_info[0]
 
         d = sys._current_frames()
+        for tid in d:
+            self.assertIsInstance(tid, int)
+            self.assertGreater(tid, 0)
 
         main_id = threading.get_ident()
         self.assertIn(main_id, d)
diff --git a/Lib/test/test_threading.py b/Lib/test/test_threading.py
index 6b6c4d2..5f7c0a8 100644
--- a/Lib/test/test_threading.py
+++ b/Lib/test/test_threading.py
@@ -181,6 +181,7 @@
         ctypes = import_module("ctypes")
 
         set_async_exc = ctypes.pythonapi.PyThreadState_SetAsyncExc
+        set_async_exc.argtypes = (ctypes.c_ulong, ctypes.py_object)
 
         class AsyncExc(Exception):
             pass
@@ -189,9 +190,11 @@
 
         # First check it works when setting the exception from the same thread.
         tid = threading.get_ident()
+        self.assertIsInstance(tid, int)
+        self.assertGreater(tid, 0)
 
         try:
-            result = set_async_exc(ctypes.c_long(tid), exception)
+            result = set_async_exc(tid, exception)
             # The exception is async, so we might have to keep the VM busy until
             # it notices.
             while True:
@@ -237,7 +240,7 @@
         # Try a thread id that doesn't make sense.
         if verbose:
             print("    trying nonsensical thread id")
-        result = set_async_exc(ctypes.c_long(-1), exception)
+        result = set_async_exc(-1, exception)
         self.assertEqual(result, 0)  # no thread states modified
 
         # Now raise an exception in the worker thread.
@@ -250,7 +253,7 @@
         self.assertFalse(t.finished)
         if verbose:
             print("    attempting to raise asynch exception in worker")
-        result = set_async_exc(ctypes.c_long(t.id), exception)
+        result = set_async_exc(t.id, exception)
         self.assertEqual(result, 1) # one thread state modified
         if verbose:
             print("    waiting for worker to say it caught the exception")
diff --git a/Lib/threading.py b/Lib/threading.py
index 95978d3..929a4b0 100644
--- a/Lib/threading.py
+++ b/Lib/threading.py
@@ -993,14 +993,14 @@
         #
         # Must take care to not raise an exception if _dummy_thread is being
         # used (and thus this module is being used as an instance of
-        # dummy_threading).  _dummy_thread.get_ident() always returns -1 since
+        # dummy_threading).  _dummy_thread.get_ident() always returns 1 since
         # there is only one thread if _dummy_thread is being used.  Thus
         # len(_active) is always <= 1 here, and any Thread instance created
         # overwrites the (if any) thread currently registered in _active.
         #
         # An instance of _MainThread is always created by 'threading'.  This
         # gets overwritten the instant an instance of Thread is created; both
-        # threads return -1 from _dummy_thread.get_ident() and thus have the
+        # threads return 1 from _dummy_thread.get_ident() and thus have the
         # same key in the dict.  So when the _MainThread instance created by
         # 'threading' tries to clean itself up when atexit calls this method
         # it gets a KeyError if another Thread instance was created.