mirror of
https://github.com/python/cpython.git
synced 2025-12-31 04:23:37 +00:00
gh-63016: Add flags parameter on mmap.flush (#139553)
Co-authored-by: Victor Stinner <vstinner@python.org>
This commit is contained in:
parent
57d569942c
commit
1af21ea320
5 changed files with 115 additions and 15 deletions
|
|
@ -212,7 +212,7 @@ To map anonymous memory, -1 should be passed as the fileno along with the length
|
|||
Writable :term:`bytes-like object` is now accepted.
|
||||
|
||||
|
||||
.. method:: flush([offset[, size]])
|
||||
.. method:: flush([offset[, size]], *, flags=MS_SYNC)
|
||||
|
||||
Flushes changes made to the in-memory copy of a file back to disk. Without
|
||||
use of this call there is no guarantee that changes are written back before
|
||||
|
|
@ -221,6 +221,12 @@ To map anonymous memory, -1 should be passed as the fileno along with the length
|
|||
whole extent of the mapping is flushed. *offset* must be a multiple of the
|
||||
:const:`PAGESIZE` or :const:`ALLOCATIONGRANULARITY`.
|
||||
|
||||
The *flags* parameter specifies the synchronization behavior.
|
||||
*flags* must be one of the :ref:`MS_* constants <ms-constants>` available
|
||||
on the system.
|
||||
|
||||
On Windows, the *flags* parameter is ignored.
|
||||
|
||||
``None`` is returned to indicate success. An exception is raised when the
|
||||
call failed.
|
||||
|
||||
|
|
@ -235,6 +241,9 @@ To map anonymous memory, -1 should be passed as the fileno along with the length
|
|||
specified alone, and the flush operation will extend from *offset*
|
||||
to the end of the mmap.
|
||||
|
||||
.. versionchanged:: next
|
||||
Added *flags* parameter to control synchronization behavior.
|
||||
|
||||
|
||||
.. method:: madvise(option[, start[, length]])
|
||||
|
||||
|
|
@ -461,3 +470,22 @@ MAP_* Constants
|
|||
:data:`MAP_TPRO`, :data:`MAP_TRANSLATED_ALLOW_EXECUTE`, and
|
||||
:data:`MAP_UNIX03` constants.
|
||||
|
||||
.. _ms-constants:
|
||||
|
||||
MS_* Constants
|
||||
++++++++++++++
|
||||
|
||||
.. data:: MS_SYNC
|
||||
MS_ASYNC
|
||||
MS_INVALIDATE
|
||||
|
||||
These flags control the synchronization behavior for :meth:`mmap.flush`:
|
||||
|
||||
* :data:`MS_SYNC` - Synchronous flush: writes are scheduled and the call
|
||||
blocks until they are physically written to storage.
|
||||
* :data:`MS_ASYNC` - Asynchronous flush: writes are scheduled but the call
|
||||
returns immediately without waiting for completion.
|
||||
* :data:`MS_INVALIDATE` - Invalidate cached data: invalidates other mappings
|
||||
of the same file so they can see the changes.
|
||||
|
||||
.. versionadded:: next
|
||||
|
|
|
|||
|
|
@ -1166,6 +1166,15 @@ def test_flush_parameters(self):
|
|||
m.flush(PAGESIZE)
|
||||
m.flush(PAGESIZE, PAGESIZE)
|
||||
|
||||
if hasattr(mmap, 'MS_SYNC'):
|
||||
m.flush(0, PAGESIZE, flags=mmap.MS_SYNC)
|
||||
if hasattr(mmap, 'MS_ASYNC'):
|
||||
m.flush(flags=mmap.MS_ASYNC)
|
||||
if hasattr(mmap, 'MS_INVALIDATE'):
|
||||
m.flush(PAGESIZE * 2, flags=mmap.MS_INVALIDATE)
|
||||
if hasattr(mmap, 'MS_ASYNC') and hasattr(mmap, 'MS_INVALIDATE'):
|
||||
m.flush(0, PAGESIZE, flags=mmap.MS_ASYNC | mmap.MS_INVALIDATE)
|
||||
|
||||
@unittest.skipUnless(sys.platform == 'linux', 'Linux only')
|
||||
@support.requires_linux_version(5, 17, 0)
|
||||
def test_set_name(self):
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
Add a ``flags`` parameter to :meth:`mmap.mmap.flush` to control synchronization behavior.
|
||||
67
Modules/clinic/mmapmodule.c.h
generated
67
Modules/clinic/mmapmodule.c.h
generated
|
|
@ -2,6 +2,10 @@
|
|||
preserve
|
||||
[clinic start generated code]*/
|
||||
|
||||
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
|
||||
# include "pycore_gc.h" // PyGC_Head
|
||||
# include "pycore_runtime.h" // _Py_ID()
|
||||
#endif
|
||||
#include "pycore_abstract.h" // _PyNumber_Index()
|
||||
#include "pycore_critical_section.h"// Py_BEGIN_CRITICAL_SECTION()
|
||||
#include "pycore_modsupport.h" // _PyArg_CheckPositional()
|
||||
|
|
@ -371,29 +375,63 @@ mmap_mmap_tell(PyObject *self, PyObject *Py_UNUSED(ignored))
|
|||
}
|
||||
|
||||
PyDoc_STRVAR(mmap_mmap_flush__doc__,
|
||||
"flush($self, offset=0, size=-1, /)\n"
|
||||
"flush($self, offset=0, size=-1, /, *, flags=0)\n"
|
||||
"--\n"
|
||||
"\n");
|
||||
|
||||
#define MMAP_MMAP_FLUSH_METHODDEF \
|
||||
{"flush", _PyCFunction_CAST(mmap_mmap_flush), METH_FASTCALL, mmap_mmap_flush__doc__},
|
||||
{"flush", _PyCFunction_CAST(mmap_mmap_flush), METH_FASTCALL|METH_KEYWORDS, mmap_mmap_flush__doc__},
|
||||
|
||||
static PyObject *
|
||||
mmap_mmap_flush_impl(mmap_object *self, Py_ssize_t offset, Py_ssize_t size);
|
||||
mmap_mmap_flush_impl(mmap_object *self, Py_ssize_t offset, Py_ssize_t size,
|
||||
int flags);
|
||||
|
||||
static PyObject *
|
||||
mmap_mmap_flush(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
|
||||
mmap_mmap_flush(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
|
||||
{
|
||||
PyObject *return_value = NULL;
|
||||
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
|
||||
|
||||
#define NUM_KEYWORDS 1
|
||||
static struct {
|
||||
PyGC_Head _this_is_not_used;
|
||||
PyObject_VAR_HEAD
|
||||
Py_hash_t ob_hash;
|
||||
PyObject *ob_item[NUM_KEYWORDS];
|
||||
} _kwtuple = {
|
||||
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
|
||||
.ob_hash = -1,
|
||||
.ob_item = { &_Py_ID(flags), },
|
||||
};
|
||||
#undef NUM_KEYWORDS
|
||||
#define KWTUPLE (&_kwtuple.ob_base.ob_base)
|
||||
|
||||
#else // !Py_BUILD_CORE
|
||||
# define KWTUPLE NULL
|
||||
#endif // !Py_BUILD_CORE
|
||||
|
||||
static const char * const _keywords[] = {"", "", "flags", NULL};
|
||||
static _PyArg_Parser _parser = {
|
||||
.keywords = _keywords,
|
||||
.fname = "flush",
|
||||
.kwtuple = KWTUPLE,
|
||||
};
|
||||
#undef KWTUPLE
|
||||
PyObject *argsbuf[3];
|
||||
Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
|
||||
Py_ssize_t offset = 0;
|
||||
Py_ssize_t size = -1;
|
||||
int flags = 0;
|
||||
|
||||
if (!_PyArg_CheckPositional("flush", nargs, 0, 2)) {
|
||||
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser,
|
||||
/*minpos*/ 0, /*maxpos*/ 2, /*minkw*/ 0, /*varpos*/ 0, argsbuf);
|
||||
if (!args) {
|
||||
goto exit;
|
||||
}
|
||||
if (nargs < 1) {
|
||||
goto skip_optional;
|
||||
goto skip_optional_posonly;
|
||||
}
|
||||
noptargs--;
|
||||
{
|
||||
Py_ssize_t ival = -1;
|
||||
PyObject *iobj = _PyNumber_Index(args[0]);
|
||||
|
|
@ -407,8 +445,9 @@ mmap_mmap_flush(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
|
|||
offset = ival;
|
||||
}
|
||||
if (nargs < 2) {
|
||||
goto skip_optional;
|
||||
goto skip_optional_posonly;
|
||||
}
|
||||
noptargs--;
|
||||
{
|
||||
Py_ssize_t ival = -1;
|
||||
PyObject *iobj = _PyNumber_Index(args[1]);
|
||||
|
|
@ -421,9 +460,17 @@ mmap_mmap_flush(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
|
|||
}
|
||||
size = ival;
|
||||
}
|
||||
skip_optional:
|
||||
skip_optional_posonly:
|
||||
if (!noptargs) {
|
||||
goto skip_optional_kwonly;
|
||||
}
|
||||
flags = PyLong_AsInt(args[2]);
|
||||
if (flags == -1 && PyErr_Occurred()) {
|
||||
goto exit;
|
||||
}
|
||||
skip_optional_kwonly:
|
||||
Py_BEGIN_CRITICAL_SECTION(self);
|
||||
return_value = mmap_mmap_flush_impl((mmap_object *)self, offset, size);
|
||||
return_value = mmap_mmap_flush_impl((mmap_object *)self, offset, size, flags);
|
||||
Py_END_CRITICAL_SECTION();
|
||||
|
||||
exit:
|
||||
|
|
@ -832,4 +879,4 @@ exit:
|
|||
#ifndef MMAP_MMAP_MADVISE_METHODDEF
|
||||
#define MMAP_MMAP_MADVISE_METHODDEF
|
||||
#endif /* !defined(MMAP_MMAP_MADVISE_METHODDEF) */
|
||||
/*[clinic end generated code: output=fd9ca0ef425af934 input=a9049054013a1b77]*/
|
||||
/*[clinic end generated code: output=8389e3c8e3db3a78 input=a9049054013a1b77]*/
|
||||
|
|
|
|||
|
|
@ -1034,12 +1034,15 @@ mmap.mmap.flush
|
|||
offset: Py_ssize_t = 0
|
||||
size: Py_ssize_t = -1
|
||||
/
|
||||
*
|
||||
flags: int = 0
|
||||
|
||||
[clinic start generated code]*/
|
||||
|
||||
static PyObject *
|
||||
mmap_mmap_flush_impl(mmap_object *self, Py_ssize_t offset, Py_ssize_t size)
|
||||
/*[clinic end generated code: output=956ced67466149cf input=c50b893bc69520ec]*/
|
||||
mmap_mmap_flush_impl(mmap_object *self, Py_ssize_t offset, Py_ssize_t size,
|
||||
int flags)
|
||||
/*[clinic end generated code: output=4225f4174dc75a53 input=42ba5fb716b6c294]*/
|
||||
{
|
||||
CHECK_VALID(NULL);
|
||||
if (size == -1) {
|
||||
|
|
@ -1060,8 +1063,10 @@ mmap_mmap_flush_impl(mmap_object *self, Py_ssize_t offset, Py_ssize_t size)
|
|||
}
|
||||
Py_RETURN_NONE;
|
||||
#elif defined(UNIX)
|
||||
/* XXX flags for msync? */
|
||||
if (-1 == msync(self->data + offset, size, MS_SYNC)) {
|
||||
if (flags == 0) {
|
||||
flags = MS_SYNC;
|
||||
}
|
||||
if (-1 == msync(self->data + offset, size, flags)) {
|
||||
PyErr_SetFromErrno(PyExc_OSError);
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -2331,6 +2336,16 @@ mmap_exec(PyObject *module)
|
|||
ADD_INT_MACRO(module, ACCESS_WRITE);
|
||||
ADD_INT_MACRO(module, ACCESS_COPY);
|
||||
|
||||
#ifdef MS_INVALIDATE
|
||||
ADD_INT_MACRO(module, MS_INVALIDATE);
|
||||
#endif
|
||||
#ifdef MS_ASYNC
|
||||
ADD_INT_MACRO(module, MS_ASYNC);
|
||||
#endif
|
||||
#ifdef MS_SYNC
|
||||
ADD_INT_MACRO(module, MS_SYNC);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_MADVISE
|
||||
// Conventional advice values
|
||||
#ifdef MADV_NORMAL
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue