static int module_delete(int module_id) { module_data *module; char name[RTAPI_NAME_LEN + 1]; int n; rtapi_print_msg(RTAPI_MSG_DBG, "RTAPI:%d module %d exiting\n", rtapi_instance, module_id); /* validate module ID */ if ((module_id < 1) || (module_id > RTAPI_MAX_MODULES)) { return -EINVAL; } /* point to the module's data */ module = &(module_array[module_id]); /* check module status */ if (module->state != REALTIME) { /* not an active realtime module */ return -EINVAL; } /* clean up any mess left behind by the module */ for (n = 1; n <= RTAPI_MAX_TASKS; n++) { if ((task_array[n].state != EMPTY) && (task_array[n].owner == module_id)) { rtapi_print_msg(RTAPI_MSG_WARN, "RTAPI:%d WARNING: module '%s' failed to delete task %02d\n", rtapi_instance, module->name, n); task_array[n].state = DELETE_LOCKED; _rtapi_task_delete(n); } } for (n = 1; n <= RTAPI_MAX_SHMEMS; n++) { if (rtapi_test_bit(module_id, shmem_array[n].bitmap)) { rtapi_print_msg(RTAPI_MSG_WARN, "RTAPI:%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); } } rtapi_snprintf(name, RTAPI_NAME_LEN, "%s", module->name); /* update module data */ module->state = NO_MODULE; module->name[0] = '\0'; rtapi_data->rt_module_count--; if (rtapi_data->rt_module_count == 0) { if (rtapi_data->timer_running != 0) { #ifdef HAVE_RTAPI_MODULE_TIMER_STOP _rtapi_module_timer_stop(); #endif rtapi_data->timer_period = 0; timer_counts = 0; max_delay = DEFAULT_MAX_DELAY; rtapi_data->timer_running = 0; } } rtapi_print_msg(RTAPI_MSG_DBG, "RTAPI:%d module %d exited, name: '%s'\n", rtapi_instance, module_id, name); 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; }
/* This function is disabled everywhere... */ void _rtapi_printall(void) { module_data *modules; task_data *tasks; shmem_data *shmems; int n, m; if (rtapi_data == NULL) { rtapi_print_msg(RTAPI_MSG_DBG, "rtapi_data = NULL, not initialized\n"); return; } rtapi_print_msg(RTAPI_MSG_DBG, "rtapi_data = %p\n", rtapi_data); rtapi_print_msg(RTAPI_MSG_DBG, " magic = %d\n", rtapi_data->magic); rtapi_print_msg(RTAPI_MSG_DBG, " serial = %d\n", rtapi_data->serial); rtapi_print_msg(RTAPI_MSG_DBG, " thread_flavor id = %d\n", rtapi_data->thread_flavor_id); rtapi_print_msg(RTAPI_MSG_DBG, " mutex = %lu\n", rtapi_data->mutex); rtapi_print_msg(RTAPI_MSG_DBG, " rt_module_count = %d\n", rtapi_data->rt_module_count); rtapi_print_msg(RTAPI_MSG_DBG, " ul_module_count = %d\n", rtapi_data->ul_module_count); rtapi_print_msg(RTAPI_MSG_DBG, " task_count = %d\n", rtapi_data->task_count); rtapi_print_msg(RTAPI_MSG_DBG, " shmem_count = %d\n", rtapi_data->shmem_count); rtapi_print_msg(RTAPI_MSG_DBG, " timer_running = %d\n", rtapi_data->timer_running); rtapi_print_msg(RTAPI_MSG_DBG, " timer_period = %ld\n", rtapi_data->timer_period); modules = &(rtapi_data->module_array[0]); tasks = &(rtapi_data->task_array[0]); shmems = &(rtapi_data->shmem_array[0]); rtapi_print_msg(RTAPI_MSG_DBG, " module array = %p\n",modules); rtapi_print_msg(RTAPI_MSG_DBG, " task array = %p\n", tasks); rtapi_print_msg(RTAPI_MSG_DBG, " shmem array = %p\n", shmems); for (n = 0; n <= RTAPI_MAX_MODULES; n++) { if (modules[n].state != NO_MODULE) { rtapi_print_msg(RTAPI_MSG_DBG, " module %02d\n", n); rtapi_print_msg(RTAPI_MSG_DBG, " state = %d\n", modules[n].state); rtapi_print_msg(RTAPI_MSG_DBG, " name = %p\n", modules[n].name); rtapi_print_msg(RTAPI_MSG_DBG, " name = '%s'\n", modules[n].name); } } for (n = 0; n <= RTAPI_MAX_TASKS; n++) { if (tasks[n].state != EMPTY) { rtapi_print_msg(RTAPI_MSG_DBG, " task %02d\n", n); rtapi_print_msg(RTAPI_MSG_DBG, " state = %d\n", tasks[n].state); rtapi_print_msg(RTAPI_MSG_DBG, " prio = %d\n", tasks[n].prio); rtapi_print_msg(RTAPI_MSG_DBG, " owner = %d\n", tasks[n].owner); rtapi_print_msg(RTAPI_MSG_DBG, " code = %p\n", tasks[n].taskcode); } } for (n = 0; n <= RTAPI_MAX_SHMEMS; n++) { if (shmems[n].key != 0) { rtapi_print_msg(RTAPI_MSG_DBG, " shmem %02d\n", n); rtapi_print_msg(RTAPI_MSG_DBG, " key = %d\n", shmems[n].key); rtapi_print_msg(RTAPI_MSG_DBG, " rtusers = %d\n", shmems[n].rtusers); rtapi_print_msg(RTAPI_MSG_DBG, " ulusers = %d\n", shmems[n].ulusers); rtapi_print_msg(RTAPI_MSG_DBG, " size = %ld\n", shmems[n].size); rtapi_print_msg(RTAPI_MSG_DBG, " bitmap = "); for (m = 0; m <= RTAPI_MAX_MODULES; m++) { if (rtapi_test_bit(m, shmems[n].bitmap)) { putchar('1'); } else { putchar('0'); } } putchar('\n'); } } }
int _rtapi_shmem_delete_inst(int shmem_id, int instance, int module_id) { shmem_data *shmem; int manage_lock, retval; #ifdef RTAPI struct shm_status sm; #endif /* validate shmem ID */ if ((shmem_id < 1) || (shmem_id > RTAPI_MAX_SHMEMS)) { return -EINVAL; } /* point to the shmem's data */ shmem = &(shmem_array[shmem_id]); /* is the block valid? */ if (shmem->key == 0) { return -EINVAL; } /* validate module_id */ if ((module_id < 1) || (module_id > RTAPI_MAX_MODULES)) { return -EINVAL; } if (module_array[module_id].state != MODULE_STATE) { return -EINVAL; } /* is this module using the block? */ if (rtapi_test_bit(module_id, shmem->bitmap) == 0) { return -EINVAL; } /* check if we need to manage the mutex */ manage_lock = (shmem->magic != SHMEM_MAGIC_DEL_LOCKED); /* if no magic delete lock held is set, get the mutex */ if (manage_lock) rtapi_mutex_get(&(rtapi_data->mutex)); /* OK, we're no longer using it */ rtapi_clear_bit(module_id, shmem->bitmap); #ifdef ULAPI shmem->ulusers--; if ((shmem->ulusers == 0) && (shmem->rtusers == 0)) { // shmdrv can detach unused shared memory from userland too // this will munmap() the segment causing a drop in uattach refcount // and eventual free by garbage collect in shmdrv retval = shm_common_detach(shmem->size, shmem_addr_array[shmem_id]); if (retval) { rtapi_print_msg(RTAPI_MSG_ERR, "ULAPI:%d ERROR: shm_common_detach(%02d) failed: %s\n", rtapi_instance, shmem_id, strerror(-retval)); } } /* unmap the block */ shmem_addr_array[shmem_id] = NULL; #else /* RTAPI */ shmem->rtusers--; #endif /* RTAPI */ /* is somebody else still using the block? */ if ((shmem->ulusers > 0) || (shmem->rtusers > 0)) { /* yes, we're done for now */ rtapi_print_msg(RTAPI_MSG_DBG, "RTAPI: shmem %02d closed by module %02d\n", shmem_id, module_id); if (manage_lock) rtapi_mutex_give(&(rtapi_data->mutex)); return 0; } #ifdef RTAPI /* no other realtime users, free the shared memory from kernel space */ shmem_addr_array[shmem_id] = NULL; shmem->rtusers = 0; /* are any user processes using the block? */ if (shmem->ulusers > 0) { /* yes, we're done for now */ rtapi_print_msg(RTAPI_MSG_DBG, "RTAPI: shmem %02d unmapped by module %02d\n", shmem_id, module_id); if (manage_lock) rtapi_mutex_give(&(rtapi_data->mutex)); return 0; } /* no other users at all, this ID is now free */ sm.key = shmem->key; sm.size = shmem->size; sm.flags = 0; if ((retval = shmdrv_detach(&sm)) < 0) { rtapi_print_msg(RTAPI_MSG_ERR, "RTAPI:%d ERROR: shmdrv_detach(%x,%d) fail: %d\n", rtapi_instance, sm.key, sm.size, retval); } #endif /* RTAPI */ /* update the data array and usage count */ shmem->key = 0; shmem->size = 0; rtapi_data->shmem_count--; /* release the lock if needed, print a debug message and return */ if (manage_lock) rtapi_mutex_give(&(rtapi_data->mutex)); rtapi_print_msg(RTAPI_MSG_DBG, "RTAPI: shmem %02d freed by module %02d\n", shmem_id, module_id); return 0; }
int _rtapi_shmem_new_inst(int userkey, int instance, int module_id, unsigned long int size) { int n, retval; int shmem_id; shmem_data *shmem; struct shm_status sm; int key = OS_KEY(userkey, instance); /* key must be non-zero, and also cannot match the key that RTAPI uses */ if ((key == 0) || (key == OS_KEY(RTAPI_KEY, instance))) { rtapi_print_msg(RTAPI_MSG_ERR, "RTAPI: ERROR: bad shmem key: %d\n", key); return -EINVAL; } /* get the mutex */ rtapi_mutex_get(&(rtapi_data->mutex)); /* validate module_id */ if ((module_id < 1) || (module_id > RTAPI_MAX_MODULES)) { rtapi_mutex_give(&(rtapi_data->mutex)); rtapi_print_msg(RTAPI_MSG_ERR, "RTAPI: ERROR: bad module ID: %d\n", module_id); return -EINVAL; } if (module_array[module_id].state != MODULE_STATE) { rtapi_print_msg(RTAPI_MSG_ERR, "RTAPI: ERROR: not a " OUR_API " module ID: %d\n", module_id); rtapi_mutex_give(&(rtapi_data->mutex)); return -EINVAL; } /* check if a block is already open for this key */ for (n = 1; n <= RTAPI_MAX_SHMEMS; n++) { if (shmem_array[n].key == key) { /* found a match */ shmem_id = n; shmem = &(shmem_array[n]); /* is it big enough? */ if (shmem->size < size) { rtapi_mutex_give(&(rtapi_data->mutex)); rtapi_print_msg(RTAPI_MSG_ERR, "RTAPI: ERROR: shmem size mismatch\n"); return -EINVAL; } /* is this module already using it? */ if (rtapi_test_bit(module_id, shmem->bitmap)) { rtapi_mutex_give(&(rtapi_data->mutex)); rtapi_print_msg(RTAPI_MSG_WARN, "RTAPI: Warning: shmem already mapped\n"); return -EEXIST; } /* yes, has it been mapped into kernel space? */ #ifdef RTAPI if (shmem->rtusers == 0) { #endif /* no, map it and save the address */ sm.key = key; sm.size = size; sm.flags = 0; #ifdef ULAPI sm.driver_fd = shmdrv_driver_fd(); #endif retval = shmdrv_attach(&sm, &shmem_addr_array[shmem_id]); if (retval < 0) { rtapi_mutex_give(&(rtapi_data->mutex)); rtapi_print_msg(RTAPI_MSG_ERR, "shmdrv attached failed key=0x%x size=%ld\n", key, size); return retval; } if (shmem_addr_array[shmem_id] == NULL) { rtapi_print_msg(RTAPI_MSG_ERR, "RTAPI: ERROR: failed to map shmem\n"); rtapi_mutex_give(&(rtapi_data->mutex)); #ifdef ULAPI check_memlock_limit("failed to map shmem"); #endif return -ENOMEM; } #ifdef RTAPI } #endif /* update usage data */ rtapi_set_bit(module_id, shmem->bitmap); #ifdef ULAPI shmem->ulusers++; #else /* RTAPI */ shmem->rtusers++; #endif /* RTAPI */ /* announce another user for this shmem */ rtapi_print_msg(RTAPI_MSG_DBG, "RTAPI: shmem %02d opened by module %02d\n", shmem_id, module_id); /* done */ rtapi_mutex_give(&(rtapi_data->mutex)); return shmem_id; } } /* find empty spot in shmem array */ n = 1; while ((n <= RTAPI_MAX_SHMEMS) && (shmem_array[n].key != 0)) { rtapi_print_msg(RTAPI_MSG_DBG, OUR_API ": shmem %d occupuied \n",n); n++; } if (n > RTAPI_MAX_SHMEMS) { /* no room */ rtapi_mutex_give(&(rtapi_data->mutex)); rtapi_print_msg(RTAPI_MSG_ERR, "RTAPI: ERROR: reached shmem limit %d\n", n); return -EMFILE; } /* we have space for the block data */ rtapi_print_msg(RTAPI_MSG_DBG, OUR_API ": using new shmem %d \n",n); shmem_id = n; shmem = &(shmem_array[n]); /* get shared memory block from OS and save its address */ sm.key = key; sm.size = size; sm.flags = 0; #ifdef ULAPI sm.driver_fd = shmdrv_driver_fd(); #endif retval = shmdrv_create(&sm); if (retval < 0) { rtapi_mutex_give(&(rtapi_data->mutex)); rtapi_print_msg(RTAPI_MSG_ERR,"shmdrv create failed key=0x%x size=%ld\n", key, size); return retval; } retval = shmdrv_attach(&sm, &shmem_addr_array[shmem_id]); if (retval < 0) { rtapi_mutex_give(&(rtapi_data->mutex)); rtapi_print_msg(RTAPI_MSG_ERR,"shmdrv attached failed key=0x%x size=%ld\n", key, size); return retval; } if (shmem_addr_array[shmem_id] == NULL) { rtapi_mutex_give(&(rtapi_data->mutex)); rtapi_print_msg(RTAPI_MSG_ERR, "RTAPI: ERROR: could not create shmem %d\n", n); return -ENOMEM; } /* the block has been created, update data */ rtapi_set_bit(module_id, shmem->bitmap); shmem->key = key; #ifdef RTAPI shmem->rtusers = 1; shmem->ulusers = 0; #else /* ULAPI */ shmem->rtusers = 0; shmem->ulusers = 1; #endif /* ULAPI */ shmem->size = size; shmem->magic = SHMEM_MAGIC; shmem->instance = instance; rtapi_data->shmem_count++; /* zero the first word of the shmem area */ *((long int *) (shmem_addr_array[shmem_id])) = 0; /* announce the birth of a brand new baby shmem */ rtapi_print_msg(RTAPI_MSG_DBG, "RTAPI: shmem %02d created by module %02d, key: %d, size: %lu\n", shmem_id, module_id, key, size); /* and return the ID to the proud parent */ rtapi_mutex_give(&(rtapi_data->mutex)); return shmem_id; }