/* * Copyright (C) by Argonne National Laboratory * See COPYRIGHT in top-level directory */ #include "mpl.h" MPL_SUPPRESS_OSX_HAS_NO_SYMBOLS_WARNING; #ifdef MPL_USE_NT_SHM #include #include /* A template function which creates/attaches shm seg handle * to the shared memory. Used by user-exposed functions below */ static inline int MPL_shm_seg_create_attach_templ(MPL_shm_hnd_t hnd, intptr_t seg_sz, void **shm_addr_ptr, int offset, int flag) { HANDLE lhnd = INVALID_HANDLE_VALUE; int rc = MPL_SUCCESS; ULARGE_INTEGER seg_sz_large; seg_sz_large.QuadPart = seg_sz; if (!MPLI_shm_ghnd_is_valid(hnd)) { rc = MPLI_shm_ghnd_set_uniq(hnd); if (rc) { goto fn_exit; } } if (flag & MPLI_SHM_FLAG_SHM_CREATE) { lhnd = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, seg_sz_large.HighPart, seg_sz_large.LowPart, MPLI_shm_ghnd_get_by_ref(hnd)); if (lhnd == NULL) { rc = MPL_ERR_SHM_INTERN; goto fn_exit; } MPLI_shm_lhnd_set(hnd, lhnd); } else { if (!MPLI_shm_lhnd_is_valid(hnd)) { /* Strangely OpenFileMapping() returns NULL on error! */ lhnd = OpenFileMapping(FILE_MAP_WRITE, FALSE, MPLI_shm_ghnd_get_by_ref(hnd)); if (lhnd == NULL) { rc = MPL_ERR_SHM_INTERN; goto fn_exit; } MPLI_shm_lhnd_set(hnd, lhnd); } } if (flag & MPLI_SHM_FLAG_SHM_ATTACH) { if (flag & MPLI_SHM_FLAG_FIXED_ADDR) { void *start_addr = (void *) *shm_addr_ptr; /* The start_addr must be a multiple of the system's memory allocation granularity, * or the function fails. To determine the memory allocation granularity of the system, * use the GetSystemInfo function. If there is not enough address space at the * specified address, the function fails. * If the function fails, the return value is NULL.*/ *shm_addr_ptr = MapViewOfFileEx(MPLI_shm_lhnd_get(hnd), FILE_MAP_WRITE, 0, offset, 0, start_addr); } else { *shm_addr_ptr = MapViewOfFile(MPLI_shm_lhnd_get(hnd), FILE_MAP_WRITE, 0, offset, 0); } if (*shm_addr_ptr == NULL) { rc = MPL_ERR_SHM_INVAL; } } fn_exit: return rc; } /* Create new SHM segment * hnd : A "init"ed shared memory handle * seg_sz : Size of shared memory segment to be created */ int MPL_shm_seg_create(MPL_shm_hnd_t hnd, intptr_t seg_sz) { return MPL_shm_seg_create_attach_templ(hnd, seg_sz, NULL, 0, MPLI_SHM_FLAG_SHM_CREATE); } /* Open an existing SHM segment * hnd : A shm handle with a valid global handle * seg_sz : Size of shared memory segment to open * Currently only using internally within wrapper funcs */ int MPL_shm_seg_open(MPL_shm_hnd_t hnd, intptr_t seg_sz) { return MPL_shm_seg_create_attach_templ(hnd, seg_sz, NULL, 0, MPLI_SHM_FLAG_CLR); } /* Create new SHM segment and attach to it * hnd : A "init"ed shared mem handle * seg_sz: Size of shared mem segment * shm_addr_ptr : Pointer to shared memory address to attach * the shared mem segment * offset : Offset to attach the shared memory address to */ int MPL_shm_seg_create_and_attach(MPL_shm_hnd_t hnd, intptr_t seg_sz, void **shm_addr_ptr, int offset) { return MPL_shm_seg_create_attach_templ(hnd, seg_sz, shm_addr_ptr, offset, MPLI_SHM_FLAG_SHM_CREATE | MPLI_SHM_FLAG_SHM_ATTACH); } /* Attach to an existing SHM segment * hnd : A "init"ed shared mem handle * seg_sz: Size of shared mem segment * shm_addr_ptr : Pointer to shared memory address to attach * the shared mem segment * offset : Offset to attach the shared memory address to */ int MPL_shm_seg_attach(MPL_shm_hnd_t hnd, intptr_t seg_sz, void **shm_addr_ptr, int offset) { return MPL_shm_seg_create_attach_templ(hnd, seg_sz, shm_addr_ptr, offset, MPLI_SHM_FLAG_SHM_ATTACH); } /* Create new SHM segment and attach to it with specified starting address * hnd : A "init"ed shared mem handle * seg_sz: Size of shared mem segment * shm_addr_ptr (inout): Pointer to specified starting address, the address cannot be NULL. * The actual attached memory address is updated at return. * offset : Offset to attach the shared memory address to */ int MPL_shm_fixed_seg_create_and_attach(MPL_shm_hnd_t hnd, intptr_t seg_sz, void **shm_addr_ptr, int offset) { return MPL_shm_seg_create_attach_templ(hnd, seg_sz, shm_addr_ptr, offset, MPLI_SHM_FLAG_SHM_CREATE | MPLI_SHM_FLAG_SHM_ATTACH | MPLI_SHM_FLAG_FIXED_ADDR, MPL_MEM_SHM); } /* Attach to an existing SHM segment with specified starting address * hnd : A "init"ed shared mem handle * seg_sz: Size of shared mem segment * shm_addr_ptr (inout): Pointer to specified starting address, the address cannot be NULL. * The actual attached memory address is updated at return. * offset : Offset to attach the shared memory address to */ int MPL_shm_fixed_seg_attach(MPL_shm_hnd_t hnd, intptr_t seg_sz, void **shm_addr_ptr, int offset) { return MPL_shm_seg_create_attach_templ(hnd, seg_sz, shm_addr_ptr, offset, MPLI_SHM_FLAG_SHM_ATTACH | MPLI_SHM_FLAG_FIXED_ADDR); } /* Detach from an attached SHM segment */ static inline int MPL_shm_seg_detach(MPL_shm_hnd_t hnd, void **shm_addr_ptr, intptr_t seg_sz) { int rc = -1; rc = UnmapViewOfFile(*shm_addr_ptr); *shm_addr_ptr = NULL; /* If the function succeeds, the return value is nonzero, * otherwise the return value is zero. */ return (rc != 0) ? MPL_SUCCESS : MPL_ERR_SHM_INTERN; } #endif /* MPL_USE_NT_SHM */