| 1351 | } |
| 1352 | |
| 1353 | u32 block_t::alloc(const u32 orig_size, const std::shared_ptr<utils::shm>* src, u32 align, u64 flags) |
| 1354 | { |
| 1355 | if (!src) |
| 1356 | { |
| 1357 | // Use the block's flags (excpet for protection) |
| 1358 | flags = (this->flags & ~alloc_prot_mask) | (flags & alloc_prot_mask); |
| 1359 | } |
| 1360 | |
| 1361 | // Determine minimal alignment |
| 1362 | const u32 min_page_size = flags & page_size_4k ? 0x1000 : 0x10000; |
| 1363 | |
| 1364 | // Align to minimal page size |
| 1365 | const u32 size = rx::alignUp(orig_size, min_page_size) + (flags & stack_guarded ? 0x2000 : 0); |
| 1366 | |
| 1367 | // Check alignment (it's page allocation, so passing small values there is just silly) |
| 1368 | if (align < min_page_size || align != (0x80000000u >> std::countl_zero(align))) |
| 1369 | { |
| 1370 | fmt::throw_exception("Invalid alignment (size=0x%x, align=0x%x)", size, align); |
| 1371 | } |
| 1372 | |
| 1373 | // Return if size is invalid |
| 1374 | if (!orig_size || !size || orig_size > size || size > this->size) |
| 1375 | { |
| 1376 | return 0; |
| 1377 | } |
| 1378 | |
| 1379 | // Create or import shared memory object |
| 1380 | std::shared_ptr<utils::shm> shm; |
| 1381 | |
| 1382 | if (m_common) |
| 1383 | ensure(!src); |
| 1384 | else if (src) |
| 1385 | shm = *src; |
| 1386 | else |
| 1387 | { |
| 1388 | shm = std::make_shared<utils::shm>(size); |
| 1389 | } |
| 1390 | |
| 1391 | const u32 max = (this->addr + this->size - size) & (0 - align); |
| 1392 | |
| 1393 | u32 addr = rx::alignUp(this->addr, align); |
| 1394 | |
| 1395 | if (this->addr > max || addr > max) |
| 1396 | { |
| 1397 | return 0; |
| 1398 | } |
| 1399 | |
| 1400 | vm::writer_lock lock; |
| 1401 | |
| 1402 | if (!is_valid()) |
| 1403 | { |
| 1404 | // Expired block |
| 1405 | return 0; |
| 1406 | } |
| 1407 | |
| 1408 | // Search for an appropriate place (unoptimized) |
| 1409 | for (;; addr += align) |
| 1410 | { |
no test coverage detected