Update copyright to LGPL on all files
[dyninst.git] / valueAdded / sharedMem / src / shmSegment-win.C
1 /*
2  * Copyright (c) 1996-2009 Barton P. Miller
3  * 
4  * We provide the Paradyn Parallel Performance Tools (below
5  * described as "Paradyn") on an AS IS basis, and do not warrant its
6  * validity or performance.  We reserve the right to update, modify,
7  * or discontinue this software at any time.  We shall have no
8  * obligation to supply such updates or modifications or any other
9  * form of support to you.
10  * 
11  * By your use of Paradyn, you understand and agree that we (or any
12  * other person or entity with proprietary rights in Paradyn) are
13  * under no obligation to provide either maintenance services,
14  * update services, notices of latent defects, or correction of
15  * defects for Paradyn.
16  * 
17  * This library is free software; you can redistribute it and/or
18  * modify it under the terms of the GNU Lesser General Public
19  * License as published by the Free Software Foundation; either
20  * version 2.1 of the License, or (at your option) any later version.
21  * 
22  * This library is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25  * Lesser General Public License for more details.
26  * 
27  * You should have received a copy of the GNU Lesser General Public
28  * License along with this library; if not, write to the Free Software
29  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
30  */
31 //----------------------------------------------------------------------------
32 // $Id: shmSegment-win.C,v 1.1 2006/11/22 21:45:03 bernat Exp $
33 //----------------------------------------------------------------------------
34 //
35 // Definition of the ShmSegment class.
36 // A ShmSegment object represents a shared memory segment, providing an
37 // OS-independent interface to management of shared memory segments to 
38 // paradynd.
39 //
40 //----------------------------------------------------------------------------
41 #include "common/h/headers.h"
42 #include "common/h/std_namesp.h"
43 #include "shmSegment.h"
44 #include "../h/SharedMem.h"
45 #include "sharedMemInternal.h"
46
47
48 //----------------------------------------------------------------------------
49 // Prototypes of local functions
50 //----------------------------------------------------------------------------
51 static  BuildSegmentName( key_t key, unsigned int size, char* buffer );
52
53
54
55
56 //
57 // ShmSegment::~ShmSegment
58 //
59 // Release shared memory segment.
60 // 
61 ShmSegment::~ShmSegment( void )
62 {
63     assert( baseAddrInDaemon != NULL );
64     assert( seg_id != NULL );
65
66     // unmap the segment from our address space
67     if( !UnmapViewOfFile( (void *)baseAddrInDaemon ) )
68     {
69 #if READY
70         indicate error to user?  how?
71 #endif // READY
72     }
73
74     if(! leaveSegmentAroundOnExit) {  
75        // release the segment
76        if( !CloseHandle( seg_id ) )
77        {
78 #if READY
79        // indicate error to user? how?
80 #endif // READY
81        }
82     }
83 }
84
85
86
87 //
88 // ShmSegment::Create
89 //
90 // Access a shared memory segment whose name is based on the value
91 // of the given key, of at least the indicated size, and mapped into
92 // our address space at the indicated address (if specified).
93 // 
94 ShmSegment*
95 ShmSegment::Create( key_t& key, unsigned int size, bool freeWhenDeleted )
96 {
97     ShmSegment* seg = NULL;
98     key_t curr_key = key;
99     HANDLE hMapping = NULL;
100
101
102     while( true )
103     {
104         // attempt to create a shared memory segment
105         // with a name based on "key"
106         char segName[32];
107
108         BuildSegmentName( curr_key, size, segName );
109         hMapping = CreateFileMapping( INVALID_HANDLE_VALUE,  // shared memory
110             NULL,
111             PAGE_READWRITE,
112             0, size,
113             segName );
114         if( hMapping == NULL )
115         {
116             // unable to create segment
117 #if READY
118             indicate error to user?
119 #else
120         cerr << "Failed to create file mapping object : " << GetLastError() << endl;
121 #endif // READY
122         }
123         else if( GetLastError() == ERROR_ALREADY_EXISTS )
124         {
125             // we were trying to create a new segment,
126             // but we found an existing one
127             CloseHandle( hMapping );
128             hMapping = NULL;
129         }
130         else
131         {
132             // we created the new mapping successfully
133             key = curr_key;
134             break;
135         }
136
137         // try the next key
138         curr_key++;
139     }
140
141     // we have a mapping object, now map it into our address space
142     assert( hMapping != NULL );
143     void* mapAddr = MapViewOfFile( hMapping,
144                                     FILE_MAP_ALL_ACCESS,
145                                     0, 0,
146                                     0 );
147     if( mapAddr != NULL )
148     {
149       // we mapped the object successfully
150       // build an object to represent the segment
151       memset(mapAddr, 0, size);
152       seg = new ShmSegment( hMapping, curr_key, size, (Address) mapAddr );
153     }
154     else
155     {
156 #if READY
157         indicate failure to user
158 #else
159         cerr << "Failed to map shared memory into address space : " << GetLastError() << endl;
160 #endif // READY
161         CloseHandle( hMapping );
162     }
163
164     if (!freeWhenDeleted)
165         seg->markAsLeaveSegmentAroundOnExit();
166     
167     return seg;
168 }
169
170
171
172 //
173 // ShmSegment::Open
174 //
175 // Open and attach to an existing shared memory segment, whose name
176 // is based on the given key, of at least the indicated size, and 
177 // map it into our address space at the indcated address (if given).
178 //
179 ShmSegment*
180 ShmSegment::Open( key_t key, unsigned int size, void* addr )
181 {
182     HANDLE hMapping = NULL;
183     ShmSegment* shm = NULL;
184     char segName[32];
185
186
187     BuildSegmentName( key, size, segName );
188     hMapping = OpenFileMapping( PAGE_READWRITE, FALSE, segName );
189     if( hMapping != NULL )
190     {
191         // we opened the existing mapping object,
192         // now we need to map it into our address space
193         void* mapAddr = MapViewOfFile( hMapping,      // map object
194                                         FILE_MAP_ALL_ACCESS,    // permissions
195                                         0, 0,                   // high and low offsets of map start address
196                                         0 );                    // map entire file
197         if( mapAddr != NULL )
198         {
199             // build an object to represent the segment
200           shm = new ShmSegment( hMapping, key, size, (Address) mapAddr );
201         }
202         else
203         {
204 #if READY
205             indicate failure to user?
206 #else
207             cerr << "Failed to map shared memory into address space : " << GetLastError() << endl;
208 #endif // READY
209             CloseHandle( hMapping );
210             hMapping = NULL;
211         }
212     }
213     else
214     {
215 #if READY
216         indicate failure to user?
217 #else
218         cerr << "Failed to create file mapping object : " << GetLastError() << endl;
219 #endif // READY
220     }
221
222     return shm;
223 }
224
225 ShmSegment *ShmSegment::Copy(BPatch_process *child_thr,
226                              bool sameAddress) {
227     // Not implemented
228     assert(0 && "Not implemented");
229     return NULL;
230 }
231
232 //
233 // BuildSegmentName
234 //
235 // Build a name for a named shared memory semgent based on the 
236 // given key value and size.
237 //
238 static int
239 BuildSegmentName( key_t key, unsigned int size, char* buffer )
240 {
241     sprintf( buffer, "ParadynD_%d_%d", key, size );
242     return 0;
243 }
244
245
246