source: ThirdParty/mpqc_open/src/lib/util/group/memshm.cc@ 7516f6

Action_Thermostats Adding_MD_integration_tests Adding_StructOpt_integration_tests AutomationFragmentation_failures Candidate_v1.6.1 ChemicalSpaceEvaluator Enhanced_StructuralOptimization Enhanced_StructuralOptimization_continued Exclude_Hydrogens_annealWithBondGraph Fix_Verbose_Codepatterns ForceAnnealing_with_BondGraph ForceAnnealing_with_BondGraph_continued ForceAnnealing_with_BondGraph_continued_betteresults ForceAnnealing_with_BondGraph_contraction-expansion Gui_displays_atomic_force_velocity JobMarket_RobustOnKillsSegFaults JobMarket_StableWorkerPool PythonUI_with_named_parameters Recreated_GuiChecks StoppableMakroAction TremoloParser_IncreasedPrecision
Last change on this file since 7516f6 was 860145, checked in by Frederik Heber <heber@…>, 8 years ago

Merge commit '0b990dfaa8c6007a996d030163a25f7f5fc8a7e7' as 'ThirdParty/mpqc_open'

  • Property mode set to 100644
File size: 12.8 KB
Line 
1//
2// memshm.cc
3//
4// Copyright (C) 1996 Limit Point Systems, Inc.
5//
6// Author: Curtis Janssen <cljanss@limitpt.com>
7// Maintainer: LPS
8//
9// This file is part of the SC Toolkit.
10//
11// The SC Toolkit is free software; you can redistribute it and/or modify
12// it under the terms of the GNU Library General Public License as published by
13// the Free Software Foundation; either version 2, or (at your option)
14// any later version.
15//
16// The SC Toolkit is distributed in the hope that it will be useful,
17// but WITHOUT ANY WARRANTY; without even the implied warranty of
18// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19// GNU Library General Public License for more details.
20//
21// You should have received a copy of the GNU Library General Public License
22// along with the SC Toolkit; see the file COPYING.LIB. If not, write to
23// the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
24//
25// The U.S. Government is granted a limited license as per AL 91-7.
26//
27
28#ifndef _util_group_memshm_cc
29#define _util_group_memshm_cc
30
31#ifdef __GNUC__
32#pragma implementation
33#endif
34
35#include <util/misc/formio.h>
36#include <util/group/pool.h>
37#include <util/group/memshm.h>
38#include <limits.h>
39#include <errno.h>
40
41using namespace std;
42using namespace sc;
43
44#ifndef SHMMAX
45// glibc 2.0.3 isn't defining SHMMAX so make set it here
46# ifdef __linux__
47# define SHMMAX 0x1000000
48# else
49# define SHMMAX INT_MAX
50# endif
51#endif
52
53#ifndef SHMMIN
54#define SHMMIN 1
55#endif
56
57#ifndef SIMPLE_LOCK
58#define SIMPLE_LOCK 1
59#endif
60
61#undef DEBUG
62
63static ClassDesc ShmMemoryGrp_cd(
64 typeid(ShmMemoryGrp),"ShmMemoryGrp",1,"public MsgMemoryGrp",
65 0, create<ShmMemoryGrp>, 0);
66
67ShmMemoryGrp::ShmMemoryGrp(const Ref<MessageGrp>& msg):
68 MsgMemoryGrp(msg)
69{
70 update_ = 0;
71 data_ = 0;
72 memory_ = 0;
73 pool_ = 0;
74 rangelock_ = 0;
75 nregion_ = 0;
76 shmid_ = 0;
77 attach_address_ = 0;
78}
79
80ShmMemoryGrp::ShmMemoryGrp(const Ref<KeyVal>& keyval):
81 MsgMemoryGrp(keyval)
82{
83 update_ = 0;
84 data_ = 0;
85 memory_ = 0;
86 pool_ = 0;
87 rangelock_ = 0;
88 nregion_ = 0;
89 shmid_ = 0;
90 attach_address_ = 0;
91}
92
93int
94ShmMemoryGrp::attach_memory(void *ataddress, int size)
95{
96 int i;
97 int fail = 0;
98 int isize;
99 int rsize = size;
100 for (i=0; i<nregion_; i++) {
101 attach_address_[i] = 0;
102 }
103 for (i=0; rsize>0; i++,rsize-=isize) {
104 isize = rsize;
105 if (isize > SHMMAX) isize = SHMMAX;
106 else if (isize < SHMMIN) isize = SHMMIN;
107 if (debug_) {
108 ExEnv::outn() << me() << ": ";
109 ExEnv::outn() << "ShmMemoryGrp: attaching segment with "
110 << isize << " bytes at address " << (void*)ataddress
111 << " on node " << me()
112 << endl;
113 }
114 attach_address_[i] = shmat(shmid_[i],(SHMTYPE)ataddress,0);
115 if (debug_) {
116 ExEnv::outn() << me() << ": ";
117 ExEnv::outn() << "ShmMemoryGrp: got address "
118 << (void*)attach_address_[i]
119 << " on node " << me()
120 << endl;
121 }
122 if (attach_address_[i] == 0
123 || attach_address_[i] == (void*) -1
124 || ataddress && attach_address_[i] != ataddress) {
125 //ExEnv::outn() << "ShmMemoryGrp: shmat: problem attaching using address: "
126 // << " " << (void*) ataddress
127 // << ": got address: "
128 // << (void*) attach_address_[i]
129 // << " on node " << me()
130 // << endl;
131 fail = 1;
132 }
133 ataddress = (void*)((char*)(attach_address_[i]) + isize);
134 }
135
136 memory_ = (void*) attach_address_[0];
137
138 if (fail) detach_memory();
139
140 return fail;
141}
142
143void
144ShmMemoryGrp::detach_memory()
145{
146 int i;
147 for (i=0; i<nregion_; i++) {
148 if (attach_address_[i] != 0 && attach_address_[i] != (void*) -1) {
149 if (debug_) {
150 ExEnv::outn() << "detaching " << (void*)attach_address_[i]
151 << " on node " << me() << endl;
152 }
153 shmdt((SHMTYPE)attach_address_[i]);
154 }
155 attach_address_[i] = 0;
156 }
157}
158
159void
160ShmMemoryGrp::set_localsize(size_t localsize)
161{
162 int i;
163
164 cleanup();
165
166 MsgMemoryGrp::set_localsize(localsize);
167
168 const int poolallocation = 160000;
169
170 update_ = new GlobalCounter[n()];
171
172 // allocate memory both the data and the Pool
173 int size = poolallocation + distsize_to_size(totalsize());
174 // compute the number of shared memory regions that will be needed
175 nregion_ = size/SHMMAX;
176 if (size%SHMMAX) nregion_++;
177 shmid_ = new int[nregion_];
178 attach_address_ = new void*[nregion_];
179
180 // get the shared memory segments
181 if (me() == 0) {
182 int rsize = size;
183 int isize;
184 for (i=0; rsize>0; i++,rsize-=isize) {
185 isize = rsize;
186 if (isize > SHMMAX) isize = SHMMAX;
187 else if (isize < SHMMIN) isize = SHMMIN;
188 if (debug_) {
189 ExEnv::outn() << me() << ": ";
190 ExEnv::outn() << "ShmMemoryGrp: getting segment with " << isize
191 << " bytes" << endl;
192 }
193 shmid_[i] = shmget(IPC_PRIVATE, isize, IPC_CREAT | SHM_R | SHM_W);
194 if (shmid_[i] == -1) {
195 ExEnv::outn() << me() << ": ";
196 ExEnv::outn() << "ShmMemoryGrp: shmget failed for "
197 << isize << " bytes: "
198 << strerror(errno) << endl;
199 abort();
200 }
201 }
202 }
203
204 if (me() == 0) {
205 lock_.initialize();
206 lock_ = 1;
207 char * stringrep = lock_.stringrep();
208 int length = strlen(stringrep) + 1;
209 msg_->bcast(&length, 1);
210 msg_->bcast(stringrep, length);
211#ifdef DEBUG
212 ExEnv::outn() << scprintf("%d: sent initialize string of \"%s\" (%d)\n",
213 me(), stringrep, length);
214 ExEnv::outn().flush();
215#endif // DEBUG
216 delete[] stringrep;
217 for (i=0; i<n(); i++) {
218 update_[i].initialize();
219 char * stringrep = update_[i].stringrep();
220 int length = strlen(stringrep) + 1;
221 msg_->bcast(&length, 1);
222 msg_->bcast(stringrep, length);
223#ifdef DEBUG
224 ExEnv::outn() << scprintf("%d: sent initialize string of \"%s\" (%d) for %d\n",
225 me(), stringrep, length, i);
226 ExEnv::outn().flush();
227#endif // DEBUG
228 delete[] stringrep;
229 }
230 }
231 else {
232 int length;
233 msg_->bcast(&length, 1);
234 char * stringrep = new char[length];
235 msg_->bcast(stringrep, length);
236#ifdef DEBUG
237 ExEnv::outn() << scprintf("%d: got initialize string of \"%s\" (%d)\n",
238 me(), stringrep, length);
239 ExEnv::outn().flush();
240#endif // DEBUG
241 lock_.initialize(stringrep);
242 delete[] stringrep;
243 for (i=0; i<n(); i++) {
244 msg_->bcast(&length, 1);
245 stringrep = new char[length];
246 msg_->bcast(stringrep, length);
247#ifdef DEBUG
248 ExEnv::outn() << scprintf("%d: got initialize string of \"%s\" (%d) for %d\n",
249 me(), stringrep, length, i);
250 ExEnv::outn().flush();
251#endif // DEBUG
252 update_[i].initialize(stringrep);
253 delete[] stringrep;
254 }
255 }
256
257 // get an initial starting address on node 0
258 int ntry = 20;
259 int itry;
260 void *address;
261 if (me() == 0) {
262 address = 0;
263 itry = 0;
264 while (attach_memory(address,size) && itry < ntry) {
265 if (address == 0) address = memory_;
266 else address = (void*) &((char*)address)[0x1000000];
267 itry++;
268 }
269 if (itry == ntry) {
270 ExEnv::errn() << "ShmMemoryGrp: ntry exhausted on node 0" << endl;
271 abort();
272 }
273 // detach again, since we all try together below
274 detach_memory();
275 }
276
277 msg_->bcast(shmid_, nregion_);
278 msg_->raw_bcast((void*)&memory_, sizeof(void*));
279
280 address = memory_;
281 itry = 0;
282 int fail;
283 do {
284 fail = attach_memory(address,size);
285 msg_->max(fail);
286 if (fail) {
287 detach_memory();
288 }
289 address = (void*) &((char*)address)[0x1000000];
290 itry++;
291 } while(fail && itry < ntry);
292 if (itry == ntry) {
293 ExEnv::errn() << "ShmMemoryGrp: ntry exhausted on node " << me()
294 << " on joint attach phase" << endl;
295 abort();
296 }
297
298 if (me() == 0) {
299 // initialize the pool
300 pool_ = new(memory_) Pool(poolallocation);
301 rangelock_ = new(pool_->allocate(sizeof(RangeLock))) RangeLock(pool_);
302 }
303
304 msg_->raw_bcast((void*)&pool_, sizeof(void*));
305 msg_->raw_bcast((void*)&rangelock_, sizeof(void*));
306
307 if (debug_) {
308 ExEnv::outn() << scprintf("%d: memory_ = 0x%x shmid_[0] = %d\n",
309 me(), memory_, shmid_[0]);
310 }
311
312 data_ = (void *) &((char*)memory_)[poolallocation];
313}
314
315void *
316ShmMemoryGrp::localdata()
317{
318 return &((char*)data_)[distsize_to_size(localoffset())];
319}
320
321void
322ShmMemoryGrp::cleanup()
323{
324
325 if (memory_) {
326 for (int i=0; i<nregion_; i++) {
327 shmdt((SHMTYPE)attach_address_[i]);
328 }
329
330 msg_->sync();
331
332 if (me() == 0) {
333 for (int i=0; i<nregion_; i++) {
334 shmctl(shmid_[i],IPC_RMID,0);
335 }
336 }
337 memory_ = 0;
338 }
339
340 delete[] update_;
341 update_ = 0;
342
343 nregion_ = 0;
344 delete[] shmid_;
345 delete[] attach_address_;
346 shmid_ = 0;
347 attach_address_ = 0;
348}
349
350ShmMemoryGrp::~ShmMemoryGrp()
351{
352 cleanup();
353
354#ifdef DEBUG
355 ExEnv::outn() << scprintf("msg_->nreference() = %d\n", msg_->nreference());
356 ExEnv::outn().flush();
357#endif // DEBUG
358 msg_ = 0;
359}
360
361void *
362ShmMemoryGrp::obtain_readwrite(distsize_t offset, int size)
363{
364 if (offset + size > totalsize()) {
365 ExEnv::errn() << scprintf("ShmMemoryGrp::obtain_readwrite: arg out of range\n");
366 abort();
367 }
368
369#if SIMPLE_LOCK
370 obtain_lock();
371#else // SIMPLE_LOCK
372#ifdef DEBUG
373 ExEnv::outn() << scprintf("%d: clear_release_count\n", me());
374 ExEnv::outn().flush();
375#endif // DEBUG
376 clear_release_count();
377#ifdef DEBUG
378 ExEnv::outn() << scprintf("%d: obtain_lock\n", me());
379 ExEnv::outn().flush();
380#endif // DEBUG
381 obtain_lock();
382#ifdef DEBUG
383 ExEnv::outn() << scprintf("%d: checkeq\n", me());
384 ExEnv::outn().flush();
385#endif
386 while (!rangelock_->checkeq(offset, offset + size, 0)) {
387#ifdef DEBUG
388 ExEnv::outn() << scprintf("%d: range not zero -- waiting for release\n", me());
389 ExEnv::outn().flush();
390#endif // DEBUG
391 //rangelock_->print();
392 release_lock();
393 wait_for_release();
394 obtain_lock();
395 }
396 rangelock_->decrement(offset, offset + size);
397#ifdef DEBUG
398 ExEnv::outn() << scprintf("%d: after obtain write\n", me());
399 ExEnv::outn().flush();
400 //rangelock_->print();
401#endif // DEBUG
402 release_lock();
403#endif // SIMPLE_LOCK
404
405 return &((char*)data_)[distsize_to_size(offset)];
406}
407
408void *
409ShmMemoryGrp::obtain_readonly(distsize_t offset, int size)
410{
411 if (offset + size > totalsize()) {
412 ExEnv::errn() << scprintf("ShmMemoryGrp::obtain_readonly: arg out of range\n");
413 abort();
414 }
415
416 return &((char*)data_)[distsize_to_size(offset)];
417}
418
419void *
420ShmMemoryGrp::obtain_writeonly(distsize_t offset, int size)
421{
422 if (offset + size > totalsize()) {
423 ExEnv::errn() << scprintf("ShmMemoryGrp::obtain_writeonly: arg out of range\n");
424 abort();
425 }
426
427 return &((char*)data_)[distsize_to_size(offset)];
428}
429
430void
431ShmMemoryGrp::release_readonly(void *data, distsize_t offset, int size)
432{
433}
434
435void
436ShmMemoryGrp::release_writeonly(void *data, distsize_t offset, int size)
437{
438}
439
440void
441ShmMemoryGrp::release_readwrite(void *data, distsize_t offset, int size)
442{
443#if SIMPLE_LOCK
444 release_lock();
445#else // SIMPLE_LOCK
446 obtain_lock();
447 rangelock_->increment(offset, offset + size);
448 note_release();
449#ifdef DEBUG
450 ExEnv::outn() << scprintf("%d: after release write\n", me());
451 //rangelock_->print();
452 ExEnv::outn().flush();
453#endif // DEBUG
454 release_lock();
455#endif // SIMPLE_LOCK
456}
457
458void
459ShmMemoryGrp::obtain_lock()
460{
461#ifdef DEBUG
462 ExEnv::outn() << scprintf("%d: lock val = %d\n", me(), lock_.val());
463 ExEnv::outn().flush();
464#endif // DEBUG
465 lock_--;
466#ifdef DEBUG
467 ExEnv::outn() << scprintf("%d: lock decremented\n", me());
468 ExEnv::outn().flush();
469#endif // DEBUG
470}
471
472void
473ShmMemoryGrp::release_lock()
474{
475 lock_++;
476#ifdef DEBUG
477 ExEnv::outn() << scprintf("%d: incremented lock\n", me());
478 ExEnv::outn().flush();
479#endif // DEBUG
480}
481
482void
483ShmMemoryGrp::note_release()
484{
485 for (int i=0; i<n(); i++) {
486 update_[i]++;
487 }
488#ifdef DEBUG
489 ExEnv::outn() << scprintf("%d: incremented release flags\n", me());
490 ExEnv::outn().flush();
491#endif // DEBUG
492}
493
494void
495ShmMemoryGrp::wait_for_release()
496{
497#ifdef DEBUG
498 ExEnv::outn() << scprintf("%d: decrementing release flag\n", me());
499 ExEnv::outn().flush();
500#endif // DEBUG
501 update_[me()]--;
502#ifdef DEBUG
503 ExEnv::outn() << scprintf("%d: decremented release flag\n", me());
504 ExEnv::outn().flush();
505#endif // DEBUG
506}
507
508void
509ShmMemoryGrp::clear_release_count()
510{
511 update_[me()] = 0;
512#ifdef DEBUG
513 ExEnv::outn() << scprintf("%d: clearing release count\n", me());
514 ExEnv::outn().flush();
515#endif // DEBUG
516}
517
518void
519ShmMemoryGrp::print(ostream &o) const
520{
521 MemoryGrp::print(o);
522}
523
524#endif
525
526/////////////////////////////////////////////////////////////////////////////
527
528// Local Variables:
529// mode: c++
530// c-file-style: "CLJ"
531// End:
Note: See TracBrowser for help on using the repository browser.