diff -r d748fd2647f8 -r b619ba39d10a mercurial/cext/osutil.c --- a/mercurial/cext/osutil.c Thu Jul 25 14:40:38 2024 -0400 +++ b/mercurial/cext/osutil.c Tue Jul 09 20:08:48 2024 +0200 @@ -36,6 +36,12 @@ #endif #endif +#ifndef _WIN32 +#include +#include +#endif + + #ifdef __APPLE__ #include #include @@ -1203,6 +1209,49 @@ } #endif +#ifdef MADV_POPULATE_READ + +typedef struct { + void * mmap_address; + size_t length; +} mmap_info; + +static void _mmap_populate(mmap_info *info) { + /* We explicitly does not check the return value as we don't care about it. + * the madvise is here to help performance and we don't care if it fails + * (for example because the mapping is no longer valid) */ + void * mmap_address = info->mmap_address; + size_t length = info->length; + free(info); + madvise(mmap_address, length, MADV_POPULATE_READ); +} + +static PyObject *background_mmap_populate(PyObject *self, PyObject *mmap) { + Py_buffer b; + pthread_t thread_id; + mmap_info *info; + if (PyObject_GetBuffer(mmap, &b, PyBUF_CONTIG_RO | PyBUF_C_CONTIGUOUS) == -1) { + return NULL; + } + info = (mmap_info *)malloc(sizeof(mmap_info)); + info->mmap_address=b.buf; + info->length=b.len; + /* note: for very large map, we could spin multiple thread populating + * different area */ + pthread_create(&thread_id, NULL, (void *) &_mmap_populate, info); + /* We don't keep track of this thread as it is fine for it to die when we + * exit. */ + pthread_detach(thread_id); + /* We release the PyBuffer in the main thread to let the object be garbage + * collected as soon as possible. This might result in the memory map being + * closed while the background thread is working. That will result in a + * error in the background thread we can ignore. */ + PyBuffer_Release(&b); + Py_RETURN_NONE; +} + +#endif + static char osutil_doc[] = "Native operating system services."; static PyMethodDef methods[] = { @@ -1237,6 +1286,10 @@ "Is a CoreGraphics session available?" }, #endif +#ifdef MADV_POPULATE_READ + {"background_mmap_populate", (PyCFunction)background_mmap_populate, METH_O, + "populate a mmap in the background\n"}, +#endif {NULL, NULL} };