// return number of params in a component int halpr_param_count(const char *name) { hal_comp_t *comp; hal_comp_t *owner; int count = 0; comp = halpr_find_comp_by_name(name); if (comp == 0) return -ENOENT; int next = hal_data->param_list_ptr; while (next != 0) { hal_param_t *param = (hal_param_t *)SHMPTR(next); owner = halpr_find_owning_comp(param->owner_id); if (owner->comp_id == comp->comp_id) count++; next = param->next_ptr; } return count; }
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; } }
int hal_compile_comp(const char *name, hal_compiled_comp_t **ccomp) { hal_compiled_comp_t *tc; int pincount = 0; CHECK_HALDATA(); CHECK_STRLEN(name, HAL_NAME_LEN); { hal_comp_t *comp __attribute__((cleanup(halpr_autorelease_mutex))); int next, n; hal_comp_t *owner; hal_pin_t *pin; rtapi_mutex_get(&(hal_data->mutex)); if ((comp = halpr_find_comp_by_name(name)) == NULL) { HALERR("no such component '%s'", name); return -EINVAL; } // array sizing: count pins owned by this component next = hal_data->pin_list_ptr; n = 0; while (next != 0) { pin = SHMPTR(next); owner = halpr_find_owning_comp(pin->owner_id); if (owner->comp_id == comp->comp_id) { if (!(pin->flags & PIN_DO_NOT_TRACK)) n++; pincount++; } next = pin->next_ptr; } if (n == 0) { HALERR("component %s has no pins to watch for changes", name); return -EINVAL; } // a compiled comp is a userland/per process memory object if ((tc = malloc(sizeof(hal_compiled_comp_t))) == NULL) return -ENOMEM; memset(tc, 0, sizeof(hal_compiled_comp_t)); tc->comp = comp; tc->n_pins = n; // alloc pin array if ((tc->pin = malloc(sizeof(hal_pin_t *) * tc->n_pins)) == NULL) return -ENOMEM; // alloc tracking value array if ((tc->tracking = malloc(sizeof(hal_data_u) * tc->n_pins )) == NULL) return -ENOMEM; // alloc change bitmap if ((tc->changed = malloc(RTAPI_BITMAP_BYTES(tc->n_pins))) == NULL) return -ENOMEM; memset(tc->pin, 0, sizeof(hal_pin_t *) * tc->n_pins); memset(tc->tracking, 0, sizeof(hal_data_u) * tc->n_pins); RTAPI_ZERO_BITMAP(tc->changed,tc->n_pins); // fill in pin array n = 0; next = hal_data->pin_list_ptr; while (next != 0) { pin = SHMPTR(next); owner = halpr_find_owning_comp(pin->owner_id); if ((owner->comp_id == comp->comp_id) && !(pin->flags & PIN_DO_NOT_TRACK)) tc->pin[n++] = pin; next = pin->next_ptr; } assert(n == tc->n_pins); tc->magic = CCOMP_MAGIC; *ccomp = tc; } HALDBG("ccomp '%s': %d pins, %d tracked", name, pincount, tc->n_pins); return 0; }
int hal_retrieve_pinstate(const char *comp_name, hal_retrieve_pins_callback_t callback, void *cb_data) { int next; int nvisited = 0; int result; hal_comp_t *comp = NULL; hal_comp_t *owner; hal_pinstate_t pinstate; CHECK_HALDATA(); CHECK_STRLEN(comp_name, HAL_NAME_LEN); { hal_pin_t *pin __attribute__((cleanup(halpr_autorelease_mutex))); /* get mutex before accessing shared data */ rtapi_mutex_get(&(hal_data->mutex)); if (comp_name != NULL) { comp = halpr_find_comp_by_name(comp_name); if (comp == NULL) { HALERR("no such component '%s'", comp_name); return -EINVAL; } } // either comp == NULL, so visit all pins // or comp != NULL, in which case visit only this // component's pins // walk the pinlist next = hal_data->pin_list_ptr; while (next != 0) { pin = SHMPTR(next); owner = halpr_find_owning_comp(pin->owner_id); if (!comp_name || (owner->comp_id == comp->comp_id)) { nvisited++; /* this is the right comp */ if (callback) { // fill in the details: // NB: cover remote link case! pinstate.value = SHMPTR(pin->data_ptr_addr); pinstate.type = pin->type; pinstate.dir = pin->dir; pinstate.epsilon = hal_data->epsilon[pin->eps_index]; pinstate.flags = pin->flags; strncpy(pinstate.name, pin->name, sizeof(pin->name)); strncpy(pinstate.owner_name, owner->name, sizeof(owner->name)); result = callback(&pinstate, cb_data); if (result < 0) { // callback signaled an error, pass that back up. return result; } else if (result > 0) { // callback signaled 'stop iterating'. // pass back the number of visited pins so far. return nvisited; } else { // callback signaled 'OK to continue' // fall through } } else { // null callback passed in, // just count pins // nvisited already bumped above. } } /* no match, try the next one */ next = pin->next_ptr; } HALDBG("hal_retrieve_pinstate: visited %d pins", nvisited); /* if we get here, we ran through all the pins, so return count */ return nvisited; } }
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; }