static void free_comp_struct(hal_comp_t * comp) { int *prev, next; #ifdef RTAPI hal_funct_t *funct; #endif /* RTAPI */ hal_pin_t *pin; hal_param_t *param; /* can't delete the component until we delete its "stuff" */ /* need to check for functs only if a realtime component */ #ifdef RTAPI // first unlink and destroy all functs, so an RT thread // cant trample on the comp while it's being destroyed /* search the function list for this component's functs */ prev = &(hal_data->funct_list_ptr); next = *prev; while (next != 0) { funct = SHMPTR(next); hal_comp_t *owner = halpr_find_owning_comp(funct->owner_id); if (owner == comp) { /* this function belongs to our component, unlink from list */ *prev = funct->next_ptr; /* and delete it */ free_funct_struct(funct); } else { /* no match, try the next one */ prev = &(funct->next_ptr); } next = *prev; } // here, technically all the comp's functs are // delf'd and not visible anymore // now that the funct is gone, // exit all the comp's instances next = hal_data->inst_list_ptr; while (next != 0) { hal_inst_t *inst = SHMPTR(next); next = inst->next_ptr; if (inst->comp_id == comp->comp_id) { // this instance is owned by this comp free_inst_struct(inst); } } // here all insts, their pins, params and functs are gone. #endif /* RTAPI */ // now work the legacy pins and params which are // directly owned by the comp. /* search the pin list for this component's pins */ prev = &(hal_data->pin_list_ptr); next = *prev; while (next != 0) { pin = SHMPTR(next); if (pin->owner_id == comp->comp_id) { /* this pin belongs to our component, unlink from list */ *prev = pin->next_ptr; /* and delete it */ free_pin_struct(pin); } else { /* no match, try the next one */ prev = &(pin->next_ptr); } next = *prev; } /* search the parameter list for this component's parameters */ prev = &(hal_data->param_list_ptr); next = *prev; while (next != 0) { param = SHMPTR(next); if (param->owner_id == comp->comp_id) { /* this param belongs to our component, unlink from list */ *prev = param->next_ptr; /* and delete it */ free_param_struct(param); } else { /* no match, try the next one */ prev = &(param->next_ptr); } next = *prev; } /* now we can delete the component itself */ /* clear contents of struct */ comp->comp_id = 0; comp->type = TYPE_INVALID; comp->state = COMP_INVALID; comp->last_bound = 0; comp->last_unbound = 0; comp->last_update = 0; comp->shmem_base = 0; comp->name[0] = '\0'; }
// almost a copy of free_comp_struct(), but based on instance // // unlinks and frees functs exported by this instance // then calls any custom destructor // then unlinks & deletes all pins owned by this instance // then deletes params owned by this instance void free_inst_struct(hal_inst_t * inst) { int *prev, next; #ifdef RTAPI hal_funct_t *funct; #endif /* RTAPI */ hal_pin_t *pin; hal_param_t *param; /* can't delete the instance until we delete its "stuff" */ /* need to check for functs only if a realtime component */ #ifdef RTAPI /* search the function list for this instance's functs */ prev = &(hal_data->funct_list_ptr); next = *prev; while (next != 0) { funct = SHMPTR(next); if (funct->owner_id == inst->inst_id) { /* this function belongs to this instance, unlink from list */ *prev = funct->next_ptr; /* and delete it */ free_funct_struct(funct); } else { /* no match, try the next one */ prev = &(funct->next_ptr); } next = *prev; } // now that the funct is gone, call the dtor for this instance // get owning comp hal_comp_t *comp = halpr_find_owning_comp(inst->comp_id); if (comp->dtor) { //NB - pins, params etc still intact // this instance is owned by this comp, call destructor HALDBG("calling custom destructor(%s,%s)", comp->name, inst->name); comp->dtor(inst->name, SHMPTR(inst->inst_data_ptr), inst->inst_size); } #endif /* RTAPI */ /* search the pin list for this instance's pins */ prev = &(hal_data->pin_list_ptr); next = *prev; while (next != 0) { pin = SHMPTR(next); if (pin->owner_id == inst->inst_id) { /* this pin belongs to our instance, unlink from list */ *prev = pin->next_ptr; /* and delete it */ free_pin_struct(pin); } else { /* no match, try the next one */ prev = &(pin->next_ptr); } next = *prev; } /* search the parameter list for this instance's parameters */ prev = &(hal_data->param_list_ptr); next = *prev; while (next != 0) { param = SHMPTR(next); if (param->owner_id == inst->inst_id) { /* this param belongs to our instance, unlink from list */ *prev = param->next_ptr; /* and delete it */ free_param_struct(param); } else { /* no match, try the next one */ prev = &(param->next_ptr); } next = *prev; } /* now we can delete the instance itself */ // search the instance list and unlink instances owned by this comp hal_inst_t *ip; prev = &(hal_data->inst_list_ptr); next = *prev; while (next != 0) { ip = SHMPTR(next); if (ip == inst) { // this instance is owned by this comp *prev = ip->next_ptr; // zap the instance structure ip->comp_id = 0; ip->inst_id = 0; ip->inst_data_ptr = 0; // NB - loosing HAL memory here ip->inst_size = 0; ip->name[0] = '\0'; // add it to free list ip->next_ptr = hal_data->inst_free_ptr; hal_data->inst_free_ptr = SHMOFF(ip); } else { prev = &(ip->next_ptr); } next = *prev; } }
static void free_comp_struct(hal_comp_t * comp) { int *prev, next; #ifdef RTAPI hal_funct_t *funct; #endif /* RTAPI */ hal_pin_t *pin; hal_param_t *param; /* can't delete the component until we delete its "stuff" */ /* need to check for functs only if a realtime component */ #ifdef RTAPI /* search the function list for this component's functs */ prev = &(hal_data->funct_list_ptr); next = *prev; while (next != 0) { funct = SHMPTR(next); if (SHMPTR(funct->owner_ptr) == comp) { /* this function belongs to our component, unlink from list */ *prev = funct->next_ptr; /* and delete it */ free_funct_struct(funct); } else { /* no match, try the next one */ prev = &(funct->next_ptr); } next = *prev; } #endif /* RTAPI */ /* search the pin list for this component's pins */ prev = &(hal_data->pin_list_ptr); next = *prev; while (next != 0) { pin = SHMPTR(next); if (SHMPTR(pin->owner_ptr) == comp) { /* this pin belongs to our component, unlink from list */ *prev = pin->next_ptr; /* and delete it */ free_pin_struct(pin); } else { /* no match, try the next one */ prev = &(pin->next_ptr); } next = *prev; } /* search the parameter list for this component's parameters */ prev = &(hal_data->param_list_ptr); next = *prev; while (next != 0) { param = SHMPTR(next); if (SHMPTR(param->owner_ptr) == comp) { /* this param belongs to our component, unlink from list */ *prev = param->next_ptr; /* and delete it */ free_param_struct(param); } else { /* no match, try the next one */ prev = &(param->next_ptr); } next = *prev; } /* now we can delete the component itself */ /* clear contents of struct */ comp->comp_id = -1; comp->type = TYPE_INVALID; comp->state = COMP_INVALID; comp->last_bound = 0; comp->last_unbound = 0; comp->last_update = 0; comp->shmem_base = 0; comp->name[0] = '\0'; /* add it to free list */ comp->next_ptr = hal_data->comp_free_ptr; hal_data->comp_free_ptr = SHMOFF(comp); }
static int hal_export_xfunctfv(const hal_export_xfunct_args_t *xf, const char *fmt, va_list ap) { int *prev, next, cmp, sz; hal_funct_t *nf, *fptr; char name[HAL_NAME_LEN + 1]; CHECK_HALDATA(); CHECK_LOCK(HAL_LOCK_LOAD); sz = rtapi_vsnprintf(name, sizeof(name), fmt, ap); if(sz == -1 || sz > HAL_NAME_LEN) { HALERR("length %d invalid for name starting '%s'", sz, name); return -ENOMEM; } HALDBG("exporting function '%s' type %d", name, xf->type); { hal_comp_t *comp __attribute__((cleanup(halpr_autorelease_mutex))); /* get mutex before accessing shared data */ rtapi_mutex_get(&(hal_data->mutex)); comp = halpr_find_owning_comp(xf->owner_id); if (comp == 0) { /* bad comp_id */ HALERR("funct '%s': owning component %d not found", name, xf->owner_id); return -EINVAL; } if (comp->type == TYPE_USER) { /* not a realtime component */ HALERR("funct '%s': component %s/%d is not realtime (%d)", name, comp->name, comp->comp_id, comp->type); return -EINVAL; } bool legacy = (halpr_find_inst_by_id(xf->owner_id) == NULL); // instances may export functs post hal_ready if (legacy && (comp->state > COMP_INITIALIZING)) { HALERR("funct '%s': called after hal_ready", name); return -EINVAL; } /* allocate a new function structure */ nf = alloc_funct_struct(); if (nf == 0) NOMEM("function '%s'", name); /* initialize the structure */ nf->uses_fp = xf->uses_fp; nf->owner_id = xf->owner_id; nf->reentrant = xf->reentrant; nf->users = 0; nf->handle = rtapi_next_handle(); nf->arg = xf->arg; nf->type = xf->type; nf->funct.l = xf->funct.l; // a bit of a cheat really rtapi_snprintf(nf->name, sizeof(nf->name), "%s", name); /* search list for 'name' and insert new structure */ prev = &(hal_data->funct_list_ptr); next = *prev; while (1) { if (next == 0) { /* reached end of list, insert here */ nf->next_ptr = next; *prev = SHMOFF(nf); /* break out of loop and init the new function */ break; } fptr = SHMPTR(next); cmp = strcmp(fptr->name, nf->name); if (cmp > 0) { /* found the right place for it, insert here */ nf->next_ptr = next; *prev = SHMOFF(nf); /* break out of loop and init the new function */ break; } if (cmp == 0) { /* name already in list, can't insert */ free_funct_struct(nf); HALERR("duplicate function '%s'", name); return -EINVAL; } /* didn't find it yet, look at next one */ prev = &(fptr->next_ptr); next = *prev; } // at this point we have a new function and can // yield the mutex by scope exit } /* init time logging variables */ nf->runtime = 0; nf->maxtime = 0; nf->maxtime_increased = 0; /* at this point we have a new function and can yield the mutex */ rtapi_mutex_give(&(hal_data->mutex)); switch (xf->type) { case FS_LEGACY_THREADFUNC: case FS_XTHREADFUNC: /* create a pin with the function's runtime in it */ if (hal_pin_s32_newf(HAL_OUT, &(nf->runtime), xf->owner_id, "%s.time",name)) { HALERR("failed to create pin '%s.time'", name); return -EINVAL; } *(nf->runtime) = 0; /* note that failure to successfully create the following params does not cause the "export_funct()" call to fail - they are for debugging and testing use only */ /* create a parameter with the function's maximum runtime in it */ nf->maxtime = 0; hal_param_s32_newf(HAL_RW, &(nf->maxtime), xf->owner_id, "%s.tmax", name); /* create a parameter with the function's maximum runtime in it */ nf->maxtime_increased = 0; hal_param_bit_newf(HAL_RO, &(nf->maxtime_increased), xf->owner_id, "%s.tmax-inc", name); break; case FS_USERLAND: // no timing pins/params ; } return 0; }