static int _module_load(module_handler_t* hMod) { int idx; // Check if module loaded idx = module_find(hMod->name); if ( idx>=0 ) return idx; // Find empty slot for ( idx=0; idx<MAX_NUM_LOADED_MODULES && modules[idx].hdr; idx++ ); if ( idx == MAX_NUM_LOADED_MODULES ) { moduleload_error("%d already loaded",MAX_NUM_LOADED_MODULES); return -1; } if (module_preload(hMod->name, hMod->version) != 0) { // Module is valid. Finalize binding modules[idx].hdr = flat_buf; // store runtime params flat_module_name_make(modules[idx].modulename, module_filename); modules[idx].hMod = hMod; int bind_err = bind_module( hMod, flat_buf->_module_info->lib ); if ( flat_buf->_module_info->lib->loader ) { uint32_t x = flat_buf->_module_info->lib->loader(); bind_err = bind_err || x; } if ( bind_err ) { module_unload(module_filename); moduleload_error("chdk mismatch",0); return -1; } return idx; } return -1; }
//----------------------------------------------- static void module_unload_idx(int idx) { if ( idx>=0 ) { module_log_unload(modules[idx].modulename); // Make finalization module if ( modules[idx].hdr->_module_info->lib->unloader ) modules[idx].hdr->_module_info->lib->unloader(); // Unbind pointers to module (chdk core callback) bind_module(modules[idx].hMod,0); // Free slot free ( modules[idx].hdr ); modules[idx].hdr = 0; } }
//----------------------------------------------- // Unload module at given index in modules array static void module_unload_idx(int idx) { if ((idx >= 0) && (modules[idx].hdr != 0)) { // Log unload module_log_unload(modules[idx].hMod->name); // Call module unload function if (modules[idx].hdr->_module_info->lib->unloader) modules[idx].hdr->_module_info->lib->unloader(); // Unbind pointers to module (chdk core callback) bind_module(modules[idx].hMod, 0); // Free module memory, and mark module as inactive free(modules[idx].hdr); modules[idx].hdr = 0; } }
// Load a module referenced by a 'module_handler_t' structure // Returns index into modules array if successful (or module already loaded) // otherwise returns -1 static int _module_load(module_handler_t* hMod) { int idx; // Get full path to module file, and hash of path char path[60]; unsigned int hash = get_module_path(path, hMod->name); // Check if module already loaded idx = module_find(hash); if (idx >= 0) return idx; // Reset lib (should not be needed, loader should only be called from 'default' lib) *hMod->lib = hMod->default_lib; // Simple lock to prevent multiple attempts to load modules simultaneously (in different tasks) // Not perfect; but should be sufficient static int isLoading = 0; while (isLoading != 0) msleep(10); isLoading = 1; // Find empty slot for (idx=0; idx<MAX_NUM_LOADED_MODULES && modules[idx].hdr; idx++) ; // If no slot found return error if (idx == MAX_NUM_LOADED_MODULES) { moduleload_error(hMod->name, "too many modules loaded"); idx = -1; } else { // Load and relocate module (returns 0 if error) flat_hdr* mod = module_preload(path, hMod->name, hMod->version); if (mod != 0) { // Module is valid. Finalize binding modules[idx].hdr = mod; modules[idx].hName = hash; modules[idx].hMod = hMod; int bind_err = bind_module(hMod, mod->_module_info->lib); // Call module loader if required if (!bind_err && mod->_module_info->lib->loader) { bind_err = mod->_module_info->lib->loader(); } // If any errors, unload module and display error message if (bind_err) { module_unload_idx(idx); moduleload_error(hMod->name, "loader error"); idx = -1; } } else { // module did not load, return invalid index idx = -1; } } // Release lock isLoading = 0; return idx; }