1 /*
2 * Copyright (C) by Argonne National Laboratory
3 * See COPYRIGHT in top-level directory
4 */
5
6 #include "mpl.h"
7
8 MPL_SUPPRESS_OSX_HAS_NO_SYMBOLS_WARNING;
9
10 #ifdef MPL_USE_SYSV_SHM
11
12 #include <sys/stat.h>
13 #include <sys/ipc.h>
14 #include <sys/shm.h>
15
16 /* A template function which creates/attaches shm seg handle
17 * to the shared memory. Used by user-exposed functions below
18 */
MPL_shm_seg_create_attach_templ(MPL_shm_hnd_t hnd,intptr_t seg_sz,void ** shm_addr_ptr,int offset,int flag)19 static inline int MPL_shm_seg_create_attach_templ(MPL_shm_hnd_t hnd, intptr_t seg_sz,
20 void **shm_addr_ptr, int offset, int flag)
21 {
22 int rc = MPL_SUCCESS;
23 int lhnd = -1;
24
25 if (flag & MPLI_SHM_FLAG_SHM_CREATE) {
26 lhnd = shmget(IPC_PRIVATE, seg_sz, IPC_CREAT | S_IRWXU);
27 MPLI_shm_lhnd_set(hnd, lhnd);
28 rc = MPLI_shm_ghnd_alloc(hnd, MPL_MEM_SHM);
29 if (rc) {
30 goto fn_exit;
31 }
32 rc = MPLI_shm_ghnd_set_by_val(hnd, "%d", lhnd);
33 if (rc != MPL_SUCCESS) {
34 goto fn_exit;
35 }
36 } else {
37 /* Open an existing shared memory seg */
38 if (!MPLI_shm_lhnd_is_valid(hnd)) {
39 lhnd = atoi(MPLI_shm_ghnd_get_by_ref(hnd));
40 MPLI_shm_lhnd_set(hnd, lhnd);
41 }
42 }
43
44 if (flag & MPLI_SHM_FLAG_SHM_ATTACH) {
45 const void *start_addr = NULL;
46
47 /* Caller ensures that shmaddr must be a page-aligned address
48 * at which the attach occurs. EINVAL error would result if a
49 * mapping already exists in this address range or the address
50 * is not page-aligned. */
51 if (flag & MPLI_SHM_FLAG_FIXED_ADDR)
52 start_addr = (const void *) *shm_addr_ptr;
53
54 /* Attach to shared mem seg */
55 *shm_addr_ptr = shmat(MPLI_shm_lhnd_get(hnd), start_addr, 0x0);
56 if (*shm_addr_ptr == (void *) -1) {
57 rc = MPL_ERR_SHM_INVAL;
58 }
59 }
60
61 fn_exit:
62 return rc;
63 }
64
65 /* Create new SHM segment
66 * hnd : A "init"ed shared memory handle
67 * seg_sz : Size of shared memory segment to be created
68 */
MPL_shm_seg_create(MPL_shm_hnd_t hnd,intptr_t seg_sz)69 int MPL_shm_seg_create(MPL_shm_hnd_t hnd, intptr_t seg_sz)
70 {
71 return MPL_shm_seg_create_attach_templ(hnd, seg_sz, NULL, 0, MPLI_SHM_FLAG_SHM_CREATE);
72 }
73
74 /* Open an existing SHM segment
75 * hnd : A shm handle with a valid global handle
76 * seg_sz : Size of shared memory segment to open
77 * Currently only using internally within wrapper funcs
78 */
MPL_shm_seg_open(MPL_shm_hnd_t hnd,intptr_t seg_sz)79 int MPL_shm_seg_open(MPL_shm_hnd_t hnd, intptr_t seg_sz)
80 {
81 return MPL_shm_seg_create_attach_templ(hnd, seg_sz, NULL, 0, MPLI_SHM_FLAG_CLR);
82 }
83
84 /* Create new SHM segment and attach to it
85 * hnd : A "init"ed shared mem handle
86 * seg_sz: Size of shared mem segment
87 * shm_addr_ptr : Pointer to shared memory address to attach
88 * the shared mem segment
89 * offset : Offset to attach the shared memory address to
90 */
MPL_shm_seg_create_and_attach(MPL_shm_hnd_t hnd,intptr_t seg_sz,void ** shm_addr_ptr,int offset)91 int MPL_shm_seg_create_and_attach(MPL_shm_hnd_t hnd, intptr_t seg_sz,
92 void **shm_addr_ptr, int offset)
93 {
94 return MPL_shm_seg_create_attach_templ(hnd, seg_sz, shm_addr_ptr, offset,
95 MPLI_SHM_FLAG_SHM_CREATE | MPLI_SHM_FLAG_SHM_ATTACH);
96 }
97
98 /* Attach to an existing SHM segment
99 * hnd : A "init"ed shared mem handle
100 * seg_sz: Size of shared mem segment
101 * shm_addr_ptr : Pointer to shared memory address to attach
102 * the shared mem segment
103 * offset : Offset to attach the shared memory address to
104 */
MPL_shm_seg_attach(MPL_shm_hnd_t hnd,intptr_t seg_sz,void ** shm_addr_ptr,int offset)105 int MPL_shm_seg_attach(MPL_shm_hnd_t hnd, intptr_t seg_sz, void **shm_addr_ptr, int offset)
106 {
107 return MPL_shm_seg_create_attach_templ(hnd, seg_sz, shm_addr_ptr, offset,
108 MPLI_SHM_FLAG_SHM_ATTACH);
109 }
110
111 /* Create new SHM segment and attach to it with specified starting address
112 * hnd : A "init"ed shared mem handle
113 * seg_sz: Size of shared mem segment
114 * shm_addr_ptr (inout): Pointer to specified starting address, the address cannot be NULL.
115 * The actual attached memory address is updated at return.
116 * offset : Offset to attach the shared memory address to
117 */
MPL_shm_fixed_seg_create_and_attach(MPL_shm_hnd_t hnd,intptr_t seg_sz,void ** shm_addr_ptr,int offset)118 int MPL_shm_fixed_seg_create_and_attach(MPL_shm_hnd_t hnd, intptr_t seg_sz,
119 void **shm_addr_ptr, int offset)
120 {
121 return MPL_shm_seg_create_attach_templ(hnd, seg_sz, shm_addr_ptr, offset,
122 MPLI_SHM_FLAG_SHM_CREATE | MPLI_SHM_FLAG_SHM_ATTACH |
123 MPLI_SHM_FLAG_FIXED_ADDR);
124 }
125
126 /* Attach to an existing SHM segment with specified starting address
127 * hnd : A "init"ed shared mem handle
128 * seg_sz: Size of shared mem segment
129 * shm_addr_ptr (inout): Pointer to specified starting address, the address cannot be NULL.
130 * The actual attached memory address is updated at return.
131 * offset : Offset to attach the shared memory address to
132 */
MPL_shm_fixed_seg_attach(MPL_shm_hnd_t hnd,intptr_t seg_sz,void ** shm_addr_ptr,int offset)133 int MPL_shm_fixed_seg_attach(MPL_shm_hnd_t hnd, intptr_t seg_sz, void **shm_addr_ptr, int offset)
134 {
135 return MPL_shm_seg_create_attach_templ(hnd, seg_sz, shm_addr_ptr, offset,
136 MPLI_SHM_FLAG_SHM_ATTACH | MPLI_SHM_FLAG_FIXED_ADDR);
137 }
138
139 /* Detach from an attached SHM segment
140 * hnd : Handle to the shm segment
141 * shm_addr_ptr : Pointer to the shm address to detach
142 * seg_sz : Size of shm segment
143 */
MPL_shm_seg_detach(MPL_shm_hnd_t hnd,void ** shm_addr_ptr,intptr_t seg_sz)144 int MPL_shm_seg_detach(MPL_shm_hnd_t hnd, void **shm_addr_ptr, intptr_t seg_sz)
145 {
146 int rc = -1;
147
148 rc = shmdt(*shm_addr_ptr);
149 *shm_addr_ptr = NULL;
150
151 return (rc == 0) ? MPL_SUCCESS : MPL_ERR_SHM_INTERN;
152 }
153
154 /* Remove a shared memory segment
155 * hnd : Handle to the shared memory segment to be removed
156 */
MPL_shm_seg_remove(MPL_shm_hnd_t hnd)157 int MPL_shm_seg_remove(MPL_shm_hnd_t hnd)
158 {
159 struct shmid_ds ds;
160 int rc = -1;
161
162 rc = shmctl(MPLI_shm_lhnd_get(hnd), IPC_RMID, &ds);
163
164 return (rc == 0) ? MPL_SUCCESS : MPL_ERR_SHM_INTERN;
165 }
166
167 #endif /* MPL_USE_SYSV_SHM */
168