X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/blobdiff_plain/294f95a39505231ba48a99c4c4a9f4ecaeed7e40..7d21ff085ab97827a9a1b352bdf697009aff2662:/src/gras/Virtu/gras_module.c diff --git a/src/gras/Virtu/gras_module.c b/src/gras/Virtu/gras_module.c index a9b49b7ddd..a400d2d2a8 100644 --- a/src/gras/Virtu/gras_module.c +++ b/src/gras/Virtu/gras_module.c @@ -27,7 +27,7 @@ process-wide globals. An example may be the list of attached callbacks. That is why we have 4 functions per module: the join function is called by any process, and is in charge of creating the process-wide globals. If it is the first time a process uses the module, it also calls the init function, in -charge of initializing the world-wide globals. We have the symetric functions +charge of initializing the world-wide globals. We have the symmetric functions leave, called by any process not using the module anymore, and exit, in charge of freeing the world-wide globals when no process use it anymore. @@ -36,12 +36,12 @@ creating the module, which contains a factory (the join function) able to create process-wide globals. The fact that indeed the calling sequence goes from join to init and not the other side is just an implementation bias ;) -Then again, we want these functionnalities to be quick. We want to access +Then again, we want these functionalities to be quick. We want to access the process-wide globals by providing their rank in a dynar, we don't want to -search them in a dictionnary. This is especially true in the module +search them in a dictionary. This is especially true in the module implementation, where each functions is likely to require them to work. The position could be a stored in a global variable only visible from the module -implementation. +implementation. The need for an array in which to store the globals does not hold for world-wide globals: only one instance of them can exist in the same unix naming @@ -59,7 +59,7 @@ will load their code in as plugin), we want to give the module handling library tables. This is why we have the ID field in the module structure: it points exactly to the implementation side global. -Yeah, I know. All this is not that clear. But at least, writing this helped me +Yeah, I know. All this is not that clear. But at least, writing this helped me to design that crap ;) */ @@ -73,18 +73,19 @@ typedef struct s_gras_module { allow modules initializing other modules while tracking dependencies properly and leave() only when needed. This would allow dynamic module loading/unloading */ - + int *p_id; /* where the module stores the libdata ID (a global somewhere), to tweak it on need */ - void_f_void_t *init_f; /* First time the module is referenced. */ - void_f_void_t *exit_f; /* When last process referencing it stops doing so. */ - void_f_pvoid_t *join_f; /* Called by each process in initialization phase (init_f called once for all processes) */ - void_f_pvoid_t *leave_f; /* Called by each process in finalization phase. Should free moddata passed */ + void_f_void_t init_f; /* First time the module is referenced. */ + void_f_void_t exit_f; /* When last process referencing it stops doing so. */ + void_f_pvoid_t join_f; /* Called by each process in initialization phase (init_f called once for all processes) */ + void_f_pvoid_t leave_f; /* Called by each process in finalization phase. Should free moddata passed */ } s_gras_module_t, *gras_module_t; static xbt_set_t _gras_modules = NULL; /* content: s_gras_module_t */ static void gras_module_freep(void *p) { free( ((gras_module_t)p) ->name); + free(p); } @@ -93,11 +94,11 @@ static void gras_module_freep(void *p) { * @param name: name of the module, of course (beware of dupplicates!) * @param datasize: the size of your data, ie of the state this module has on each process * @param ID: address of a global you use as parameter to gras_module_data_by_id - * @param init_f: function called the first time a module gets by a process of the naming space. + * @param init_f: function called the first time a module gets by a process of the naming space. * A classical use is to declare some messages the module uses, as well as the initialization * of module constants (accross processes boundaries in SG). * @param exit_f: function called when the last process of this naming space unref this module. - * @param join_f: function called each time a process references the module. + * @param join_f: function called each time a process references the module. * It is passed the moddata already malloced, and should initialize the fields as it wants. * It can also attach some callbacks to the module messages. * @param leave_f: function called each time a process unrefs the module. @@ -106,11 +107,11 @@ static void gras_module_freep(void *p) { */ void gras_module_add(const char *name, unsigned int datasize, int *ID, - void_f_void_t *init_f, void_f_void_t *exit_f, - void_f_pvoid_t *join_f, void_f_pvoid_t *leave_f) { - gras_module_t mod; + void_f_void_t init_f, void_f_void_t exit_f, + void_f_pvoid_t join_f, void_f_pvoid_t leave_f) { + gras_module_t mod=NULL; xbt_ex_t e; - int found = 0; + volatile int found = 0; if (!_gras_modules) _gras_modules = xbt_set_new(); @@ -125,13 +126,19 @@ void gras_module_add(const char *name, unsigned int datasize, int *ID, } if (found) { - xbt_assert(mod->init_f == init_f); - xbt_assert(mod->exit_f == exit_f); - xbt_assert(mod->join_f == join_f); - xbt_assert(mod->leave_f == leave_f); - xbt_assert(mod->datasize == datasize); - xbt_assert(mod->p_id == ID); - + xbt_assert1(mod->init_f == init_f, + "Module %s reregistered with a different init_f!", name); + xbt_assert1(mod->exit_f == exit_f, + "Module %s reregistered with a different exit_f!", name); + xbt_assert1(mod->join_f == join_f, + "Module %s reregistered with a different join_f!", name); + xbt_assert1(mod->leave_f == leave_f, + "Module %s reregistered with a different leave_f!", name); + xbt_assert1(mod->datasize == datasize, + "Module %s reregistered with a different datasize!", name); + xbt_assert1(mod->p_id == ID, + "Module %s reregistered with a different p_id field!", name); + DEBUG1("Module %s already registered. Ignoring re-registration",name); return; } @@ -140,7 +147,7 @@ void gras_module_add(const char *name, unsigned int datasize, int *ID, mod = xbt_new(s_gras_module_t, 1); mod->name = xbt_strdup(name); mod->name_len = strlen(name); - + mod->datasize = datasize; mod->p_id = ID; mod->init_f = init_f; @@ -148,28 +155,40 @@ void gras_module_add(const char *name, unsigned int datasize, int *ID, mod->join_f = join_f; mod->leave_f = leave_f; mod->refcount = 0; - - + *mod->p_id = xbt_set_length(_gras_modules); - + xbt_set_add(_gras_modules,(void*)mod,gras_module_freep); } -/* Removes & frees a moddata */ +/* shutdown the module mechanism (world-wide cleanups) */ +void gras_moddata_exit(void) { + xbt_set_free(&_gras_modules); +} + +/* frees the moddata on this host (process-wide cleanups) */ +void gras_moddata_leave(void) { + gras_procdata_t *pd=gras_procdata_get(); + + xbt_dynar_free(&pd->moddata); +} + +/* Removes & frees a given moddata from the current host */ static void moddata_freep(void *p) { gras_procdata_t *pd=gras_procdata_get(); int id = xbt_dynar_search (pd->moddata, p); gras_module_t mod = (gras_module_t)xbt_set_get_by_id(_gras_modules, id); - (*mod->leave_f)(p); - free(p); + (*mod->leave_f)(gras_moddata_by_id(id)); } void gras_module_join(const char *name) { + gras_procdata_t *pd; + void *moddata; gras_module_t mod = (gras_module_t)xbt_set_get_by_name(_gras_modules, name); - + VERB2("Join to module %s (%p)",name,mod); - + /* NEW */ if (mod->refcount == 0) { VERB1("Init module %s",name); @@ -183,10 +202,9 @@ void gras_module_join(const char *name) { mod->refcount++; /* JOIN */ - gras_procdata_t *pd=gras_procdata_get(); - void *moddata; + pd=gras_procdata_get(); - if (!pd->moddata) /* Damn. I must be the first module on this process. Scary ;) */ + if (!pd->moddata) /* Damn. I must be the first module on this process. Scary ;)*/ pd->moddata = xbt_dynar_new(sizeof(gras_module_t),&moddata_freep); moddata = xbt_malloc(mod->datasize); @@ -198,12 +216,13 @@ void gras_module_join(const char *name) { DEBUG2("Module %s joined successfully (ID=%d)", name,*(mod->p_id)); } void gras_module_leave(const char *name) { + void *moddata; gras_module_t mod = (gras_module_t)xbt_set_get_by_name(_gras_modules, name); VERB1("Leave module %s",name); /* LEAVE */ - void *moddata = gras_moddata_by_id( *(mod->p_id) ); + moddata = gras_moddata_by_id( *(mod->p_id) ); (*mod->leave_f)(moddata); /* EXIT */ @@ -213,7 +232,7 @@ void gras_module_leave(const char *name) { (*mod->exit_f)(); - /* Don't remove the module for real, sets don't allow to + /* Don't remove the module for real, sets don't allow to free(mod->name); free(mod); @@ -221,7 +240,7 @@ void gras_module_leave(const char *name) { } } - + void *gras_moddata_by_id(unsigned int ID) { gras_procdata_t *pd=gras_procdata_get(); void *p;