Esempio n. 1
0
int shm_common_exists(int key)
{
    struct shm_status sm;
    int retval;

    if (shmdrv_loaded) {
	memset(&sm, 0, sizeof(struct shm_status));
	sm.driver_fd = shmdrv_driver_fd();
	sm.key = key;
	sm.flags = 0;
	retval =  shmdrv_status(&sm);
	close(sm.driver_fd);
	return retval == 0;
    } else {
	int shmfd;
	char segment_name[LINELEN];

	sprintf(segment_name, SHM_FMT, INSTANCE_OF(key), key);
	if ((shmfd = shm_open(segment_name, O_RDWR,
			      (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP))) < 0) {
	    retval = 0;
	} else {
	    close(shmfd);
	    retval = 1;
	}
	return retval;
    }
}
Esempio n. 2
0
int shmdrv_gc(void)
{
    int retval;
    int fd = shmdrv_driver_fd();
    if (fd < 0)
	return fd;
    retval = ioctl(fd, IOC_SHM_GC, NULL);
    close(fd);
    return retval;
}
Esempio n. 3
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;
}
Esempio n. 4
0
int shm_common_new(int key, int *size, int instance, void **shmptr, int create)
{
    struct shm_status sm;
    int retval;
    int is_new = 0;

    if (shmdrv_loaded) {
	// use shmdrv kernel driver
	sm.driver_fd = shmdrv_driver_fd();
	sm.key = key;
	sm.size = (size == NULL? 0: *size);
	sm.flags = 0;
	retval = shmdrv_status(&sm); // check if exists
	if (retval && !create) {
	    // didnt exist, but just attach requested, so fail
	    close(sm.driver_fd);
	    return -ENOENT;
	}
	if (retval) { // didnt exist, so create
	    retval = shmdrv_create(&sm); 
	    if (retval < 0) {
		return retval;
	    }
	    is_new = 1;
	}
	// now attach
	retval = shmdrv_attach(&sm, shmptr);
	if (retval < 0) {
	    close(sm.driver_fd);
	    return retval;
	}
	// if size was passed in as 0 (attach), fill in actual size
	if (size && (*size == 0)) 
	    *size = sm.size;
	close(sm.driver_fd);
	return is_new;

    } else {
	// use POSIX shared memory

	int shmfd, mmap_size;
	mode_t old_umask;
	char segment_name[LINELEN];
	if ((size == 0) || (*size == 0))
	    mmap_size = 0;
	else
	    mmap_size = *size;
	sprintf(segment_name, SHM_FMT, instance, key);
	old_umask = umask(0); //S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
	if (create && ((shmfd = shm_open(segment_name, 
					 (O_CREAT | O_EXCL | O_RDWR),
 				(S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP))) > 0)) {
	    // initial creation
	    if (fchown(shmfd, getuid(),getgid()))
		perror("fchown");
	    if (ftruncate(shmfd, mmap_size))
		perror("ftruncate");
	    is_new = 1;
	} else if((shmfd = shm_open(segment_name, O_RDWR,
				    (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP))) < 0) {
	    // just attach, and that failed:
	    umask(old_umask);
	    return -errno;
	} else {  // shmfd open
	    if (mmap_size == 0) {
		struct stat st;
		if (fstat(shmfd, &st)) {
		    perror("fstat");
		    return -errno;
		}
		mmap_size = st.st_size;
	    }
	}
	if((*shmptr = mmap(0, mmap_size, (PROT_READ | PROT_WRITE),
			   MAP_SHARED, shmfd, 0)) == MAP_FAILED) {
	    perror("shm_common_new:mmap");
	    close(shmfd);
	    umask(old_umask);
	    return -errno;
	}
	if (size)  // return actual shm size as determined in attach
	    *size = mmap_size;
	umask(old_umask);
	close(shmfd);
	return is_new;
    }
}