mirror of
https://github.com/python/cpython.git
synced 2024-11-23 01:45:25 +08:00
c2627d6eea
This PR adds the ability to enable the GIL if it was disabled at interpreter startup, and modifies the multi-phase module initialization path to enable the GIL when loading a module, unless that module's spec includes a slot indicating it can run safely without the GIL. PEP 703 called the constant for the slot `Py_mod_gil_not_used`; I went with `Py_MOD_GIL_NOT_USED` for consistency with gh-104148. A warning will be issued up to once per interpreter for the first GIL-using module that is loaded. If `-v` is given, a shorter message will be printed to stderr every time a GIL-using module is loaded (including the first one that issues a warning).
131 lines
3.3 KiB
C
131 lines
3.3 KiB
C
/*
|
|
* Python UUID module that wraps libuuid or Windows rpcrt4.dll.
|
|
* DCE compatible Universally Unique Identifier library.
|
|
*/
|
|
|
|
// Need limited C API version 3.13 for Py_mod_gil
|
|
#include "pyconfig.h" // Py_GIL_DISABLED
|
|
#ifndef Py_GIL_DISABLED
|
|
# define Py_LIMITED_API 0x030d0000
|
|
#endif
|
|
|
|
#include "Python.h"
|
|
#if defined(HAVE_UUID_H)
|
|
// AIX, FreeBSD, libuuid with pkgconf
|
|
#include <uuid.h>
|
|
#elif defined(HAVE_UUID_UUID_H)
|
|
// libuuid without pkgconf
|
|
#include <uuid/uuid.h>
|
|
#endif
|
|
|
|
#ifdef MS_WINDOWS
|
|
#include <rpc.h>
|
|
#endif
|
|
|
|
#ifndef MS_WINDOWS
|
|
|
|
static PyObject *
|
|
py_uuid_generate_time_safe(PyObject *Py_UNUSED(context),
|
|
PyObject *Py_UNUSED(ignored))
|
|
{
|
|
uuid_t uuid;
|
|
#ifdef HAVE_UUID_GENERATE_TIME_SAFE
|
|
int res;
|
|
|
|
res = uuid_generate_time_safe(uuid);
|
|
return Py_BuildValue("y#i", (const char *) uuid, sizeof(uuid), res);
|
|
#elif defined(HAVE_UUID_CREATE)
|
|
uint32_t status;
|
|
uuid_create(&uuid, &status);
|
|
# if defined(HAVE_UUID_ENC_BE)
|
|
unsigned char buf[sizeof(uuid)];
|
|
uuid_enc_be(buf, &uuid);
|
|
return Py_BuildValue("y#i", buf, sizeof(uuid), (int) status);
|
|
# else
|
|
return Py_BuildValue("y#i", (const char *) &uuid, sizeof(uuid), (int) status);
|
|
# endif /* HAVE_UUID_CREATE */
|
|
#else /* HAVE_UUID_GENERATE_TIME_SAFE */
|
|
uuid_generate_time(uuid);
|
|
return Py_BuildValue("y#O", (const char *) uuid, sizeof(uuid), Py_None);
|
|
#endif /* HAVE_UUID_GENERATE_TIME_SAFE */
|
|
}
|
|
|
|
#else /* MS_WINDOWS */
|
|
|
|
static PyObject *
|
|
py_UuidCreate(PyObject *Py_UNUSED(context),
|
|
PyObject *Py_UNUSED(ignored))
|
|
{
|
|
UUID uuid;
|
|
RPC_STATUS res;
|
|
|
|
Py_BEGIN_ALLOW_THREADS
|
|
res = UuidCreateSequential(&uuid);
|
|
Py_END_ALLOW_THREADS
|
|
|
|
switch (res) {
|
|
case RPC_S_OK:
|
|
case RPC_S_UUID_LOCAL_ONLY:
|
|
case RPC_S_UUID_NO_ADDRESS:
|
|
/*
|
|
All success codes, but the latter two indicate that the UUID is random
|
|
rather than based on the MAC address. If the OS can't figure this out,
|
|
neither can we, so we'll take it anyway.
|
|
*/
|
|
return Py_BuildValue("y#", (const char *)&uuid, sizeof(uuid));
|
|
}
|
|
PyErr_SetFromWindowsErr(res);
|
|
return NULL;
|
|
}
|
|
|
|
#endif /* MS_WINDOWS */
|
|
|
|
|
|
static int
|
|
uuid_exec(PyObject *module) {
|
|
assert(sizeof(uuid_t) == 16);
|
|
#if defined(MS_WINDOWS)
|
|
int has_uuid_generate_time_safe = 0;
|
|
#elif defined(HAVE_UUID_GENERATE_TIME_SAFE)
|
|
int has_uuid_generate_time_safe = 1;
|
|
#else
|
|
int has_uuid_generate_time_safe = 0;
|
|
#endif
|
|
if (PyModule_AddIntConstant(module, "has_uuid_generate_time_safe",
|
|
has_uuid_generate_time_safe) < 0) {
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static PyMethodDef uuid_methods[] = {
|
|
#if defined(HAVE_UUID_UUID_H) || defined(HAVE_UUID_H)
|
|
{"generate_time_safe", py_uuid_generate_time_safe, METH_NOARGS, NULL},
|
|
#endif
|
|
#if defined(MS_WINDOWS)
|
|
{"UuidCreate", py_UuidCreate, METH_NOARGS, NULL},
|
|
#endif
|
|
{NULL, NULL, 0, NULL} /* sentinel */
|
|
};
|
|
|
|
static PyModuleDef_Slot uuid_slots[] = {
|
|
{Py_mod_exec, uuid_exec},
|
|
{Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
|
|
{Py_mod_gil, Py_MOD_GIL_NOT_USED},
|
|
{0, NULL}
|
|
};
|
|
|
|
static struct PyModuleDef uuidmodule = {
|
|
PyModuleDef_HEAD_INIT,
|
|
.m_name = "_uuid",
|
|
.m_size = 0,
|
|
.m_methods = uuid_methods,
|
|
.m_slots = uuid_slots,
|
|
};
|
|
|
|
PyMODINIT_FUNC
|
|
PyInit__uuid(void)
|
|
{
|
|
return PyModuleDef_Init(&uuidmodule);
|
|
}
|