1201 Py_RETURN_FALSE; |
1207 Py_RETURN_FALSE; |
1202 } |
1208 } |
1203 } |
1209 } |
1204 #endif |
1210 #endif |
1205 |
1211 |
|
1212 #ifdef MADV_POPULATE_READ |
|
1213 |
|
1214 typedef struct { |
|
1215 void * mmap_address; |
|
1216 size_t length; |
|
1217 } mmap_info; |
|
1218 |
|
1219 static void _mmap_populate(mmap_info *info) { |
|
1220 /* We explicitly does not check the return value as we don't care about it. |
|
1221 * the madvise is here to help performance and we don't care if it fails |
|
1222 * (for example because the mapping is no longer valid) */ |
|
1223 void * mmap_address = info->mmap_address; |
|
1224 size_t length = info->length; |
|
1225 free(info); |
|
1226 madvise(mmap_address, length, MADV_POPULATE_READ); |
|
1227 } |
|
1228 |
|
1229 static PyObject *background_mmap_populate(PyObject *self, PyObject *mmap) { |
|
1230 Py_buffer b; |
|
1231 pthread_t thread_id; |
|
1232 mmap_info *info; |
|
1233 if (PyObject_GetBuffer(mmap, &b, PyBUF_CONTIG_RO | PyBUF_C_CONTIGUOUS) == -1) { |
|
1234 return NULL; |
|
1235 } |
|
1236 info = (mmap_info *)malloc(sizeof(mmap_info)); |
|
1237 info->mmap_address=b.buf; |
|
1238 info->length=b.len; |
|
1239 /* note: for very large map, we could spin multiple thread populating |
|
1240 * different area */ |
|
1241 pthread_create(&thread_id, NULL, (void *) &_mmap_populate, info); |
|
1242 /* We don't keep track of this thread as it is fine for it to die when we |
|
1243 * exit. */ |
|
1244 pthread_detach(thread_id); |
|
1245 /* We release the PyBuffer in the main thread to let the object be garbage |
|
1246 * collected as soon as possible. This might result in the memory map being |
|
1247 * closed while the background thread is working. That will result in a |
|
1248 * error in the background thread we can ignore. */ |
|
1249 PyBuffer_Release(&b); |
|
1250 Py_RETURN_NONE; |
|
1251 } |
|
1252 |
|
1253 #endif |
|
1254 |
1206 static char osutil_doc[] = "Native operating system services."; |
1255 static char osutil_doc[] = "Native operating system services."; |
1207 |
1256 |
1208 static PyMethodDef methods[] = { |
1257 static PyMethodDef methods[] = { |
1209 {"listdir", (PyCFunction)listdir, METH_VARARGS | METH_KEYWORDS, |
1258 {"listdir", (PyCFunction)listdir, METH_VARARGS | METH_KEYWORDS, |
1210 "list a directory\n"}, |
1259 "list a directory\n"}, |
1235 { |
1284 { |
1236 "isgui", (PyCFunction)isgui, METH_NOARGS, |
1285 "isgui", (PyCFunction)isgui, METH_NOARGS, |
1237 "Is a CoreGraphics session available?" |
1286 "Is a CoreGraphics session available?" |
1238 }, |
1287 }, |
1239 #endif |
1288 #endif |
|
1289 #ifdef MADV_POPULATE_READ |
|
1290 {"background_mmap_populate", (PyCFunction)background_mmap_populate, METH_O, |
|
1291 "populate a mmap in the background\n"}, |
|
1292 #endif |
1240 {NULL, NULL} |
1293 {NULL, NULL} |
1241 }; |
1294 }; |
1242 |
1295 |
1243 static const int version = 4; |
1296 static const int version = 4; |
1244 |
1297 |