/** * \file kernel_loader.c * \author Ilja Booij * \date 07/03/03 */ #include "kernel_loader.h" #include "corral.h" #include "element.h" #include "loader.h" #include "type.h" #include "database.h" /* #include "device.h" */ #include "mutex.h" /* get some includes from the kernel */ #include /* for string manipulation */ #include /* for semaphore operations */ #include /* for atomic_t */ #include /* for inter_module_* */ /* some prototypes for functions we define later on */ /** \brief get pointer to a function * * get a pointer to a function that is exported by a module * \param function_name name of the function * \param func pointer to a pointer to the function, this will * be filled with a pointer to the target function on exit, or * NULL in case of failure * \returns CORRAL_SUCCESS or CORRAL_FAILURE */ static corral_uint kernel_get_function(char *function_name, void **func); /** \brief release a pointer to a function * * release a pointer to a function exported by a module. * \param function_name the name of the function to release * \returns CORRAL_SUCCESS or CORRAL_FAILURE */ static corral_uint kernel_put_function(char *function_name); /** \brief fill a Corral_ElementClass * * fill all members of a Corral_ElementClass. * \param classname name of the Corral_ElementClass * \param eclass pointer to the Corral_ElementClass * \return CORRAL_SUCCESS or CORRAL_FAILURE */ static corral_uint kernel_fill_Corral_ElementClass(char *classname, Corral_ElementClass * eclass); /* exported functions */ corral_uint corral_load_kernel_register_class(char *classname) { Corral_ElementClass *eclass = corral_do_malloc(sizeof(Corral_ElementClass)); /* try to initialise eclass */ if (kernel_fill_Corral_ElementClass(classname, eclass) == CORRAL_FAILURE) { corral_free(eclass); return CORRAL_FAILURE; } /* initialise use_count and add to database */ atomic_set(&(eclass->use_count), 0); corral_class_db->add(corral_class_db, classname, eclass); return CORRAL_SUCCESS; } corral_uint corral_load_kernel_unregister_class(char *classname) { Corral_ElementClass *eclass; char *(*get_members) (Corral_Loader_Members member); char *function_name; int function_name_length; int i; corral_uint result = CORRAL_SUCCESS; if ((corral_class_db == NULL) || (corral_kmodule_db == NULL)) return CORRAL_FAILURE; /* first check if this is a loadable module */ get_members = corral_kmodule_db->find(corral_kmodule_db, classname); if (get_members == NULL) return CORRAL_FAILURE; result = corral_load_try_remove_class(classname, &eclass); if (result == CORRAL_FAILURE) { return CORRAL_FAILURE; } /* dirty to use this enum value in this way! */ for (i = 0; i < CORRAL_LOADER_PUT_FUNCTIONS; i++) { if (i != CORRAL_LOADER_DESC) if (kernel_put_function((*get_members) (i)) == CORRAL_FAILURE) return CORRAL_FAILURE; } /* also release the get_members function itself */ function_name_length = strlen("corral_") + strlen(classname) + strlen("_get_members"); function_name = corral_do_malloc((function_name_length + 1) * sizeof(char)); snprintf(function_name, function_name_length + 1, "corral_%s_get_members", classname); kernel_put_function(function_name); corral_free(function_name); corral_kmodule_db->remove(corral_kmodule_db, get_members); corral_free(eclass); return CORRAL_SUCCESS; } void corral_load_kernel_register_functions() { /* register functions for inter module communication */ inter_module_register("corral_load_kernel_register_class", THIS_MODULE, corral_load_kernel_register_class); inter_module_register("corral_pull", THIS_MODULE, corral_pull); inter_module_register("corral_push", THIS_MODULE, corral_push); inter_module_register("corral_pull_safe", THIS_MODULE, corral_pull_safe); inter_module_register("corral_push_safe", THIS_MODULE, corral_push_safe); inter_module_register("corral_mutex_lock", THIS_MODULE, corral_mutex_lock); inter_module_register("corral_mutex_try_lock", THIS_MODULE, down_trylock); inter_module_register("corral_mutex_unlock", THIS_MODULE, up); inter_module_register("corral_sem_down", THIS_MODULE, corral_sem_down); inter_module_register("corral_sem_try_down", THIS_MODULE, down_trylock); inter_module_register("corral_sem_up", THIS_MODULE, up); } void corral_load_kernel_unregister_functions() { /* unregister functions for inter module communication */ inter_module_unregister("corral_load_kernel_register_class"); inter_module_unregister("corral_pull"); inter_module_unregister("corral_push"); inter_module_unregister("corral_pull_safe"); inter_module_unregister("corral_push_safe"); inter_module_unregister("corral_mutex_lock"); inter_module_unregister("corral_mutex_try_lock"); inter_module_unregister("corral_mutex_unlock"); inter_module_unregister("corral_sem_down"); inter_module_unregister("corral_sem_try_down"); inter_module_unregister("corral_sem_up"); } /* static functions */ static corral_uint kernel_fill_Corral_ElementClass(char *classname, Corral_ElementClass * eclass) { char *(*get_members) (const Corral_Loader_Members); int (*get_members_variables) (const Corral_Loader_Variables); int function_name_length; char *function_name; function_name_length = strlen("corral_") + strlen(classname) + strlen("_get_members"); function_name = corral_do_malloc((function_name_length + 1) * sizeof(char)); snprintf(function_name, function_name_length + 1, "corral_%s_get_members", classname); if (kernel_get_function(function_name, (void **) &get_members) == CORRAL_FAILURE) return CORRAL_FAILURE; if (get_members == NULL) /* if this function is NULL, we are lost.. */ return CORRAL_FAILURE; /* now get all the functions in the Corral_ElementClass */ if (kernel_get_function((*get_members) (CORRAL_LOADER_INITFUNC), (void **) &(eclass->initfunc)) == CORRAL_FAILURE) return CORRAL_FAILURE; if (kernel_get_function((*get_members) (CORRAL_LOADER_DEINITFUNC), (void **) &(eclass->deinitfunc)) == CORRAL_FAILURE) return CORRAL_FAILURE; if (kernel_get_function((*get_members) (CORRAL_LOADER_RUNFUNC), (void **) &(eclass->runfunc)) == CORRAL_FAILURE) return CORRAL_FAILURE; if (kernel_get_function((*get_members) (CORRAL_LOADER_ALLOWFUNC), (void **) &(eclass->allowfunc)) == CORRAL_FAILURE) return CORRAL_FAILURE; if (kernel_get_function((*get_members) (CORRAL_LOADER_PUSHFUNC), (void **) &(eclass->pushfunc)) == CORRAL_FAILURE) return CORRAL_FAILURE; if (kernel_get_function((*get_members) (CORRAL_LOADER_PULLFUNC), (void **) &(eclass->pullfunc)) == CORRAL_FAILURE) return CORRAL_FAILURE; /* also get the function that holds the variale values */ if (kernel_get_function((*get_members) (CORRAL_LOADER_GET_VARIABLES), (void **) &get_members_variables) == CORRAL_FAILURE) return CORRAL_FAILURE; /* and get the variables */ eclass->datasize = (*get_members_variables) (CORRAL_LOADER_DATASIZE); eclass->datamod = (*get_members_variables) (CORRAL_LOADER_DATAMOD); eclass->desc = (*get_members) (CORRAL_LOADER_DESC); if (corral_kmodule_db == NULL) corral_kmodule_db = corral_new_database(); corral_kmodule_db->add(corral_kmodule_db, classname, get_members); return CORRAL_SUCCESS; } /* corral_kernel_fill_element_class */ static corral_uint kernel_get_function(char *function_name, void **func) { char *error; if (function_name == NULL) *func = NULL; else { *func = (void *) inter_module_get(function_name); if (*func == NULL) { corral_print("kloader.o: failure loading function %s\n", function_name); return CORRAL_FAILURE; } } return CORRAL_SUCCESS; } static corral_uint kernel_put_function(char *function_name) { if (function_name != NULL) inter_module_put(function_name); return CORRAL_SUCCESS; }