Skip to content

Commit 7da3d4b

Browse files
gbaralditopolarity
andcommitted
Add hook to initialize Julia on-the-fly during thread adoption (#56334)
This adds `jl_pgcstack_default_func` to allow an uninitialized runtime to make it into `jl_autoinit_and_adopt_thread` The init changes themselves are left to #57498 --------- Co-authored-by: Cody Tapscott <topolarity@tapscott.me>
1 parent eb09ae1 commit 7da3d4b

File tree

7 files changed

+52
-15
lines changed

7 files changed

+52
-15
lines changed

src/aotcompile.cpp

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -968,18 +968,26 @@ static GlobalVariable *emit_shard_table(Module &M, Type *T_size, Type *T_psize,
968968
return tables_gv;
969969
}
970970

971+
static Function *emit_pgcstack_default_func(Module &M, Type *T_ptr) {
972+
auto FT = FunctionType::get(T_ptr, false);
973+
auto F = Function::Create(FT, GlobalValue::InternalLinkage, "pgcstack_default_func", &M);
974+
llvm::IRBuilder<> builder(BasicBlock::Create(M.getContext(), "top", F));
975+
builder.CreateRet(Constant::getNullValue(T_ptr));
976+
return F;
977+
}
978+
971979
// See src/processor.h for documentation about this table. Corresponds to jl_image_ptls_t.
972-
static GlobalVariable *emit_ptls_table(Module &M, Type *T_size, Type *T_psize) {
980+
static GlobalVariable *emit_ptls_table(Module &M, Type *T_size, Type *T_ptr) {
973981
std::array<Constant *, 3> ptls_table{
974-
new GlobalVariable(M, T_size, false, GlobalValue::ExternalLinkage, Constant::getNullValue(T_size), "jl_pgcstack_func_slot"),
982+
new GlobalVariable(M, T_ptr, false, GlobalValue::ExternalLinkage, emit_pgcstack_default_func(M, T_ptr), "jl_pgcstack_func_slot"),
975983
new GlobalVariable(M, T_size, false, GlobalValue::ExternalLinkage, Constant::getNullValue(T_size), "jl_pgcstack_key_slot"),
976984
new GlobalVariable(M, T_size, false, GlobalValue::ExternalLinkage, Constant::getNullValue(T_size), "jl_tls_offset"),
977985
};
978986
for (auto &gv : ptls_table) {
979987
cast<GlobalVariable>(gv)->setVisibility(GlobalValue::HiddenVisibility);
980988
cast<GlobalVariable>(gv)->setDSOLocal(true);
981989
}
982-
auto ptls_table_arr = ConstantArray::get(ArrayType::get(T_psize, ptls_table.size()), ptls_table);
990+
auto ptls_table_arr = ConstantArray::get(ArrayType::get(T_ptr, ptls_table.size()), ptls_table);
983991
auto ptls_table_gv = new GlobalVariable(M, ptls_table_arr->getType(), false,
984992
GlobalValue::ExternalLinkage, ptls_table_arr, "jl_ptls_table");
985993
ptls_table_gv->setVisibility(GlobalValue::HiddenVisibility);
@@ -2178,6 +2186,7 @@ void jl_dump_native_impl(void *native_code,
21782186

21792187
Type *T_size = DL.getIntPtrType(Context);
21802188
Type *T_psize = T_size->getPointerTo();
2189+
Type *T_ptr = PointerType::get(Context, 0);
21812190

21822191
auto FT = FunctionType::get(Type::getInt8Ty(Context)->getPointerTo()->getPointerTo(), {}, false);
21832192
auto F = Function::Create(FT, Function::ExternalLinkage, "get_jl_RTLD_DEFAULT_handle_addr", metadataM);
@@ -2220,7 +2229,7 @@ void jl_dump_native_impl(void *native_code,
22202229
GlobalVariable::InternalLinkage,
22212230
value, "jl_dispatch_target_ids");
22222231
auto shards = emit_shard_table(metadataM, T_size, T_psize, threads);
2223-
auto ptls = emit_ptls_table(metadataM, T_size, T_psize);
2232+
auto ptls = emit_ptls_table(metadataM, T_size, T_ptr);
22242233
auto header = emit_image_header(metadataM, threads, nfvars, ngvars);
22252234
auto AT = ArrayType::get(T_size, sizeof(jl_small_typeof) / sizeof(void*));
22262235
auto jl_small_typeof_copy = new GlobalVariable(metadataM, AT, false,

src/dlload.c

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -240,21 +240,32 @@ JL_DLLEXPORT int jl_dlclose(void *handle) JL_NOTSAFEPOINT
240240
#endif
241241
}
242242

243-
void *jl_find_dynamic_library_by_addr(void *symbol) {
243+
void *jl_find_dynamic_library_by_addr(void *symbol, int throw_err) {
244244
void *handle;
245245
#ifdef _OS_WINDOWS_
246246
if (!GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
247247
(LPCWSTR)symbol,
248248
(HMODULE*)&handle)) {
249-
jl_error("could not load base module");
249+
if (throw_err)
250+
jl_error("could not load base module");
251+
return NULL;
250252
}
251253
#else
252254
Dl_info info;
253255
if (!dladdr(symbol, &info) || !info.dli_fname) {
254-
jl_error("could not load base module");
256+
if (throw_err)
257+
jl_error("could not load base module");
258+
return NULL;
255259
}
256260
handle = dlopen(info.dli_fname, RTLD_NOW | RTLD_NOLOAD | RTLD_LOCAL);
257-
dlclose(handle); // Undo ref count increment from `dlopen`
261+
#if !defined(__APPLE__)
262+
if (handle == RTLD_DEFAULT && (RTLD_DEFAULT != NULL || dlerror() == NULL)) {
263+
// We loaded the executable but got RTLD_DEFAULT back, ask for a real handle instead
264+
handle = dlopen("", RTLD_NOW | RTLD_NOLOAD | RTLD_LOCAL);
265+
}
266+
#endif
267+
if (handle != NULL)
268+
dlclose(handle); // Undo ref count increment from `dlopen`
258269
#endif
259270
return handle;
260271
}
@@ -277,7 +288,7 @@ JL_DLLEXPORT void *jl_load_dynamic_library(const char *modname, unsigned flags,
277288

278289
// modname == NULL is a sentinel value requesting the handle of libjulia-internal
279290
if (modname == NULL)
280-
return jl_find_dynamic_library_by_addr(&jl_load_dynamic_library);
291+
return jl_find_dynamic_library_by_addr(&jl_load_dynamic_library, throw_err);
281292

282293
abspath = jl_isabspath(modname);
283294
is_atpath = 0;

src/init.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -808,8 +808,8 @@ JL_DLLEXPORT void julia_init(JL_IMAGE_SEARCH rel)
808808
void *stack_lo, *stack_hi;
809809
jl_init_stack_limits(1, &stack_lo, &stack_hi);
810810

811-
jl_libjulia_internal_handle = jl_find_dynamic_library_by_addr(&jl_load_dynamic_library);
812-
jl_libjulia_handle = jl_find_dynamic_library_by_addr(&jl_any_type);
811+
jl_libjulia_internal_handle = jl_find_dynamic_library_by_addr(&jl_load_dynamic_library, /* throw_err */ 1);
812+
jl_libjulia_handle = jl_find_dynamic_library_by_addr(&jl_any_type, /* throw_err */ 1);
813813
#ifdef _OS_WINDOWS_
814814
jl_exe_handle = GetModuleHandleA(NULL);
815815
jl_RTLD_DEFAULT_handle = jl_libjulia_internal_handle;

src/jl_exported_funcs.inc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
XX(jl_atomic_store_bits) \
4040
XX(jl_atomic_storeonce_bits) \
4141
XX(jl_atomic_swap_bits) \
42+
XX(jl_autoinit_and_adopt_thread) \
4243
XX(jl_backtrace_from_here) \
4344
XX(jl_base_relative_to) \
4445
XX(jl_bitcast) \

src/julia_internal.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1605,7 +1605,7 @@ void win32_formatmessage(DWORD code, char *reason, int len) JL_NOTSAFEPOINT;
16051605
#endif
16061606

16071607
JL_DLLEXPORT void *jl_get_library_(const char *f_lib, int throw_err);
1608-
void *jl_find_dynamic_library_by_addr(void *symbol);
1608+
void *jl_find_dynamic_library_by_addr(void *symbol, int throw_err);
16091609
#define jl_get_library(f_lib) jl_get_library_(f_lib, 1)
16101610
JL_DLLEXPORT void *jl_load_and_lookup(const char *f_lib, const char *f_name, _Atomic(void*) *hnd);
16111611
JL_DLLEXPORT void *jl_lazy_load_and_lookup(jl_value_t *lib_val, const char *f_name);

src/llvm-ptls.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -170,11 +170,11 @@ void LowerPTLS::fix_pgcstack_use(CallInst *pgcstack, Function *pgcstack_getter,
170170
*CFGModified = true;
171171
// emit slow branch code
172172
CallInst *adopt = cast<CallInst>(pgcstack->clone());
173-
Function *adoptFunc = M->getFunction(XSTR(jl_adopt_thread));
173+
Function *adoptFunc = M->getFunction(XSTR(jl_autoinit_and_adopt_thread));
174174
if (adoptFunc == NULL) {
175175
adoptFunc = Function::Create(pgcstack_getter->getFunctionType(),
176176
pgcstack_getter->getLinkage(), pgcstack_getter->getAddressSpace(),
177-
XSTR(jl_adopt_thread), M);
177+
XSTR(jl_autoinit_and_adopt_thread), M);
178178
adoptFunc->copyAttributesFrom(pgcstack_getter);
179179
adoptFunc->copyMetadata(pgcstack_getter, 0);
180180
}

src/threading.c

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -423,7 +423,6 @@ static void jl_init_task_lock(jl_task_t *ct)
423423
}
424424
}
425425

426-
427426
JL_DLLEXPORT jl_gcframe_t **jl_adopt_thread(void)
428427
{
429428
// `jl_init_threadtls` puts us in a GC unsafe region, so ensure GC isn't running.
@@ -449,6 +448,23 @@ JL_DLLEXPORT jl_gcframe_t **jl_adopt_thread(void)
449448
return &ct->gcstack;
450449
}
451450

451+
JL_DLLEXPORT jl_gcframe_t **jl_autoinit_and_adopt_thread(void)
452+
{
453+
if (!jl_is_initialized()) {
454+
void *retaddr = __builtin_extract_return_addr(__builtin_return_address(0));
455+
void *sysimg_handle = jl_find_dynamic_library_by_addr(retaddr, /* throw_err */ 0);
456+
457+
if (sysimg_handle == NULL) {
458+
fprintf(stderr, "error: runtime auto-initialization failed due to bad sysimage lookup\n"
459+
" (this should not happen, please file a bug report)\n");
460+
abort();
461+
}
462+
463+
assert(0 && "TODO: implement auto-init");
464+
}
465+
466+
return jl_adopt_thread();
467+
}
452468

453469
void jl_safepoint_suspend_all_threads(jl_task_t *ct)
454470
{

0 commit comments

Comments
 (0)