示例#1
0
static void
cleanup_actions(void)
{
    int retval;

    if (global_data) {
	if (global_data->rtapi_app_pid > 0) {
	    kill(global_data->rtapi_app_pid, SIGTERM);
	    syslog_async(LOG_INFO,"sent SIGTERM to rtapi (pid %d)\n",
		   global_data->rtapi_app_pid);
	}
	// in case some process catches a leftover shm segment
	global_data->magic = GLOBAL_EXITED;
	global_data->rtapi_msgd_pid = 0;
	if (rtapi_msg_buffer.header != NULL)
	    rtapi_msg_buffer.header->refcount--;
	retval = shm_common_detach(sizeof(global_data_t), global_data);
	if (retval < 0) {
	    syslog_async(LOG_ERR,"shm_common_detach(global) failed: %s\n",
		   strerror(-retval));
	} else {
	    shm_common_unlink(OS_KEY(GLOBAL_KEY, rtapi_instance));
	    syslog_async(LOG_DEBUG,"normal shutdown - global segment detached");
	}
	global_data = NULL;
    }
}
示例#2
0
static int ulapi_load(rtapi_switch_t **ulapi_switch)
{
    int retval;
    const char *errmsg;
    rtapi_get_handle_t rtapi_get_handle;
    char ulapi_lib_fname[PATH_MAX];
    char *instance = getenv("INSTANCE");
    char *debug_env = getenv("ULAPI_DEBUG");
    int size = 0;
    int globalkey;

    // set the rtapi_instance global for this hal library instance
    if (instance != NULL)
	rtapi_instance = atoi(instance);

    if (debug_env)
	ulapi_debug = atoi(debug_env);

    rtapi_set_msg_level(ulapi_debug);

    // tag message origin field
    rtapi_set_logtag("ulapi");

    // first thing is to attach the global segment, based on
    // the RTAPI instance id. This will contain the flavor
    // this ULAPI HAL instance is to run with.

    // Also, it's the prerequisite for common error message
    // handling through the message ringbuffer; unless then
    // error messages will go to stderr.

    // the global segment is attached once here per ULAPI instance;
    // it's address is passed to the ulapi-<flavor>.so module once loaded.

    // init the common shared memory driver APU
    shm_common_init();

    globalkey = OS_KEY(GLOBAL_KEY, rtapi_instance);
    retval = shm_common_new(globalkey, &size,
			    rtapi_instance, (void **) &global_data, 0);

    if (retval == -ENOENT) {
	// the global_data segment does not exist. Happens if the realtime
	// script was not started
	rtapi_print_msg(RTAPI_MSG_ERR,
			"ULAPI:%d ERROR: realtime not started\n",
			rtapi_instance);
	return retval;
    }

    if (retval < 0) {
	// some other error attaching global
	rtapi_print_msg(RTAPI_MSG_ERR,
			"ULAPI:%d ERROR: shm_common_new() failed key=0x%x %s\n",
			rtapi_instance, globalkey, strerror(-retval));
	return retval;
    }

    if (size != sizeof(global_data_t)) {
	rtapi_print_msg(RTAPI_MSG_ERR,
			"ULAPI:%d ERROR: global segment size mismatch,"
			" expected: %zd, actual:%d\n",
		 rtapi_instance, sizeof(global_data_t), size);
	return -EINVAL;
    }

    if (global_data->magic != GLOBAL_READY) {
	rtapi_print_msg(RTAPI_MSG_ERR,
			"ULAPI:%d ERROR: global segment invalid magic:"
			" expected: 0x%x, actual: 0x%x\n",
			rtapi_instance, GLOBAL_READY,
			global_data->magic);
	return -EINVAL;
    }

    // global data set up ok

    // obtain handle on flavor descriptor as detected by rtapi_msgd
    flavor = flavor_byid(global_data->rtapi_thread_flavor);
    if (flavor == NULL) {
	rtapi_print_msg(RTAPI_MSG_ERR,
			"HAL_LIB:%d BUG - invalid flavor id: %d\n",
			rtapi_instance, global_data->rtapi_thread_flavor);
	return -EINVAL;
    }

    snprintf(ulapi_lib_fname,PATH_MAX,"%s/%s-%s%s",
	     EMC2_RTLIB_DIR, ulapi_lib, flavor->name, flavor->so_ext);

    // dynload the proper ulapi.so:
    if ((ulapi_so = dlopen(ulapi_lib_fname, RTLD_GLOBAL|RTLD_NOW))  == NULL) {
	errmsg = dlerror();
	rtapi_print_msg(RTAPI_MSG_ERR,
			"HAL_LIB:%d FATAL - dlopen(%s) failed: %s\n",
			rtapi_instance, ulapi_lib_fname,
			errmsg ? errmsg : "NULL");
	return -ENOENT;
    }

    // resolve rtapi_switch getter function
    dlerror();
    if ((rtapi_get_handle = (rtapi_get_handle_t)
	 dlsym(ulapi_so, "rtapi_get_handle")) == NULL) {
	errmsg = dlerror();
	rtapi_print_msg(RTAPI_MSG_ERR,
			"HAL_LIB:%d FATAL - resolving %s: cant"
			" dlsym(rtapi_get_handle): %s\n",
			rtapi_instance, ulapi_lib, errmsg ? errmsg : "NULL");
	return -ENOENT;
    }

    assert(rtapi_get_handle != NULL);

    // this redirects calls to rtapi through the just-loaded ulapi
    *ulapi_switch = rtapi_get_handle();

    // from here on it is safe to call all RTAPI functions (i.e. including those
    // which go through rtapi_switch)

    // resolve main function
    dlerror();
    if ((ulapi_main_ref = (ulapi_main_t)
	 dlsym(ulapi_so, "ulapi_main")) == NULL) {
	errmsg = dlerror();
	rtapi_print_msg(RTAPI_MSG_ERR,
			"HAL_LIB:%d FATAL - resolving %s: "
			"cant dlsym(ulapi_main): %s\n",
			rtapi_instance, ulapi_lib, errmsg ? errmsg : "NULL");
	return -ENOENT;
    }
    // resolve exit function
    dlerror();
    if ((ulapi_exit_ref = (ulapi_exit_t)
	 dlsym(ulapi_so, "ulapi_exit")) == NULL) {
	errmsg = dlerror();
	rtapi_print_msg(RTAPI_MSG_ERR,
			"HAL_LIB: FATAL - resolving %s:"
			" cant dlsym(ulapi_exit): %s\n",
		ulapi_lib, errmsg ? errmsg : "NULL");
	return -ENOENT;
    }

    assert(ulapi_main_ref != NULL);
    assert(ulapi_exit_ref != NULL);

    // call the ulapi init method, passing in the global segment
    if ((retval = ulapi_main_ref(rtapi_instance,
				 flavor->id, global_data)) < 0) {
	// check shmdrv, permissions
	rtapi_print_msg(RTAPI_MSG_ERR,
		"HAL_LIB: FATAL - cannot attach to instance %d"
			" - realtime not started?\n",
		rtapi_instance);
	return -ENOENT;
    }

    // pretty bad - we loaded the wrong ulapi.so
    if (flavor->id != rtapi_switch->thread_flavor_id) {
	rtapi_print_msg(RTAPI_MSG_ERR, "HAL_LIB: BUG: thread flavors disagree:"
			" hal_lib.c=%d rtapi=%d\n",
		flavor->id, rtapi_switch->thread_flavor_id);
    }

    // sanity check - may be harmless
    if (strcmp(GIT_VERSION, rtapi_switch->git_version)) {
	rtapi_print_msg(RTAPI_MSG_WARN,
			"HAL_LIB: UP API warning - git versions disagree:"
			" hal_lib.c=%s %s=%s\n",
			GIT_VERSION, ulapi_lib, rtapi_switch->git_version);
    }

    // declare victory
    return 0;
}
示例#3
0
static int create_global_segment()
{
    int retval = 0;

    int globalkey = OS_KEY(GLOBAL_KEY, rtapi_instance);
    int rtapikey = OS_KEY(RTAPI_KEY, rtapi_instance);
    int halkey = OS_KEY(HAL_KEY, rtapi_instance);

    int global_exists = shm_common_exists(globalkey);
    int hal_exists = shm_common_exists(halkey);
    int rtapi_exists = shm_common_exists(rtapikey);

    if (global_exists || rtapi_exists || hal_exists) {
	// hm, something is wrong here

	pid_t msgd_pid = pid_of("msgd:%d", rtapi_instance);

	if (rtapi_instance == kernel_instance_id()) {

	    // collision with a running kernel instance - not good.
	    int shmdrv_loaded = is_module_loaded("shmdrv");
	    int rtapi_loaded = is_module_loaded("rtapi");
	    int hal_loaded = is_module_loaded("hal_lib");

	    fprintf(stderr, "ERROR: found existing kernel "
		   "instance with the same instance id (%d)\n",
		   rtapi_instance);

	    fprintf(stderr,"kernel modules loaded: %s%s%s\n",
		   shmdrv_loaded ? "shmdrv " : "",
		   rtapi_loaded ? "rtapi " : "",
		   hal_loaded ? "hal_lib " : "");

	    if (msgd_pid > 0)
		fprintf(stderr,"the msgd process msgd:%d is "
		       "already running, pid: %d\n",
		       rtapi_instance, msgd_pid);
	    else
		fprintf(stderr,"msgd:%d not running!\n",
		       rtapi_instance);
	    return -EEXIST;
	}

	// running userthreads instance?
	pid_t app_pid = pid_of("rtapi:%d", rtapi_instance);

	if ((msgd_pid > -1) || (app_pid > -1)) {

	    fprintf(stderr, "ERROR: found existing user RT "
		   "instance with the same instance id (%d)\n",
		   rtapi_instance);
	    if (msgd_pid > 0)
		fprintf(stderr,"the msgd process msgd:%d is "
		       "already running, pid: %d\n",
		       rtapi_instance, msgd_pid);
	    else
		fprintf(stderr,"msgd:%d not running!\n",
		       rtapi_instance);

	    if (app_pid > 0)
		fprintf(stderr,"the RT process rtapi:%d is "
		       "already running, pid: %d\n",
		       rtapi_instance, app_pid);
	    else
		fprintf(stderr,"the RT process rtapi:%d not running!\n",
		       rtapi_instance);

	    // TBD: might check for other user HAL processes still
	    // around. This might work with fuser on the HAL segment
	    // but might be tricky wit shmdrv.

	    return -EEXIST;
	}

	// leftover shared memory segments were around, but no using
	// entities (user process or kernel modules).
	// Remove and keep going:
	if (shmdrv_loaded) {
	    // since neiter rtapi.ko nor hal_lib.ko is loaded
	    // cause a garbage collect in shmdrv
	    shmdrv_gc();
	} else {
	    // Posix shm case.
	    char segment_name[LINELEN];

	    if (hal_exists) {
		sprintf(segment_name, SHM_FMT, rtapi_instance, halkey);
		fprintf(stderr,"warning: removing unused HAL shm segment %s\n",
			segment_name);
		if (shm_unlink(segment_name))
		    perror(segment_name);
	    }
	    if (rtapi_exists) {
		sprintf(segment_name, SHM_FMT, rtapi_instance, rtapikey);
		fprintf(stderr,"warning: removing unused RTAPI"
			" shm segment %s\n",
			segment_name);
		if (shm_unlink(segment_name))
		    perror(segment_name);
	    }
	    if (global_exists) {
		sprintf(segment_name, SHM_FMT, rtapi_instance, globalkey);
		fprintf(stderr,"warning: removing unused global"
			" shm segment %s\n",
			segment_name);
		if (shm_unlink(segment_name))
		    perror(segment_name);
	    }
	}
    }

    // now try again:
    if (shm_common_exists(globalkey)) {
	fprintf(stderr,
		"MSGD:%d ERROR: found existing global segment key=0x%x\n",
		rtapi_instance, globalkey);

	return -EEXIST;
    }

    int size = sizeof(global_data_t);

    retval = shm_common_new(globalkey, &size,
			    rtapi_instance, (void **) &global_data, 1);
    if (retval < 0) {
	fprintf(stderr,
		"MSGD:%d ERROR: cannot create global segment key=0x%x %s\n",
	       rtapi_instance, globalkey, strerror(-retval));
    }
    if (size != sizeof(global_data_t)) {
	fprintf(stderr,
		"MSGD:%d ERROR: global segment size mismatch: expect %d got %d\n",
	       rtapi_instance, sizeof(global_data_t), size);
	return -EINVAL;
    }
    return retval;
}
示例#4
0
int _rtapi_init(const char *modname) {
    int n, module_id;
    module_data *module;
    struct shm_status sm;
    int retval;

    /* say hello */
    rtapi_print_msg(RTAPI_MSG_DBG, "ULAPI:%d initing module %s\n", 
		    rtapi_instance, modname);
    errno = 0;

    // if not done yet, attach global and rtapi_data segments now
    if (global_data == NULL) {
	sm.key = OS_KEY(GLOBAL_KEY, rtapi_instance);
	sm.size = sizeof(global_data_t);
	sm.flags = 0;
	if ((retval = shmdrv_attach(&sm, (void **)&global_data)) < 0) {
	    rtapi_print_msg(RTAPI_MSG_ERR,
			    "ULAPI:%d ERROR: can attach global segment: %d\n",
			    rtapi_instance, retval);
	    return -EINVAL;
	}
	sm.key = OS_KEY(RTAPI_KEY, rtapi_instance);
	sm.size = sizeof(rtapi_data_t);
	sm.flags = 0;
	if ((retval = shmdrv_attach(&sm, (void **)&rtapi_data)) < 0) {
	    rtapi_print_msg(RTAPI_MSG_ERR,
			    "ULAPI:%d ERROR: cant attach rtapi segment: %d\n",
			    rtapi_instance, retval);
	    return -EINVAL;
	}
    }
    // I consider this very dubious - there is no reason for ULAPI to start without
    // rtapi_data already being inited: -mah
    // init_rtapi_data(rtapi_data);

    /* check flavor and serial codes */
    if (rtapi_data->thread_flavor_id != THREAD_FLAVOR_ID) {
	/* mismatch - release master shared memory block */
	rtapi_print_msg(RTAPI_MSG_ERR,
			"ULAPI:%d ERROR: flavor mismatch %d vs %d\n",
			rtapi_instance, 
			rtapi_data->thread_flavor_id, THREAD_FLAVOR_ID);
	return -EINVAL;
    }
    if (rtapi_data->serial != RTAPI_SERIAL) {
	/* mismatch - release master shared memory block */
	rtapi_print_msg(RTAPI_MSG_ERR,
			"ULAPI:%d ERROR: serial mismatch %d vs %d\n",
			rtapi_instance, rtapi_data->serial, RTAPI_SERIAL);
	return -EINVAL;
    }
    /* set up local pointers to global data */
    module_array = rtapi_data->module_array;
    task_array = rtapi_data->task_array;
    shmem_array = rtapi_data->shmem_array;

    /* perform local init */
    for (n = 0; n <= RTAPI_MAX_SHMEMS; n++) {
	shmem_addr_array[n] = NULL;
    }

    /* 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,
			"ULAPI:%d ERROR: reached module limit %d\n", 
			rtapi_instance,n);
	return -EMFILE;
    }
    /* we have space for the module */
    module_id = n;
    module = &(module_array[n]);
    /* update module data */
    module->state = USERSPACE;
    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_mutex_give(&(rtapi_data->mutex));
    rtapi_print_msg(RTAPI_MSG_DBG, "ULAPI:%d module '%s' inited, ID = %02d\n",
		    rtapi_instance,module->name, module_id);
    return module_id;
}
示例#5
0
int init_module(void) {
    int n;
    struct shm_status sm;
    int retval;

    rtapi_switch = rtapi_get_handle();

    // first thing: attach global_data
    sm.key = OS_KEY(GLOBAL_KEY, rtapi_instance);
    sm.size = 0;
    sm.flags = 0;

    if ((retval = shmdrv_attach(&sm, (void **)&global_data)) < 0) {
	// cant use the  message ringbuffer just yet
	printk("RTAPI:%d ERROR: can attach global segment: %d\n",
	       rtapi_instance, retval);
	return -EINVAL;
    }
    
    // fail immediately if the global segment isnt in shape yet
    // this catches https://github.com/zultron/linuxcnc/issues/49 early
    if (global_data->magic != GLOBAL_READY) {
	
	printk("RTAPI:%d ERROR: bad global magic: 0x%x\n",
	       rtapi_instance,global_data->magic);

	// TBD: remove once cause identified
	printk("halsize=%d\n", global_data->hal_size);
	printk("msgd pid=%d\n", global_data->rtapi_msgd_pid);
	printk("magic=%x\n", global_data->magic);
	printk("flavor=%d\n", global_data->rtapi_thread_flavor);
	// fail the insmod
	return -EINVAL;
    }

    // say hello - this now goes through the message ringbuffer
    rtapi_print_msg(RTAPI_MSG_INFO, "RTAPI:%d %s %s init\n", 
		    rtapi_instance,
		    rtapi_get_handle()->thread_flavor_name, 
		    GIT_VERSION);


    sm.key = OS_KEY(RTAPI_KEY, rtapi_instance);
    sm.size = sizeof(rtapi_data_t);
    sm.flags = 0;
    if ((retval = shmdrv_create(&sm)) < 0) {
	rtapi_print_msg(RTAPI_MSG_ERR,
			"RTAPI:%d ERROR: can create rtapi segment: %d\n",
			rtapi_instance, retval);
	return -EINVAL;
    }
    if ((retval = shmdrv_attach(&sm, (void **)&rtapi_data)) < 0) {
	rtapi_print_msg(RTAPI_MSG_ERR,
			"RTAPI:%d ERROR: cant attach rtapi segment: %d\n",
			rtapi_instance, retval);
	return -EINVAL;
    }

    // make error ringbuffer accessible within RTAPI
    ringbuffer_init(&global_data->rtapi_messages, &rtapi_message_buffer);
    global_data->rtapi_messages.refcount += 1;   // rtapi is 'attached'

    // tag messages originating from RT proper
    rtapi_set_logtag("rt");

    /* this will take care of any threads flavor hook */
    init_rtapi_data(rtapi_data);

    /* check flavor and serial codes */
    if (rtapi_data->thread_flavor_id != THREAD_FLAVOR_ID) {
	/* mismatch - release master shared memory block */
	rtapi_print_msg(RTAPI_MSG_ERR,
			"RTAPI: ERROR: flavor mismatch %d vs %d\n",
			rtapi_data->thread_flavor_id, THREAD_FLAVOR_ID);

	sm.key = OS_KEY(RTAPI_KEY, rtapi_instance);
	sm.size = sizeof(global_data_t);
	sm.flags = 0;
	if ((retval = shmdrv_detach(&sm)) < 0) {
	    rtapi_print_msg(RTAPI_MSG_ERR,
			    "INSTANCE:%d ERROR: shmdrv_detach() returns %d\n",
			    rtapi_instance, retval);
	}
	sm.key = OS_KEY(GLOBAL_KEY, rtapi_instance);
	sm.size = sizeof(global_data_t);
	sm.flags = 0;
	if ((retval = shmdrv_detach(&sm)) < 0) {
	    rtapi_print_msg(RTAPI_MSG_ERR,
			    "INSTANCE:%d ERROR: shmdrv_detach() returns %d\n",
			    rtapi_instance, retval);
	}
	return -EINVAL;
    }
    if (rtapi_data->serial != RTAPI_SERIAL) {
	/* mismatch - release master shared memory block */
	rtapi_print_msg(RTAPI_MSG_ERR,
			"RTAPI: ERROR: serial mismatch '%d' vs '%d'\n",
			rtapi_data->serial, RTAPI_SERIAL);
	return -EINVAL;
    }
    /* set up local pointers to global data */
    module_array = rtapi_data->module_array;
    task_array = rtapi_data->task_array;
    shmem_array = rtapi_data->shmem_array;

    /* perform local init */
    for (n = 0; n <= RTAPI_MAX_TASKS; n++) {
	ostask_array[n] = NULL;
    }
    for (n = 0; n <= RTAPI_MAX_SHMEMS; n++) {
	shmem_addr_array[n] = NULL;
    }
    rtapi_data->timer_running = 0;
    rtapi_data->timer_period = 0;
    max_delay = DEFAULT_MAX_DELAY;

#ifdef RT_LINUX_USE_FPU
    rt_linux_use_fpu(1);
#endif

#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0)
    /* on SMP machines, we want to put RT code on the last CPU */
    n = NR_CPUS-1;
    while ( ! cpu_online(n) ) {
	n--;
    }
    rtapi_data->rt_cpu = n;
#else
    /* old kernel, the SMP hooks aren't available, so use CPU 0 */
    rtapi_data->rt_cpu = 0;
#endif


#ifdef CONFIG_PROC_FS
    /* set up /proc/rtapi */
    if (proc_init() != 0) {
	rtapi_print_msg(RTAPI_MSG_WARN,
	    "RTAPI: WARNING: Could not activate /proc entries\n");
	proc_clean();
    }
#endif

#ifdef HAVE_RTAPI_MODULE_INIT_HOOK
    _rtapi_module_init_hook();
#endif

    /* done */
    rtapi_print_msg(RTAPI_MSG_INFO, "RTAPI:%d Init complete\n", 
		    rtapi_instance);
    return 0;
}
示例#6
0
void cleanup_module(void) {
    int n;
    struct shm_status sm;
    int retval;

    if (rtapi_data == NULL) {
	/* never got inited, nothing to do */
	return;
    }

#ifdef HAVE_RTAPI_MODULE_EXIT_HOOK
    _rtapi_module_exit_hook();
#endif

    /* grab the mutex */
    rtapi_mutex_get(&(rtapi_data->mutex));
    rtapi_print_msg(RTAPI_MSG_INFO, "RTAPI:%d exit\n", rtapi_instance);

    /* clean up leftover modules (start at 1, we don't use ID 0 */
    for (n = 1; n <= RTAPI_MAX_MODULES; n++) {
	if (module_array[n].state == REALTIME) {
	    rtapi_print_msg(RTAPI_MSG_WARN,
			    "RTAPI: WARNING: module '%s' (ID: %02d) did not "
			    "call rtapi_exit()\n",
			    module_array[n].name, n);
	    module_delete(n);
	}
    }

    /* cleaning up modules should clean up everything, if not there has
       probably been an unrecoverable internal error.... */
    for (n = 1; n <= RTAPI_MAX_SHMEMS; n++) {
	if (shmem_array[n].rtusers > 0) {
	    rtapi_print_msg(RTAPI_MSG_ERR,
		"RTAPI: ERROR: shared memory block %02d not deleted\n", n);
	}
    }
    for (n = 1; n <= RTAPI_MAX_TASKS; n++) {
	if (task_array[n].state != EMPTY) {
	    rtapi_print_msg(RTAPI_MSG_ERR,
		"RTAPI: ERROR: task %02d not deleted\n", n);
	    /* probably un-recoverable, but try anyway */
	    _rtapi_task_pause(n);
	    /* rtapi_task_delete should not grab mutex  */
	    task_array[n].state = DELETE_LOCKED;
	    _rtapi_task_delete(n);
	}
    }
    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;
	rtapi_data->timer_running = 0;
	max_delay = DEFAULT_MAX_DELAY;
    }
    rtapi_mutex_give(&(rtapi_data->mutex));
#ifdef CONFIG_PROC_FS
    proc_clean();
#endif

    sm.key = OS_KEY(RTAPI_KEY, rtapi_instance);
    sm.size = sizeof(rtapi_data_t);
    sm.flags = 0;
    if ((retval = shmdrv_detach(&sm)) < 0) {
	rtapi_print_msg(RTAPI_MSG_ERR,
			"RTAPI:%d ERROR: detach rtapi returns %d\n",
			rtapi_instance, retval);
    }
    rtapi_data = NULL;

    global_data->rtapi_messages.refcount -= 1;   // detach rtapi end

    sm.key = OS_KEY(GLOBAL_KEY, rtapi_instance);
    sm.size = sizeof(global_data_t);
    sm.flags = 0;
    if ((retval = shmdrv_detach(&sm)) < 0) {
	rtapi_print_msg(RTAPI_MSG_ERR,
			"RTAPI:%d ERROR: detach global returns %d\n",
			rtapi_instance, retval);
    }
    global_data = NULL;
    rtapi_print_msg(RTAPI_MSG_INFO, "RTAPI:%d Exit complete\n",
		    rtapi_instance);
    return;
}
示例#7
0
int _rtapi_shmem_new_inst(int userkey, int instance, int module_id, unsigned long int size) {
    shmem_data *shmem;
    int i, ret, actual_size;
    int is_new = 0;
    int key = OS_KEY(userkey, instance);
    static int page_size;

    if (!page_size)
	page_size = sysconf(_SC_PAGESIZE);


    rtapi_mutex_get(&(rtapi_data->mutex));
    for (i = 1 ; i < RTAPI_MAX_SHMEMS; i++) {
	if (shmem_array[i].magic == SHMEM_MAGIC && shmem_array[i].key == key) {
	    shmem_array[i].count ++;
	    rtapi_mutex_give(&(rtapi_data->mutex));
	    return i;
	}
	if (shmem_array[i].magic != SHMEM_MAGIC)
	    break;
    }
    if (i == RTAPI_MAX_SHMEMS) {
	rtapi_mutex_give(&(rtapi_data->mutex));
	rtapi_print_msg(RTAPI_MSG_ERR,
			"rtapi_shmem_new failed due to RTAPI_MAX_SHMEMS\n");
	return -ENOMEM;
    }
    shmem = &shmem_array[i];

    // redefine size == 0 to mean 'attach only, dont create'
    actual_size = size;
    ret = shm_common_new(key, &actual_size, instance, &shmem->mem, size > 0);
    if (ret > 0)
	is_new = 1;
    if (ret < 0) {
	 rtapi_mutex_give(&(rtapi_data->mutex));
	 rtapi_print_msg(RTAPI_MSG_ERR,
			 "shm_common_new:%d failed key=0x%x size=%ld\n",
			 instance, key, size);
	 return ret;
    }
    // a non-zero size was given but it didn match what we found:
    if (size && (actual_size != size)) {
	rtapi_print_msg(RTAPI_MSG_ERR,
			"rtapi_shmem_new:%d 0x8.8%x: requested size %ld and actual size %d dont match\n",
			instance, key, size, actual_size);
    }
    /* Touch each page by either zeroing the whole mem (if it's a new
       SHM region), or by reading from it. */
    if (is_new) {
	memset(shmem->mem, 0, size);
    } else {
	unsigned int i;

	for (i = 0; i < size; i += page_size) {
	    unsigned int x = *(volatile unsigned int *)
		((unsigned char *)shmem->mem + i);
	    /* Use rand_r to clobber the read so GCC won't optimize it
	       out. */
	    rand_r(&x);
	}
    }

    /* label as a valid shmem structure */
    shmem->magic = SHMEM_MAGIC;
    /* fill in the other fields */
    shmem->size = actual_size;
    shmem->key = key;
    shmem->count = 1;
    shmem->instance = instance;

    rtapi_mutex_give(&(rtapi_data->mutex));

    /* return handle to the caller */
    return i;
}
示例#8
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;
}
示例#9
0
int hal_ring_new(const char *name, int size, int sp_size, int mode)
{
    hal_ring_t *rbdesc;
    int *prev, next, cmp, retval;
    int ring_id;
    ringheader_t *rhptr;

    CHECK_HALDATA();
    CHECK_STRLEN(name, HAL_NAME_LEN);
    CHECK_LOCK(HAL_LOCK_LOAD);

    {
	hal_ring_t *ptr __attribute__((cleanup(halpr_autorelease_mutex)));

	rtapi_mutex_get(&(hal_data->mutex));

	// make sure no such ring name already exists
	if ((ptr = halpr_find_ring_by_name(name)) != 0) {
	    HALERR("ring '%s' already exists", name);
	    return -EEXIST;
	}
	// allocate a new ring id - needed since we dont track ring shm
	// segments in RTAPI
	if ((ring_id = next_ring_id()) < 0) {
	    HALERR("cant allocate new ring id for '%s'", name);
	    return -ENOMEM;
	}

	// allocate a new ring descriptor
	if ((rbdesc = alloc_ring_struct()) == 0)
	    NOMEM("ring '%s'", name);

	rbdesc->handle = rtapi_next_handle();
	rbdesc->flags = mode;
	rbdesc->ring_id = ring_id;

	// make total allocation fit ringheader, ringbuffer and scratchpad
	rbdesc->total_size = ring_memsize( rbdesc->flags, size, sp_size);

	if (rbdesc->flags & ALLOC_HALMEM) {
	    void *ringmem = shmalloc_up(rbdesc->total_size);
	    if (ringmem == NULL)
		NOMEM("ring '%s' size %d - insufficient HAL memory for ring",
		      name,rbdesc->total_size);

	    rbdesc->ring_offset = SHMOFF(ringmem);
	    rhptr = ringmem;
	} else {
	    // allocate shared memory segment for ring and init
	    rbdesc->ring_shmkey = OS_KEY((RTAPI_RING_SHM_KEY + ring_id), rtapi_instance);

	    int shmid;

	    // allocate an RTAPI shm segment owned by HAL_LIB_xxx
	    if ((shmid = rtapi_shmem_new(rbdesc->ring_shmkey, lib_module_id,
					 rbdesc->total_size)) < 0)
		NOMEM("rtapi_shmem_new(0x%8.8x,%d) failed: %d",
		       rbdesc->ring_shmkey, lib_module_id,
		       rbdesc->total_size);

	    // map the segment now so we can fill in the ringheader details
	    if ((retval = rtapi_shmem_getptr(shmid,
					     (void **)&rhptr, 0)) < 0)
		NOMEM("rtapi_shmem_getptr for %d failed %d",
		       shmid, retval);
	}

	HALDBG("created ring '%s' in %s, total_size=%d",
	       name, (rbdesc->flags & ALLOC_HALMEM) ? "halmem" : "shm",
	       rbdesc->total_size);

	ringheader_init(rhptr, rbdesc->flags, size, sp_size);
	rhptr->refcount = 0; // on hal_ring_attach: increase; on hal_ring_detach: decrease
	rtapi_snprintf(rbdesc->name, sizeof(rbdesc->name), "%s", name);
	rbdesc->next_ptr = 0;

	// search list for 'name' and insert new structure
	prev = &(hal_data->ring_list_ptr);
	next = *prev;
	while (1) {
	    if (next == 0) {
		/* reached end of list, insert here */
		rbdesc->next_ptr = next;
		*prev = SHMOFF(rbdesc);
		return 0;
	    }
	    ptr = SHMPTR(next);
	    cmp = strcmp(ptr->name, rbdesc->name);
	    if (cmp > 0) {
		/* found the right place for it, insert here */
		rbdesc->next_ptr = next;
		*prev = SHMOFF(rbdesc);
		return 0;
	    }
	    /* didn't find it yet, look at next one */
	    prev = &(ptr->next_ptr);
	    next = *prev;
	}
	// automatic unlock by scope exit
    }
}
示例#10
0
int ulapi_main(int instance, int flavor, global_data_t *global)
{
    int retval = 0;
    int rtapikey;
    int size = 0;

    rtapi_instance = instance; // from here on global within ulapi.so

    // shm_common_init(); // common shared memory API needs this

    // the HAL library constructor already has the global
    // shm segment attached, so no need to do it again here
    // since we're not using the rtapi_app_init()/rtapi_app_exit()
    // calling conventions might as well pass it it

    // this sets global_data for use within ulapi.so which
    // has a disjoint symbol namespace from hal_lib
    global_data = global;

    rtapi_print_msg(RTAPI_MSG_DBG,"ULAPI:%d %s %s init\n",
		    rtapi_instance,
		    rtapi_get_handle()->thread_flavor_name,
		    GIT_VERSION);


    if (rtapi_switch->thread_flavor_flags & FLAVOR_RTAPI_DATA_IN_SHM) {

	rtapikey = OS_KEY(RTAPI_KEY, rtapi_instance);

	// attach to existing RTAPI segment
	// not all thread flavors actuall might use it
	if ((retval = shm_common_new(rtapikey, &size,
				     rtapi_instance, (void **) &rtapi_data, 0))) {
	    rtapi_print_msg(RTAPI_MSG_ERR,
			    "ULAPI:%d ERROR: cannot attach rtapi"
			    " segment key=0x%x %s\n",
			    rtapi_instance, rtapikey, strerror(-retval));
	}
	if (size != sizeof(rtapi_data_t)) {
	    rtapi_print_msg(RTAPI_MSG_ERR,
			    "ULAPI:%d ERROR: unexpected rtapi shm size:"
			    " expected: %zu actual: %d\n",
			    rtapi_instance, sizeof(rtapi_data_t), size);
	    return -EINVAL;
	}

	if (MMAP_OK(global_data) && MMAP_OK(rtapi_data)) {
	    rtapi_print_msg(RTAPI_MSG_DBG,
			    "ULAPI:%d msglevel=%d/%d halsize=%d"
			    " %s startup %s\n",
			    rtapi_instance,
			    global_data->rt_msg_level,
			    global_data->user_msg_level,
			    global_data->hal_size,
			    GIT_VERSION, retval ? "FAILED" : "OK");
	} else {
	    rtapi_print_msg(RTAPI_MSG_DBG,
			    "ULAPI:%d init failed, realtime not running?"
			    " global=%p rtapi=%p\n",
			    rtapi_instance, global_data, rtapi_data);
	}
    }
    return retval;
}