| 
56 | 56 | #include <llvm/Support/FormatAdapters.h>  | 
57 | 57 | #include <llvm/Linker/Linker.h>  | 
58 | 58 | 
 
  | 
 | 59 | +// Include necessary headers for semaphores  | 
 | 60 | +#if defined(_OS_LINUX_)  | 
 | 61 | +#include <semaphore.h>  | 
 | 62 | +#include <fcntl.h>  | 
 | 63 | +#endif  | 
59 | 64 | 
 
  | 
60 | 65 | using namespace llvm;  | 
61 | 66 | 
 
  | 
@@ -1645,6 +1650,47 @@ void jl_dump_native_impl(void *native_code,  | 
1645 | 1650 |         has_veccall = !!dataM.getModuleFlag("julia.mv.veccall");  | 
1646 | 1651 |     });  | 
1647 | 1652 | 
 
  | 
 | 1653 | +#if defined(_OS_LINUX_)  | 
 | 1654 | +    // This flag tracks if the lock was actually acquired to avoid freeing the semaphore  | 
 | 1655 | +    // if it was never opened.  | 
 | 1656 | +    bool lock_acquired = false;  | 
 | 1657 | + | 
 | 1658 | +    auto cleanup = [&](sem_t* s) {  | 
 | 1659 | +        if (s != SEM_FAILED) {  | 
 | 1660 | +            if (lock_acquired) {  | 
 | 1661 | +                // Only post if the lock was successfully acquired.  | 
 | 1662 | +                sem_post(s);  | 
 | 1663 | +            }  | 
 | 1664 | +            sem_close(s);  | 
 | 1665 | +        }  | 
 | 1666 | +    };  | 
 | 1667 | + | 
 | 1668 | +    sem_t *par_precomp_sem = SEM_FAILED;  | 
 | 1669 | +    const char *sem_name = getenv("JL_AOT_PRECOMPILE_SEMAPHORE");  | 
 | 1670 | +    if (sem_name != NULL) {  | 
 | 1671 | +        // The count for the semaphore will be initialized by the parent process that spawns compilation sub-processes.  | 
 | 1672 | +        // This is to ensure that only already created semaphores are used and that we don't end up in a situation  | 
 | 1673 | +        // where every spawned compilation subprocess creates its own semaphore. Cleanup is handled by the parent process.  | 
 | 1674 | +        par_precomp_sem = sem_open(sem_name, 0);  | 
 | 1675 | +        std::unique_ptr<sem_t, decltype(cleanup)> sem_guard(par_precomp_sem, cleanup);  | 
 | 1676 | +        if (par_precomp_sem == SEM_FAILED) {  | 
 | 1677 | +            jl_errorf("Failed to open parallel precompilation semaphore '%s': %s", sem_name, strerror(errno));  | 
 | 1678 | +        } else {  | 
 | 1679 | +            // Wait for the semaphore, retrying if interrupted by a signal (EINTR).  | 
 | 1680 | +            int ret;  | 
 | 1681 | +            do {  | 
 | 1682 | +                ret = sem_wait(par_precomp_sem);  | 
 | 1683 | +            } while (ret == -1 && errno == EINTR);  | 
 | 1684 | + | 
 | 1685 | +            if (ret == 0) {  | 
 | 1686 | +                lock_acquired = true;  | 
 | 1687 | +            } else {  | 
 | 1688 | +                jl_errorf("Failed to wait on semaphore '%s': %s", sem_name, strerror(errno));  | 
 | 1689 | +            }  | 
 | 1690 | +        }  | 
 | 1691 | +    }  | 
 | 1692 | +#endif  | 
 | 1693 | + | 
1648 | 1694 |     {  | 
1649 | 1695 |         // Don't use withModuleDo here since we delete the TSM midway through  | 
1650 | 1696 |         auto TSCtx = data->M.getContext();  | 
 | 
0 commit comments