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; } }
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; }
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; }
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; } }