46 enum class UnloadAdmission { Ready, Busy, KeepMapped };
47 using UnloadAdmissionHook = UnloadAdmission (*)(
bool terminal);
54 unloadAdmission(
nullptr),
62 runtimeUnloadable(
true),
63 unloadComplete(
false),
76 UnloadAdmissionHook unloadAdmission;
78 const char** depends_opt;
84 bool runtimeUnloadable;
86 size_t progressCredits;
88 enum ModuleStatus { Unknown, Preloaded, Executing, Active, Failed, Unloading, Unloaded } status;
90 bool isPending()
const {
91 return status == Preloaded;
94 bool isLoaded()
const {
95 return status == Preloaded || status == Active;
98 bool isUnloaded()
const {
99 return status == Unloaded || (status == Failed && unloadComplete);
102 bool isFailed()
const {
103 return status == Failed;
106 bool isActive()
const {
107 return status == Active;
110 bool isExecuting()
const {
111 return status == Executing;
114 bool isUnloading()
const {
115 return status == Unloading;
118 bool wasAttempted()
const {
119 return status == Executing || isActive() || isFailed() || isUnloading() || isUnloaded();
131 typedef bool (*TerminalQuiesceHook)();
154 void executeModules(
bool silent =
false,
bool progress =
true);
157 bool unloadModule(
const char* name,
bool silent =
false,
bool progress =
true);
158 bool unloadModule(
Module* module,
bool silent =
false,
bool progress =
true);
160 enum class RuntimeUnloadResult { Unloaded, NotFound, Busy, Pinned, DependedOn, Shutdown };
163 RuntimeUnloadResult unloadModuleRuntime(
const char* name);
165 enum class RuntimeLoadResult {
185 uint8_t* data()
const;
197 bool prepareRuntimeModules();
198 RuntimeLoadResult beginRuntimeModuleLoad(
size_t length,
RuntimeLoad& load);
199 RuntimeLoadResult loadModuleRuntime(
RuntimeLoad& load);
201#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
203 static void failRuntimeProtectionForTest(
size_t operationsBeforeFailure);
208 bool isShuttingDown()
const {
209 return __atomic_load_n(&m_ModuleShutdown, __ATOMIC_ACQUIRE);
217 bool registerTerminalQuiesce(ModuleEntry ownerEntry, TerminalQuiesceHook hook);
223 bool registerUnloadAdmission(ModuleEntry ownerEntry, Module::UnloadAdmissionHook hook);
226 bool unregisterTerminalQuiesce(ModuleEntry ownerEntry, TerminalQuiesceHook hook);
228#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
229 enum TestModuleUnloadClaim {
234 TestUnloadRuntimePinned,
235 TestUnloadDependedOn,
241 static size_t planModuleUnloadOrderForTest(
Module** modules,
size_t count,
Module** order,
245 static TestModuleUnloadClaim claimModuleUnloadForTest(
Module* module,
bool allowShutdown =
true,
246 bool* runLifecycle =
nullptr);
247 static TestModuleUnloadClaim claimNamedModuleUnloadForTest(
Module** modules,
size_t count,
249 static void completeModuleUnloadForTest(
Module* module,
bool wasFailed =
false,
250 bool runLifecycle =
false);
251 static bool moduleExecutionWaitsForUnloadForTest();
252 static bool completeGuardedModuleUnloadForTest(
Module* module,
bool terminal);
256 bool moduleIsLoaded(
char* name);
260 char* getDependingModule(
char* name);
264 uintptr_t globalLookupSymbol(
const char* pName);
265 const char* globalLookupSymbol(uintptr_t addr, uintptr_t* startAddr = 0);
268 size_t getModuleCount();
271 const Module* getModule(
size_t index);
275 return m_ModuleAllocator;
279 bool hasPendingModules()
const;
282 void updateModuleStatus(
Module* module,
bool status,
bool runFailureLifecycle =
true);
285 void waitForModulesToLoad();
296 void invokeInitModule();
311 bool moduleDependenciesSatisfiedLocked(
Module* module) const;
312 bool claimModuleExecutionLocked(
Module* module);
313 bool executeModule(
Module* module);
315 enum ModuleUnloadClaim {
326 enum TerminalQuiesceState {
333 enum ModuleShutdownState {
340 void abandonRuntimeModuleLoad(RuntimeLoad& load);
341 bool retireRuntimeModule(
Module* module,
bool runLifecycle);
342 uintptr_t runtimeExportLocked(
const char* name,
Module* owner =
nullptr)
const;
344 const char* runtimeLookupSymbolLocked(uintptr_t addr, uintptr_t* startAddr)
const;
346 uintptr_t resolveRuntimeImport(
const char* name,
Module* consumer);
347 bool beginModuleLoad();
348 void finishModuleLoad();
349 bool moduleRegisteredLocked(
Module* module)
const;
351 static bool moduleDependsOn(
Module* consumer,
Module* provider);
354 ModuleUnloadClaim claimModuleUnloadLocked(
Module* module,
bool allowShutdown,
355 bool requireMembership,
bool enforceDependencies,
356 bool& wasFailed,
bool& runLifecycle);
357 bool completeUnloadAttempt(
Module* module, ModuleUnloadClaim claim,
bool wasFailed,
358 bool runLifecycle,
bool silent,
bool progress,
bool terminal =
false);
359 void finishClaimedUnload(
Module* module,
bool wasFailed);
368 if (module->runtime) {
372 uintptr_t value =
reinterpret_cast<uintptr_t
>(ptr);
375 if (module->loadBase <= value && value <= (module->loadBase + module->loadSize)) {
379 return adjust_pointer(ptr, module->loadBase);
386 void unlockModules();
399 bool m_ModuleAllocatorInitialised;
400 bool m_RuntimeModulesPrepared;
409 bool m_ModuleShutdown;
410 ModuleShutdownState m_ModuleShutdownStatus;
411 bool m_ModuleLoading;
412 Module* m_UnloadingModule;
413 size_t m_ModuleExecutions;
414 size_t m_ModuleExecutionPasses;
415 Module* m_TerminalQuiesceOwner;
416 TerminalQuiesceHook m_TerminalQuiesceHook;
417 TerminalQuiesceState m_TerminalQuiesceStatus;