Repository: JuliaLang/julia
File: src/threading.c (C)

Code before:
    // we can't use a normal safepoint because we don't have signal handlers yet.
    jl_atomic_fetch_add(&jl_gc_disable_counter, 1);
    // pass NULL as a special token to indicate we are running on an unmanaged task
    jl_safepoint_wait_gc(NULL);
    // this check is coupled with the one in `jl_safepoint_wait_gc`, where we observe if a
    // foreign thread has asked to disable the GC, guaranteeing the order of events.

    // initialize this thread (assign tid, create heap, set up root task)
    jl_ptls_t ptls = jl_init_threadtls(-1);
    void *stack_lo, *stack_hi;
    jl_init_stack_limits(0, &stack_lo, &stack_hi);

    // warning: this changes `jl_current_task`, so be careful not to call that from this function
    jl_task_t *ct = jl_init_root_task(ptls, stack_lo, stack_hi); // assumes the GC is disabled
    JL_GC_PROMISE_ROOTED(ct);
    uv_random(NULL, NULL, &ct->rngState, sizeof(ct->rngState), 0, NULL);
    jl_atomic_fetch_add(&jl_gc_disable_counter, -1);
    jl_init_task_lock(ct);
    return &ct->gcstack;
}

JL_DLLEXPORT jl_gcframe_t **jl_autoinit_and_adopt_thread(void)
{
    if (!jl_is_initialized()) {
        void *retaddr = __builtin_extract_return_addr(__builtin_return_address(0));
        void *handle = jl_find_dynamic_library_by_addr(retaddr, 0, 1);
        if (handle == NULL) {
            fprintf(stderr, "error: runtime auto-initialization failed due to bad sysimage lookup\n"
                            "       (this should not happen, please file a bug report)\n");
            exit(1);
        }
        jl_init_with_image_handle(handle);
        return &jl_get_current_task()->gcstack;
    }

    return jl_adopt_thread();
}

void jl_safepoint_suspend_all_threads(jl_task_t *ct)
{
    // TODO: prevent jl_n_threads changing or jl_safepoint_resume_thread calls on another thread
    //uv_mutex_lock(&tls_lock);
    //disallow_resume = ct->tid;
    //uv_mutex_unlock(&tls_lock);
    for (int16_t tid = 0; tid < jl_atomic_load_relaxed(&jl_n_threads); tid++) {
        if (tid != jl_atomic_load_relaxed(&ct->tid))
            jl_safepoint_suspend_thread(tid, 1);
    };
}

void jl_safepoint_resume_all_threads(jl_task_t *ct)

Review comment (suggestion):
```suggestion
        void *handle = jl_find_dynamic_library_by_addr(retaddr, 0, 0);
```

Code after:
    // we can't use a normal safepoint because we don't have signal handlers yet.
    jl_atomic_fetch_add(&jl_gc_disable_counter, 1);
    // pass NULL as a special token to indicate we are running on an unmanaged task
    jl_safepoint_wait_gc(NULL);
    // this check is coupled with the one in `jl_safepoint_wait_gc`, where we observe if a
    // foreign thread has asked to disable the GC, guaranteeing the order of events.

    // initialize this thread (assign tid, create heap, set up root task)
    jl_ptls_t ptls = jl_init_threadtls(-1);
    void *stack_lo, *stack_hi;
    jl_init_stack_limits(0, &stack_lo, &stack_hi);

    // warning: this changes `jl_current_task`, so be careful not to call that from this function
    jl_task_t *ct = jl_init_root_task(ptls, stack_lo, stack_hi); // assumes the GC is disabled
    JL_GC_PROMISE_ROOTED(ct);
    uv_random(NULL, NULL, &ct->rngState, sizeof(ct->rngState), 0, NULL);
    jl_atomic_fetch_add(&jl_gc_disable_counter, -1);
    jl_init_task_lock(ct);
    return &ct->gcstack;
}

JL_DLLEXPORT jl_gcframe_t **jl_autoinit_and_adopt_thread(void)
{
    if (!jl_is_initialized()) {
        void *retaddr = __builtin_extract_return_addr(__builtin_return_address(0));
        void *handle = jl_find_dynamic_library_by_addr(retaddr, 0, 0);
        if (handle == NULL) {
            fprintf(stderr, "error: runtime auto-initialization failed due to bad sysimage lookup\n"
                            "       (this should not happen, please file a bug report)\n");
            exit(1);
        }
        jl_init_with_image_handle(handle);
        return &jl_get_current_task()->gcstack;
    }

    return jl_adopt_thread();
}

void jl_safepoint_suspend_all_threads(jl_task_t *ct)
{
    // TODO: prevent jl_n_threads changing or jl_safepoint_resume_thread calls on another thread
    //uv_mutex_lock(&tls_lock);
    //disallow_resume = ct->tid;
    //uv_mutex_unlock(&tls_lock);
    for (int16_t tid = 0; tid < jl_atomic_load_relaxed(&jl_n_threads); tid++) {
        if (tid != jl_atomic_load_relaxed(&ct->tid))
            jl_safepoint_suspend_thread(tid, 1);
    };
}

void jl_safepoint_resume_all_threads(jl_task_t *ct)