bpo-30054: Expose tracemalloc C API (#1236)

* Make PyTraceMalloc_Track() and PyTraceMalloc_Untrack() functions
  public (remove the "_" prefix)
* Remove the _PyTraceMalloc_domain_t type: use directly unsigned
  int.
* Document methods

Note: methods are already tested in test_tracemalloc.
diff --git a/Doc/c-api/memory.rst b/Doc/c-api/memory.rst
index 873fb2a..22b9fe2 100644
--- a/Doc/c-api/memory.rst
+++ b/Doc/c-api/memory.rst
@@ -429,6 +429,28 @@
    Set the arena allocator.
 
 
+tracemalloc C API
+=================
+
+.. versionadded:: 3.7
+
+.. c:function: int PyTraceMalloc_Track(unsigned int domain, uintptr_t ptr, size_t size)
+
+   Track an allocated memory block in the :mod:`tracemalloc` module.
+
+   Return 0 on success, return ``-1`` on error (failed to allocate memory to
+   store the trace). Return ``-2`` if tracemalloc is disabled.
+
+   If memory block is already tracked, update the existing trace.
+
+.. c:function: int PyTraceMalloc_Untrack(unsigned int domain, uintptr_t ptr)
+
+   Untrack an allocated memory block in the :mod:`tracemalloc` module.
+   Do nothing if the block was not tracked.
+
+   Return ``-2`` if tracemalloc is disabled, otherwise return ``0``.
+
+
 .. _memoryexamples:
 
 Examples
diff --git a/Doc/library/tracemalloc.rst b/Doc/library/tracemalloc.rst
index e165669..048ee64 100644
--- a/Doc/library/tracemalloc.rst
+++ b/Doc/library/tracemalloc.rst
@@ -412,6 +412,9 @@
 
       Address space of a memory block (``int`` or ``None``).
 
+      tracemalloc uses the domain ``0`` to trace memory allocations made by
+      Python. C extensions can use other domains to trace other resources.
+
    .. attribute:: inclusive
 
       If *inclusive* is ``True`` (include), only match memory blocks allocated
@@ -622,6 +625,16 @@
    The :attr:`Snapshot.traces` attribute is a sequence of :class:`Trace`
    instances.
 
+   .. versionchanged:: 3.6
+      Added the :attr:`domain` attribute.
+
+   .. attribute:: domain
+
+      Address space of a memory block (``int``). Read-only property.
+
+      tracemalloc uses the domain ``0`` to trace memory allocations made by
+      Python. C extensions can use other domains to trace other resources.
+
    .. attribute:: size
 
       Size of the memory block in bytes (``int``).
diff --git a/Include/pymem.h b/Include/pymem.h
index a7eb4d2..2170e0f 100644
--- a/Include/pymem.h
+++ b/Include/pymem.h
@@ -25,9 +25,6 @@
 PyAPI_FUNC(int) _PyMem_PymallocEnabled(void);
 #endif
 
-/* Identifier of an address space (domain) in tracemalloc */
-typedef unsigned int _PyTraceMalloc_domain_t;
-
 /* Track an allocated memory block in the tracemalloc module.
    Return 0 on success, return -1 on error (failed to allocate memory to store
    the trace).
@@ -35,8 +32,8 @@
    Return -2 if tracemalloc is disabled.
 
    If memory block is already tracked, update the existing trace. */
-PyAPI_FUNC(int) _PyTraceMalloc_Track(
-    _PyTraceMalloc_domain_t domain,
+PyAPI_FUNC(int) PyTraceMalloc_Track(
+    unsigned int domain,
     uintptr_t ptr,
     size_t size);
 
@@ -44,8 +41,8 @@
    Do nothing if the block was not tracked.
 
    Return -2 if tracemalloc is disabled, otherwise return 0. */
-PyAPI_FUNC(int) _PyTraceMalloc_Untrack(
-    _PyTraceMalloc_domain_t domain,
+PyAPI_FUNC(int) PyTraceMalloc_Untrack(
+    unsigned int domain,
     uintptr_t ptr);
 
 /* Get the traceback where a memory block was allocated.
@@ -57,7 +54,7 @@
 
    Raise an exception and return NULL on error. */
 PyAPI_FUNC(PyObject*) _PyTraceMalloc_GetTraceback(
-    _PyTraceMalloc_domain_t domain,
+    unsigned int domain,
     uintptr_t ptr);
 #endif   /* !Py_LIMITED_API */
 
diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c
index 8c44ad2..83ba33d 100644
--- a/Modules/_testcapimodule.c
+++ b/Modules/_testcapimodule.c
@@ -3958,15 +3958,15 @@
 
     if (release_gil) {
         Py_BEGIN_ALLOW_THREADS
-        res = _PyTraceMalloc_Track(domain, (uintptr_t)ptr, size);
+        res = PyTraceMalloc_Track(domain, (uintptr_t)ptr, size);
         Py_END_ALLOW_THREADS
     }
     else {
-        res = _PyTraceMalloc_Track(domain, (uintptr_t)ptr, size);
+        res = PyTraceMalloc_Track(domain, (uintptr_t)ptr, size);
     }
 
     if (res < 0) {
-        PyErr_SetString(PyExc_RuntimeError, "_PyTraceMalloc_Track error");
+        PyErr_SetString(PyExc_RuntimeError, "PyTraceMalloc_Track error");
         return NULL;
     }
 
@@ -3987,9 +3987,9 @@
     if (PyErr_Occurred())
         return NULL;
 
-    res = _PyTraceMalloc_Untrack(domain, (uintptr_t)ptr);
+    res = PyTraceMalloc_Untrack(domain, (uintptr_t)ptr);
     if (res < 0) {
-        PyErr_SetString(PyExc_RuntimeError, "_PyTraceMalloc_Track error");
+        PyErr_SetString(PyExc_RuntimeError, "PyTraceMalloc_Untrack error");
         return NULL;
     }
 
diff --git a/Modules/_tracemalloc.c b/Modules/_tracemalloc.c
index 950789b..00d3542 100644
--- a/Modules/_tracemalloc.c
+++ b/Modules/_tracemalloc.c
@@ -74,7 +74,7 @@
 #endif
 {
     uintptr_t ptr;
-    _PyTraceMalloc_domain_t domain;
+    unsigned int domain;
 } pointer_t;
 
 /* Pack the frame_t structure to reduce the memory footprint on 64-bit
@@ -578,7 +578,7 @@
 
 
 static void
-tracemalloc_remove_trace(_PyTraceMalloc_domain_t domain, uintptr_t ptr)
+tracemalloc_remove_trace(unsigned int domain, uintptr_t ptr)
 {
     trace_t trace;
     int removed;
@@ -605,7 +605,7 @@
 
 
 static int
-tracemalloc_add_trace(_PyTraceMalloc_domain_t domain, uintptr_t ptr,
+tracemalloc_add_trace(unsigned int domain, uintptr_t ptr,
                       size_t size)
 {
     pointer_t key = {ptr, domain};
@@ -1267,7 +1267,7 @@
 
 
 static PyObject*
-trace_to_pyobject(_PyTraceMalloc_domain_t domain, trace_t *trace,
+trace_to_pyobject(unsigned int domain, trace_t *trace,
                   _Py_hashtable_t *intern_tracebacks)
 {
     PyObject *trace_obj = NULL;
@@ -1313,7 +1313,7 @@
                             void *user_data)
 {
     get_traces_t *get_traces = user_data;
-    _PyTraceMalloc_domain_t domain;
+    unsigned int domain;
     trace_t trace;
     PyObject *tracemalloc_obj;
     int res;
@@ -1428,7 +1428,7 @@
 
 
 static traceback_t*
-tracemalloc_get_traceback(_PyTraceMalloc_domain_t domain, uintptr_t ptr)
+tracemalloc_get_traceback(unsigned int domain, uintptr_t ptr)
 {
     trace_t trace;
     int found;
@@ -1783,8 +1783,8 @@
 }
 
 int
-_PyTraceMalloc_Track(_PyTraceMalloc_domain_t domain, uintptr_t ptr,
-                     size_t size)
+PyTraceMalloc_Track(unsigned int domain, uintptr_t ptr,
+                    size_t size)
 {
     int res;
 #ifdef WITH_THREAD
@@ -1812,7 +1812,7 @@
 
 
 int
-_PyTraceMalloc_Untrack(_PyTraceMalloc_domain_t domain, uintptr_t ptr)
+PyTraceMalloc_Untrack(unsigned int domain, uintptr_t ptr)
 {
     if (!tracemalloc_config.tracing) {
         /* tracemalloc is not tracing: do nothing */
@@ -1828,7 +1828,7 @@
 
 
 PyObject*
-_PyTraceMalloc_GetTraceback(_PyTraceMalloc_domain_t domain, uintptr_t ptr)
+_PyTraceMalloc_GetTraceback(unsigned int domain, uintptr_t ptr)
 {
     traceback_t *traceback;