⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 memshm.cc

📁 大型并行量子化学软件;支持密度泛函(DFT)。可以进行各种量子化学计算。支持CHARMM并行计算。非常具有应用价值。
💻 CC
字号:
//// memshm.cc//// Copyright (C) 1996 Limit Point Systems, Inc.//// Author: Curtis Janssen <cljanss@limitpt.com>// Maintainer: LPS//// This file is part of the SC Toolkit.//// The SC Toolkit is free software; you can redistribute it and/or modify// it under the terms of the GNU Library General Public License as published by// the Free Software Foundation; either version 2, or (at your option)// any later version.//// The SC Toolkit is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the// GNU Library General Public License for more details.//// You should have received a copy of the GNU Library General Public License// along with the SC Toolkit; see the file COPYING.LIB.  If not, write to// the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.//// The U.S. Government is granted a limited license as per AL 91-7.//#ifndef _util_group_memshm_cc#define _util_group_memshm_cc#ifdef __GNUC__#pragma implementation#endif#include <util/misc/formio.h>#include <util/group/pool.h>#include <util/group/memshm.h>#include <limits.h>#include <errno.h>using namespace std;using namespace sc;#ifndef SHMMAX// glibc 2.0.3 isn't defining SHMMAX so make set it here#  ifdef __linux__#    define SHMMAX 0x1000000#  else#    define SHMMAX INT_MAX#  endif#endif#ifndef SHMMIN#define SHMMIN 1#endif#ifndef SIMPLE_LOCK#define SIMPLE_LOCK 1#endif#undef DEBUGstatic ClassDesc ShmMemoryGrp_cd(  typeid(ShmMemoryGrp),"ShmMemoryGrp",1,"public MsgMemoryGrp",  0, create<ShmMemoryGrp>, 0);ShmMemoryGrp::ShmMemoryGrp(const Ref<MessageGrp>& msg):  MsgMemoryGrp(msg){  update_ = 0;  data_ = 0;  memory_ = 0;  pool_ = 0;  rangelock_ = 0;  nregion_ = 0;  shmid_ = 0;  attach_address_ = 0;}ShmMemoryGrp::ShmMemoryGrp(const Ref<KeyVal>& keyval):  MsgMemoryGrp(keyval){  update_ = 0;  data_ = 0;  memory_ = 0;  pool_ = 0;  rangelock_ = 0;  nregion_ = 0;  shmid_ = 0;  attach_address_ = 0;}intShmMemoryGrp::attach_memory(void *ataddress, int size){  int i;  int fail = 0;  int isize;  int rsize = size;  for (i=0; i<nregion_; i++) {      attach_address_[i] = 0;    }  for (i=0; rsize>0; i++,rsize-=isize) {      isize = rsize;      if (isize > SHMMAX) isize = SHMMAX;      else if (isize < SHMMIN) isize = SHMMIN;      if (debug_) {          ExEnv::outn() << me() << ": ";          ExEnv::outn() << "ShmMemoryGrp: attaching segment with "               << isize << " bytes at address " << (void*)ataddress               << " on node " << me()               << endl;        }      attach_address_[i] = shmat(shmid_[i],(SHMTYPE)ataddress,0);      if (debug_) {          ExEnv::outn() << me() << ": ";          ExEnv::outn() << "ShmMemoryGrp: got address "               << (void*)attach_address_[i]               << " on node " << me()               << endl;        }      if (attach_address_[i] == 0          || attach_address_[i] == (void*) -1          || ataddress && attach_address_[i] != ataddress) {          //ExEnv::outn() << "ShmMemoryGrp: shmat: problem attaching using address: "          //     << " " << (void*) ataddress          //     << ": got address: "          //     << (void*) attach_address_[i]          //     << " on node " << me()          //     << endl;          fail = 1;        }      ataddress = (void*)((char*)(attach_address_[i]) + isize);    }  memory_ = (void*) attach_address_[0];  if (fail) detach_memory();  return fail;}voidShmMemoryGrp::detach_memory(){  int i;  for (i=0; i<nregion_; i++) {      if (attach_address_[i] != 0 && attach_address_[i] != (void*) -1) {          if (debug_) {              ExEnv::outn() << "detaching " << (void*)attach_address_[i]                   << " on node " << me() << endl;            }          shmdt((SHMTYPE)attach_address_[i]);        }      attach_address_[i] = 0;    }}voidShmMemoryGrp::set_localsize(size_t localsize){  int i;  cleanup();  MsgMemoryGrp::set_localsize(localsize);  const int poolallocation = 160000;  update_ = new GlobalCounter[n()];  // allocate memory both the data and the Pool  int size = poolallocation + distsize_to_size(totalsize());  // compute the number of shared memory regions that will be needed  nregion_ = size/SHMMAX;  if (size%SHMMAX) nregion_++;  shmid_ = new int[nregion_];  attach_address_ = new void*[nregion_];  // get the shared memory segments  if (me() == 0) {      int rsize = size;      int isize;      for (i=0; rsize>0; i++,rsize-=isize) {          isize = rsize;          if (isize > SHMMAX) isize = SHMMAX;          else if (isize < SHMMIN) isize = SHMMIN;          if (debug_) {              ExEnv::outn() << me() << ": ";              ExEnv::outn() << "ShmMemoryGrp: getting segment with " << isize                   << " bytes" << endl;            }          shmid_[i] = shmget(IPC_PRIVATE, isize, IPC_CREAT | SHM_R | SHM_W);          if (shmid_[i] == -1) {              ExEnv::outn() << me() << ": ";              ExEnv::outn() << "ShmMemoryGrp: shmget failed for "                   << isize << " bytes: "                   << strerror(errno) << endl;              abort();            }        }    }  if (me() == 0) {      lock_.initialize();      lock_ = 1;      char * stringrep = lock_.stringrep();      int length = strlen(stringrep) + 1;      msg_->bcast(&length, 1);      msg_->bcast(stringrep, length);#ifdef DEBUG      ExEnv::outn() << scprintf("%d: sent initialize string of \"%s\" (%d)\n",                       me(), stringrep, length);      ExEnv::outn().flush();#endif // DEBUG      delete[] stringrep;      for (i=0; i<n(); i++) {          update_[i].initialize();          char * stringrep = update_[i].stringrep();          int length = strlen(stringrep) + 1;          msg_->bcast(&length, 1);          msg_->bcast(stringrep, length);#ifdef DEBUG          ExEnv::outn() << scprintf("%d: sent initialize string of \"%s\" (%d) for %d\n",                           me(), stringrep, length, i);          ExEnv::outn().flush();#endif // DEBUG          delete[] stringrep;        }    }  else {      int length;      msg_->bcast(&length, 1);      char * stringrep = new char[length];      msg_->bcast(stringrep, length);#ifdef DEBUG      ExEnv::outn() << scprintf("%d: got initialize string of \"%s\" (%d)\n",                       me(), stringrep, length);      ExEnv::outn().flush();#endif // DEBUG      lock_.initialize(stringrep);      delete[] stringrep;      for (i=0; i<n(); i++) {          msg_->bcast(&length, 1);          stringrep = new char[length];          msg_->bcast(stringrep, length);#ifdef DEBUG          ExEnv::outn() << scprintf("%d: got initialize string of \"%s\" (%d) for %d\n",                           me(), stringrep, length, i);          ExEnv::outn().flush();#endif // DEBUG          update_[i].initialize(stringrep);          delete[] stringrep;        }    }  // get an initial starting address on node 0  int ntry = 20;  int itry;  void *address;  if (me() == 0) {      address = 0;      itry = 0;      while (attach_memory(address,size) && itry < ntry) {          if (address == 0) address = memory_;          else address = (void*) &((char*)address)[0x1000000];          itry++;        }      if (itry == ntry) {          ExEnv::errn() << "ShmMemoryGrp: ntry exhausted on node 0" << endl;          abort();        }      // detach again, since we all try together below      detach_memory();    }  msg_->bcast(shmid_, nregion_);  msg_->raw_bcast((void*)&memory_, sizeof(void*));  address = memory_;  itry = 0;  int fail;  do {      fail = attach_memory(address,size);      msg_->max(fail);      if (fail) {          detach_memory();        }      address = (void*) &((char*)address)[0x1000000];      itry++;    } while(fail && itry < ntry);  if (itry == ntry) {      ExEnv::errn() << "ShmMemoryGrp: ntry exhausted on node " << me()           << " on joint attach phase" << endl;      abort();    }  if (me() == 0) {      // initialize the pool      pool_ = new(memory_) Pool(poolallocation);      rangelock_ = new(pool_->allocate(sizeof(RangeLock))) RangeLock(pool_);    }  msg_->raw_bcast((void*)&pool_, sizeof(void*));  msg_->raw_bcast((void*)&rangelock_, sizeof(void*));  if (debug_) {      ExEnv::outn() << scprintf("%d: memory_ = 0x%x shmid_[0] = %d\n",                       me(), memory_, shmid_[0]);    }  data_ = (void *) &((char*)memory_)[poolallocation];}void *ShmMemoryGrp::localdata(){  return &((char*)data_)[distsize_to_size(localoffset())];}voidShmMemoryGrp::cleanup(){  if (memory_) {      for (int i=0; i<nregion_; i++) {          shmdt((SHMTYPE)attach_address_[i]);        }      msg_->sync();      if (me() == 0) {          for (int i=0; i<nregion_; i++) {              shmctl(shmid_[i],IPC_RMID,0);            }        }      memory_ = 0;    }  delete[] update_;  update_ = 0;  nregion_ = 0;  delete[] shmid_;  delete[] attach_address_;  shmid_ = 0;  attach_address_ = 0;}ShmMemoryGrp::~ShmMemoryGrp(){  cleanup();#ifdef DEBUG  ExEnv::outn() << scprintf("msg_->nreference() = %d\n", msg_->nreference());  ExEnv::outn().flush();#endif // DEBUG  msg_ = 0;}void *ShmMemoryGrp::obtain_readwrite(distsize_t offset, int size){  if (offset + size > totalsize()) {      ExEnv::errn() << scprintf("ShmMemoryGrp::obtain_readwrite: arg out of range\n");      abort();    }#if SIMPLE_LOCK  obtain_lock();#else // SIMPLE_LOCK#ifdef DEBUG  ExEnv::outn() << scprintf("%d: clear_release_count\n", me());  ExEnv::outn().flush();#endif // DEBUG  clear_release_count();#ifdef DEBUG  ExEnv::outn() << scprintf("%d: obtain_lock\n", me());  ExEnv::outn().flush();#endif // DEBUG  obtain_lock();#ifdef DEBUG  ExEnv::outn() << scprintf("%d: checkeq\n", me());  ExEnv::outn().flush();#endif  while (!rangelock_->checkeq(offset, offset + size, 0)) {#ifdef DEBUG      ExEnv::outn() << scprintf("%d: range not zero -- waiting for release\n", me());      ExEnv::outn().flush();#endif // DEBUG      //rangelock_->print();      release_lock();      wait_for_release();      obtain_lock();    }  rangelock_->decrement(offset, offset + size);#ifdef DEBUG  ExEnv::outn() << scprintf("%d: after obtain write\n", me());  ExEnv::outn().flush();  //rangelock_->print();#endif // DEBUG  release_lock();#endif // SIMPLE_LOCK  return &((char*)data_)[distsize_to_size(offset)];}void *ShmMemoryGrp::obtain_readonly(distsize_t offset, int size){  if (offset + size > totalsize()) {      ExEnv::errn() << scprintf("ShmMemoryGrp::obtain_readonly: arg out of range\n");      abort();    }  return &((char*)data_)[distsize_to_size(offset)];}void *ShmMemoryGrp::obtain_writeonly(distsize_t offset, int size){  if (offset + size > totalsize()) {      ExEnv::errn() << scprintf("ShmMemoryGrp::obtain_writeonly: arg out of range\n");      abort();    }  return &((char*)data_)[distsize_to_size(offset)];}voidShmMemoryGrp::release_readonly(void *data, distsize_t offset, int size){}voidShmMemoryGrp::release_writeonly(void *data, distsize_t offset, int size){}voidShmMemoryGrp::release_readwrite(void *data, distsize_t offset, int size){#if SIMPLE_LOCK  release_lock();#else // SIMPLE_LOCK  obtain_lock();  rangelock_->increment(offset, offset + size);  note_release();#ifdef DEBUG  ExEnv::outn() << scprintf("%d: after release write\n", me());  //rangelock_->print();  ExEnv::outn().flush();#endif // DEBUG  release_lock();#endif // SIMPLE_LOCK}voidShmMemoryGrp::obtain_lock(){#ifdef DEBUG  ExEnv::outn() << scprintf("%d: lock val = %d\n", me(), lock_.val());  ExEnv::outn().flush();#endif // DEBUG  lock_--;#ifdef DEBUG  ExEnv::outn() << scprintf("%d: lock decremented\n", me());  ExEnv::outn().flush();#endif // DEBUG}voidShmMemoryGrp::release_lock(){  lock_++;#ifdef DEBUG  ExEnv::outn() << scprintf("%d: incremented lock\n", me());  ExEnv::outn().flush();#endif // DEBUG}voidShmMemoryGrp::note_release(){  for (int i=0; i<n(); i++) {      update_[i]++;    }#ifdef DEBUG  ExEnv::outn() << scprintf("%d: incremented release flags\n", me());  ExEnv::outn().flush();#endif // DEBUG}voidShmMemoryGrp::wait_for_release(){#ifdef DEBUG  ExEnv::outn() << scprintf("%d: decrementing release flag\n", me());  ExEnv::outn().flush();#endif // DEBUG  update_[me()]--;#ifdef DEBUG  ExEnv::outn() << scprintf("%d: decremented release flag\n", me());  ExEnv::outn().flush();#endif // DEBUG}voidShmMemoryGrp::clear_release_count(){  update_[me()] = 0;#ifdef DEBUG  ExEnv::outn() << scprintf("%d: clearing release count\n", me());  ExEnv::outn().flush();#endif // DEBUG}voidShmMemoryGrp::print(ostream &o) const{  MemoryGrp::print(o);}#endif/////////////////////////////////////////////////////////////////////////////// Local Variables:// mode: c++// c-file-style: "CLJ"// End:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -