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_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 rtapi_exit(int module_id) { module_data *module; int n; if (rtapi_data == NULL) { rtapi_print_msg(RTAPI_MSG_ERR, "RTAPI: ERROR: exit called before init\n"); return -EINVAL; } rtapi_print_msg(RTAPI_MSG_DBG, "RTAPI: module %02d exiting\n", module_id); /* validate module ID */ if ((module_id < 1) || (module_id > RTAPI_MAX_MODULES)) { rtapi_print_msg(RTAPI_MSG_ERR, "RTAPI: ERROR: bad module id\n"); return -EINVAL; } /* get mutex */ rtapi_mutex_get(&(rtapi_data->mutex)); /* point to the module's data */ module = &(module_array[module_id]); /* check module status */ if (module->state != USERSPACE) { rtapi_print_msg(RTAPI_MSG_ERR, "RTAPI: ERROR: not a userspace module\n"); rtapi_mutex_give(&(rtapi_data->mutex)); return -EINVAL; } /* clean up any mess left behind by the module */ for (n = 1; n <= RTAPI_MAX_SHMEMS; n++) { if (test_bit(module_id, shmem_array[n].bitmap)) { fprintf(stderr, "ULAPI: WARNING: module '%s' failed to delete shmem %02d\n", module->name, n); shmem_delete(n, module_id); } } for (n = 1; n <= RTAPI_MAX_FIFOS; n++) { if ((fifo_array[n].reader == module_id) || (fifo_array[n].writer == module_id)) { fprintf(stderr, "ULAPI: WARNING: module '%s' failed to delete fifo %02d\n", module->name, n); fifo_delete(n, module_id); } } /* update module data */ rtapi_print_msg(RTAPI_MSG_DBG, "RTAPI: module %02d exited, name = '%s'\n", module_id, module->name); module->state = NO_MODULE; module->name[0] = '\0'; rtapi_data->ul_module_count--; rtapi_mutex_give(&(rtapi_data->mutex)); nummods--; if(nummods == 0) { rtai_free(RTAPI_KEY, rtapi_data); rtapi_data = 0; } return 0; }
int hal_set_constructor(int comp_id, constructor make) { int next; hal_comp_t *comp __attribute__((cleanup(halpr_autorelease_mutex))); rtapi_mutex_get(&(hal_data->mutex)); /* search component list for 'comp_id' */ next = hal_data->comp_list_ptr; if (next == 0) { /* list is empty - should never happen, but... */ hal_print_msg(RTAPI_MSG_ERR, "HAL: ERROR: component %d not found\n", comp_id); return -EINVAL; } comp = SHMPTR(next); while (comp->comp_id != comp_id) { /* not a match, try the next one */ next = comp->next_ptr; if (next == 0) { /* reached end of list without finding component */ hal_print_msg(RTAPI_MSG_ERR, "HAL: ERROR: component %d not found\n", comp_id); return -EINVAL; } comp = SHMPTR(next); } comp->make = make; 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_ready(int comp_id) { int next; hal_comp_t *comp __attribute__((cleanup(halpr_autorelease_mutex))); rtapi_mutex_get(&(hal_data->mutex)); /* search component list for 'comp_id' */ next = hal_data->comp_list_ptr; if (next == 0) { /* list is empty - should never happen, but... */ HALERR("BUG: no components defined - %d", comp_id); return -EINVAL; } comp = SHMPTR(next); while (comp->comp_id != comp_id) { /* not a match, try the next one */ next = comp->next_ptr; if (next == 0) { /* reached end of list without finding component */ HALERR("component %d not found", comp_id); return -EINVAL; } comp = SHMPTR(next); } if(comp->state > COMP_INITIALIZING) { HALERR("component '%s' id %d already ready (state %d)", comp->name, comp->comp_id, comp->state); return -EINVAL; } comp->state = (comp->type == TYPE_REMOTE ? COMP_UNBOUND : COMP_READY); return 0; }
int hal_ring_detach(const char *name, ringbuffer_t *rbptr) { CHECK_HALDATA(); CHECK_STRLEN(name, HAL_NAME_LEN); CHECK_LOCK(HAL_LOCK_CONFIG); if ((rbptr == NULL) || (rbptr->magic != RINGBUFFER_MAGIC)) { HALERR("ring '%s': invalid ringbuffer", name); return -EINVAL; } // no mutex(es) held up to here { int retval __attribute__((cleanup(halpr_autorelease_mutex))); rtapi_mutex_get(&(hal_data->mutex)); ringheader_t *rhptr = rbptr->header; rhptr->refcount--; rbptr->magic = 0; // invalidate FIXME // unlocking happens automatically on scope exit } return 0; }
int hal_del_funct_from_thread(const char *funct_name, const char *thread_name) { hal_funct_t *funct; hal_list_t *list_root, *list_entry; hal_funct_entry_t *funct_entry; CHECK_HALDATA(); CHECK_LOCK(HAL_LOCK_CONFIG); CHECK_STR(funct_name); CHECK_STR(thread_name); HALDBG("removing function '%s' from thread '%s'", funct_name, thread_name); { hal_thread_t *thread __attribute__((cleanup(halpr_autorelease_mutex))); /* get mutex before accessing data structures */ rtapi_mutex_get(&(hal_data->mutex)); /* search function list for the function */ funct = halpr_find_funct_by_name(funct_name); if (funct == 0) { HALERR("function '%s' not found", funct_name); return -EINVAL; } /* found the function, is it in use? */ if (funct->users == 0) { HALERR("function '%s' is not in use", funct_name); return -EINVAL; } /* search thread list for thread_name */ thread = halpr_find_thread_by_name(thread_name); if (thread == 0) { /* thread not found */ HALERR("thread '%s' not found", thread_name); return -EINVAL; } /* ok, we have thread and function, does thread use funct? */ list_root = &(thread->funct_list); list_entry = list_next(list_root); while (1) { if (list_entry == list_root) { /* reached end of list, funct not found */ HALERR("thread '%s' doesn't use %s", thread_name, funct_name); return -EINVAL; } funct_entry = (hal_funct_entry_t *) list_entry; if (SHMPTR(funct_entry->funct_ptr) == funct) { /* this funct entry points to our funct, unlink */ list_remove_entry(list_entry); /* and delete it */ free_funct_entry_struct(funct_entry); /* done */ return 0; } /* try next one */ list_entry = list_next(list_entry); } } }
int _rtapi_task_delete(int task_id) { task_data *task; int retval = 0; if(task_id < 0 || task_id >= RTAPI_MAX_TASKS) return -EINVAL; task = &(task_array[task_id]); /* validate task handle */ if (task->magic != TASK_MAGIC) // nothing to delete return -EINVAL; if (task->state != DELETE_LOCKED) // we don't already hold mutex rtapi_mutex_get(&(rtapi_data->mutex)); #ifdef MODULE if ((task->state == PERIODIC) || (task->state == FREERUN)) { /* task is running, need to stop it */ rtapi_print_msg(RTAPI_MSG_WARN, "RTAPI: WARNING: tried to delete task %02d while running\n", task_id); _rtapi_task_pause(task_id); } /* get rid of it */ rt_task_delete(ostask_array[task_id]); /* free kernel memory */ kfree(ostask_array[task_id]); /* update data */ task->prio = 0; task->owner = 0; task->taskcode = NULL; ostask_array[task_id] = NULL; rtapi_data->task_count--; /* if no more tasks, stop the timer */ if (rtapi_data->task_count == 0) { if (rtapi_data->timer_running != 0) { # ifdef HAVE_RTAPI_MODULE_TIMER_STOP _rtapi_module_timer_stop(); # endif rtapi_data->timer_period = 0; max_delay = DEFAULT_MAX_DELAY; rtapi_data->timer_running = 0; } } #endif /* MODULE */ #ifdef HAVE_RTAPI_TASK_DELETE_HOOK retval = _rtapi_task_delete_hook(task,task_id); #endif if (task->state != DELETE_LOCKED) // we don't already hold mutex rtapi_mutex_give(&(rtapi_data->mutex)); task->state = EMPTY; task->magic = 0; rtapi_print_msg(RTAPI_MSG_DBG, "rt_task_delete %d \"%s\"\n", task_id, task->name ); return retval; }
// hal mutex scope-locked version of halpr_find_pin_by_name() hal_pin_t * hal_find_pin_by_name(const char *name) { hal_pin_t *p __attribute__((cleanup(halpr_autorelease_mutex))); rtapi_mutex_get(&(hal_data->mutex)); p = halpr_find_pin_by_name(name); return p; }
int _rtapi_exit(int module_id) { int retval; rtapi_mutex_get(&(rtapi_data->mutex)); retval = module_delete(module_id); rtapi_mutex_give(&(rtapi_data->mutex)); return retval; }
int rtapi_fifo_delete(int fifo_id, int module_id) { int retval; rtapi_mutex_get(&(rtapi_data->mutex)); retval = fifo_delete(fifo_id, module_id); rtapi_mutex_give(&(rtapi_data->mutex)); return retval; }
int rtapi_shmem_delete(int shmem_id, int module_id) { int retval; rtapi_mutex_get(&(rtapi_data->mutex)); retval = shmem_delete(shmem_id, module_id); rtapi_mutex_give(&(rtapi_data->mutex)); return retval; }
char *hal_comp_name(int comp_id) { hal_comp_t *comp; char *result = NULL; rtapi_mutex_get(&(hal_data->mutex)); comp = halpr_find_comp_by_id(comp_id); if(comp) result = comp->name; rtapi_mutex_give(&(hal_data->mutex)); return result; }
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_call_usrfunct(const char *name, const int argc, const char **argv, int *ureturn) { hal_funct_t *funct; CHECK_HALDATA(); CHECK_STR(name); if (argc && (argv == NULL)) { HALERR("funct '%s': argc=%d but argv is NULL", name, argc); return -EINVAL; } { int i __attribute__((cleanup(halpr_autorelease_mutex))); rtapi_mutex_get(&(hal_data->mutex)); funct = halpr_find_funct_by_name(name); if (funct == NULL) { HALERR("funct '%s' not found", name); return -ENOENT; } if (funct->type != FS_USERLAND) { HALERR("funct '%s': invalid type %d", name, funct->type); return -ENOENT; } // argv sanity check - we dont want to fail this, esp in kernel land for (i = 0; i < argc; i++) { if (argv[i] == NULL) { HALERR("funct '%s': argc=%d but argv[%d] is NULL", name, i, i); return -EINVAL; } } } // call the function with rtapi_mutex unlocked long long int now = rtapi_get_clocks(); hal_funct_args_t fa = { .thread_start_time = now, .start_time = now, .thread = NULL, .funct = funct, .argc = argc, .argv = argv, }; int retval = funct->funct.u(&fa); if (ureturn) *ureturn = retval; return 0; }
int _rtapi_exit(int module_id) { module_data *module; int n; if (rtapi_data == NULL) { rtapi_print_msg(RTAPI_MSG_ERR, "RTAPI:%d ERROR: exit called before init\n", rtapi_instance); return -EINVAL; } rtapi_print_msg(RTAPI_MSG_DBG, "RTAPI:%d module %02d exiting\n", rtapi_instance,module_id); /* validate module ID */ if ((module_id < 1) || (module_id > RTAPI_MAX_MODULES)) { rtapi_print_msg(RTAPI_MSG_ERR, "RTAPI:%d ERROR: bad module id\n", rtapi_instance); return -EINVAL; } /* get mutex */ rtapi_mutex_get(&(rtapi_data->mutex)); /* point to the module's data */ module = &(module_array[module_id]); /* check module status */ if (module->state != USERSPACE) { rtapi_print_msg(RTAPI_MSG_ERR, "RTAPI:%d ERROR: not a userspace module\n", rtapi_instance); rtapi_mutex_give(&(rtapi_data->mutex)); return -EINVAL; } /* clean up any mess left behind by the module */ for (n = 1; n <= RTAPI_MAX_SHMEMS; n++) { if (rtapi_test_bit(module_id, shmem_array[n].bitmap)) { rtapi_print_msg(RTAPI_MSG_WARN, "ULAPI:%d WARNING: module '%s' failed to delete " "shmem %02d\n", rtapi_instance,module->name, n); // mark block as ready for delete, lock already held shmem_array[n].magic = SHMEM_MAGIC_DEL_LOCKED; _rtapi_shmem_delete(n, module_id); } } /* update module data */ rtapi_print_msg(RTAPI_MSG_DBG, "RTAPI:%d module %02d exited, name = '%s'\n", rtapi_instance, module_id, module->name); module->state = NO_MODULE; module->name[0] = '\0'; rtapi_data->ul_module_count--; rtapi_mutex_give(&(rtapi_data->mutex)); return 0; }
int _rtapi_exit(int module_id) { module_id -= MODULE_OFFSET; if (module_id < 0 || module_id >= RTAPI_MAX_MODULES) return -1; /* Remove the module from the module_array. */ rtapi_mutex_get(&(rtapi_data->mutex)); module_array[module_id].state = NO_MODULE; rtapi_print_msg(RTAPI_MSG_DBG, "rtapi_exit: freed module slot %d, was %s\n", module_id, module_array[module_id].name); rtapi_mutex_give(&(rtapi_data->mutex)); return 0; }
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; } }
void rtapi_app_exit(void) { int retval; hal_print_msg(RTAPI_MSG_DBG, "HAL_LIB:%d removing RT support\n",rtapi_instance); hal_proc_clean(); { hal_thread_t *thread __attribute__((cleanup(halpr_autorelease_mutex))); /* grab mutex before manipulating list */ rtapi_mutex_get(&(hal_data->mutex)); /* must remove all threads before unloading this module */ while (hal_data->thread_list_ptr != 0) { /* point to a thread */ thread = SHMPTR(hal_data->thread_list_ptr); /* unlink from list */ hal_data->thread_list_ptr = thread->next_ptr; /* and delete it */ free_thread_struct(thread); } } /* release RTAPI resources */ retval = rtapi_shmem_delete(lib_mem_id, lib_module_id); if (retval) { hal_print_msg(RTAPI_MSG_ERR, "HAL_LIB:%d rtapi_shmem_delete(%d,%d) failed: %d\n", rtapi_instance, lib_mem_id, lib_module_id, retval); } retval = rtapi_exit(lib_module_id); if (retval) { hal_print_msg(RTAPI_MSG_ERR, "HAL_LIB:%d rtapi_exit(%d) failed: %d\n", rtapi_instance, lib_module_id, retval); } /* done */ hal_print_msg(RTAPI_MSG_DBG, "HAL_LIB:%d RT support removed successfully\n", rtapi_instance); }
int hal_inst_delete(const char *name) { CHECK_HALDATA(); CHECK_STR(name); { hal_inst_t *inst __attribute__((cleanup(halpr_autorelease_mutex))); rtapi_mutex_get(&(hal_data->mutex)); // inst must exist if ((inst = halpr_find_inst_by_name(name)) == NULL) { HALERR("instance '%s' does not exist", name); return -ENOENT; } // this does most of the heavy lifting free_inst_struct(inst); } return 0; }
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; }
// part of public API void *hal_malloc(long int size) { void *retval; if (hal_data == 0) { HALERR("hal_malloc called before init"); return 0; } /* get the mutex */ rtapi_mutex_get(&(hal_data->mutex)); /* allocate memory */ retval = shmalloc_up(size); /* release the mutex */ rtapi_mutex_give(&(hal_data->mutex)); /* check return value */ if (retval == 0) { HALDBG("hal_malloc() can't allocate %ld bytes", size); } return retval; }
int _rtapi_shmem_delete_inst(int handle, int instance, int module_id) { shmem_data *shmem; int retval = 0; if(handle < 1 || handle >= RTAPI_MAX_SHMEMS) return -EINVAL; rtapi_mutex_get(&(rtapi_data->mutex)); shmem = &shmem_array[handle]; /* validate shmem handle */ if (shmem->magic != SHMEM_MAGIC) { rtapi_mutex_give(&(rtapi_data->mutex)); return -EINVAL; } shmem->count --; if(shmem->count) { rtapi_mutex_give(&(rtapi_data->mutex)); rtapi_print_msg(RTAPI_MSG_DBG, "rtapi_shmem_delete: handle=%d module=%d key=0x%x: " "%d remaining users\n", handle, module_id, shmem->key, shmem->count); return 0; } retval = shm_common_detach(shmem->size, shmem->mem); if (retval < 0) { rtapi_print_msg(RTAPI_MSG_ERR, "RTAPI:%d ERROR: munmap(0x%8.8x) failed: %s\n", instance, shmem->key, strerror(-retval)); } // XXX: probably shmem->mem should be set to NULL here to avoid // references to already unmapped segments (and find them early) /* free the shmem structure */ shmem->magic = 0; rtapi_mutex_give(&(rtapi_data->mutex)); return retval; }
int _rtapi_init(const char *modname) { int n, module_id = -ENOMEM; module_data *module; /* say hello */ rtapi_print_msg(RTAPI_MSG_DBG, "RTAPI: initing module %s\n", modname); /* get the mutex */ rtapi_mutex_get(&(rtapi_data->mutex)); /* find empty spot in module array */ n = 1; while ((n <= RTAPI_MAX_MODULES) && (module_array[n].state != NO_MODULE)) { n++; } if (n > RTAPI_MAX_MODULES) { /* no room */ rtapi_mutex_give(&(rtapi_data->mutex)); rtapi_print_msg(RTAPI_MSG_ERR, "RTAPI: ERROR: reached module limit %d\n", n); return -EMFILE; } /* we have space for the module */ module_id = n + MODULE_OFFSET; module = &(module_array[n]); /* update module data */ module->state = REALTIME; if (modname != NULL) { /* use name supplied by caller, truncating if needed */ rtapi_snprintf(module->name, RTAPI_NAME_LEN, "%s", modname); } else { /* make up a name */ rtapi_snprintf(module->name, RTAPI_NAME_LEN, "ULMOD%03d", module_id); } rtapi_data->ul_module_count++; rtapi_print_msg(RTAPI_MSG_DBG, "RTAPI: module '%s' loaded, ID: %d\n", module->name, module_id); rtapi_mutex_give(&(rtapi_data->mutex)); return module_id; }
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; } }
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 _rtapi_task_new(const rtapi_task_args_t *args) { int task_id; int __attribute__((__unused__)) retval = 0; task_data *task; /* get the mutex */ rtapi_mutex_get(&(rtapi_data->mutex)); #ifdef MODULE /* validate owner */ if ((args->owner < 1) || (args->owner > RTAPI_MAX_MODULES)) { rtapi_mutex_give(&(rtapi_data->mutex)); return -EINVAL; } if (module_array[args->owner].state != REALTIME) { rtapi_mutex_give(&(rtapi_data->mutex)); return -EINVAL; } if ((args->flags & (TF_NONRT|TF_NOWAIT)) != 0) { rtapi_print_msg(RTAPI_MSG_ERR, "task '%s' : nowait/posix flags not supported with kthreads\n", args->name); rtapi_mutex_give(&(rtapi_data->mutex)); return -EINVAL; } #endif /* find an empty entry in the task array */ task_id = 1; // tasks start at one! // go through task_array until an empty task slot is found while ((task_id < RTAPI_MAX_TASKS) && (task_array[task_id].magic == TASK_MAGIC)) task_id++; // if task_array is full, release lock and return error if (task_id == RTAPI_MAX_TASKS) { rtapi_mutex_give(&(rtapi_data->mutex)); return -ENOMEM; } task = &(task_array[task_id]); // if requested priority is invalid, release lock and return error if (PRIO_LT(args->prio,_rtapi_prio_lowest()) || PRIO_GT(args->prio,_rtapi_prio_highest())) { rtapi_print_msg(RTAPI_MSG_ERR, "New task %d '%s:%d': invalid priority %d " "(highest=%d lowest=%d)\n", task_id, args->name, rtapi_instance, args->prio, _rtapi_prio_highest(), _rtapi_prio_lowest()); rtapi_mutex_give(&(rtapi_data->mutex)); return -EINVAL; } if ((args->flags & (TF_NOWAIT|TF_NONRT)) == TF_NOWAIT) { rtapi_print_msg(RTAPI_MSG_ERR,"task '%s' : nowait flag invalid for RT thread\n", args->name); rtapi_mutex_give(&(rtapi_data->mutex)); return -EINVAL; } // task slot found; reserve it and release lock rtapi_print_msg(RTAPI_MSG_DBG, "Creating new task %d '%s:%d': " "req prio %d (highest=%d lowest=%d) stack=%lu fp=%d flags=%d\n", task_id, args->name, rtapi_instance, args->prio, _rtapi_prio_highest(), _rtapi_prio_lowest(), args->stacksize, args->uses_fp, args->flags); task->magic = TASK_MAGIC; /* fill out task structure */ task->owner = args->owner; task->arg = args->arg; task->stacksize = (args->stacksize < MIN_STACKSIZE) ? MIN_STACKSIZE : args->stacksize; task->taskcode = args->taskcode; task->prio = args->prio; task->flags = args->flags; task->uses_fp = args->uses_fp; task->cpu = args->cpu_id > -1 ? args->cpu_id : rtapi_data->rt_cpu; rtapi_print_msg(RTAPI_MSG_DBG, "Task CPU: %d\n", task->cpu); rtapi_snprintf(task->name, sizeof(task->name), "%s:%d", args->name, rtapi_instance); task->name[sizeof(task->name) - 1] = '\0'; #ifdef MODULE /* get space for the OS's task data - this is around 900 bytes, */ /* so we don't want to statically allocate it for unused tasks. */ ostask_array[task_id] = kmalloc(sizeof(RT_TASK), GFP_USER); if (ostask_array[task_id] == NULL) { rtapi_mutex_give(&(rtapi_data->mutex)); return -ENOMEM; } #ifdef HAVE_RTAPI_TASK_NEW_HOOK /* kernel threads: rtapi_task_new_hook() should call OS to initialize the task - use predetermined or explicitly assigned CPU */ retval = _rtapi_task_new_hook(task, task_id); if (retval) { rtapi_print_msg(RTAPI_MSG_ERR, "rt_task_create failed, rc = %d\n", retval ); /* couldn't create task, free task data memory */ kfree(ostask_array[task_id]); rtapi_mutex_give(&(rtapi_data->mutex)); if (retval == ENOMEM) { /* not enough space for stack */ return -ENOMEM; } /* unknown error */ return -EINVAL; } #endif /* the task has been created, update data */ task->state = PAUSED; retval = task_id; #else /* userland thread */ /* userland threads: rtapi_task_new_hook() should perform any thread system-specific tasks, and return task_id or an error code back to the caller (how do we know the diff between an error and a task_id???). */ task->state = USERLAND; // userland threads don't track this # ifdef HAVE_RTAPI_TASK_NEW_HOOK retval = _rtapi_task_new_hook(task,task_id); # else retval = task_id; # endif #endif /* userland thread */ rtapi_data->task_count++; rtapi_mutex_give(&(rtapi_data->mutex)); /* announce the birth of a brand new baby task */ rtapi_print_msg(RTAPI_MSG_DBG, "RTAPI: task %02d installed by module %02d, priority %d, code: %p\n", task_id, task->owner, task->prio, args->taskcode); return task_id; }
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; }
static gboolean dialog_select_source(int chan_num) { scope_vert_t *vert; scope_chan_t *chan; dialog_generic_t dialog; gchar *title, msg[BUFLEN]; int next, n, initial_page, row, initial_row, max_row; gchar *tab_label_text[3], *name; GtkWidget *hbox, *label, *notebk, *button; GtkAdjustment *adj; hal_pin_t *pin; hal_sig_t *sig; hal_param_t *param; vert = &(ctrl_usr->vert); chan = &(ctrl_usr->chan[chan_num - 1]); title = _("Select Channel Source"); snprintf(msg, BUFLEN - 1, _("Select a pin, signal, or parameter\n" "as the source for channel %d."), chan_num); /* create dialog window, disable resizing */ dialog.retval = 0; dialog.window = gtk_dialog_new(); dialog.app_data = &chan_num; /* set initial height of window */ gtk_widget_set_usize(GTK_WIDGET(dialog.window), -2, 300); /* allow user to grow but not shrink the window */ gtk_window_set_policy(GTK_WINDOW(dialog.window), FALSE, TRUE, FALSE); /* window should appear in center of screen */ gtk_window_set_position(GTK_WINDOW(dialog.window), GTK_WIN_POS_CENTER); /* set title */ gtk_window_set_title(GTK_WINDOW(dialog.window), title); /* display message */ label = gtk_label_new(msg); gtk_misc_set_padding(GTK_MISC(label), 15, 5); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog.window)->vbox), label, FALSE, TRUE, 0); /* a separator */ gtk_hseparator_new_in_box(GTK_DIALOG(dialog.window)->vbox, 0); /* create a notebook to hold pin, signal, and parameter lists */ notebk = gtk_notebook_new(); /* add the notebook to the dialog */ gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog.window)->vbox), notebk, TRUE, TRUE, 0); /* set overall notebook parameters */ gtk_notebook_set_homogeneous_tabs(GTK_NOTEBOOK(notebk), TRUE); gtk_signal_connect(GTK_OBJECT(notebk), "switch-page", GTK_SIGNAL_FUNC(change_page), &dialog); /* text for tab labels */ tab_label_text[0] = _("Pins"); tab_label_text[1] = _("Signals"); tab_label_text[2] = _("Parameters"); /* loop to create three identical tabs */ for (n = 0; n < 3; n++) { /* Create a scrolled window to display the list */ vert->windows[n] = gtk_scrolled_window_new(NULL, NULL); vert->adjs[n] = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(vert->windows[n])); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(vert->windows[n]), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS); gtk_widget_show(vert->windows[n]); /* create a list to hold the data */ vert->lists[n] = gtk_clist_new(1); /* set up a callback for when the user selects a line */ gtk_signal_connect(GTK_OBJECT(vert->lists[n]), "select_row", GTK_SIGNAL_FUNC(selection_made), &dialog); gtk_signal_connect(GTK_OBJECT(vert->lists[n]), "key-press-event", GTK_SIGNAL_FUNC(search_for_entry), &dialog); /* It isn't necessary to shadow the border, but it looks nice :) */ gtk_clist_set_shadow_type(GTK_CLIST(vert->lists[n]), GTK_SHADOW_OUT); /* set list for single selection only */ gtk_clist_set_selection_mode(GTK_CLIST(vert->lists[n]), GTK_SELECTION_BROWSE); /* put the list into the scrolled window */ gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW (vert->windows[n]), vert->lists[n]); /* another way to do it - not sure which is better gtk_container_add(GTK_CONTAINER(vert->windows[n]), vert->lists[n]); */ gtk_widget_show(vert->lists[n]); /* create a box for the tab label */ hbox = gtk_hbox_new(TRUE, 0); /* create a label for the page */ gtk_label_new_in_box(tab_label_text[n], hbox, TRUE, TRUE, 0); gtk_widget_show(hbox); /* add page to the notebook */ gtk_notebook_append_page(GTK_NOTEBOOK(notebk), vert->windows[n], hbox); /* set tab attributes */ gtk_notebook_set_tab_label_packing(GTK_NOTEBOOK(notebk), hbox, TRUE, TRUE, GTK_PACK_START); } /* determine initial page: pin, signal, or parameter */ if (( chan->data_source_type >= 0 ) && ( chan->data_source_type <= 2 )) { initial_page = chan->data_source_type; gtk_notebook_set_page(GTK_NOTEBOOK(notebk), initial_page); } else { initial_page = -1; gtk_notebook_set_page(GTK_NOTEBOOK(notebk), 0); } gtk_widget_show(notebk); /* populate the pin, signal, and parameter lists */ gtk_clist_clear(GTK_CLIST(vert->lists[0])); gtk_clist_clear(GTK_CLIST(vert->lists[1])); gtk_clist_clear(GTK_CLIST(vert->lists[2])); rtapi_mutex_get(&(hal_data->mutex)); next = hal_data->pin_list_ptr; initial_row = -1; max_row = -1; while (next != 0) { pin = SHMPTR(next); name = pin->name; row = gtk_clist_append(GTK_CLIST(vert->lists[0]), &name); if ( initial_page == 0 ) { if ( strcmp(name, chan->name) == 0 ) { initial_row = row; } max_row = row; } next = pin->next_ptr; } next = hal_data->sig_list_ptr; while (next != 0) { sig = SHMPTR(next); name = sig->name; row = gtk_clist_append(GTK_CLIST(vert->lists[1]), &name); if ( initial_page == 1 ) { if ( strcmp(name, chan->name) == 0 ) { initial_row = row; } max_row = row; } next = sig->next_ptr; } next = hal_data->param_list_ptr; while (next != 0) { param = SHMPTR(next); name = param->name; row = gtk_clist_append(GTK_CLIST(vert->lists[2]), &name); if ( initial_page == 2 ) { if ( strcmp(name, chan->name) == 0 ) { initial_row = row; } max_row = row; } next = param->next_ptr; } rtapi_mutex_give(&(hal_data->mutex)); if ( initial_row >= 0 ) { /* highlight the currently selected name */ gtk_clist_select_row(GTK_CLIST(vert->lists[initial_page]), initial_row, -1); /* set scrolling window to show the highlighted name */ /* FIXME - I can't seem to get this to work */ adj = vert->adjs[initial_page]; adj->value = adj->lower + (adj->upper - adj->lower)*((double)(initial_row)/(double)(max_row+1)); gtk_adjustment_value_changed(vert->adjs[initial_page]); } /* set up a callback function when the window is destroyed */ gtk_signal_connect(GTK_OBJECT(dialog.window), "destroy", GTK_SIGNAL_FUNC(dialog_generic_destroyed), &dialog); /* make Cancel button */ button = gtk_button_new_with_label(_("Cancel")); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog.window)->action_area), button, TRUE, TRUE, 4); gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(dialog_generic_button2), &dialog); /* make window transient and modal */ gtk_window_set_transient_for(GTK_WINDOW(dialog.window), GTK_WINDOW(ctrl_usr->main_win)); gtk_window_set_modal(GTK_WINDOW(dialog.window), TRUE); gtk_widget_show_all(dialog.window); gtk_main(); /* we get here when the user makes a selection, hits Cancel, or closes the window */ vert->lists[0] = NULL; vert->lists[1] = NULL; vert->lists[2] = NULL; if ((dialog.retval == 0) || (dialog.retval == 2)) { /* user either closed dialog, or hit cancel */ return FALSE; } /* user made a selection */ channel_changed(); return TRUE; }