static int mca_btl_scif_progress_recvs (mca_btl_base_endpoint_t *ep) { const mca_btl_active_message_callback_t *reg; unsigned int start = ep->recv_buffer.start; unsigned int end = ep->recv_buffer.endp[0]; mca_btl_scif_base_frag_t frag; mca_btl_scif_frag_hdr_t *hdr; /* changing this value does not appear to have a signifigant impact * on performance */ int frags_per_loop = 5; if (end == start) { return 0; } end &= ~ (1 << 31); start &= ~ (1 << 31); /* force all prior reads to complete before continuing */ opal_atomic_rmb (); do { hdr = (mca_btl_scif_frag_hdr_t *) (ep->recv_buffer.buffer + start); /* force all prior reads to complete before continuing */ MB(); BTL_VERBOSE(("got frag with header {.tag = %d, .size = %d} from offset %u", hdr->tag, hdr->size, start)); #if defined(SCIF_USE_SEQ) if (hdr->seq != ep->seq_expected) { break; } ep->seq_expected++; #endif /* message to skip the rest of the buffer */ if (0xff != hdr->tag) { reg = mca_btl_base_active_message_trigger + hdr->tag; /* fragment fits entirely in the remaining buffer space. some * btl users do not handle fragmented data so we can't split * the fragment without introducing another copy here. this * limitation has not appeared to cause any performance * problems. */ frag.base.des_segment_count = 1; frag.segments[0].seg_len = hdr->size; frag.segments[0].seg_addr.pval = (void *) (hdr + 1); frag.base.des_segments = frag.segments; /* call the registered callback function */ reg->cbfunc(&mca_btl_scif_module.super, hdr->tag, &frag.base, reg->cbdata); } start = (start + hdr->size + sizeof (*hdr) + 63) & ~63; /* skip unusable space at the end of the buffer */ if (mca_btl_scif_component.segment_size == start) { start = 64; ep->recv_buffer.start = ((ep->recv_buffer.start & (1 << 31)) ^ (1 << 31)) | 64; } else { ep->recv_buffer.start = (ep->recv_buffer.start & (1 << 31)) | start; } } while (start != end && --frags_per_loop); /* let the sender know where we stopped */ ep->recv_buffer.startp[0] = ep->recv_buffer.start; /* return the number of fragments processed */ return 5 - frags_per_loop; }
int mca_pml_ob1_start(size_t count, ompi_request_t** requests) { int rc; for (size_t i = 0 ; i < count ; ++i) { mca_pml_base_request_t *pml_request = (mca_pml_base_request_t*)requests[i]; if (NULL == pml_request || OMPI_REQUEST_PML != requests[i]->req_type) { continue; } /* If the persistent request is currently active - verify the status * is incomplete. if the pml layer has not completed the request - mark * the request as free called - so that it will be freed when the request * completes - and create a new request. */ #if OPAL_ENABLE_MULTI_THREADS opal_atomic_rmb(); #endif /* start the request */ switch(pml_request->req_type) { case MCA_PML_REQUEST_SEND: { mca_pml_ob1_send_request_t* sendreq = (mca_pml_ob1_send_request_t*)pml_request; MEMCHECKER( memchecker_call(&opal_memchecker_base_isdefined, pml_request->req_addr, pml_request->req_count, pml_request->req_datatype); ); if (!pml_request->req_pml_complete) { ompi_request_t *request; /* buffered sends can be mpi complete and pml incomplete. to support this * case we need to allocate a new request. */ rc = mca_pml_ob1_isend_init (pml_request->req_addr, pml_request->req_count, pml_request->req_datatype, pml_request->req_peer, pml_request->req_tag, sendreq->req_send.req_send_mode, pml_request->req_comm, &request); if (OPAL_UNLIKELY(OMPI_SUCCESS != rc)) { return rc; } /* copy the callback and callback data to the new requests */ request->req_complete_cb = pml_request->req_ompi.req_complete_cb; request->req_complete_cb_data = pml_request->req_ompi.req_complete_cb_data; /* ensure the old request gets released */ pml_request->req_free_called = true; sendreq = (mca_pml_ob1_send_request_t *) request; requests[i] = request; } else if (sendreq->req_send.req_bytes_packed != 0) { size_t offset = 0; /** * Reset the convertor in case we're dealing with the original * request, which when completed do not reset the convertor. */ opal_convertor_set_position (&sendreq->req_send.req_base.req_convertor, &offset); } /* reset the completion flag */ pml_request->req_pml_complete = false; MCA_PML_OB1_SEND_REQUEST_START(sendreq, rc); if(rc != OMPI_SUCCESS) return rc; break; } case MCA_PML_REQUEST_RECV: { mca_pml_ob1_recv_request_t* recvreq = (mca_pml_ob1_recv_request_t*)pml_request; MCA_PML_OB1_RECV_REQUEST_START(recvreq); break; } default: return OMPI_ERR_REQUEST; } }
/* ////////////////////////////////////////////////////////////////////////// */ static int segment_create(opal_shmem_ds_t *ds_buf, const char *file_name, size_t size) { int rc = OPAL_SUCCESS; pid_t my_pid = getpid(); /* the real size of the shared memory segment. this includes enough space * to store our segment header. */ size_t real_size = size + sizeof(opal_shmem_seg_hdr_t); opal_shmem_seg_hdr_t *seg_hdrp = MAP_FAILED; /* init the contents of opal_shmem_ds_t */ shmem_ds_reset(ds_buf); /* for posix shared memory we don't have to worry about the backing store * being located on a network file system... so no check is needed here. */ /* calling shmem_posix_shm_open searches for an available posix shared * memory object name and upon successful completion populates the name * buffer */ if (-1 == (ds_buf->seg_id = shmem_posix_shm_open( ds_buf->seg_name, OPAL_SHMEM_POSIX_FILE_LEN_MAX - 1))) { /* snaps! something happened in posix_shm_open. don't report anything * here because posix_shm_open will display all the necessary info. */ rc = OPAL_ERROR; goto out; } /* size backing file - note the use of real_size here */ else if (0 != ftruncate(ds_buf->seg_id, real_size)) { int err = errno; char hn[MAXHOSTNAMELEN]; gethostname(hn, MAXHOSTNAMELEN - 1); hn[MAXHOSTNAMELEN - 1] = '\0'; opal_show_help("help-opal-shmem-posix.txt", "sys call fail", 1, hn, "ftruncate(2)", "", strerror(err), err); rc = OPAL_ERROR; goto out; } else if (MAP_FAILED == (seg_hdrp = (opal_shmem_seg_hdr_t*)mmap(NULL, real_size, PROT_READ | PROT_WRITE, MAP_SHARED, ds_buf->seg_id, 0))) { int err = errno; char hn[MAXHOSTNAMELEN]; gethostname(hn, MAXHOSTNAMELEN - 1); hn[MAXHOSTNAMELEN - 1] = '\0'; opal_show_help("help-opal-shmem-posix.txt", "sys call fail", 1, hn, "mmap(2)", "", strerror(err), err); rc = OPAL_ERROR; goto out; } /* all is well */ else { /* -- initialize the shared memory segment -- */ opal_atomic_rmb(); /* init segment lock */ opal_atomic_init(&seg_hdrp->lock, OPAL_ATOMIC_UNLOCKED); /* i was the creator of this segment, so note that fact */ seg_hdrp->cpid = my_pid; opal_atomic_wmb(); /* -- initialize the contents of opal_shmem_ds_t -- */ ds_buf->seg_cpid = my_pid; ds_buf->seg_size = real_size; ds_buf->seg_base_addr = (unsigned char *)seg_hdrp; /* notice that we are not setting ds_buf->name here. at this point, * posix_shm_open was successful, so the contents of ds_buf->name are * already set for us :-) */ /* set "valid" bit because setment creation was successful */ OPAL_SHMEM_DS_SET_VALID(ds_buf); OPAL_OUTPUT_VERBOSE( (70, opal_shmem_base_framework.framework_output, "%s: %s: create successful " "(id: %d, size: %lu, name: %s)\n", mca_shmem_posix_component.super.base_version.mca_type_name, mca_shmem_posix_component.super.base_version.mca_component_name, ds_buf->seg_id, (unsigned long)ds_buf->seg_size, ds_buf->seg_name) ); } out: /* in this component, the id is the file descriptor returned by open. this * check is here to see if it is safe to call close on the file descriptor. * that is, we are making sure that our call to open was successful and * we are not not in an error path. */ if (-1 != ds_buf->seg_id) { if (0 != close(ds_buf->seg_id)) { int err = errno; char hn[MAXHOSTNAMELEN]; gethostname(hn, MAXHOSTNAMELEN - 1); hn[MAXHOSTNAMELEN - 1] = '\0'; opal_show_help("help-opal-shmem-mmap.txt", "sys call fail", 1, hn, "close(2)", "", strerror(err), err); rc = OPAL_ERROR; } } /* an error occured, so invalidate the shmem object and release any * allocated resources. */ if (OPAL_SUCCESS != rc) { /* posix_shm_open was successful, but something else wasn't. * note: if the id is not equal to -1 and we are here, name will be * valid. that is, we can safely call shm_unlink with ds_buf->name. */ if (-1 != ds_buf->seg_id) { shm_unlink(ds_buf->seg_name); } if (MAP_FAILED != seg_hdrp) { munmap((void*)seg_hdrp, real_size); } /* always invalidate in this error path */ shmem_ds_reset(ds_buf); } return rc; }
/* ////////////////////////////////////////////////////////////////////////// */ static int segment_create(opal_shmem_ds_t *ds_buf, const char *file_name, size_t size) { int rc = OPAL_SUCCESS; char *real_file_name = NULL; pid_t my_pid = getpid(); bool space_available = false; uint64_t amount_space_avail = 0; /* the real size of the shared memory segment. this includes enough space * to store our segment header. */ size_t real_size = size + sizeof(opal_shmem_seg_hdr_t); opal_shmem_seg_hdr_t *seg_hdrp = MAP_FAILED; /* init the contents of opal_shmem_ds_t */ shmem_ds_reset(ds_buf); /* change the path of shmem mmap's backing store? */ if (0 != opal_shmem_mmap_relocate_backing_file) { int err; if (path_usable(opal_shmem_mmap_backing_file_base_dir, &err)) { if (NULL == (real_file_name = get_uniq_file_name(opal_shmem_mmap_backing_file_base_dir, file_name))) { /* out of resources */ return OPAL_ERROR; } } /* a relocated backing store was requested, but the path specified * cannot be used :-(. if the flag is negative, then warn and continue * with the default path. otherwise, fail. */ else if (opal_shmem_mmap_relocate_backing_file < 0) { opal_output(0, "shmem: mmap: WARNING: could not relocate " "backing store to \"%s\" (%s). Continuing with " "default path.\n", opal_shmem_mmap_backing_file_base_dir, strerror(err)); } /* must be positive, so fail */ else { opal_output(0, "shmem: mmap: WARNING: could not relocate " "backing store to \"%s\" (%s). Cannot continue with " "shmem mmap.\n", opal_shmem_mmap_backing_file_base_dir, strerror(err)); return OPAL_ERROR; } } /* are we using the default path? */ if (NULL == real_file_name) { /* use the path specified by the caller of this function */ if (NULL == (real_file_name = strdup(file_name))) { /* out of resources */ return OPAL_ERROR; } } OPAL_OUTPUT_VERBOSE( (70, opal_shmem_base_framework.framework_output, "%s: %s: backing store base directory: %s\n", mca_shmem_mmap_component.super.base_version.mca_type_name, mca_shmem_mmap_component.super.base_version.mca_component_name, real_file_name) ); /* determine whether the specified filename is on a network file system. * this is an important check because if the backing store is located on * a network filesystem, the user may see a shared memory performance hit. */ if (opal_shmem_mmap_nfs_warning && opal_path_nfs(real_file_name)) { char hn[MAXHOSTNAMELEN]; gethostname(hn, MAXHOSTNAMELEN - 1); hn[MAXHOSTNAMELEN - 1] = '\0'; opal_show_help("help-opal-shmem-mmap.txt", "mmap on nfs", 1, hn, real_file_name); } /* let's make sure we have enough space for the backing file */ if (OPAL_SUCCESS != (rc = enough_space(real_file_name, real_size, &amount_space_avail, &space_available))) { opal_output(0, "shmem: mmap: an error occurred while determining " "whether or not %s could be created.", real_file_name); /* rc is set */ goto out; } if (!space_available) { char hn[MAXHOSTNAMELEN]; gethostname(hn, MAXHOSTNAMELEN - 1); hn[MAXHOSTNAMELEN - 1] = '\0'; rc = OPAL_ERR_OUT_OF_RESOURCE; opal_show_help("help-opal-shmem-mmap.txt", "target full", 1, real_file_name, hn, (unsigned long)real_size, (unsigned long long)amount_space_avail); goto out; } /* enough space is available, so create the segment */ if (-1 == (ds_buf->seg_id = open(real_file_name, O_CREAT | O_RDWR, 0600))) { int err = errno; char hn[MAXHOSTNAMELEN]; gethostname(hn, MAXHOSTNAMELEN - 1); hn[MAXHOSTNAMELEN - 1] = '\0'; opal_show_help("help-opal-shmem-mmap.txt", "sys call fail", 1, hn, "open(2)", "", strerror(err), err); rc = OPAL_ERROR; goto out; } /* size backing file - note the use of real_size here */ if (0 != ftruncate(ds_buf->seg_id, real_size)) { int err = errno; char hn[MAXHOSTNAMELEN]; gethostname(hn, MAXHOSTNAMELEN - 1); hn[MAXHOSTNAMELEN - 1] = '\0'; opal_show_help("help-opal-shmem-mmap.txt", "sys call fail", 1, hn, "ftruncate(2)", "", strerror(err), err); rc = OPAL_ERROR; goto out; } if (MAP_FAILED == (seg_hdrp = (opal_shmem_seg_hdr_t *) mmap(NULL, real_size, PROT_READ | PROT_WRITE, MAP_SHARED, ds_buf->seg_id, 0))) { int err = errno; char hn[MAXHOSTNAMELEN]; gethostname(hn, MAXHOSTNAMELEN - 1); hn[MAXHOSTNAMELEN - 1] = '\0'; opal_show_help("help-opal-shmem-mmap.txt", "sys call fail", 1, hn, "mmap(2)", "", strerror(err), err); rc = OPAL_ERROR; goto out; } /* all is well */ else { /* -- initialize the shared memory segment -- */ opal_atomic_rmb(); /* init segment lock */ opal_atomic_init(&seg_hdrp->lock, OPAL_ATOMIC_UNLOCKED); /* i was the creator of this segment, so note that fact */ seg_hdrp->cpid = my_pid; opal_atomic_wmb(); /* -- initialize the contents of opal_shmem_ds_t -- */ ds_buf->seg_cpid = my_pid; ds_buf->seg_size = real_size; ds_buf->seg_base_addr = (unsigned char *)seg_hdrp; (void)strncpy(ds_buf->seg_name, real_file_name, OPAL_PATH_MAX - 1); /* set "valid" bit because setment creation was successful */ OPAL_SHMEM_DS_SET_VALID(ds_buf); OPAL_OUTPUT_VERBOSE( (70, opal_shmem_base_framework.framework_output, "%s: %s: create successful " "(id: %d, size: %lu, name: %s)\n", mca_shmem_mmap_component.super.base_version.mca_type_name, mca_shmem_mmap_component.super.base_version.mca_component_name, ds_buf->seg_id, (unsigned long)ds_buf->seg_size, ds_buf->seg_name) ); } out: /* in this component, the id is the file descriptor returned by open. this * check is here to see if it is safe to call close on the file descriptor. * that is, we are making sure that our call to open was successful and * we are not not in an error path. */ if (-1 != ds_buf->seg_id) { if (0 != close(ds_buf->seg_id)) { int err = errno; char hn[MAXHOSTNAMELEN]; gethostname(hn, MAXHOSTNAMELEN - 1); hn[MAXHOSTNAMELEN - 1] = '\0'; opal_show_help("help-opal-shmem-mmap.txt", "sys call fail", 1, hn, "close(2)", "", strerror(err), err); rc = OPAL_ERROR; } } /* an error occured, so invalidate the shmem object and munmap if needed */ if (OPAL_SUCCESS != rc) { if (MAP_FAILED != seg_hdrp) { munmap((void *)seg_hdrp, real_size); } shmem_ds_reset(ds_buf); } /* safe to free now because its contents have already been copied */ if (NULL != real_file_name) { free(real_file_name); } return rc; }
/* ////////////////////////////////////////////////////////////////////////// */ static int segment_create(opal_shmem_ds_t *ds_buf, const char *file_name, size_t size) { int rc = OPAL_SUCCESS; pid_t my_pid = getpid(); /* the real size of the shared memory segment. this includes enough space * to store our segment header. */ size_t real_size = size + sizeof(opal_shmem_seg_hdr_t); opal_shmem_seg_hdr_t *seg_hdrp = MAP_FAILED; /* init the contents of opal_shmem_ds_t */ shmem_ds_reset(ds_buf); /* for sysv shared memory we don't have to worry about the backing store * being located on a network file system... so no check is needed here. */ /* create a new shared memory segment and save the shmid. note the use of * real_size here */ if (-1 == (ds_buf->seg_id = shmget(IPC_PRIVATE, real_size, IPC_CREAT | IPC_EXCL | S_IRWXU))) { int err = errno; char hn[MAXHOSTNAMELEN]; gethostname(hn, MAXHOSTNAMELEN - 1); hn[MAXHOSTNAMELEN - 1] = '\0'; opal_show_help("help-opal-shmem-sysv.txt", "sys call fail", 1, hn, "shmget(2)", "", strerror(err), err); rc = OPAL_ERROR; goto out; } /* attach to the sement */ else if ((void *)-1 == (seg_hdrp = shmat(ds_buf->seg_id, NULL, 0))) { int err = errno; char hn[MAXHOSTNAMELEN]; gethostname(hn, MAXHOSTNAMELEN - 1); hn[MAXHOSTNAMELEN - 1] = '\0'; opal_show_help("help-opal-shmem-sysv.txt", "sys call fail", 1, hn, "shmat(2)", "", strerror(err), err); shmctl(ds_buf->seg_id, IPC_RMID, NULL); rc = OPAL_ERROR; goto out; } /* mark the segment for destruction - if we are here, then the run-time * component selection test detected adequate support for this type of * thing. */ else if (0 != shmctl(ds_buf->seg_id, IPC_RMID, NULL)) { int err = errno; char hn[MAXHOSTNAMELEN]; gethostname(hn, MAXHOSTNAMELEN - 1); hn[MAXHOSTNAMELEN - 1] = '\0'; opal_show_help("help-opal-shmem-sysv.txt", "sys call fail", 1, hn, "shmctl(2)", "", strerror(err), err); rc = OPAL_ERROR; goto out; } /* all is well */ else { /* -- initialize the shared memory segment -- */ opal_atomic_rmb(); /* init segment lock */ opal_atomic_init(&seg_hdrp->lock, OPAL_ATOMIC_UNLOCKED); /* i was the creator of this segment, so note that fact */ seg_hdrp->cpid = my_pid; opal_atomic_wmb(); /* -- initialize the contents of opal_shmem_ds_t -- */ ds_buf->seg_cpid = my_pid; ds_buf->seg_size = real_size; ds_buf->seg_base_addr = (unsigned char *)seg_hdrp; /* notice that we are not setting ds_buf->name here. sysv doesn't use * it, so don't worry about it - shmem_ds_reset took care of * initialization, so we aren't passing garbage around. */ /* set "valid" bit because setment creation was successful */ OPAL_SHMEM_DS_SET_VALID(ds_buf); OPAL_OUTPUT_VERBOSE( (70, opal_shmem_base_framework.framework_output, "%s: %s: create successful " "(id: %d, size: %lu, name: %s)\n", mca_shmem_sysv_component.super.base_version.mca_type_name, mca_shmem_sysv_component.super.base_version.mca_component_name, ds_buf->seg_id, (unsigned long)ds_buf->seg_size, ds_buf->seg_name) ); } out: /* an error occured, so invalidate the shmem object and release any * allocated resources. */ if (OPAL_SUCCESS != rc) { /* best effort to delete the segment. */ if ((void *)-1 != seg_hdrp) { shmdt((char*)seg_hdrp); } shmctl(ds_buf->seg_id, IPC_RMID, NULL); /* always invalidate in this error path */ shmem_ds_reset(ds_buf); } return rc; }
int mca_btl_sm_add_procs( struct mca_btl_base_module_t* btl, size_t nprocs, struct opal_proc_t **procs, struct mca_btl_base_endpoint_t **peers, opal_bitmap_t* reachability) { int return_code = OPAL_SUCCESS; int32_t n_local_procs = 0, proc, j, my_smp_rank = -1; const opal_proc_t* my_proc; /* pointer to caller's proc structure */ mca_btl_sm_t *sm_btl; bool have_connected_peer = false; char **bases; /* for easy access to the mpool_sm_module */ mca_mpool_sm_module_t *sm_mpool_modp = NULL; /* initializion */ sm_btl = (mca_btl_sm_t *)btl; /* get pointer to my proc structure */ if( NULL == (my_proc = opal_proc_local_get()) ) return OPAL_ERR_OUT_OF_RESOURCE; /* Get unique host identifier for each process in the list, * and idetify procs that are on this host. Add procs on this * host to shared memory reachbility list. Also, get number * of local procs in the procs list. */ for (proc = 0; proc < (int32_t)nprocs; proc++) { /* check to see if this proc can be reached via shmem (i.e., if they're on my local host and in my job) */ if (opal_process_name_jobid(procs[proc]->proc_name) != opal_process_name_jobid(my_proc->proc_name) || !OPAL_PROC_ON_LOCAL_NODE(procs[proc]->proc_flags)) { peers[proc] = NULL; continue; } /* check to see if this is me */ if(my_proc == procs[proc]) { my_smp_rank = mca_btl_sm_component.my_smp_rank = n_local_procs++; continue; } /* sm doesn't support heterogeneous yet... */ if (procs[proc]->proc_arch != my_proc->proc_arch) { continue; } /* we have someone to talk to */ have_connected_peer = true; if(!(peers[proc] = create_sm_endpoint(n_local_procs, procs[proc]))) { return_code = OPAL_ERROR; goto CLEANUP; } n_local_procs++; /* add this proc to shared memory accessibility list */ return_code = opal_bitmap_set_bit(reachability, proc); if(OPAL_SUCCESS != return_code) goto CLEANUP; } /* jump out if there's not someone we can talk to */ if (!have_connected_peer) goto CLEANUP; /* make sure that my_smp_rank has been defined */ if (-1 == my_smp_rank) { return_code = OPAL_ERROR; goto CLEANUP; } if (!sm_btl->btl_inited) { return_code = sm_btl_first_time_init(sm_btl, my_smp_rank, mca_btl_sm_component.sm_max_procs); if (return_code != OPAL_SUCCESS) { goto CLEANUP; } } /* set local proc's smp rank in the peers structure for * rapid access and calculate reachability */ for(proc = 0; proc < (int32_t)nprocs; proc++) { if(NULL == peers[proc]) continue; mca_btl_sm_component.sm_peers[peers[proc]->peer_smp_rank] = peers[proc]; peers[proc]->my_smp_rank = my_smp_rank; } bases = mca_btl_sm_component.shm_bases; sm_mpool_modp = (mca_mpool_sm_module_t *)mca_btl_sm_component.sm_mpool; /* initialize own FIFOs */ /* * The receiver initializes all its FIFOs. All components will * be allocated near the receiver. Nothing will be local to * "the sender" since there will be many senders. */ for(j = mca_btl_sm_component.num_smp_procs; j < mca_btl_sm_component.num_smp_procs + FIFO_MAP_NUM(n_local_procs); j++) { return_code = sm_fifo_init( mca_btl_sm_component.fifo_size, mca_btl_sm_component.sm_mpool, &mca_btl_sm_component.fifo[my_smp_rank][j], mca_btl_sm_component.fifo_lazy_free); if(return_code != OPAL_SUCCESS) goto CLEANUP; } opal_atomic_wmb(); /* Sync with other local procs. Force the FIFO initialization to always * happens before the readers access it. */ opal_atomic_add_32(&mca_btl_sm_component.sm_seg->module_seg->seg_inited, 1); while( n_local_procs > mca_btl_sm_component.sm_seg->module_seg->seg_inited) { opal_progress(); opal_atomic_rmb(); } /* it is now safe to unlink the shared memory segment. only one process * needs to do this, so just let smp rank zero take care of it. */ if (0 == my_smp_rank) { if (OPAL_SUCCESS != mca_common_sm_module_unlink(mca_btl_sm_component.sm_seg)) { /* it is "okay" if this fails at this point. we have gone this far, * so just warn about the failure and continue. this is probably * only triggered by a programming error. */ opal_output(0, "WARNING: common_sm_module_unlink failed.\n"); } /* SKG - another abstraction violation here, but I don't want to add * extra code in the sm mpool for further synchronization. */ /* at this point, all processes have attached to the mpool segment. so * it is safe to unlink it here. */ if (OPAL_SUCCESS != mca_common_sm_module_unlink(sm_mpool_modp->sm_common_module)) { opal_output(0, "WARNING: common_sm_module_unlink failed.\n"); } if (-1 == unlink(mca_btl_sm_component.sm_mpool_rndv_file_name)) { opal_output(0, "WARNING: %s unlink failed.\n", mca_btl_sm_component.sm_mpool_rndv_file_name); } if (-1 == unlink(mca_btl_sm_component.sm_rndv_file_name)) { opal_output(0, "WARNING: %s unlink failed.\n", mca_btl_sm_component.sm_rndv_file_name); } } /* free up some space used by the name buffers */ free(mca_btl_sm_component.sm_mpool_ctl_file_name); free(mca_btl_sm_component.sm_mpool_rndv_file_name); free(mca_btl_sm_component.sm_ctl_file_name); free(mca_btl_sm_component.sm_rndv_file_name); /* coordinate with other processes */ for(j = mca_btl_sm_component.num_smp_procs; j < mca_btl_sm_component.num_smp_procs + n_local_procs; j++) { ptrdiff_t diff; /* spin until this element is allocated */ /* doesn't really wait for that process... FIFO might be allocated, but not initialized */ opal_atomic_rmb(); while(NULL == mca_btl_sm_component.shm_fifo[j]) { opal_progress(); opal_atomic_rmb(); } /* Calculate the difference as (my_base - their_base) */ diff = ADDR2OFFSET(bases[my_smp_rank], bases[j]); /* store local address of remote fifos */ mca_btl_sm_component.fifo[j] = (sm_fifo_t*)OFFSET2ADDR(diff, mca_btl_sm_component.shm_fifo[j]); /* cache local copy of peer memory node number */ mca_btl_sm_component.mem_nodes[j] = mca_btl_sm_component.shm_mem_nodes[j]; } /* update the local smp process count */ mca_btl_sm_component.num_smp_procs += n_local_procs; /* make sure we have enough eager fragmnents for each process */ return_code = ompi_free_list_resize_mt(&mca_btl_sm_component.sm_frags_eager, mca_btl_sm_component.num_smp_procs * 2); if (OPAL_SUCCESS != return_code) goto CLEANUP; CLEANUP: return return_code; }
/* ////////////////////////////////////////////////////////////////////////// */ static int segment_create(opal_shmem_ds_t *ds_buf, const char *file_name, size_t size) { int rc = OPAL_SUCCESS; pid_t my_pid = getpid(); char *temp1 = NULL, *temp2 = NULL; bool space_available = false; uint64_t amount_space_avail = 0; /* the real size of the shared memory segment. this includes enough space * to store our segment header. */ size_t real_size = size + sizeof(opal_shmem_seg_hdr_t); opal_shmem_seg_hdr_t *seg_hdrp = NULL; HANDLE hMapObject = INVALID_HANDLE_VALUE; LPVOID lpvMem = NULL; /* init the contents of opal_shmem_ds_t */ shmem_ds_reset(ds_buf); /* On Windows the shared file will be created by the OS directly on the * system ressources. Therefore, no file get involved in the operation. * However, a unique key should be used as name for the shared memory object * in order to allow all processes to access the same unique shared memory * region. The key will be obtained from the original file_name by replacing * all path separator occurences by '/' (as '\' is not allowed on the object * name). */ temp1 = strdup(file_name); if (NULL == temp1) { return OPAL_ERR_OUT_OF_RESOURCE; } temp2 = temp1; while (NULL != (temp2 = strchr(temp2, OPAL_PATH_SEP[0])) ) { *temp2 = '/'; } /* let's make sure we have enough space for the backing file */ if (OPAL_SUCCESS != (rc = enough_space(temp1, real_size, &amount_space_avail, &space_available))) { opal_output(0, "shmem: windows: an error occurred while determining " "whether or not %s could be created.", temp1); /* rc is set */ free(temp1); goto out; } if (!space_available) { char hn[MAXHOSTNAMELEN]; gethostname(hn, MAXHOSTNAMELEN - 1); hn[MAXHOSTNAMELEN - 1] = '\0'; rc = OPAL_ERR_OUT_OF_RESOURCE; opal_show_help("help-opal-shmem-windows.txt", "target full", 1, temp1, hn, (unsigned long)real_size, (unsigned long long)amount_space_avail); free(temp1); goto out; } /* enough space is available, so create the segment */ /* use paging file */ hMapObject = CreateFileMapping(INVALID_HANDLE_VALUE, /* no security attributes */ NULL, /* read/write access */ PAGE_READWRITE, /* size: high 32-bits */ 0, /* size: low 32-bits */ (DWORD)real_size, /* name of map object */ temp1); if (NULL == hMapObject) { rc = OPAL_ERROR; goto out; } /* Get a pointer to the file-mapped shared memory. */ lpvMem = MapViewOfFile(hMapObject, /* object to map view of */ FILE_MAP_WRITE, /* read/write access */ 0, /* high offset: map from */ 0, /* low offset: beginning */ 0); /* default: map entire file */ if (NULL == lpvMem) { rc = OPAL_ERROR; goto out; } seg_hdrp = (opal_shmem_seg_hdr_t *)lpvMem; /* all is well */ /* -- initialize the shared memory segment -- */ opal_atomic_rmb(); /* init segment lock */ opal_atomic_init(&seg_hdrp->lock, OPAL_ATOMIC_UNLOCKED); /* i was the creator of this segment, so note that fact */ seg_hdrp->cpid = my_pid; opal_atomic_wmb(); /* -- initialize the contents of opal_shmem_ds_t -- */ ds_buf->seg_cpid = my_pid; ds_buf->seg_size = real_size; ds_buf->seg_base_addr = (unsigned char *)seg_hdrp; /* update path change in ds_buf */ memcpy(ds_buf->seg_name, temp1, OPAL_PATH_MAX); /* relase the temporary file name */ free(temp1); /* set "valid" bit because setment creation was successful */ OPAL_SHMEM_DS_SET_VALID(ds_buf); OPAL_OUTPUT_VERBOSE( (70, opal_shmem_base_output, "%s: %s: create successful " "(id: %d, size: %"PRIsize_t", name: %s)\n", mca_shmem_windows_component.super.base_version.mca_type_name, mca_shmem_windows_component.super.base_version.mca_component_name, ds_buf->seg_id, ds_buf->seg_size, ds_buf->seg_name) ); out: /* an error occured, so invalidate the shmem object and munmap if needed */ if (OPAL_SUCCESS != rc) { if (NULL != seg_hdrp) { UnmapViewOfFile((LPVOID)seg_hdrp); } shmem_ds_reset(ds_buf); } return rc; }
int main(int argc, char *argv[]) { int tid; pthread_t *th; if (argc != 2) { printf("*** Incorrect number of arguments. Skipping test\n"); return 77; } nthreads = atoi(argv[1]); /* first test single-threaded functionality */ /* -- cmpset 32-bit tests -- */ vol32 = 42, old32 = 42, new32 = 50; assert(opal_atomic_compare_exchange_strong_32 (&vol32, &old32, new32) == true); opal_atomic_rmb(); assert(vol32 == new32); assert(old32 == 42); vol32 = 42, old32 = 420, new32 = 50; assert(opal_atomic_compare_exchange_strong_32 (&vol32, &old32, new32) == false); opal_atomic_rmb(); assert(vol32 == 42); assert(old32 == 42); vol32 = 42, old32 = 42, new32 = 50; assert(opal_atomic_compare_exchange_strong_32 (&vol32, &old32, new32) == true); assert(vol32 == new32); assert(old32 == 42); vol32 = 42, old32 = 420, new32 = 50; assert(opal_atomic_compare_exchange_strong_acq_32 (&vol32, &old32, new32) == false); assert(vol32 == 42); assert(old32 == 42); vol32 = 42, old32 = 42, new32 = 50; assert(opal_atomic_compare_exchange_strong_rel_32 (&vol32, &old32, new32) == true); opal_atomic_rmb(); assert(vol32 == new32); assert(old32 == 42); vol32 = 42, old32 = 420, new32 = 50; assert(opal_atomic_compare_exchange_strong_rel_32 (&vol32, &old32, new32) == false); opal_atomic_rmb(); assert(vol32 == 42); assert(old32 == 42); /* -- cmpset 64-bit tests -- */ #if OPAL_HAVE_ATOMIC_MATH_64 vol64 = 42, old64 = 42, new64 = 50; assert(opal_atomic_compare_exchange_strong_64 (&vol64, &old64, new64) == true); opal_atomic_rmb(); assert(new64 == vol64); assert(old64 == 42); vol64 = 42, old64 = 420, new64 = 50; assert(opal_atomic_compare_exchange_strong_64 (&vol64, &old64, new64) == false); opal_atomic_rmb(); assert(vol64 == 42); assert(old64 == 42); vol64 = 42, old64 = 42, new64 = 50; assert(opal_atomic_compare_exchange_strong_acq_64 (&vol64, &old64, new64) == true); assert(vol64 == new64); assert(old64 == 42); vol64 = 42, old64 = 420, new64 = 50; assert(opal_atomic_compare_exchange_strong_acq_64 (&vol64, &old64, new64) == false); assert(vol64 == 42); assert(old64 == 42); vol64 = 42, old64 = 42, new64 = 50; assert(opal_atomic_compare_exchange_strong_rel_64 (&vol64, &old64, new64) == true); opal_atomic_rmb(); assert(vol64 == new64); assert(old64 == 42); vol64 = 42, old64 = 420, new64 = 50; assert(opal_atomic_compare_exchange_strong_rel_64 (&vol64, &old64, new64) == false); opal_atomic_rmb(); assert(vol64 == 42); assert(old64 == 42); #endif /* -- cmpset 128-bit tests -- */ #if OPAL_HAVE_ATOMIC_COMPARE_EXCHANGE_128 vol128 = 42, old128 = 42, new128 = 50; assert(opal_atomic_compare_exchange_strong_128 (&vol128, &old128, new128) == true); opal_atomic_rmb(); assert(new128 == vol128); assert(old128 == 42); vol128 = 42, old128 = 420, new128 = 50; assert(opal_atomic_compare_exchange_strong_128 (&vol128, &old128, new128) == false); opal_atomic_rmb(); assert(vol128 == 42); assert(old128 == 42); #endif /* -- cmpset int tests -- */ volint = 42, oldint = 42, newint = 50; assert(opal_atomic_compare_exchange_strong (&volint, &oldint, newint) == true); opal_atomic_rmb(); assert(volint == newint); assert(oldint == 42); volint = 42, oldint = 420, newint = 50; assert(opal_atomic_compare_exchange_strong (&volint, &oldint, newint) == false); opal_atomic_rmb(); assert(volint == 42); assert(oldint == 42); volint = 42, oldint = 42, newint = 50; assert(opal_atomic_compare_exchange_strong_acq (&volint, &oldint, newint) == true); assert(volint == newint); assert(oldint == 42); volint = 42, oldint = 420, newint = 50; assert(opal_atomic_compare_exchange_strong_acq (&volint, &oldint, newint) == false); assert(volint == 42); assert(oldint == 42); volint = 42, oldint = 42, newint = 50; assert(opal_atomic_compare_exchange_strong_rel (&volint, &oldint, newint) == true); opal_atomic_rmb(); assert(volint == newint); assert(oldint == 42); volint = 42, oldint = 420, newint = 50; assert(opal_atomic_compare_exchange_strong_rel (&volint, &oldint, newint) == false); opal_atomic_rmb(); assert(volint == 42); assert(oldint == 42); /* -- cmpset ptr tests -- */ volptr = 42, oldptr = 42, newptr = 50; assert(opal_atomic_compare_exchange_strong_ptr (&volptr, &oldptr, newptr) == true); opal_atomic_rmb(); assert(volptr == newptr); assert(oldptr == 42); volptr = 42, oldptr = 420, newptr = 50; assert(opal_atomic_compare_exchange_strong_ptr (&volptr, &oldptr, newptr) == false); opal_atomic_rmb(); assert(volptr == 42); assert(oldptr == 42); volptr = 42, oldptr = 42, newptr = 50; assert(opal_atomic_compare_exchange_strong_acq_ptr (&volptr, &oldptr, newptr) == true); assert(volptr == newptr); assert(oldptr == 42); volptr = 42, oldptr = 420, newptr = 50; assert(opal_atomic_compare_exchange_strong_acq_ptr (&volptr, &oldptr, newptr) == false); assert(volptr == 42); assert(oldptr == 42); volptr = 42, oldptr = 42, newptr = 50; assert(opal_atomic_compare_exchange_strong_rel_ptr (&volptr, &oldptr, newptr) == true); opal_atomic_rmb(); assert(volptr == newptr); assert(oldptr == 42); volptr = 42, oldptr = 420, newptr = 50; assert(opal_atomic_compare_exchange_strong_rel_ptr (&volptr, &oldptr, newptr) == false); opal_atomic_rmb(); assert(volptr == 42); assert(oldptr == 42); /* -- add_32 tests -- */ val32 = 42; assert(opal_atomic_add_fetch_32(&val32, 5) == (42 + 5)); opal_atomic_rmb(); assert((42 + 5) == val32); /* -- add_64 tests -- */ #if OPAL_HAVE_ATOMIC_MATH_64 val64 = 42; assert(opal_atomic_add_fetch_64(&val64, 5) == (42 + 5)); opal_atomic_rmb(); assert((42 + 5) == val64); #endif /* -- add_int tests -- */ valint = 42; opal_atomic_add (&valint, 5); opal_atomic_rmb(); assert((42 + 5) == valint); /* threaded tests */ val32 = 0; #if OPAL_HAVE_ATOMIC_MATH_64 val64 = 0ul; #endif valint = 0; /* -- create the thread set -- */ th = (pthread_t *) malloc(nthreads * sizeof(pthread_t)); if (!th) { perror("malloc"); exit(EXIT_FAILURE); } for (tid = 0; tid < nthreads; tid++) { if (pthread_create(&th[tid], NULL, thread_main, (void *) (unsigned long) tid) != 0) { perror("pthread_create"); exit(EXIT_FAILURE); } } /* -- wait for the thread set to finish -- */ for (tid = 0; tid < nthreads; tid++) { void *thread_return; if (pthread_join(th[tid], &thread_return) != 0) { perror("pthread_join"); exit(EXIT_FAILURE); } } free(th); opal_atomic_rmb(); assert((5 * nthreads * nreps) == val32); #if OPAL_HAVE_ATOMIC_MATH_64 opal_atomic_rmb(); assert((5 * nthreads * nreps) == val64); #endif opal_atomic_rmb(); assert((5 * nthreads * nreps) == valint); return 0; }