Esempio n. 1
0
// 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;
}
Esempio n. 2
0
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';

}
Esempio n. 3
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;
    }
}
Esempio n. 4
0
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;
}
Esempio n. 5
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;
    }
}
Esempio n. 6
0
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;
}