19f0612e4SBarry Smith /* 29f0612e4SBarry Smith Code for allocating Unix shared memory on MPI rank 0 and later accessing it from other MPI processes 39f0612e4SBarry Smith */ 4ce78bad3SBarry Smith #include <petsc/private/petscimpl.h> 59f0612e4SBarry Smith #include <petscsys.h> 69f0612e4SBarry Smith 79f0612e4SBarry Smith PetscBool PCMPIServerActive = PETSC_FALSE; // PETSc is running in server mode 8927f4375SPierre Jolivet PetscBool PCMPIServerInSolve = PETSC_FALSE; // A parallel server solve is occurring 99f0612e4SBarry Smith PetscBool PCMPIServerUseShmget = PETSC_TRUE; // Use Unix shared memory for distributing objects 109f0612e4SBarry Smith 119f0612e4SBarry Smith #if defined(PETSC_HAVE_SHMGET) 129f0612e4SBarry Smith #include <sys/shm.h> 139f0612e4SBarry Smith #include <sys/mman.h> 149f0612e4SBarry Smith #include <errno.h> 159f0612e4SBarry Smith 169f0612e4SBarry Smith typedef struct _PetscShmgetAllocation *PetscShmgetAllocation; 179f0612e4SBarry Smith struct _PetscShmgetAllocation { 189f0612e4SBarry Smith void *addr; // address on this process; points to same physical address on all processes 199f0612e4SBarry Smith int shmkey, shmid; 209f0612e4SBarry Smith size_t sz; 219f0612e4SBarry Smith PetscShmgetAllocation next; 229f0612e4SBarry Smith }; 239f0612e4SBarry Smith static PetscShmgetAllocation allocations = NULL; 249f0612e4SBarry Smith 259f0612e4SBarry Smith typedef struct { 269f0612e4SBarry Smith size_t shmkey[3]; 279f0612e4SBarry Smith size_t sz[3]; 289f0612e4SBarry Smith } BcastInfo; 299f0612e4SBarry Smith 309f0612e4SBarry Smith #endif 319f0612e4SBarry Smith 329f0612e4SBarry Smith /*@C 339f0612e4SBarry Smith PetscShmgetAddressesFinalize - frees any shared memory that was allocated by `PetscShmgetAllocateArray()` but 349f0612e4SBarry Smith not deallocated with `PetscShmgetDeallocateArray()` 359f0612e4SBarry Smith 369f0612e4SBarry Smith Level: developer 379f0612e4SBarry Smith 389f0612e4SBarry Smith Notes: 399f0612e4SBarry Smith This prevents any shared memory allocated, but not deallocated, from remaining on the system and preventing 409f0612e4SBarry Smith its future use. 419f0612e4SBarry Smith 429f0612e4SBarry Smith If the program crashes outstanding shared memory allocations may remain. 439f0612e4SBarry Smith 449f0612e4SBarry Smith .seealso: `PetscShmgetAllocateArray()`, `PetscShmgetDeallocateArray()`, `PetscShmgetUnmapAddresses()` 459f0612e4SBarry Smith @*/ 469f0612e4SBarry Smith PetscErrorCode PetscShmgetAddressesFinalize(void) 479f0612e4SBarry Smith { 489f0612e4SBarry Smith PetscFunctionBegin; 499f0612e4SBarry Smith #if defined(PETSC_HAVE_SHMGET) 509f0612e4SBarry Smith PetscShmgetAllocation next = allocations, previous = NULL; 519f0612e4SBarry Smith 529f0612e4SBarry Smith while (next) { 537255af2bSBarry Smith PetscCheck(!shmctl(next->shmid, IPC_RMID, NULL), PETSC_COMM_SELF, PETSC_ERR_SYS, "Unable to free shared memory key %d shmid %d %s, see PCMPIServerBegin()", next->shmkey, next->shmid, strerror(errno)); 549f0612e4SBarry Smith previous = next; 559f0612e4SBarry Smith next = next->next; 569f0612e4SBarry Smith PetscCall(PetscFree(previous)); 579f0612e4SBarry Smith } 589f0612e4SBarry Smith #endif 599f0612e4SBarry Smith PetscFunctionReturn(PETSC_SUCCESS); 609f0612e4SBarry Smith } 619f0612e4SBarry Smith 629f0612e4SBarry Smith /* takes a void so can work bsan safe with PetscObjectContainerCompose() */ 6349abdd8aSBarry Smith PetscErrorCode PCMPIServerAddressesDestroy(void **ctx) 649f0612e4SBarry Smith { 6549abdd8aSBarry Smith PCMPIServerAddresses *addresses = (PCMPIServerAddresses *)*ctx; 669f0612e4SBarry Smith 679f0612e4SBarry Smith PetscFunctionBegin; 689f0612e4SBarry Smith #if defined(PETSC_HAVE_SHMGET) 699f0612e4SBarry Smith PetscCall(PetscShmgetUnmapAddresses(addresses->n, addresses->addr)); 709f0612e4SBarry Smith PetscCall(PetscFree(addresses)); 719f0612e4SBarry Smith #endif 729f0612e4SBarry Smith PetscFunctionReturn(PETSC_SUCCESS); 739f0612e4SBarry Smith } 749f0612e4SBarry Smith 759f0612e4SBarry Smith /*@C 769f0612e4SBarry Smith PetscShmgetMapAddresses - given shared address on the first MPI process determines the 779f0612e4SBarry Smith addresses on the other MPI processes that map to the same physical memory 789f0612e4SBarry Smith 799f0612e4SBarry Smith Input Parameters: 809f0612e4SBarry Smith + comm - the `MPI_Comm` to scatter the address 819f0612e4SBarry Smith . n - the number of addresses, each obtained on MPI process zero by `PetscShmgetAllocateArray()` 829f0612e4SBarry Smith - baseaddres - the addresses on the first MPI process, ignored on all but first process 839f0612e4SBarry Smith 849f0612e4SBarry Smith Output Parameter: 859f0612e4SBarry Smith . addres - the addresses on each MPI process, the array of void * must already be allocated 869f0612e4SBarry Smith 879f0612e4SBarry Smith Level: developer 889f0612e4SBarry Smith 899f0612e4SBarry Smith Note: 909f0612e4SBarry Smith This routine does nothing if `PETSC_HAVE_SHMGET` is not defined 919f0612e4SBarry Smith 929f0612e4SBarry Smith .seealso: `PetscShmgetDeallocateArray()`, `PetscShmgetAllocateArray()`, `PetscShmgetUnmapAddresses()` 939f0612e4SBarry Smith @*/ 949f0612e4SBarry Smith PetscErrorCode PetscShmgetMapAddresses(MPI_Comm comm, PetscInt n, const void **baseaddres, void **addres) 959f0612e4SBarry Smith { 969f0612e4SBarry Smith PetscFunctionBegin; 979f0612e4SBarry Smith #if defined(PETSC_HAVE_SHMGET) 989f0612e4SBarry Smith if (PetscGlobalRank == 0) { 999f0612e4SBarry Smith BcastInfo bcastinfo = { 1009f0612e4SBarry Smith {0, 0, 0}, 1019f0612e4SBarry Smith {0, 0, 0} 1029f0612e4SBarry Smith }; 1039f0612e4SBarry Smith for (PetscInt i = 0; i < n; i++) { 1049f0612e4SBarry Smith PetscShmgetAllocation allocation = allocations; 1059f0612e4SBarry Smith 1069f0612e4SBarry Smith while (allocation) { 1079f0612e4SBarry Smith if (allocation->addr == baseaddres[i]) { 1089f0612e4SBarry Smith bcastinfo.shmkey[i] = allocation->shmkey; 1099f0612e4SBarry Smith bcastinfo.sz[i] = allocation->sz; 1109f0612e4SBarry Smith addres[i] = (void *)baseaddres[i]; 1119f0612e4SBarry Smith break; 1129f0612e4SBarry Smith } 1139f0612e4SBarry Smith allocation = allocation->next; 1149f0612e4SBarry Smith } 1157255af2bSBarry Smith PetscCheck(allocation, comm, PETSC_ERR_PLIB, "Unable to locate PCMPI allocated shared address %p, see PCMPIServerBegin()", baseaddres[i]); 1169f0612e4SBarry Smith } 1179f0612e4SBarry Smith PetscCall(PetscInfo(NULL, "Mapping PCMPI Server array %p\n", addres[0])); 1189f0612e4SBarry Smith PetscCallMPI(MPI_Bcast(&bcastinfo, 6, MPIU_SIZE_T, 0, comm)); 1199f0612e4SBarry Smith } else { 1209f0612e4SBarry Smith BcastInfo bcastinfo = { 1219f0612e4SBarry Smith {0, 0, 0}, 1229f0612e4SBarry Smith {0, 0, 0} 1239f0612e4SBarry Smith }; 1249f0612e4SBarry Smith int shmkey = 0; 1259f0612e4SBarry Smith size_t sz = 0; 1269f0612e4SBarry Smith 1279f0612e4SBarry Smith PetscCallMPI(MPI_Bcast(&bcastinfo, 6, MPIU_SIZE_T, 0, comm)); 1289f0612e4SBarry Smith for (PetscInt i = 0; i < n; i++) { 1299f0612e4SBarry Smith PetscShmgetAllocation next = allocations, previous = NULL; 1309f0612e4SBarry Smith 1319f0612e4SBarry Smith shmkey = (int)bcastinfo.shmkey[i]; 1329f0612e4SBarry Smith sz = bcastinfo.sz[i]; 1339f0612e4SBarry Smith while (next) { 134835f2295SStefano Zampini if (next->shmkey == shmkey) addres[i] = next->addr; 1359f0612e4SBarry Smith previous = next; 1369f0612e4SBarry Smith next = next->next; 1379f0612e4SBarry Smith } 1389f0612e4SBarry Smith if (!next) { 1399f0612e4SBarry Smith PetscShmgetAllocation allocation; 1409f0612e4SBarry Smith PetscCall(PetscCalloc(sizeof(struct _PetscShmgetAllocation), &allocation)); 1419f0612e4SBarry Smith allocation->shmkey = shmkey; 1429f0612e4SBarry Smith allocation->sz = sz; 1439f0612e4SBarry Smith allocation->shmid = shmget(allocation->shmkey, allocation->sz, 0666); 1447255af2bSBarry Smith PetscCheck(allocation->shmid != -1, PETSC_COMM_SELF, PETSC_ERR_SYS, "Unable to map PCMPI shared memory key %d of size %d, see PCMPIServerBegin()", allocation->shmkey, (int)allocation->sz); 145c8025a54SPierre Jolivet allocation->addr = shmat(allocation->shmid, NULL, 0); 1467255af2bSBarry Smith PetscCheck(allocation->addr, PETSC_COMM_SELF, PETSC_ERR_SYS, "Unable to map PCMPI shared memory key %d, see PCMPIServerBegin()", allocation->shmkey); 1479f0612e4SBarry Smith addres[i] = allocation->addr; 1489f0612e4SBarry Smith if (previous) previous->next = allocation; 1499f0612e4SBarry Smith else allocations = allocation; 1509f0612e4SBarry Smith } 1519f0612e4SBarry Smith } 1529f0612e4SBarry Smith } 1539f0612e4SBarry Smith #endif 1549f0612e4SBarry Smith PetscFunctionReturn(PETSC_SUCCESS); 1559f0612e4SBarry Smith } 1569f0612e4SBarry Smith 1579f0612e4SBarry Smith /*@C 1589f0612e4SBarry Smith PetscShmgetUnmapAddresses - given shared addresses on a MPI process unlink it 1599f0612e4SBarry Smith 1609f0612e4SBarry Smith Input Parameters: 1619f0612e4SBarry Smith + n - the number of addresses, each obtained on MPI process zero by `PetscShmgetAllocateArray()` 1629f0612e4SBarry Smith - addres - the addresses 1639f0612e4SBarry Smith 1649f0612e4SBarry Smith Level: developer 1659f0612e4SBarry Smith 1669f0612e4SBarry Smith Note: 1679f0612e4SBarry Smith This routine does nothing if `PETSC_HAVE_SHMGET` is not defined 1689f0612e4SBarry Smith 1699f0612e4SBarry Smith .seealso: `PetscShmgetDeallocateArray()`, `PetscShmgetAllocateArray()`, `PetscShmgetMapAddresses()` 1709f0612e4SBarry Smith @*/ 171ce78bad3SBarry Smith PetscErrorCode PetscShmgetUnmapAddresses(PetscInt n, void **addres) PeNS 1729f0612e4SBarry Smith { 1739f0612e4SBarry Smith PetscFunctionBegin; 1749f0612e4SBarry Smith #if defined(PETSC_HAVE_SHMGET) 1759f0612e4SBarry Smith if (PetscGlobalRank > 0) { 1769f0612e4SBarry Smith for (PetscInt i = 0; i < n; i++) { 1779f0612e4SBarry Smith PetscShmgetAllocation next = allocations, previous = NULL; 1789f0612e4SBarry Smith PetscBool found = PETSC_FALSE; 1799f0612e4SBarry Smith 1809f0612e4SBarry Smith while (next) { 1819f0612e4SBarry Smith if (next->addr == addres[i]) { 1827255af2bSBarry Smith PetscCheck(!shmdt(next->addr), PETSC_COMM_SELF, PETSC_ERR_SYS, "Unable to shmdt() location %s, see PCMPIServerBegin()", strerror(errno)); 1839f0612e4SBarry Smith if (previous) previous->next = next->next; 1849f0612e4SBarry Smith else allocations = next->next; 1859f0612e4SBarry Smith PetscCall(PetscFree(next)); 1869f0612e4SBarry Smith found = PETSC_TRUE; 1879f0612e4SBarry Smith break; 1889f0612e4SBarry Smith } 1899f0612e4SBarry Smith previous = next; 1909f0612e4SBarry Smith next = next->next; 1919f0612e4SBarry Smith } 1927255af2bSBarry Smith PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unable to find address %p to unmap, see PCMPIServerBegin()", addres[i]); 1939f0612e4SBarry Smith } 1949f0612e4SBarry Smith } 1959f0612e4SBarry Smith #endif 1969f0612e4SBarry Smith PetscFunctionReturn(PETSC_SUCCESS); 1979f0612e4SBarry Smith } 1989f0612e4SBarry Smith 1999f0612e4SBarry Smith /*@C 200d7c1f440SPierre Jolivet PetscShmgetAllocateArray - allocates shared memory accessible by all MPI processes in the server 2019f0612e4SBarry Smith 2029f0612e4SBarry Smith Not Collective, only called on the first MPI process 2039f0612e4SBarry Smith 2049f0612e4SBarry Smith Input Parameters: 2059f0612e4SBarry Smith + sz - the number of elements in the array 2069f0612e4SBarry Smith - asz - the size of an entry in the array, for example `sizeof(PetscScalar)` 2079f0612e4SBarry Smith 2089f0612e4SBarry Smith Output Parameters: 2099f0612e4SBarry Smith . addr - the address of the array 2109f0612e4SBarry Smith 2119f0612e4SBarry Smith Level: developer 2129f0612e4SBarry Smith 2139f0612e4SBarry Smith Notes: 2149f0612e4SBarry Smith Uses `PetscMalloc()` if `PETSC_HAVE_SHMGET` is not defined or the MPI linear solver server is not running 2159f0612e4SBarry Smith 2169f0612e4SBarry Smith Sometimes when a program crashes, shared memory IDs may remain, making it impossible to rerun the program. 2177255af2bSBarry Smith Use 2187255af2bSBarry Smith .vb 2197255af2bSBarry Smith $PETSC_DIR/lib/petsc/bin/petscfreesharedmemory 2207255af2bSBarry Smith .ve to free that memory. The Linux command `ipcrm --all` or macOS command `for i in $(ipcs -m | tail -$(expr $(ipcs -m | wc -l) - 3) | tr -s ' ' | cut -d" " -f3); do ipcrm -M $i; done` 2217255af2bSBarry Smith will also free the memory. 2229f0612e4SBarry Smith 2239f0612e4SBarry Smith Use the Unix command `ipcs -m` to see what memory IDs are currently allocated and `ipcrm -m ID` to remove a memory ID 2249f0612e4SBarry Smith 2257255af2bSBarry Smith Under Apple macOS the following file must be copied to /Library/LaunchDaemons/sharedmemory.plist (ensure this file is owned by root and not the user) 2267255af2bSBarry Smith and the machine rebooted before using shared memory 2279f0612e4SBarry Smith .vb 2289f0612e4SBarry Smith <?xml version="1.0" encoding="UTF-8"?> 2299f0612e4SBarry Smith <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> 2309f0612e4SBarry Smith <plist version="1.0"> 2319f0612e4SBarry Smith <dict> 2329f0612e4SBarry Smith <key>Label</key> 2339f0612e4SBarry Smith <string>shmemsetup</string> 2349f0612e4SBarry Smith <key>UserName</key> 2359f0612e4SBarry Smith <string>root</string> 2369f0612e4SBarry Smith <key>GroupName</key> 2379f0612e4SBarry Smith <string>wheel</string> 2389f0612e4SBarry Smith <key>ProgramArguments</key> 2399f0612e4SBarry Smith <array> 2409f0612e4SBarry Smith <string>/usr/sbin/sysctl</string> 2419f0612e4SBarry Smith <string>-w</string> 2429f0612e4SBarry Smith <string>kern.sysv.shmmax=4194304000</string> 2439f0612e4SBarry Smith <string>kern.sysv.shmmni=2064</string> 2449f0612e4SBarry Smith <string>kern.sysv.shmseg=2064</string> 2459f0612e4SBarry Smith <string>kern.sysv.shmall=131072000</string> 2469f0612e4SBarry Smith </array> 2479f0612e4SBarry Smith <key>KeepAlive</key> 2489f0612e4SBarry Smith <false/> 2499f0612e4SBarry Smith <key>RunAtLoad</key> 2509f0612e4SBarry Smith <true/> 2519f0612e4SBarry Smith </dict> 2529f0612e4SBarry Smith </plist> 2539f0612e4SBarry Smith .ve 2549f0612e4SBarry Smith 2557255af2bSBarry Smith Use the command 2567255af2bSBarry Smith .vb 2577255af2bSBarry Smith /usr/sbin/sysctl -a | grep shm 2587255af2bSBarry Smith .ve 2597255af2bSBarry Smith to confirm that the shared memory limits you have requested are available. 2607255af2bSBarry Smith 2619f0612e4SBarry Smith Fortran Note: 2629f0612e4SBarry Smith The calling sequence is `PetscShmgetAllocateArray[Scalar,Int](PetscInt start, PetscInt len, Petsc[Scalar,Int], pointer :: d1(:), ierr)` 2639f0612e4SBarry Smith 2649f0612e4SBarry Smith Developer Note: 2659f0612e4SBarry Smith More specifically this uses `PetscMalloc()` if `!PCMPIServerUseShmget` || `!PCMPIServerActive` || `PCMPIServerInSolve` 2669f0612e4SBarry Smith where `PCMPIServerInSolve` indicates that the solve is nested inside a MPI linear solver server solve and hence should 2679f0612e4SBarry Smith not allocate the vector and matrix memory in shared memory. 2689f0612e4SBarry Smith 2699f0612e4SBarry Smith .seealso: [](sec_pcmpi), `PCMPIServerBegin()`, `PCMPI`, `KSPCheckPCMPI()`, `PetscShmgetDeallocateArray()` 2709f0612e4SBarry Smith @*/ 271ce78bad3SBarry Smith PetscErrorCode PetscShmgetAllocateArray(size_t sz, size_t asz, void *addr[]) 2729f0612e4SBarry Smith { 2739f0612e4SBarry Smith PetscFunctionBegin; 2749f0612e4SBarry Smith if (!PCMPIServerUseShmget || !PCMPIServerActive || PCMPIServerInSolve) PetscCall(PetscMalloc(sz * asz, addr)); 2759f0612e4SBarry Smith #if defined(PETSC_HAVE_SHMGET) 2769f0612e4SBarry Smith else { 2779f0612e4SBarry Smith PetscShmgetAllocation allocation; 2789f0612e4SBarry Smith static int shmkeys = 10; 2799f0612e4SBarry Smith 2809f0612e4SBarry Smith PetscCall(PetscCalloc(sizeof(struct _PetscShmgetAllocation), &allocation)); 2819f0612e4SBarry Smith allocation->shmkey = shmkeys++; 2829f0612e4SBarry Smith allocation->sz = sz * asz; 2839f0612e4SBarry Smith allocation->shmid = shmget(allocation->shmkey, allocation->sz, 0666 | IPC_CREAT); 2849f0612e4SBarry Smith PetscCheck(allocation->shmid != -1, PETSC_COMM_SELF, PETSC_ERR_LIB, "Unable to schmget() of size %d with key %d %s see PetscShmgetAllocateArray()", (int)allocation->sz, allocation->shmkey, strerror(errno)); 285c8025a54SPierre Jolivet allocation->addr = shmat(allocation->shmid, NULL, 0); 286835f2295SStefano Zampini PetscCheck(allocation->addr, PETSC_COMM_SELF, PETSC_ERR_LIB, "Unable to shmat() of shmid %d %s", allocation->shmid, strerror(errno)); 2879f0612e4SBarry Smith #if PETSC_SIZEOF_VOID_P == 8 2887a533827SSatish Balay PetscCheck((uint64_t)allocation->addr != 0xffffffffffffffff, PETSC_COMM_SELF, PETSC_ERR_LIB, "shmat() of shmid %d returned 0xffffffffffffffff %s, see PCMPIServerBegin()", allocation->shmid, strerror(errno)); 2899f0612e4SBarry Smith #endif 2909f0612e4SBarry Smith 2919f0612e4SBarry Smith if (!allocations) allocations = allocation; 2929f0612e4SBarry Smith else { 2939f0612e4SBarry Smith PetscShmgetAllocation next = allocations; 2949f0612e4SBarry Smith while (next->next) next = next->next; 2959f0612e4SBarry Smith next->next = allocation; 2969f0612e4SBarry Smith } 2979f0612e4SBarry Smith *addr = allocation->addr; 2989f0612e4SBarry Smith PetscCall(PetscInfo(NULL, "Allocating PCMPI Server array %p shmkey %d shmid %d size %d\n", *addr, allocation->shmkey, allocation->shmid, (int)allocation->sz)); 2999f0612e4SBarry Smith } 3009f0612e4SBarry Smith #endif 3019f0612e4SBarry Smith PetscFunctionReturn(PETSC_SUCCESS); 3029f0612e4SBarry Smith } 3039f0612e4SBarry Smith 3049f0612e4SBarry Smith /*@C 305d7c1f440SPierre Jolivet PetscShmgetDeallocateArray - deallocates shared memory accessible by all MPI processes in the server 3069f0612e4SBarry Smith 3079f0612e4SBarry Smith Not Collective, only called on the first MPI process 3089f0612e4SBarry Smith 3099f0612e4SBarry Smith Input Parameter: 3109f0612e4SBarry Smith . addr - the address of array 3119f0612e4SBarry Smith 3129f0612e4SBarry Smith Level: developer 3139f0612e4SBarry Smith 3149f0612e4SBarry Smith Note: 3159f0612e4SBarry Smith Uses `PetscFree()` if `PETSC_HAVE_SHMGET` is not defined or the MPI linear solver server is not running 3169f0612e4SBarry Smith 3179f0612e4SBarry Smith Fortran Note: 3189f0612e4SBarry Smith The calling sequence is `PetscShmgetDeallocateArray[Scalar,Int](Petsc[Scalar,Int], pointer :: d1(:), ierr)` 3199f0612e4SBarry Smith 3209f0612e4SBarry Smith .seealso: [](sec_pcmpi), `PCMPIServerBegin()`, `PCMPI`, `KSPCheckPCMPI()`, `PetscShmgetAllocateArray()` 3219f0612e4SBarry Smith @*/ 322ce78bad3SBarry Smith PetscErrorCode PetscShmgetDeallocateArray(void *addr[]) 3239f0612e4SBarry Smith { 3249f0612e4SBarry Smith PetscFunctionBegin; 3259f0612e4SBarry Smith if (!*addr) PetscFunctionReturn(PETSC_SUCCESS); 3269f0612e4SBarry Smith if (!PCMPIServerUseShmget || !PCMPIServerActive || PCMPIServerInSolve) PetscCall(PetscFree(*addr)); 3279f0612e4SBarry Smith #if defined(PETSC_HAVE_SHMGET) 3289f0612e4SBarry Smith else { 3299f0612e4SBarry Smith PetscShmgetAllocation next = allocations, previous = NULL; 3309f0612e4SBarry Smith 3319f0612e4SBarry Smith while (next) { 3329f0612e4SBarry Smith if (next->addr == *addr) { 3339f0612e4SBarry Smith PetscCall(PetscInfo(NULL, "Deallocating PCMPI Server array %p shmkey %d shmid %d size %d\n", *addr, next->shmkey, next->shmid, (int)next->sz)); 3347255af2bSBarry Smith PetscCheck(!shmdt(next->addr), PETSC_COMM_SELF, PETSC_ERR_SYS, "Unable to shmdt() location %s, see PCMPIServerBegin()", strerror(errno)); 3357255af2bSBarry Smith PetscCheck(!shmctl(next->shmid, IPC_RMID, NULL), PETSC_COMM_SELF, PETSC_ERR_SYS, "Unable to free shared memory addr %p key %d shmid %d %s, see PCMPIServerBegin()", *addr, next->shmkey, next->shmid, strerror(errno)); 3369f0612e4SBarry Smith *addr = NULL; 3379f0612e4SBarry Smith if (previous) previous->next = next->next; 3389f0612e4SBarry Smith else allocations = next->next; 3399f0612e4SBarry Smith PetscCall(PetscFree(next)); 3409f0612e4SBarry Smith PetscFunctionReturn(PETSC_SUCCESS); 3419f0612e4SBarry Smith } 3429f0612e4SBarry Smith previous = next; 3439f0612e4SBarry Smith next = next->next; 3449f0612e4SBarry Smith } 3459f0612e4SBarry Smith SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unable to locate PCMPI allocated shared memory address %p", *addr); 3469f0612e4SBarry Smith } 3479f0612e4SBarry Smith #endif 3489f0612e4SBarry Smith PetscFunctionReturn(PETSC_SUCCESS); 3499f0612e4SBarry Smith } 3509f0612e4SBarry Smith 3519f0612e4SBarry Smith #if defined(PETSC_USE_FORTRAN_BINDINGS) 352*6dd63270SBarry Smith #include <petsc/private/ftnimpl.h> 3539f0612e4SBarry Smith 3549f0612e4SBarry Smith #if defined(PETSC_HAVE_FORTRAN_CAPS) 3559f0612e4SBarry Smith #define petscshmgetallocatearrayscalar_ PETSCSHMGETALLOCATEARRAYSCALAR 3569f0612e4SBarry Smith #define petscshmgetdeallocatearrayscalar_ PETSCSHMGETDEALLOCATEARRAYSCALAR 3579f0612e4SBarry Smith #define petscshmgetallocatearrayint_ PETSCSHMGETALLOCATEARRAYINT 3589f0612e4SBarry Smith #define petscshmgetdeallocatearrayint_ PETSCSHMGETDEALLOCATEARRAYINT 3599f0612e4SBarry Smith #elif !defined(PETSC_HAVE_FORTRAN_UNDERSCORE) 3609f0612e4SBarry Smith #define petscshmgetallocatearrayscalar_ petscshmgetallocatearrayscalar 3619f0612e4SBarry Smith #define petscshmgetdeallocatearrayscalar_ petscshmgetdeallocatearrayscalar 3629f0612e4SBarry Smith #define petscshmgetallocatearrayint_ petscshmgetallocatearrayint 3639f0612e4SBarry Smith #define petscshmgetdeallocatearrayint_ petscshmgetdeallocatearrayint 3649f0612e4SBarry Smith #endif 3659f0612e4SBarry Smith 3669f0612e4SBarry Smith PETSC_EXTERN void petscshmgetallocatearrayscalar_(PetscInt *start, PetscInt *len, F90Array1d *a, PetscErrorCode *ierr PETSC_F90_2PTR_PROTO(ptrd)) 3679f0612e4SBarry Smith { 3689f0612e4SBarry Smith PetscScalar *aa; 3699f0612e4SBarry Smith 3709f0612e4SBarry Smith *ierr = PetscShmgetAllocateArray(*len, sizeof(PetscScalar), (void **)&aa); 3719f0612e4SBarry Smith if (*ierr) return; 3729f0612e4SBarry Smith *ierr = F90Array1dCreate(aa, MPIU_SCALAR, *start, *len, a PETSC_F90_2PTR_PARAM(ptrd)); 3739f0612e4SBarry Smith } 3749f0612e4SBarry Smith 3759f0612e4SBarry Smith PETSC_EXTERN void petscshmgetdeallocatearrayscalar_(F90Array1d *a, PetscErrorCode *ierr PETSC_F90_2PTR_PROTO(ptrd)) 3769f0612e4SBarry Smith { 3779f0612e4SBarry Smith PetscScalar *aa; 3789f0612e4SBarry Smith 3799f0612e4SBarry Smith *ierr = F90Array1dAccess(a, MPIU_SCALAR, (void **)&aa PETSC_F90_2PTR_PARAM(ptrd)); 3809f0612e4SBarry Smith if (*ierr) return; 3819f0612e4SBarry Smith *ierr = PetscShmgetDeallocateArray((void **)&aa); 3829f0612e4SBarry Smith if (*ierr) return; 3839f0612e4SBarry Smith *ierr = F90Array1dDestroy(a, MPIU_SCALAR PETSC_F90_2PTR_PARAM(ptrd)); 3849f0612e4SBarry Smith } 3859f0612e4SBarry Smith 3869f0612e4SBarry Smith PETSC_EXTERN void petscshmgetallocatearrayint_(PetscInt *start, PetscInt *len, F90Array1d *a, PetscErrorCode *ierr PETSC_F90_2PTR_PROTO(ptrd)) 3879f0612e4SBarry Smith { 388ce78bad3SBarry Smith PetscInt *aa; 3899f0612e4SBarry Smith 3909f0612e4SBarry Smith *ierr = PetscShmgetAllocateArray(*len, sizeof(PetscInt), (void **)&aa); 3919f0612e4SBarry Smith if (*ierr) return; 3929f0612e4SBarry Smith *ierr = F90Array1dCreate(aa, MPIU_INT, *start, *len, a PETSC_F90_2PTR_PARAM(ptrd)); 3939f0612e4SBarry Smith } 3949f0612e4SBarry Smith 3959f0612e4SBarry Smith PETSC_EXTERN void petscshmgetdeallocatearrayint_(F90Array1d *a, PetscErrorCode *ierr PETSC_F90_2PTR_PROTO(ptrd)) 3969f0612e4SBarry Smith { 397ce78bad3SBarry Smith PetscInt *aa; 3989f0612e4SBarry Smith 3999f0612e4SBarry Smith *ierr = F90Array1dAccess(a, MPIU_INT, (void **)&aa PETSC_F90_2PTR_PARAM(ptrd)); 4009f0612e4SBarry Smith if (*ierr) return; 4019f0612e4SBarry Smith *ierr = PetscShmgetDeallocateArray((void **)&aa); 4029f0612e4SBarry Smith if (*ierr) return; 4039f0612e4SBarry Smith *ierr = F90Array1dDestroy(a, MPIU_INT PETSC_F90_2PTR_PARAM(ptrd)); 4049f0612e4SBarry Smith } 4059f0612e4SBarry Smith 4069f0612e4SBarry Smith #endif 407