/** * test_two_shares - same as test_base, but with two sources and two consumers * Description: * Two consumers of two different apids. * Return Values: * Success: 0 * Failure: -2 */ int test_two_shares(test_args *xpmem_args) { xpmem_segid_t segid[2]; xpmem_apid_t apid[2]; int i, ret=0, *data[2]; char *tmp; tmp = xpmem_args->share; segid[0] = strtol(tmp, NULL, 16); tmp += strlen(tmp) + 1; segid[1] = strtol(tmp, NULL, 16); data[0] = attach_segid(segid[0], &apid[0]); data[1] = attach_segid(segid[1], &apid[1]); if (data[0] == (void *)-1 || data[1] == (void *)-1) { perror("xpmem_attach"); return -2; } printf("xpmem_proc2: mypid = %d\n", getpid()); printf("xpmem_proc2: segid[0] = %llx\n", segid[0]); printf("xpmem_proc2: segid[1] = %llx\n", segid[1]); printf("xpmem_proc2: data[0] attached at %p\n", data[0]); printf("xpmem_proc2: data[1] attached at %p\n", data[1]); printf("xpmem_proc2: adding 1 to all elems using %p\n", data[0]); printf("xpmem_proc2: adding 1 to all elems using %p\n\n", data[1]); for (i = 0; i < SHARE_INT_SIZE; i++) { if (*(data[0] + i) != i) { printf("xpmem_proc2: ***mismatch at %d: expected %d " "got %d\n", i, i, *(data[0] + i)); ret = -2; } if (*(data[1] + i) != i) { printf("xpmem_proc2: ***mismatch at %d: expected %d " "got %d\n", i, i, *(data[1] + i)); ret = -2; } *(data[0] + i) += 1; *(data[1] + i) += 1; } xpmem_detach(data[0]); xpmem_detach(data[1]); xpmem_release(apid[0]); xpmem_release(apid[1]); return ret; }
/** * test_base - a simple test to share and attach * Description: * Creates a share (initialized to a random value), calls a second process * to attach to the shared address and increment its value. * Return Values: * Success: 0 * Failure: -2 */ int test_base(test_args *xpmem_args) { xpmem_segid_t segid; xpmem_apid_t apid; int i, ret=0, *data; segid = strtol(xpmem_args->share, NULL, 16); data = attach_segid(segid, &apid); if (data == (void *)-1) { perror("xpmem_attach"); return -2; } printf("xpmem_proc2: mypid = %d\n", getpid()); printf("xpmem_proc2: segid = %llx\n", segid); printf("xpmem_proc2: attached at %p\n", data); printf("xpmem_proc2: adding 1 to all elems\n\n"); for (i = 0; i < SHARE_INT_SIZE; i++) { if (*(data + i) != i) { printf("xpmem_proc2: ***mismatch at %d: expected %d " "got %d\n", i, i, *(data + i)); ret = -2; } *(data + i) += 1; } xpmem_detach(data); xpmem_release(apid); return ret; }
static ucs_status_t uct_xpmem_detach(uct_mm_remote_seg_t *mm_desc) { xpmem_apid_t apid = mm_desc->cookie; void *address; int ret; address = ucs_align_down_pow2_ptr(mm_desc->address, ucs_get_page_size()); ucs_trace("xpmem detaching address %p", address); ret = xpmem_detach(address); if (ret < 0) { ucs_error("Failed to xpmem_detach: %m"); return UCS_ERR_IO_ERROR; } VALGRIND_MAKE_MEM_UNDEFINED(mm_desc->address, mm_desc->length); ucs_trace("xpmem releasing segment apid 0x%llx", apid); ret = xpmem_release(apid); if (ret < 0) { ucs_error("Failed to release xpmem segment apid 0x%llx", apid); return UCS_ERR_IO_ERROR; } return UCS_OK; }
void mca_btl_vader_xpmem_cleanup_endpoint (struct mca_btl_base_endpoint_t *ep) { /* clean out the registration cache */ (void) mca_rcache_base_vma_iterate (mca_btl_vader_component.vma_module, NULL, (size_t) -1, mca_btl_vader_endpoint_xpmem_rcache_cleanup, (void *) ep); if (ep->segment_base) { xpmem_release (ep->segment_data.xpmem.apid); ep->segment_data.xpmem.apid = 0; } }
int shmem_transport_xpmem_fini(void) { int i, peer_num; if (NULL != shmem_transport_xpmem_peers) { for (i = 0 ; i < shmem_internal_num_pes; ++i) { peer_num = SHMEM_GET_RANK_SAME_NODE(i); if (-1 == peer_num) continue; if (shmem_internal_my_pe == i) continue; if (NULL != shmem_transport_xpmem_peers[peer_num].data_ptr) { xpmem_detach(shmem_transport_xpmem_peers[peer_num].data_attach_ptr); } if (0 != shmem_transport_xpmem_peers[peer_num].data_apid) { xpmem_release(shmem_transport_xpmem_peers[peer_num].data_apid); } if (NULL != shmem_transport_xpmem_peers[peer_num].heap_ptr) { xpmem_detach(shmem_transport_xpmem_peers[peer_num].heap_attach_ptr); } if (0 != shmem_transport_xpmem_peers[peer_num].heap_apid) { xpmem_release(shmem_transport_xpmem_peers[peer_num].heap_apid); } } free(shmem_transport_xpmem_peers); } if (0 != my_info.data_seg) { xpmem_remove(my_info.data_seg); } if (0 != my_info.heap_seg) { xpmem_remove(my_info.heap_seg); } return 0; }
static void mca_btl_vader_endpoint_destructor (mca_btl_vader_endpoint_t *ep) { OBJ_DESTRUCT(&ep->pending_frags); #if OPAL_BTL_VADER_HAVE_XPMEM if (MCA_BTL_VADER_XPMEM == mca_btl_vader_component.single_copy_mechanism) { if (ep->segment_data.xpmem.rcache) { /* clean out the registration cache */ const int nregs = 100; mca_mpool_base_registration_t *regs[nregs]; int reg_cnt; do { reg_cnt = ep->segment_data.xpmem.rcache->rcache_find_all(ep->segment_data.xpmem.rcache, 0, (size_t)-1, regs, nregs); for (int i = 0 ; i < reg_cnt ; ++i) { /* otherwise dereg will fail on assert */ regs[i]->ref_count = 0; OBJ_RELEASE(regs[i]); } } while (reg_cnt == nregs); ep->segment_data.xpmem.rcache = NULL; } if (ep->segment_base) { xpmem_release (ep->segment_data.xpmem.apid); ep->segment_data.xpmem.apid = 0; } } else #endif if (ep->segment_data.other.seg_ds) { opal_shmem_ds_t seg_ds; /* opal_shmem_segment_detach expects a opal_shmem_ds_t and will * stomp past the end of the seg_ds if it is too small (which * ep->seg_ds probably is) */ memcpy (&seg_ds, ep->segment_data.other.seg_ds, opal_shmem_sizeof_shmem_ds (ep->segment_data.other.seg_ds)); free (ep->segment_data.other.seg_ds); ep->segment_data.other.seg_ds = NULL; /* disconnect from the peer's segment */ opal_shmem_segment_detach (&seg_ds); } ep->fbox_in.buffer = ep->fbox_out.buffer = NULL; ep->segment_base = NULL; ep->fifo = NULL; }
/** * test_fork - test if forks are handled properly * Description: * Called by xpmem_master, but do nothing. xpmem_proc1 does the fork. * Return Values: * Success: 0 * Failure: -2 */ int test_fork(test_args *xpmem_args) { xpmem_segid_t segid; xpmem_apid_t apid; struct xpmem_addr addr; int i, ret=0, *data; segid = strtol(xpmem_args->share, NULL, 16); apid = xpmem_get(segid, XPMEM_RDWR, XPMEM_PERMIT_MODE, NULL); addr.apid = apid; addr.offset = PAGE_SIZE; data = (int *)xpmem_attach(addr, PAGE_SIZE, NULL); if (data == (void *)-1) { perror("xpmem_attach"); return -2; } printf("xpmem_proc2: mypid = %d\n", getpid()); printf("xpmem_proc2: segid = %llx\n", segid); printf("xpmem_proc2: attached at %p\n", data); printf("xpmem_proc2: reading to pin pages\n"); for (i = 0; i < PAGE_INT_SIZE; i++) { if (*(data + i) != PAGE_INT_SIZE + i) { printf("xpmem_proc2: ***mismatch at %d: expected %lu " "got %d\n", i, PAGE_INT_SIZE + i, *(data + i)); ret = -2; } } /* Now wait for xpmem_proc1 to invoke COW */ printf("xpmem_proc2: waiting for COW...\n\n"); while (xpmem_args->share[COW_LOCK_INDEX] == 0) { xpmem_args->share[COW_LOCK_INDEX] = 1; } sleep(1); printf("xpmem_proc2: adding 1 to all elems\n\n"); for (i = 0; i < PAGE_INT_SIZE; i++) *(data + i) += 1; xpmem_detach(data); xpmem_release(apid); return ret; }
static ucs_status_t uct_xpmem_attach(uct_mm_id_t mmid, size_t length, void *remote_address, void **local_address, uint64_t *cookie, const char *path) { struct xpmem_addr addr; ucs_status_t status; ptrdiff_t offset; void *address; addr.offset = 0; addr.apid = xpmem_get(mmid, XPMEM_RDWR, XPMEM_PERMIT_MODE, NULL); VALGRIND_MAKE_MEM_DEFINED(&addr.apid, sizeof(addr.apid)); if (addr.apid < 0) { ucs_error("Failed to acquire xpmem segment 0x%"PRIx64": %m", mmid); status = UCS_ERR_IO_ERROR; goto err_xget; } ucs_trace("xpmem acquired segment 0x%"PRIx64" apid 0x%llx remote_address %p", mmid, addr.apid, remote_address); offset = ((uintptr_t)remote_address) % ucs_get_page_size(); address = xpmem_attach(addr, length + offset, NULL); VALGRIND_MAKE_MEM_DEFINED(&address, sizeof(address)); if (address == MAP_FAILED) { ucs_error("Failed to attach xpmem segment 0x%"PRIx64" apid 0x%llx " "with length %zu: %m", mmid, addr.apid, length); status = UCS_ERR_IO_ERROR; goto err_xattach; } VALGRIND_MAKE_MEM_DEFINED(address + offset, length); *local_address = address + offset; *cookie = addr.apid; ucs_trace("xpmem attached segment 0x%"PRIx64" apid 0x%llx %p..%p at %p (+%zd)", mmid, addr.apid, remote_address, remote_address + length, address, offset); return UCS_OK; err_xattach: xpmem_release(addr.apid); err_xget: return status; }
/* * User ioctl to the XPMEM driver. Only 64-bit user applications are * supported. */ static long xpmem_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { long ret; switch (cmd) { case XPMEM_CMD_VERSION: { return XPMEM_CURRENT_VERSION; } case XPMEM_CMD_MAKE: { struct xpmem_cmd_make make_info; xpmem_segid_t segid; if (copy_from_user(&make_info, (void __user *)arg, sizeof(struct xpmem_cmd_make))) return -EFAULT; ret = xpmem_make(make_info.vaddr, make_info.size, make_info.permit_type, (void *)make_info.permit_value, &segid); if (ret != 0) return ret; if (put_user(segid, &((struct xpmem_cmd_make __user *)arg)->segid)) { (void)xpmem_remove(segid); return -EFAULT; } return 0; } case XPMEM_CMD_REMOVE: { struct xpmem_cmd_remove remove_info; if (copy_from_user(&remove_info, (void __user *)arg, sizeof(struct xpmem_cmd_remove))) return -EFAULT; return xpmem_remove(remove_info.segid); } case XPMEM_CMD_GET: { struct xpmem_cmd_get get_info; xpmem_apid_t apid; if (copy_from_user(&get_info, (void __user *)arg, sizeof(struct xpmem_cmd_get))) return -EFAULT; ret = xpmem_get(get_info.segid, get_info.flags, get_info.permit_type, (void *)get_info.permit_value, &apid); if (ret != 0) return ret; if (put_user(apid, &((struct xpmem_cmd_get __user *)arg)->apid)) { (void)xpmem_release(apid); return -EFAULT; } return 0; } case XPMEM_CMD_RELEASE: { struct xpmem_cmd_release release_info; if (copy_from_user(&release_info, (void __user *)arg, sizeof(struct xpmem_cmd_release))) return -EFAULT; return xpmem_release(release_info.apid); } case XPMEM_CMD_ATTACH: { struct xpmem_cmd_attach attach_info; u64 at_vaddr; if (copy_from_user(&attach_info, (void __user *)arg, sizeof(struct xpmem_cmd_attach))) return -EFAULT; ret = xpmem_attach(file, attach_info.apid, attach_info.offset, attach_info.size, attach_info.vaddr, attach_info.fd, attach_info.flags, &at_vaddr); if (ret != 0) return ret; if (put_user(at_vaddr, &((struct xpmem_cmd_attach __user *)arg)->vaddr)) { (void)xpmem_detach(at_vaddr); return -EFAULT; } return 0; } case XPMEM_CMD_DETACH: { struct xpmem_cmd_detach detach_info; if (copy_from_user(&detach_info, (void __user *)arg, sizeof(struct xpmem_cmd_detach))) return -EFAULT; return xpmem_detach(detach_info.vaddr); } case XPMEM_CMD_FORK_BEGIN: { return xpmem_fork_begin(); } case XPMEM_CMD_FORK_END: { return xpmem_fork_end(); } default: break; } return -ENOIOCTLCMD; }