Skip to content

Commit 94486f1

Browse files
gbaralditopolarity
andauthored
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 <[email protected]>
1 parent 66780fd commit 94486f1

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
@@ -974,18 +974,26 @@ static GlobalVariable *emit_shard_table(Module &M, Type *T_size, Type *T_psize,
974974
return tables_gv;
975975
}
976976

977+
static Function *emit_pgcstack_default_func(Module &M, Type *T_ptr) {
978+
auto FT = FunctionType::get(T_ptr, false);
979+
auto F = Function::Create(FT, GlobalValue::InternalLinkage, "pgcstack_default_func", &M);
980+
llvm::IRBuilder<> builder(BasicBlock::Create(M.getContext(), "top", F));
981+
builder.CreateRet(Constant::getNullValue(T_ptr));
982+
return F;
983+
}
984+
977985
// See src/processor.h for documentation about this table. Corresponds to jl_image_ptls_t.
978-
static GlobalVariable *emit_ptls_table(Module &M, Type *T_size, Type *T_psize) {
986+
static GlobalVariable *emit_ptls_table(Module &M, Type *T_size, Type *T_ptr) {
979987
std::array<Constant *, 3> ptls_table{
980-
new GlobalVariable(M, T_size, false, GlobalValue::ExternalLinkage, Constant::getNullValue(T_size), "jl_pgcstack_func_slot"),
988+
new GlobalVariable(M, T_ptr, false, GlobalValue::ExternalLinkage, emit_pgcstack_default_func(M, T_ptr), "jl_pgcstack_func_slot"),
981989
new GlobalVariable(M, T_size, false, GlobalValue::ExternalLinkage, Constant::getNullValue(T_size), "jl_pgcstack_key_slot"),
982990
new GlobalVariable(M, T_size, false, GlobalValue::ExternalLinkage, Constant::getNullValue(T_size), "jl_tls_offset"),
983991
};
984992
for (auto &gv : ptls_table) {
985993
cast<GlobalVariable>(gv)->setVisibility(GlobalValue::HiddenVisibility);
986994
cast<GlobalVariable>(gv)->setDSOLocal(true);
987995
}
988-
auto ptls_table_arr = ConstantArray::get(ArrayType::get(T_psize, ptls_table.size()), ptls_table);
996+
auto ptls_table_arr = ConstantArray::get(ArrayType::get(T_ptr, ptls_table.size()), ptls_table);
989997
auto ptls_table_gv = new GlobalVariable(M, ptls_table_arr->getType(), false,
990998
GlobalValue::ExternalLinkage, ptls_table_arr, "jl_ptls_table");
991999
ptls_table_gv->setVisibility(GlobalValue::HiddenVisibility);
@@ -2184,6 +2192,7 @@ void jl_dump_native_impl(void *native_code,
21842192

21852193
Type *T_size = DL.getIntPtrType(Context);
21862194
Type *T_psize = T_size->getPointerTo();
2195+
Type *T_ptr = PointerType::get(Context, 0);
21872196

21882197
auto FT = FunctionType::get(Type::getInt8Ty(Context)->getPointerTo()->getPointerTo(), {}, false);
21892198
auto F = Function::Create(FT, Function::ExternalLinkage, "get_jl_RTLD_DEFAULT_handle_addr", metadataM);
@@ -2226,7 +2235,7 @@ void jl_dump_native_impl(void *native_code,
22262235
GlobalVariable::InternalLinkage,
22272236
value, "jl_dispatch_target_ids");
22282237
auto shards = emit_shard_table(metadataM, T_size, T_psize, threads);
2229-
auto ptls = emit_ptls_table(metadataM, T_size, T_psize);
2238+
auto ptls = emit_ptls_table(metadataM, T_size, T_ptr);
22302239
auto header = emit_image_header(metadataM, threads, nfvars, ngvars);
22312240
auto AT = ArrayType::get(T_size, sizeof(jl_small_typeof) / sizeof(void*));
22322241
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
@@ -809,8 +809,8 @@ JL_DLLEXPORT void julia_init(JL_IMAGE_SEARCH rel)
809809
void *stack_lo, *stack_hi;
810810
jl_init_stack_limits(1, &stack_lo, &stack_hi);
811811

812-
jl_libjulia_internal_handle = jl_find_dynamic_library_by_addr(&jl_load_dynamic_library);
813-
jl_libjulia_handle = jl_find_dynamic_library_by_addr(&jl_any_type);
812+
jl_libjulia_internal_handle = jl_find_dynamic_library_by_addr(&jl_load_dynamic_library, /* throw_err */ 1);
813+
jl_libjulia_handle = jl_find_dynamic_library_by_addr(&jl_any_type, /* throw_err */ 1);
814814
#ifdef _OS_WINDOWS_
815815
jl_exe_handle = GetModuleHandleA(NULL);
816816
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
@@ -40,6 +40,7 @@
4040
XX(jl_atomic_store_bits) \
4141
XX(jl_atomic_storeonce_bits) \
4242
XX(jl_atomic_swap_bits) \
43+
XX(jl_autoinit_and_adopt_thread) \
4344
XX(jl_backtrace_from_here) \
4445
XX(jl_base_relative_to) \
4546
XX(jl_bitcast) \

src/julia_internal.h

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

15151515
JL_DLLEXPORT void *jl_get_library_(const char *f_lib, int throw_err);
1516-
void *jl_find_dynamic_library_by_addr(void *symbol);
1516+
void *jl_find_dynamic_library_by_addr(void *symbol, int throw_err);
15171517
#define jl_get_library(f_lib) jl_get_library_(f_lib, 1)
15181518
JL_DLLEXPORT void *jl_load_and_lookup(const char *f_lib, const char *f_name, _Atomic(void*) *hnd);
15191519
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
@@ -439,7 +439,6 @@ static void jl_init_task_lock(jl_task_t *ct)
439439
}
440440
}
441441

442-
443442
JL_DLLEXPORT jl_gcframe_t **jl_adopt_thread(void)
444443
{
445444
// `jl_init_threadtls` puts us in a GC unsafe region, so ensure GC isn't running.
@@ -465,6 +464,23 @@ JL_DLLEXPORT jl_gcframe_t **jl_adopt_thread(void)
465464
return &ct->gcstack;
466465
}
467466

467+
JL_DLLEXPORT jl_gcframe_t **jl_autoinit_and_adopt_thread(void)
468+
{
469+
if (!jl_is_initialized()) {
470+
void *retaddr = __builtin_extract_return_addr(__builtin_return_address(0));
471+
void *sysimg_handle = jl_find_dynamic_library_by_addr(retaddr, /* throw_err */ 0);
472+
473+
if (sysimg_handle == NULL) {
474+
fprintf(stderr, "error: runtime auto-initialization failed due to bad sysimage lookup\n"
475+
" (this should not happen, please file a bug report)\n");
476+
abort();
477+
}
478+
479+
assert(0 && "TODO: implement auto-init");
480+
}
481+
482+
return jl_adopt_thread();
483+
}
468484

469485
void jl_safepoint_suspend_all_threads(jl_task_t *ct)
470486
{

0 commit comments

Comments
 (0)