Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 770f06d

Browse files
ngoldbaumcharris
authored andcommitted
MAINT: from_dlpack thread safety fixes (#28883)
Fixes #28881 Moves the global variables defined in from_dlpack to the npy_static_pydata struct and initializes them during module init.
1 parent 73b7e54 commit 770f06d

File tree

3 files changed

+27
-27
lines changed

3 files changed

+27
-27
lines changed

numpy/_core/src/multiarray/dlpack.c

Lines changed: 4 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -504,36 +504,12 @@ from_dlpack(PyObject *NPY_UNUSED(self),
504504
return NULL;
505505
}
506506

507-
/* Prepare the arguments to call objects __dlpack__() method */
508-
static PyObject *call_kwnames = NULL;
509-
static PyObject *dl_cpu_device_tuple = NULL;
510-
static PyObject *max_version = NULL;
511-
512-
if (call_kwnames == NULL) {
513-
call_kwnames = Py_BuildValue("(sss)", "dl_device", "copy", "max_version");
514-
if (call_kwnames == NULL) {
515-
return NULL;
516-
}
517-
}
518-
if (dl_cpu_device_tuple == NULL) {
519-
dl_cpu_device_tuple = Py_BuildValue("(i,i)", 1, 0);
520-
if (dl_cpu_device_tuple == NULL) {
521-
return NULL;
522-
}
523-
}
524-
if (max_version == NULL) {
525-
max_version = Py_BuildValue("(i,i)", 1, 0);
526-
if (max_version == NULL) {
527-
return NULL;
528-
}
529-
}
530-
531507
/*
532508
* Prepare arguments for the full call. We always forward copy and pass
533509
* our max_version. `device` is always passed as `None`, but if the user
534510
* provided a device, we will replace it with the "cpu": (1, 0).
535511
*/
536-
PyObject *call_args[] = {obj, Py_None, copy, max_version};
512+
PyObject *call_args[] = {obj, Py_None, copy, npy_static_pydata.dl_max_version};
537513
Py_ssize_t nargsf = 1 | PY_VECTORCALL_ARGUMENTS_OFFSET;
538514

539515
/* If device is passed it must be "cpu" and replace it with (1, 0) */
@@ -544,12 +520,13 @@ from_dlpack(PyObject *NPY_UNUSED(self),
544520
return NULL;
545521
}
546522
assert(device_request == NPY_DEVICE_CPU);
547-
call_args[1] = dl_cpu_device_tuple;
523+
call_args[1] = npy_static_pydata.dl_cpu_device_tuple;
548524
}
549525

550526

551527
PyObject *capsule = PyObject_VectorcallMethod(
552-
npy_interned_str.__dlpack__, call_args, nargsf, call_kwnames);
528+
npy_interned_str.__dlpack__, call_args, nargsf,
529+
npy_static_pydata.dl_call_kwnames);
553530
if (capsule == NULL) {
554531
/*
555532
* TODO: This path should be deprecated in NumPy 2.1. Once deprecated

numpy/_core/src/multiarray/npy_static_data.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,22 @@ initialize_static_globals(void)
184184
return -1;
185185
}
186186

187+
npy_static_pydata.dl_call_kwnames =
188+
Py_BuildValue("(sss)", "dl_device", "copy", "max_version");
189+
if (npy_static_pydata.dl_call_kwnames == NULL) {
190+
return -1;
191+
}
192+
193+
npy_static_pydata.dl_cpu_device_tuple = Py_BuildValue("(i,i)", 1, 0);
194+
if (npy_static_pydata.dl_cpu_device_tuple == NULL) {
195+
return -1;
196+
}
197+
198+
npy_static_pydata.dl_max_version = Py_BuildValue("(i,i)", 1, 0);
199+
if (npy_static_pydata.dl_max_version == NULL) {
200+
return -1;
201+
}
202+
187203
/*
188204
* Initialize contents of npy_static_cdata struct
189205
*

numpy/_core/src/multiarray/npy_static_data.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,13 @@ typedef struct npy_static_pydata_struct {
138138
PyObject *GenericToVoidMethod;
139139
PyObject *ObjectToGenericMethod;
140140
PyObject *GenericToObjectMethod;
141+
142+
/*
143+
* Used in from_dlpack
144+
*/
145+
PyObject *dl_call_kwnames;
146+
PyObject *dl_cpu_device_tuple;
147+
PyObject *dl_max_version;
141148
} npy_static_pydata_struct;
142149

143150

0 commit comments

Comments
 (0)