| 584 | inline int fd() const noexcept { return _fd; } |
| 585 | |
| 586 | Error open(bool prefer_tmp_over_dev_shm) noexcept { |
| 587 | #if defined(__linux__) && defined(__NR_memfd_create) |
| 588 | // Linux specific 'memfd_create' - if the syscall returns `ENOSYS` it means |
| 589 | // it's not available and we will never call it again (would be pointless). |
| 590 | // |
| 591 | // NOTE: There is also memfd_create() libc function in FreeBSD, but it internally |
| 592 | // uses `shm_open(SHM_ANON, ...)` so it's not needed to add support for it (it's |
| 593 | // not a syscall as in Linux). |
| 594 | |
| 595 | // Zero initialized, if ever changed to '1' that would mean the syscall is not |
| 596 | // available and we must use `shm_open()` and `shm_unlink()` (or regular `open()`). |
| 597 | static volatile uint32_t memfd_create_not_supported; |
| 598 | |
| 599 | if (!memfd_create_not_supported) { |
| 600 | _fd = (int)syscall(__NR_memfd_create, "vmem", MFD_CLOEXEC | get_mfd_exec_flag()); |
| 601 | if (ASMJIT_LIKELY(_fd >= 0)) { |
| 602 | return Error::kOk; |
| 603 | } |
| 604 | |
| 605 | int e = errno; |
| 606 | if (e == ENOSYS) { |
| 607 | memfd_create_not_supported = 1; |
| 608 | } |
| 609 | else { |
| 610 | return make_error(asmjit_error_from_errno(e)); |
| 611 | } |
| 612 | } |
| 613 | #endif // __linux__ && __NR_memfd_create |
| 614 | |
| 615 | #if defined(ASMJIT_HAS_SHM_OPEN) && defined(SHM_ANON) |
| 616 | // Originally FreeBSD extension, apparently works in other BSDs too. |
| 617 | Support::maybe_unused(prefer_tmp_over_dev_shm); |
| 618 | _fd = ::shm_open(SHM_ANON, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR); |
| 619 | |
| 620 | if (ASMJIT_LIKELY(_fd >= 0)) { |
| 621 | return Error::kOk; |
| 622 | } |
| 623 | else { |
| 624 | return make_error(asmjit_error_from_errno(errno)); |
| 625 | } |
| 626 | #else |
| 627 | // POSIX API. We have to generate somehow a unique name, so use `generate_random_bits()` helper. To prevent |
| 628 | // having file collisions we use `shm_open()` with flags that require creation of the file so we never open |
| 629 | // an existing shared memory. |
| 630 | static const char shm_format_string[] = "/shm-id-%016llX"; |
| 631 | uint32_t retry_count = 100; |
| 632 | |
| 633 | for (uint32_t i = 0; i < retry_count; i++) { |
| 634 | bool use_tmp = !ASMJIT_VM_SHM_DETECT || prefer_tmp_over_dev_shm; |
| 635 | uint64_t bits = generate_random_bits((uintptr_t)this, i); |
| 636 | |
| 637 | if (use_tmp) { |
| 638 | _tmp_name.assign(get_tmp_dir()); |
| 639 | _tmp_name.append_format(shm_format_string, (unsigned long long)bits); |
| 640 | _fd = ASMJIT_FILE64_API(::open)(_tmp_name.data(), O_RDWR | O_CREAT | O_EXCL, 0); |
| 641 | if (ASMJIT_LIKELY(_fd >= 0)) { |
| 642 | _file_type = kFileTypeTmp; |
| 643 | return Error::kOk; |
nothing calls this directly
no test coverage detected