Skip to content

Commit 1af21ea

Browse files
aiskvstinner
andauthored
gh-63016: Add flags parameter on mmap.flush (#139553)
Co-authored-by: Victor Stinner <vstinner@python.org>
1 parent 57d5699 commit 1af21ea

File tree

5 files changed

+115
-15
lines changed

5 files changed

+115
-15
lines changed

Doc/library/mmap.rst

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ To map anonymous memory, -1 should be passed as the fileno along with the length
212212
Writable :term:`bytes-like object` is now accepted.
213213

214214

215-
.. method:: flush([offset[, size]])
215+
.. method:: flush([offset[, size]], *, flags=MS_SYNC)
216216

217217
Flushes changes made to the in-memory copy of a file back to disk. Without
218218
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
221221
whole extent of the mapping is flushed. *offset* must be a multiple of the
222222
:const:`PAGESIZE` or :const:`ALLOCATIONGRANULARITY`.
223223

224+
The *flags* parameter specifies the synchronization behavior.
225+
*flags* must be one of the :ref:`MS_* constants <ms-constants>` available
226+
on the system.
227+
228+
On Windows, the *flags* parameter is ignored.
229+
224230
``None`` is returned to indicate success. An exception is raised when the
225231
call failed.
226232

@@ -235,6 +241,9 @@ To map anonymous memory, -1 should be passed as the fileno along with the length
235241
specified alone, and the flush operation will extend from *offset*
236242
to the end of the mmap.
237243

244+
.. versionchanged:: next
245+
Added *flags* parameter to control synchronization behavior.
246+
238247

239248
.. method:: madvise(option[, start[, length]])
240249

@@ -461,3 +470,22 @@ MAP_* Constants
461470
:data:`MAP_TPRO`, :data:`MAP_TRANSLATED_ALLOW_EXECUTE`, and
462471
:data:`MAP_UNIX03` constants.
463472

473+
.. _ms-constants:
474+
475+
MS_* Constants
476+
++++++++++++++
477+
478+
.. data:: MS_SYNC
479+
MS_ASYNC
480+
MS_INVALIDATE
481+
482+
These flags control the synchronization behavior for :meth:`mmap.flush`:
483+
484+
* :data:`MS_SYNC` - Synchronous flush: writes are scheduled and the call
485+
blocks until they are physically written to storage.
486+
* :data:`MS_ASYNC` - Asynchronous flush: writes are scheduled but the call
487+
returns immediately without waiting for completion.
488+
* :data:`MS_INVALIDATE` - Invalidate cached data: invalidates other mappings
489+
of the same file so they can see the changes.
490+
491+
.. versionadded:: next

Lib/test/test_mmap.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1166,6 +1166,15 @@ def test_flush_parameters(self):
11661166
m.flush(PAGESIZE)
11671167
m.flush(PAGESIZE, PAGESIZE)
11681168

1169+
if hasattr(mmap, 'MS_SYNC'):
1170+
m.flush(0, PAGESIZE, flags=mmap.MS_SYNC)
1171+
if hasattr(mmap, 'MS_ASYNC'):
1172+
m.flush(flags=mmap.MS_ASYNC)
1173+
if hasattr(mmap, 'MS_INVALIDATE'):
1174+
m.flush(PAGESIZE * 2, flags=mmap.MS_INVALIDATE)
1175+
if hasattr(mmap, 'MS_ASYNC') and hasattr(mmap, 'MS_INVALIDATE'):
1176+
m.flush(0, PAGESIZE, flags=mmap.MS_ASYNC | mmap.MS_INVALIDATE)
1177+
11691178
@unittest.skipUnless(sys.platform == 'linux', 'Linux only')
11701179
@support.requires_linux_version(5, 17, 0)
11711180
def test_set_name(self):
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add a ``flags`` parameter to :meth:`mmap.mmap.flush` to control synchronization behavior.

Modules/clinic/mmapmodule.c.h

Lines changed: 57 additions & 10 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Modules/mmapmodule.c

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1034,12 +1034,15 @@ mmap.mmap.flush
10341034
offset: Py_ssize_t = 0
10351035
size: Py_ssize_t = -1
10361036
/
1037+
*
1038+
flags: int = 0
10371039
10381040
[clinic start generated code]*/
10391041

10401042
static PyObject *
1041-
mmap_mmap_flush_impl(mmap_object *self, Py_ssize_t offset, Py_ssize_t size)
1042-
/*[clinic end generated code: output=956ced67466149cf input=c50b893bc69520ec]*/
1043+
mmap_mmap_flush_impl(mmap_object *self, Py_ssize_t offset, Py_ssize_t size,
1044+
int flags)
1045+
/*[clinic end generated code: output=4225f4174dc75a53 input=42ba5fb716b6c294]*/
10431046
{
10441047
CHECK_VALID(NULL);
10451048
if (size == -1) {
@@ -1060,8 +1063,10 @@ mmap_mmap_flush_impl(mmap_object *self, Py_ssize_t offset, Py_ssize_t size)
10601063
}
10611064
Py_RETURN_NONE;
10621065
#elif defined(UNIX)
1063-
/* XXX flags for msync? */
1064-
if (-1 == msync(self->data + offset, size, MS_SYNC)) {
1066+
if (flags == 0) {
1067+
flags = MS_SYNC;
1068+
}
1069+
if (-1 == msync(self->data + offset, size, flags)) {
10651070
PyErr_SetFromErrno(PyExc_OSError);
10661071
return NULL;
10671072
}
@@ -2331,6 +2336,16 @@ mmap_exec(PyObject *module)
23312336
ADD_INT_MACRO(module, ACCESS_WRITE);
23322337
ADD_INT_MACRO(module, ACCESS_COPY);
23332338

2339+
#ifdef MS_INVALIDATE
2340+
ADD_INT_MACRO(module, MS_INVALIDATE);
2341+
#endif
2342+
#ifdef MS_ASYNC
2343+
ADD_INT_MACRO(module, MS_ASYNC);
2344+
#endif
2345+
#ifdef MS_SYNC
2346+
ADD_INT_MACRO(module, MS_SYNC);
2347+
#endif
2348+
23342349
#ifdef HAVE_MADVISE
23352350
// Conventional advice values
23362351
#ifdef MADV_NORMAL

0 commit comments

Comments
 (0)