17db96d56Sopenharmony_ci/* Common code for use by all hashlib related modules. */
27db96d56Sopenharmony_ci
37db96d56Sopenharmony_ci/*
47db96d56Sopenharmony_ci * Given a PyObject* obj, fill in the Py_buffer* viewp with the result
57db96d56Sopenharmony_ci * of PyObject_GetBuffer.  Sets an exception and issues the erraction
67db96d56Sopenharmony_ci * on any errors, e.g. 'return NULL' or 'goto error'.
77db96d56Sopenharmony_ci */
87db96d56Sopenharmony_ci#define GET_BUFFER_VIEW_OR_ERROR(obj, viewp, erraction) do { \
97db96d56Sopenharmony_ci        if (PyUnicode_Check((obj))) { \
107db96d56Sopenharmony_ci            PyErr_SetString(PyExc_TypeError, \
117db96d56Sopenharmony_ci                            "Strings must be encoded before hashing");\
127db96d56Sopenharmony_ci            erraction; \
137db96d56Sopenharmony_ci        } \
147db96d56Sopenharmony_ci        if (!PyObject_CheckBuffer((obj))) { \
157db96d56Sopenharmony_ci            PyErr_SetString(PyExc_TypeError, \
167db96d56Sopenharmony_ci                            "object supporting the buffer API required"); \
177db96d56Sopenharmony_ci            erraction; \
187db96d56Sopenharmony_ci        } \
197db96d56Sopenharmony_ci        if (PyObject_GetBuffer((obj), (viewp), PyBUF_SIMPLE) == -1) { \
207db96d56Sopenharmony_ci            erraction; \
217db96d56Sopenharmony_ci        } \
227db96d56Sopenharmony_ci        if ((viewp)->ndim > 1) { \
237db96d56Sopenharmony_ci            PyErr_SetString(PyExc_BufferError, \
247db96d56Sopenharmony_ci                            "Buffer must be single dimension"); \
257db96d56Sopenharmony_ci            PyBuffer_Release((viewp)); \
267db96d56Sopenharmony_ci            erraction; \
277db96d56Sopenharmony_ci        } \
287db96d56Sopenharmony_ci    } while(0)
297db96d56Sopenharmony_ci
307db96d56Sopenharmony_ci#define GET_BUFFER_VIEW_OR_ERROUT(obj, viewp) \
317db96d56Sopenharmony_ci    GET_BUFFER_VIEW_OR_ERROR(obj, viewp, return NULL)
327db96d56Sopenharmony_ci
337db96d56Sopenharmony_ci/*
347db96d56Sopenharmony_ci * Helper code to synchronize access to the hash object when the GIL is
357db96d56Sopenharmony_ci * released around a CPU consuming hashlib operation. All code paths that
367db96d56Sopenharmony_ci * access a mutable part of obj must be enclosed in an ENTER_HASHLIB /
377db96d56Sopenharmony_ci * LEAVE_HASHLIB block or explicitly acquire and release the lock inside
387db96d56Sopenharmony_ci * a PY_BEGIN / END_ALLOW_THREADS block if they wish to release the GIL for
397db96d56Sopenharmony_ci * an operation.
407db96d56Sopenharmony_ci */
417db96d56Sopenharmony_ci
427db96d56Sopenharmony_ci#include "pythread.h"
437db96d56Sopenharmony_ci#define ENTER_HASHLIB(obj) \
447db96d56Sopenharmony_ci    if ((obj)->lock) { \
457db96d56Sopenharmony_ci        if (!PyThread_acquire_lock((obj)->lock, 0)) { \
467db96d56Sopenharmony_ci            Py_BEGIN_ALLOW_THREADS \
477db96d56Sopenharmony_ci            PyThread_acquire_lock((obj)->lock, 1); \
487db96d56Sopenharmony_ci            Py_END_ALLOW_THREADS \
497db96d56Sopenharmony_ci        } \
507db96d56Sopenharmony_ci    }
517db96d56Sopenharmony_ci#define LEAVE_HASHLIB(obj) \
527db96d56Sopenharmony_ci    if ((obj)->lock) { \
537db96d56Sopenharmony_ci        PyThread_release_lock((obj)->lock); \
547db96d56Sopenharmony_ci    }
557db96d56Sopenharmony_ci
567db96d56Sopenharmony_ci/* TODO(gps): We should probably make this a module or EVPobject attribute
577db96d56Sopenharmony_ci * to allow the user to optimize based on the platform they're using. */
587db96d56Sopenharmony_ci#define HASHLIB_GIL_MINSIZE 2048
597db96d56Sopenharmony_ci
60