int hal_unbind(const char *comp_name) { CHECK_HALDATA(); CHECK_STRLEN(comp_name, HAL_NAME_LEN); { hal_comp_t *comp __attribute__((cleanup(halpr_autorelease_mutex))); rtapi_mutex_get(&(hal_data->mutex)); comp = halpr_find_comp_by_name(comp_name); if (comp == NULL) { HALERR("no such component '%s'", comp_name); return -EINVAL; } if (comp->type != TYPE_REMOTE) { HALERR("component '%s' not a remote component (%d)", comp_name, comp->type); return -EINVAL; } if (comp->state != COMP_BOUND) { HALERR("component '%s': state not bound (%d)", comp_name, comp->state); return -EINVAL; } comp->state = COMP_UNBOUND; comp->last_unbound = (long int) time(NULL); } return 0; }
int hal_release(const char *comp_name) { CHECK_HALDATA(); CHECK_STRLEN(comp_name, HAL_NAME_LEN); { hal_comp_t *comp __attribute__((cleanup(halpr_autorelease_mutex))); rtapi_mutex_get(&(hal_data->mutex)); comp = halpr_find_comp_by_name(comp_name); if (comp == NULL) { HALERR("no such component '%s'", comp_name); return -EINVAL; } if (comp->type != TYPE_REMOTE) { HALERR("component '%s' not a remote component (%d)", comp_name, comp->type); return -EINVAL; } if (comp->pid == 0) { HALERR("component '%s': component already disowned", comp_name); return -EINVAL; } if (comp->pid != getpid()) { HALERR("component '%s': component owned by pid %d", comp_name, comp->pid); // return -EINVAL; } comp->pid = 0; } return 0; }
int hal_bind(const char *comp_name) { if (hal_data == 0) { hal_print_msg(RTAPI_MSG_ERR, "HAL: ERROR: hal_bind called before hal_init\n"); return -EINVAL; } { hal_comp_t *comp __attribute__((cleanup(halpr_autorelease_mutex))); rtapi_mutex_get(&(hal_data->mutex)); comp = halpr_find_comp_by_name(comp_name); if (comp == NULL) { hal_print_msg(RTAPI_MSG_ERR, "HAL: hal_bind(): no such component '%s'\n", comp_name); return -EINVAL; } if (comp->type != TYPE_REMOTE) { hal_print_msg(RTAPI_MSG_ERR, "HAL: hal_bind(%s): not a remote componet (%d)\n", comp_name, comp->type); return -EINVAL; } if (comp->state != COMP_UNBOUND) { hal_print_msg(RTAPI_MSG_ERR, "HAL: hal_bind(%s): state not unbound (%d)\n", comp_name, comp->state); return -EINVAL; } comp->state = COMP_BOUND; comp->last_bound = (long int) time(NULL);; // XXX ugly } return 0; }
int hal_comp_state_by_name(const char *name) { hal_comp_t *comp __attribute__((cleanup(halpr_autorelease_mutex))); rtapi_mutex_get(&(hal_data->mutex)); comp = halpr_find_comp_by_name(name); if (comp == NULL) return -ENOENT; return comp->state; }
int hal_acquire(const char *comp_name, int pid) { if (hal_data == 0) { hal_print_msg(RTAPI_MSG_ERR, "HAL: ERROR: hal_acquire called before hal_init\n"); return -EINVAL; } { hal_comp_t *comp __attribute__((cleanup(halpr_autorelease_mutex))); rtapi_mutex_get(&(hal_data->mutex)); comp = halpr_find_comp_by_name(comp_name); if (comp == NULL) { hal_print_msg(RTAPI_MSG_ERR, "HAL: hal_acquire(): no such component '%s'\n", comp_name); return -EINVAL; } if (comp->type != TYPE_REMOTE) { hal_print_msg(RTAPI_MSG_ERR, "HAL: hal_acquire(%s): not a remote component (%d)\n", comp_name, comp->type); return -EINVAL; } if (comp->state == COMP_BOUND) { hal_print_msg(RTAPI_MSG_ERR, "HAL: hal_acquire(%s): cant reown a bound component (%d)\n", comp_name, comp->state); return -EINVAL; } // let a comp be 'adopted away' from the RT environment // this is a tad hacky, should separate owner pid from RT/user distinction if ((comp->pid !=0) && (comp->pid != global_data->rtapi_app_pid)) { hal_print_msg(RTAPI_MSG_ERR, "HAL: hal_acquire(%s): component already owned by pid %d\n", comp_name, comp->pid); return -EINVAL; } comp->pid = pid; return comp->comp_id; } }
int hal_release(const char *comp_name) { if (hal_data == 0) { hal_print_msg(RTAPI_MSG_ERR, "HAL: ERROR: hal_release called before hal_init\n"); return -EINVAL; } { hal_comp_t *comp __attribute__((cleanup(halpr_autorelease_mutex))); rtapi_mutex_get(&(hal_data->mutex)); comp = halpr_find_comp_by_name(comp_name); if (comp == NULL) { hal_print_msg(RTAPI_MSG_ERR, "HAL: hal_release(): no such component '%s'\n", comp_name); return -EINVAL; } if (comp->type != TYPE_REMOTE) { hal_print_msg(RTAPI_MSG_ERR, "HAL: hal_release(%s): not a remote componet (%d)\n", comp_name, comp->type); return -EINVAL; } if (comp->pid == 0) { hal_print_msg(RTAPI_MSG_ERR, "HAL: hal_release(%s): component already disowned\n", comp_name); return -EINVAL; } if (comp->pid != getpid()) { hal_print_msg(RTAPI_MSG_WARN, "HAL: hal_release(%s): component owned by pid %d\n", comp_name, comp->pid); // return -EINVAL; } comp->pid = 0; } return 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; }
int hal_acquire(const char *comp_name, int pid) { CHECK_HALDATA(); CHECK_STRLEN(comp_name, HAL_NAME_LEN); { hal_comp_t *comp __attribute__((cleanup(halpr_autorelease_mutex))); rtapi_mutex_get(&(hal_data->mutex)); comp = halpr_find_comp_by_name(comp_name); if (comp == NULL) { HALERR("no such component '%s'", comp_name); return -EINVAL; } if (comp->type != TYPE_REMOTE) { HALERR("component '%s' not a remote component (%d)", comp_name, comp->type); return -EINVAL; } if (comp->state == COMP_BOUND) { HALERR("component '%s': cant reown a bound component (%d)", comp_name, comp->state); return -EINVAL; } // let a comp be 'adopted away' from the RT environment // this is a tad hacky, should separate owner pid from RT/user distinction if ((comp->pid !=0) && (comp->pid != global_data->rtapi_app_pid)) { HALERR("component '%s': already owned by pid %d", comp_name, comp->pid); return -EINVAL; } comp->pid = pid; return comp->comp_id; } }
// instantiation handlers static int create_instance(const hal_funct_args_t *fa) { const int argc = fa_argc(fa); const char **argv = fa_argv(fa); #if 0 HALDBG("'%s' called, arg=%p argc=%d", fa_funct_name(fa), fa_arg(fa), argc); int i; for (i = 0; i < argc; i++) HALDBG(" argv[%d] = \"%s\"", i,argv[i]); #endif if (argc < 2) { HALERR("need component name and instance name"); return -EINVAL; } const char *cname = argv[0]; const char *iname = argv[1]; hal_comp_t *comp = halpr_find_comp_by_name(cname); if (!comp) { HALERR("no such component '%s'", cname); return -EINVAL; } if (!comp->ctor) { HALERR("component '%s' not instantiable", cname); return -EINVAL; } hal_inst_t *inst = halpr_find_inst_by_name(iname); if (inst) { HALERR("instance '%s' already exists", iname); return -EBUSY; } return comp->ctor(iname, argc - 2, &argv[2]); }
int hal_xinit(const int type, const int userarg1, const int userarg2, const hal_constructor_t ctor, const hal_destructor_t dtor, const char *name) { int comp_id, retval; rtapi_set_logtag("hal_lib"); CHECK_STRLEN(name, HAL_NAME_LEN); // sanity: these must have been inited before by the // respective rtapi.so/.ko module CHECK_NULL(rtapi_switch); if ((dtor != NULL) && (ctor == NULL)) { HALERR("component '%s': NULL constructor doesnt make" " sense with non-NULL destructor", name); return -EINVAL; } // RTAPI initialisation already done HALDBG("initializing component '%s' type=%d arg1=%d arg2=%d/0x%x", name, type, userarg1, userarg2, userarg2); if ((lib_module_id < 0) && (type != TYPE_HALLIB)) { // if hal_lib not inited yet, do so now - recurse #ifdef RTAPI retval = hal_xinit(TYPE_HALLIB, 0, 0, NULL, NULL, "hal_lib"); #else retval = hal_xinitf(TYPE_HALLIB, 0, 0, NULL, NULL, "hal_lib%ld", (long) getpid()); #endif if (retval < 0) return retval; } // tag message origin field since ulapi autoload re-tagged them temporarily rtapi_set_logtag("hal_lib"); /* copy name to local vars, truncating if needed */ char rtapi_name[RTAPI_NAME_LEN + 1]; char hal_name[HAL_NAME_LEN + 1]; rtapi_snprintf(hal_name, sizeof(hal_name), "%s", name); rtapi_snprintf(rtapi_name, RTAPI_NAME_LEN, "HAL_%s", hal_name); /* do RTAPI init */ comp_id = rtapi_init(rtapi_name); if (comp_id < 0) { HALERR("rtapi init(%s) failed", rtapi_name); return -EINVAL; } // recursing? init HAL shm if ((lib_module_id < 0) && (type == TYPE_HALLIB)) { // recursion case, we're initing hal_lib // get HAL shared memory from RTAPI int shm_id = rtapi_shmem_new(HAL_KEY, comp_id, global_data->hal_size); if (shm_id < 0) { HALERR("hal_lib:%d failed to allocate HAL shm %x, rc=%d", comp_id, HAL_KEY, shm_id); rtapi_exit(comp_id); return -EINVAL; } // retrieve address of HAL shared memory segment void *mem; retval = rtapi_shmem_getptr(shm_id, &mem, 0); if (retval < 0) { HALERR("hal_lib:%d failed to acquire HAL shm %x, id=%d rc=%d", comp_id, HAL_KEY, shm_id, retval); rtapi_exit(comp_id); return -EINVAL; } // set up internal pointers to shared mem and data structure hal_shmem_base = (char *) mem; hal_data = (hal_data_t *) mem; #ifdef RTAPI // only on RTAPI hal_lib initialization: // initialize up the HAL shm segment retval = init_hal_data(); if (retval) { HALERR("could not init HAL shared memory rc=%d", retval); rtapi_exit(lib_module_id); lib_module_id = -1; return -EINVAL; } retval = hal_proc_init(); if (retval) { HALERR("could not init /proc files"); rtapi_exit(lib_module_id); lib_module_id = -1; return -EINVAL; } #endif // record hal_lib comp_id lib_module_id = comp_id; // and the HAL shm segmed id lib_mem_id = shm_id; } // global_data MUST be at hand now: HAL_ASSERT(global_data != NULL); // paranoia HAL_ASSERT(hal_shmem_base != NULL); HAL_ASSERT(hal_data != NULL); HAL_ASSERT(lib_module_id > -1); HAL_ASSERT(lib_mem_id > -1); if (lib_module_id < 0) { HALERR("giving up"); return -EINVAL; } { hal_comp_t *comp __attribute__((cleanup(halpr_autorelease_mutex))); /* get mutex before manipulating the shared data */ rtapi_mutex_get(&(hal_data->mutex)); /* make sure name is unique in the system */ if (halpr_find_comp_by_name(hal_name) != 0) { /* a component with this name already exists */ HALERR("duplicate component name '%s'", hal_name); rtapi_exit(comp_id); return -EINVAL; } /* allocate a new component structure */ comp = halpr_alloc_comp_struct(); if (comp == 0) { HALERR("insufficient memory for component '%s'", hal_name); rtapi_exit(comp_id); return -ENOMEM; } /* initialize the comp structure */ comp->userarg1 = userarg1; comp->userarg2 = userarg2; comp->comp_id = comp_id; comp->type = type; comp->ctor = ctor; comp->dtor = dtor; #ifdef RTAPI comp->pid = 0; #else /* ULAPI */ // a remote component starts out disowned comp->pid = comp->type == TYPE_REMOTE ? 0 : getpid(); #endif comp->state = COMP_INITIALIZING; comp->last_update = 0; comp->last_bound = 0; comp->last_unbound = 0; comp->shmem_base = hal_shmem_base; comp->insmod_args = 0; rtapi_snprintf(comp->name, sizeof(comp->name), "%s", hal_name); /* insert new structure at head of list */ comp->next_ptr = hal_data->comp_list_ptr; hal_data->comp_list_ptr = SHMOFF(comp); } // scope exited - mutex released // finish hal_lib initialisation // in ULAPI this will happen after the recursion on hal_lib%d unwinds if (type == TYPE_HALLIB) { #ifdef RTAPI // only on RTAPI hal_lib initialization: // export the instantiation support userfuncts hal_export_xfunct_args_t ni = { .type = FS_USERLAND, .funct.u = create_instance, .arg = NULL, .owner_id = lib_module_id }; if ((retval = hal_export_xfunctf( &ni, "newinst")) < 0) return retval; hal_export_xfunct_args_t di = { .type = FS_USERLAND, .funct.u = delete_instance, .arg = NULL, .owner_id = lib_module_id }; if ((retval = hal_export_xfunctf( &di, "delinst")) < 0) return retval; #endif retval = hal_ready(lib_module_id); if (retval) HALERR("hal_ready(%d) failed rc=%d", lib_module_id, retval); else HALDBG("%s initialization complete", hal_name); return retval; } HALDBG("%s component '%s' id=%d initialized%s", (ctor != NULL) ? "instantiable" : "legacy", hal_name, comp_id, (dtor != NULL) ? ", has destructor" : ""); return comp_id; } int hal_exit(int comp_id) { int *prev, next, comptype; char name[HAL_NAME_LEN + 1]; CHECK_HALDATA(); HALDBG("removing component %d", comp_id); { hal_comp_t *comp __attribute__((cleanup(halpr_autorelease_mutex))); /* grab mutex before manipulating list */ rtapi_mutex_get(&(hal_data->mutex)); /* search component list for 'comp_id' */ prev = &(hal_data->comp_list_ptr); next = *prev; if (next == 0) { /* list is empty - should never happen, but... */ HALERR("no components defined"); return -EINVAL; } comp = SHMPTR(next); while (comp->comp_id != comp_id) { /* not a match, try the next one */ prev = &(comp->next_ptr); next = *prev; if (next == 0) { /* reached end of list without finding component */ HALERR("no such component with id %d", comp_id); return -EINVAL; } comp = SHMPTR(next); } // record type, since we're about to zap the comp in free_comp_struct() comptype = comp->type; /* save component name for later */ rtapi_snprintf(name, sizeof(name), "%s", comp->name); /* get rid of the component */ free_comp_struct(comp); // unlink the comp only now as free_comp_struct() must // determine ownership of pins/params/functs and this // requires access to the current comp, too // since this is all under lock it should not matter *prev = comp->next_ptr; // add it to free list comp->next_ptr = hal_data->comp_free_ptr; hal_data->comp_free_ptr = SHMOFF(comp); // scope exit - mutex released } // if unloading the hal_lib component, destroy HAL shm if (comptype == TYPE_HALLIB) { int retval; /* release RTAPI resources */ retval = rtapi_shmem_delete(lib_mem_id, comp_id); if (retval) { HALERR("rtapi_shmem_delete(%d,%d) failed: %d", lib_mem_id, comp_id, retval); } // HAL shm is history, take note ASAP lib_mem_id = -1; hal_shmem_base = NULL; hal_data = NULL;; retval = rtapi_exit(comp_id); if (retval) { HALERR("rtapi_exit(%d) failed: %d", lib_module_id, retval); } // the hal_lib RTAPI module is history, too // in theory we'd be back to square 1 lib_module_id = -1; } else { // the standard case rtapi_exit(comp_id); } //HALDBG("component '%s' id=%d removed", name, comp_id); return 0; }
int hal_init_mode(const char *name, int type, int userarg1, int userarg2) { int comp_id; char rtapi_name[RTAPI_NAME_LEN + 1]; char hal_name[HAL_NAME_LEN + 1]; // tag message origin field rtapi_set_logtag("hal_lib"); if (name == 0) { hal_print_msg(RTAPI_MSG_ERR, "HAL: ERROR: no component name\n"); return -EINVAL; } if (strlen(name) > HAL_NAME_LEN) { hal_print_msg(RTAPI_MSG_ERR, "HAL: ERROR: component name '%s' is too long\n", name); return -EINVAL; } // rtapi initialisation already done // since this happens through the constructor hal_print_msg(RTAPI_MSG_DBG, "HAL: initializing component '%s' type=%d arg1=%d arg2=%d/0x%x\n", name, type, userarg1, userarg2, userarg2); /* copy name to local vars, truncating if needed */ rtapi_snprintf(rtapi_name, RTAPI_NAME_LEN, "HAL_%s", name); rtapi_snprintf(hal_name, sizeof(hal_name), "%s", name); /* do RTAPI init */ comp_id = rtapi_init(rtapi_name); if (comp_id < 0) { hal_print_msg(RTAPI_MSG_ERR, "HAL: ERROR: rtapi init failed\n"); return -EINVAL; } // tag message origin field since ulapi autoload re-tagged them rtapi_set_logtag("hal_lib"); #ifdef ULAPI hal_rtapi_attach(); #endif { hal_comp_t *comp __attribute__((cleanup(halpr_autorelease_mutex))); /* get mutex before manipulating the shared data */ rtapi_mutex_get(&(hal_data->mutex)); /* make sure name is unique in the system */ if (halpr_find_comp_by_name(hal_name) != 0) { /* a component with this name already exists */ hal_print_msg(RTAPI_MSG_ERR, "HAL: ERROR: duplicate component name '%s'\n", hal_name); rtapi_exit(comp_id); return -EINVAL; } /* allocate a new component structure */ comp = halpr_alloc_comp_struct(); if (comp == 0) { /* couldn't allocate structure */ hal_print_msg(RTAPI_MSG_ERR, "HAL: ERROR: insufficient memory for component '%s'\n", hal_name); rtapi_exit(comp_id); return -ENOMEM; } /* initialize the comp structure */ comp->userarg1 = userarg1; comp->userarg2 = userarg2; comp->comp_id = comp_id; comp->type = type; #ifdef RTAPI comp->pid = 0; //FIXME revisit this #else /* ULAPI */ // a remote component starts out disowned comp->pid = comp->type == TYPE_REMOTE ? 0 : getpid(); //FIXME revisit this #endif comp->state = COMP_INITIALIZING; comp->last_update = 0; comp->last_bound = 0; comp->last_unbound = 0; comp->shmem_base = hal_shmem_base; comp->insmod_args = 0; rtapi_snprintf(comp->name, sizeof(comp->name), "%s", hal_name); /* insert new structure at head of list */ comp->next_ptr = hal_data->comp_list_ptr; hal_data->comp_list_ptr = SHMOFF(comp); } // scope exited - mutex released /* done */ hal_print_msg(RTAPI_MSG_DBG, "HAL: component '%s' initialized, ID = %02d\n", hal_name, comp_id); return comp_id; }
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; } }
int hal_compile_comp(const char *name, hal_compiled_comp_t **ccomp) { hal_compiled_comp_t *tc; int pincount = 0; if (!name) { hal_print_msg(RTAPI_MSG_ERR, "HAL:%d ERROR: hal_compile_comp() called with NULL name\n", rtapi_instance); return -EINVAL; } { 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) { hal_print_msg(RTAPI_MSG_ERR, "HAL:%d ERROR: hal_comp_compile(%s): no such comp\n", rtapi_instance, 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 = SHMPTR(pin->owner_ptr); if (owner->comp_id == comp->comp_id) { if (!(pin->flags & PIN_DO_NOT_TRACK)) n++; pincount++; } next = pin->next_ptr; } if (n == 0) { hal_print_msg(RTAPI_MSG_ERR, "ERROR: component %s has no pins to watch for changes\n", 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 = SHMPTR(pin->owner_ptr); 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; } hal_print_msg(RTAPI_MSG_DBG, "hal_compile_comp(%s): %d pins, %d tracked", name, pincount, tc->n_pins); return 0; }