Line data Source code
1 : /** \file sharedMemSegment.cpp
2 : * \author Jared R. Males (jaredmales@gmail.com)
3 : * \brief Definitions for the mxlib shared memory facility
4 : * \ingroup IPC_sharedmem
5 : * \ingroup IPC
6 : *
7 : */
8 :
9 : //***********************************************************************//
10 : // Copyright 2021 Jared R. Males (jaredmales@gmail.com)
11 : //
12 : // This file is part of mxlib.
13 : //
14 : // mxlib is free software: you can redistribute it and/or modify
15 : // it under the terms of the GNU General Public License as published by
16 : // the Free Software Foundation, either version 3 of the License, or
17 : // (at your option) any later version.
18 : //
19 : // mxlib is distributed in the hope that it will be useful,
20 : // but WITHOUT ANY WARRANTY; without even the implied warranty of
21 : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 : // GNU General Public License for more details.
23 : //
24 : // You should have received a copy of the GNU General Public License
25 : // along with mxlib. If not, see <http://www.gnu.org/licenses/>.
26 : //***********************************************************************//
27 :
28 : #include "ipc/sharedMemSegment.hpp"
29 :
30 : namespace mx
31 : {
32 : namespace ipc
33 : {
34 :
35 0 : void sharedMemSegment::initialize()
36 : {
37 0 : key_id = 0;
38 0 : key = 0;
39 0 : shmemid = 0;
40 0 : addr = 0;
41 0 : size = 0;
42 :
43 0 : attached = 0;
44 0 : }
45 :
46 0 : key_t sharedMemSegment::setKey( const char *path, const int id )
47 : {
48 0 : if( path != 0 )
49 : {
50 0 : strncpy( key_path, path, MX_IPC_KEYLEN );
51 0 : key_id = id;
52 :
53 0 : key = ftok( key_path, key_id );
54 : }
55 : else
56 : {
57 0 : key_path[0] = 0;
58 0 : key_id = id;
59 :
60 0 : key = id;
61 : }
62 :
63 0 : return key;
64 : }
65 :
66 0 : int sharedMemSegment::create( size_t sz )
67 : {
68 0 : if( ( shmemid = shmget( key, sz + 1 * sizeof( uintptr_t ), IPC_CREAT | 0666 ) ) < 0 )
69 : {
70 : // If it failed, try to remove the shmem block and recreate it.
71 0 : shmemid = shmget( key, 1, 0666 );
72 0 : if( shmctl( shmemid, IPC_RMID, 0 ) < 0 )
73 : {
74 0 : fprintf( stderr, "Could not remove shared memory with key %i\n", key );
75 0 : return -1;
76 : }
77 :
78 : // removal successful, now try to create again
79 0 : if( ( shmemid = shmget( key, sz + 1 * sizeof( uintptr_t ), IPC_CREAT | 0666 ) ) < 0 )
80 : {
81 0 : fprintf( stderr, "Could not create shared memory with key %i\n", key );
82 0 : return -1;
83 : }
84 : }
85 :
86 0 : attach( true );
87 :
88 : // Since we created this segment, we set the address field.
89 0 : *( (uintptr_t *)addr ) = (uintptr_t)addr;
90 :
91 0 : return 0;
92 : }
93 :
94 0 : int sharedMemSegment::attach( bool donot_set_addr )
95 : {
96 : struct shmid_ds shmstats;
97 : void *new_addr;
98 :
99 0 : if( shmemid == 0 )
100 : {
101 0 : if( ( shmemid = shmget( key, 0, 0666 ) ) < 0 )
102 : {
103 0 : fprintf( stderr, "Could not remove shared memory with key %i\n", key );
104 0 : return -1;
105 : }
106 : }
107 :
108 0 : if( ( new_addr = shmat( shmemid, 0, 0 ) ) == (char *)-1 )
109 : {
110 0 : fprintf( stderr, "Could not attach to shared memory with key %i\n", key );
111 0 : return -1;
112 : }
113 :
114 0 : attached = 1;
115 :
116 0 : if( shmctl( shmemid, IPC_STAT, &shmstats ) < 0 )
117 : {
118 0 : fprintf( stderr, "Could not get shared memory stats with key %i\n", key );
119 0 : return -1;
120 : }
121 :
122 0 : size = shmstats.shm_segsz;
123 :
124 : // Here we first read in the address from the first unitptr_t size block
125 : // then detach, then re-attach specifying the address.
126 0 : if( !donot_set_addr )
127 : {
128 0 : addr = (void *)*( (uintptr_t *)new_addr ); // read the address from the segment itself
129 :
130 : // now detach
131 0 : if( shmdt( new_addr ) != 0 )
132 : {
133 0 : fprintf( stderr, "Unable to detach from shared memory\n" );
134 0 : return -1;
135 : }
136 :
137 0 : attached = 0;
138 :
139 : // and then re-attach, but now specifying an address
140 0 : if( ( new_addr = shmat( shmemid, addr, 0 ) ) == (char *)-1 )
141 : {
142 0 : fprintf( stderr, "Could not re-attach shared memory with key %i\n", key );
143 0 : return -1;
144 : }
145 : }
146 : else
147 : {
148 0 : addr = new_addr;
149 : }
150 :
151 0 : attached = 1;
152 :
153 0 : return 0;
154 : }
155 :
156 0 : int sharedMemSegment::detach()
157 : {
158 :
159 0 : if( attached )
160 0 : return 0;
161 :
162 0 : if( addr == 0 )
163 0 : return 0;
164 :
165 : // now detach
166 0 : if( shmdt( addr ) != 0 )
167 : {
168 0 : fprintf( stderr, "Unable to detach from shared memory\n" );
169 0 : return -1;
170 : }
171 :
172 0 : return 0;
173 : }
174 :
175 : } // namespace ipc
176 : } // namespace mx
|