Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 29 additions & 1 deletion Doc/library/mmap.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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.

Expand All @@ -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]])

Expand Down Expand Up @@ -450,3 +459,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
9 changes: 9 additions & 0 deletions Lib/test/test_mmap.py
Original file line number Diff line number Diff line change
Expand Up @@ -1157,6 +1157,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)


class LargeMmapTests(unittest.TestCase):

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add a ``flags`` parameter to :meth:`mmap.mmap.flush` to control synchronization behavior.
25 changes: 20 additions & 5 deletions Modules/mmapmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -930,13 +930,16 @@ mmap_tell_method(PyObject *op, PyObject *Py_UNUSED(ignored))
}

static PyObject *
mmap_flush_method(PyObject *op, PyObject *args)
mmap_flush_method(PyObject *op, PyObject *args, PyObject *kwargs)
{
Py_ssize_t offset = 0;
Py_ssize_t size = -1;
int flags = 0;
mmap_object *self = mmap_object_CAST(op);
static char *kwlist[] = {"offset", "size", "flags", NULL};
CHECK_VALID(NULL);
if (!PyArg_ParseTuple(args, "|nn:flush", &offset, &size)) {
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|nn$i:flush", kwlist,
&offset, &size, &flags)) {
return NULL;
}
if (size == -1) {
Expand All @@ -957,8 +960,10 @@ mmap_flush_method(PyObject *op, PyObject *args)
}
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;
}
Expand Down Expand Up @@ -1203,7 +1208,7 @@ static struct PyMethodDef mmap_object_methods[] = {
{"close", mmap_close_method, METH_NOARGS},
{"find", mmap_find_method, METH_VARARGS},
{"rfind", mmap_rfind_method, METH_VARARGS},
{"flush", mmap_flush_method, METH_VARARGS},
{"flush", _PyCFunction_CAST(mmap_flush_method), METH_VARARGS | METH_KEYWORDS},
#ifdef HAVE_MADVISE
{"madvise", mmap_madvise_method, METH_VARARGS},
#endif
Expand Down Expand Up @@ -2047,6 +2052,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
Expand Down
Loading