image_id preload_image(char const* path) { if (path == NULL) return B_BAD_VALUE; KTRACE("rld: preload_image(\"%s\")", path); image_t *image = NULL; status_t status = load_image(path, B_LIBRARY_IMAGE, NULL, NULL, &image); if (status < B_OK) { KTRACE("rld: preload_image(\"%s\") failed to load container: %s", path, strerror(status)); return status; } if (image->find_undefined_symbol == NULL) image->find_undefined_symbol = find_undefined_symbol_global; status = load_dependencies(image); if (status < B_OK) goto err; set_image_flags_recursively(image, RTLD_GLOBAL); status = relocate_dependencies(image); if (status < B_OK) goto err; status = add_preloaded_image(image); if (status < B_OK) goto err; inject_runtime_loader_api(image); remap_images(); init_dependencies(image, true); // if the image contains an add-on, register it runtime_loader_add_on* addOnStruct; if (find_symbol(image, SymbolLookupInfo("__gRuntimeLoaderAddOn", B_SYMBOL_TYPE_DATA), (void**)&addOnStruct) == B_OK) { add_add_on(image, addOnStruct); } KTRACE("rld: preload_image(\"%s\") done: id: %" B_PRId32, path, image->id); return image->id; err: KTRACE("rld: preload_image(\"%s\") failed: %s", path, strerror(status)); dequeue_loaded_image(image); delete_image(image); return status; }
int main(int argc, const char* argv[]) { ProgramOptions opts; if( opts.parse(argc, argv) ) { return 1; } { Debug_DisablePhase("Load Repository"); Debug_DisablePhase("Load Root"); Debug_DisablePhase("Load Dependencies"); Debug_DisablePhase("Enumerate Build"); Debug_DisablePhase("Run Build"); if( const char* e = getenv("MINICARGO_DEBUG") ) { while( *e ) { const char* colon = ::std::strchr(e, ':'); size_t len = colon ? colon - e : ::std::strlen(e); Debug_EnablePhase(::std::string(e, len).c_str()); if( colon ) e = colon + 1; else e = e + len; } } } try { Debug_SetPhase("Load Repository"); // Load package database Repository repo; // TODO: load repository from a local cache if( opts.vendor_dir ) { repo.load_vendored(opts.vendor_dir); } auto bs_override_dir = opts.override_directory ? ::helpers::path(opts.override_directory) : ::helpers::path(); // 1. Load the Cargo.toml file from the passed directory Debug_SetPhase("Load Root"); auto dir = ::helpers::path(opts.directory ? opts.directory : "."); auto m = PackageManifest::load_from_toml( dir / "Cargo.toml" ); // 2. Load all dependencies Debug_SetPhase("Load Dependencies"); m.load_dependencies(repo, !bs_override_dir.is_valid()); // 3. Build dependency tree and build program. BuildOptions build_opts; build_opts.build_script_overrides = ::std::move(bs_override_dir); build_opts.output_dir = opts.output_directory ? ::helpers::path(opts.output_directory) : ::helpers::path("output"); build_opts.lib_search_dirs.reserve(opts.lib_search_dirs.size()); build_opts.emit_mmir = opts.emit_mmir; build_opts.target_name = opts.target; for(const auto* d : opts.lib_search_dirs) build_opts.lib_search_dirs.push_back( ::helpers::path(d) ); Debug_SetPhase("Enumerate Build"); auto build_list = BuildList(m, build_opts); Debug_SetPhase("Run Build"); if( !build_list.build(::std::move(build_opts), opts.build_jobs) ) { ::std::cerr << "BUILD FAILED" << ::std::endl; if(opts.pause_before_quit) { ::std::cout << "Press enter to exit..." << ::std::endl; ::std::cin.get(); } return 1; } } catch(const ::std::exception& e) { ::std::cerr << "EXCEPTION: " << e.what() << ::std::endl; if(opts.pause_before_quit) { ::std::cout << "Press enter to exit..." << ::std::endl; ::std::cin.get(); } return 1; } if(opts.pause_before_quit) { ::std::cout << "Press enter to exit..." << ::std::endl; ::std::cin.get(); } return 0; }
static void hclib_entrypoint(const char **module_dependencies, const int n_module_dependencies, const int instrument) { /* * Assert that the completion flag structures are each on separate cache * lines. */ HASSERT(sizeof(worker_done_t) == 64); load_dependencies(module_dependencies, n_module_dependencies); hclib_call_module_pre_init_functions(); srand(0); hc_context = (hclib_context *)malloc(sizeof(hclib_context)); HASSERT(hc_context); /* * Parse the platform description from the HPT configuration file and load * it into the hclib_context. */ hclib_global_init(); // Initialize any registered modules hclib_call_module_post_init_functions(); // init timer stats hclib_init_stats(0, hc_context->nworkers); if (instrument) { initialize_instrumentation(hc_context->nworkers); } /* Create key to store per thread worker_state */ if (pthread_key_create(&ws_key, NULL) != 0) { log_die("Cannot create ws_key for worker-specific data"); } /* * set pthread's concurrency. Doesn't seem to do much on Linux, only * relevant when there are more pthreads than hardware cores to schedule * them on. */ pthread_setconcurrency(hc_context->nworkers); #ifdef HCLIB_STATS worker_stats = (per_worker_stats *)calloc(hc_context->nworkers, sizeof(*worker_stats)); HASSERT(worker_stats); for (int i = 0; i < hc_context->nworkers; i++) { worker_stats[i].stolen_tasks_per_thread = (size_t *)calloc( hc_context->nworkers, sizeof(size_t)); HASSERT(worker_stats[i].stolen_tasks_per_thread); } #endif // Launch the worker threads pthread_attr_t attr; if (pthread_attr_init(&attr) != 0) { fprintf(stderr, "Error in pthread_attr_init\n"); exit(3); } create_hwloc_cpusets(); // Start workers for (int i = 1; i < hc_context->nworkers; i++) { if (pthread_create(&hc_context->workers[i]->t, &attr, worker_routine, &hc_context->workers[i]->id) != 0) { fprintf(stderr, "Error launching thread\n"); exit(4); } } set_current_worker(0); set_up_worker_thread_affinities(0); const unsigned dist_id = hclib_register_dist_func(default_dist_func); HASSERT(dist_id == HCLIB_DEFAULT_LOOP_DIST); // allocate root finish hclib_start_finish(); }
image_id load_library(char const *path, uint32 flags, bool addOn, void** _handle) { image_t *image = NULL; image_type type = (addOn ? B_ADD_ON_IMAGE : B_LIBRARY_IMAGE); status_t status; if (path == NULL && addOn) return B_BAD_VALUE; KTRACE("rld: load_library(\"%s\", %#" B_PRIx32 ", %d)", path, flags, addOn); rld_lock(); // for now, just do stupid simple global locking // have we already loaded this library? // Checking it at this stage saves loading its dependencies again if (!addOn) { // a NULL path is fine -- it means the global scope shall be opened if (path == NULL) { *_handle = RLD_GLOBAL_SCOPE; rld_unlock(); return 0; } image = find_loaded_image_by_name(path, APP_OR_LIBRARY_TYPE); if (image != NULL && (flags & RTLD_GLOBAL) != 0) set_image_flags_recursively(image, RTLD_GLOBAL); if (image) { atomic_add(&image->ref_count, 1); rld_unlock(); KTRACE("rld: load_library(\"%s\"): already loaded: %" B_PRId32, path, image->id); *_handle = image; return image->id; } } status = load_image(path, type, NULL, NULL, &image); if (status < B_OK) { rld_unlock(); KTRACE("rld: load_library(\"%s\") failed to load container: %s", path, strerror(status)); return status; } if (image->find_undefined_symbol == NULL) { if (addOn) image->find_undefined_symbol = find_undefined_symbol_add_on; else image->find_undefined_symbol = find_undefined_symbol_global; } status = load_dependencies(image); if (status < B_OK) goto err; // If specified, set the RTLD_GLOBAL flag recursively on this image and all // dependencies. If not specified, we temporarily set // RFLAG_USE_FOR_RESOLVING so that the dependencies will correctly be used // for undefined symbol resolution. if ((flags & RTLD_GLOBAL) != 0) set_image_flags_recursively(image, RTLD_GLOBAL); else set_image_flags_recursively(image, RFLAG_USE_FOR_RESOLVING); status = relocate_dependencies(image); if (status < B_OK) goto err; if ((flags & RTLD_GLOBAL) == 0) clear_image_flags_recursively(image, RFLAG_USE_FOR_RESOLVING); remap_images(); init_dependencies(image, true); rld_unlock(); KTRACE("rld: load_library(\"%s\") done: id: %" B_PRId32, path, image->id); *_handle = image; return image->id; err: KTRACE("rld: load_library(\"%s\") failed: %s", path, strerror(status)); dequeue_loaded_image(image); delete_image(image); rld_unlock(); return status; }
image_id load_program(char const *path, void **_entry) { status_t status; image_t *image; KTRACE("rld: load_program(\"%s\")", path); rld_lock(); // for now, just do stupid simple global locking preload_images(); TRACE(("rld: load %s\n", path)); status = load_image(path, B_APP_IMAGE, NULL, NULL, &gProgramImage); if (status < B_OK) goto err; if (gProgramImage->find_undefined_symbol == NULL) gProgramImage->find_undefined_symbol = find_undefined_symbol_global; status = load_dependencies(gProgramImage); if (status < B_OK) goto err; // Set RTLD_GLOBAL on all libraries including the program. // This results in the desired symbol resolution for dlopen()ed libraries. set_image_flags_recursively(gProgramImage, RTLD_GLOBAL); status = relocate_dependencies(gProgramImage); if (status < B_OK) goto err; inject_runtime_loader_api(gProgramImage); remap_images(); init_dependencies(gProgramImage, true); // Since the images are initialized now, we no longer should use our // getenv(), but use the one from libroot.so find_symbol_breadth_first(gProgramImage, SymbolLookupInfo("getenv", B_SYMBOL_TYPE_TEXT), &image, (void**)&gGetEnv); if (gProgramImage->entry_point == 0) { status = B_NOT_AN_EXECUTABLE; goto err; } *_entry = (void *)(gProgramImage->entry_point); rld_unlock(); gProgramLoaded = true; KTRACE("rld: load_program(\"%s\") done: entry: %p, id: %" B_PRId32 , path, *_entry, gProgramImage->id); return gProgramImage->id; err: KTRACE("rld: load_program(\"%s\") failed: %s", path, strerror(status)); delete_image(gProgramImage); if (report_errors()) { // send error message gErrorMessage.AddInt32("error", status); gErrorMessage.SetDeliveryInfo(gProgramArgs->error_token, -1, 0, find_thread(NULL)); _kern_write_port_etc(gProgramArgs->error_port, 'KMSG', gErrorMessage.Buffer(), gErrorMessage.ContentSize(), 0, 0); } _kern_loading_app_failed(status); rld_unlock(); return status; }