Allocate MI_SEGMENT_SIZE aligned huge pages
| 1275 | |
| 1276 | // Allocate MI_SEGMENT_SIZE aligned huge pages |
| 1277 | void* _mi_os_alloc_huge_os_pages(size_t pages, int numa_node, mi_msecs_t max_msecs, size_t* pages_reserved, size_t* psize) { |
| 1278 | if (psize != NULL) *psize = 0; |
| 1279 | if (pages_reserved != NULL) *pages_reserved = 0; |
| 1280 | size_t size = 0; |
| 1281 | uint8_t* start = mi_os_claim_huge_pages(pages, &size); |
| 1282 | if (start == NULL) return NULL; // or 32-bit systems |
| 1283 | |
| 1284 | // Allocate one page at the time but try to place them contiguously |
| 1285 | // We allocate one page at the time to be able to abort if it takes too long |
| 1286 | // or to at least allocate as many as available on the system. |
| 1287 | mi_msecs_t start_t = _mi_clock_start(); |
| 1288 | size_t page; |
| 1289 | for (page = 0; page < pages; page++) { |
| 1290 | // allocate a page |
| 1291 | void* addr = start + (page * MI_HUGE_OS_PAGE_SIZE); |
| 1292 | void* p = mi_os_alloc_huge_os_pagesx(addr, MI_HUGE_OS_PAGE_SIZE, numa_node); |
| 1293 | |
| 1294 | // Did we succeed at a contiguous address? |
| 1295 | if (p != addr) { |
| 1296 | // no success, issue a warning and break |
| 1297 | if (p != NULL) { |
| 1298 | _mi_warning_message("could not allocate contiguous huge page %zu at %p\n", page, addr); |
| 1299 | _mi_os_free(p, MI_HUGE_OS_PAGE_SIZE, &_mi_stats_main); |
| 1300 | } |
| 1301 | break; |
| 1302 | } |
| 1303 | |
| 1304 | // success, record it |
| 1305 | _mi_stat_increase(&_mi_stats_main.committed, MI_HUGE_OS_PAGE_SIZE); |
| 1306 | _mi_stat_increase(&_mi_stats_main.reserved, MI_HUGE_OS_PAGE_SIZE); |
| 1307 | |
| 1308 | // check for timeout |
| 1309 | if (max_msecs > 0) { |
| 1310 | mi_msecs_t elapsed = _mi_clock_end(start_t); |
| 1311 | if (page >= 1) { |
| 1312 | mi_msecs_t estimate = ((elapsed / (page+1)) * pages); |
| 1313 | if (estimate > 2*max_msecs) { // seems like we are going to timeout, break |
| 1314 | elapsed = max_msecs + 1; |
| 1315 | } |
| 1316 | } |
| 1317 | if (elapsed > max_msecs) { |
| 1318 | _mi_warning_message("huge page allocation timed out\n"); |
| 1319 | break; |
| 1320 | } |
| 1321 | } |
| 1322 | } |
| 1323 | mi_assert_internal(page*MI_HUGE_OS_PAGE_SIZE <= size); |
| 1324 | if (pages_reserved != NULL) { *pages_reserved = page; } |
| 1325 | if (psize != NULL) { *psize = page * MI_HUGE_OS_PAGE_SIZE; } |
| 1326 | return (page == 0 ? NULL : start); |
| 1327 | } |
| 1328 | |
| 1329 | // free every huge page in a range individually (as we allocated per page) |
| 1330 | // note: needed with VirtualAlloc but could potentially be done in one go on mmap'd systems. |
no test coverage detected