00001
00002
00003
00004
00005
00010 #include "ParFUM.h"
00011 #include "ParFUM_internals.h"
00012
00013 FEM_lock::FEM_lock(int i, femMeshModify *m) {
00014 idx = i;
00015 owner = -1;
00016 isOwner = false;
00017 isLocked = false;
00018 hasLocks = false;
00019 isLocking = false;
00020 isUnlocking = false;
00021 lockedChunks.removeAll();
00022 mmod = m;
00023 }
00024
00025 FEM_lock::FEM_lock(femMeshModify *m) {
00026 idx = -1;
00027 owner = -1;
00028 isOwner = false;
00029 isLocked = false;
00030 hasLocks = false;
00031 isLocking = false;
00032 isUnlocking = false;
00033 lockedChunks.removeAll();
00034 mmod = m;
00035 }
00036
00037 FEM_lock::~FEM_lock() {
00038
00039 if(hasLocks) {
00040 unlock();
00041 }
00042 }
00043
00044 void FEM_lock::pup(PUP::er &p) {
00045 p|idx;
00046 p|owner;
00047 p|isOwner;
00048 p|isLocked;
00049 p|hasLocks;
00050 p|isLocking;
00051 p|isUnlocking;
00052 p|lockedChunks;
00053 }
00054
00055
00056
00057 bool FEM_lock::existsChunk(int index) {
00058 for(int i=0; i<lockedChunks.size(); i++) {
00059 if(lockedChunks[i] == index) return true;
00060 }
00061 return false;
00062 }
00063
00064
00065
00071 int FEM_lock::lock(int numNodes, int *nodes, int numElems, int* elems, int elemType) {
00072 bool done = false;
00073 int ret = 0;
00074 CkAssert(!hasLocks && (lockedChunks.size()==0) && !isLocking && !isUnlocking);
00075 while(!done) {
00076 if((!isLocked || (isLocked && isOwner)) && !isUnlocking && !isLocking) {
00077 isLocking = true;
00078 for(int i=0; i<numNodes; i++) {
00079 if(i==0) {
00080 if(!existsChunk(idx)) {
00081 lockedChunks.push_back(idx);
00082 }
00083 }
00084
00085
00086 if(nodes[i] != -1) {
00087 if(nodes[i] < -1) {
00088 if(!mmod->fmMesh->node.ghost->is_valid(FEM_To_ghost_index(nodes[i]))) {
00089
00090 lockedChunks.removeAll();
00091 isLocking = false;
00092 return 0;
00093 }
00094 }
00095 else if(!mmod->fmMesh->node.is_valid(nodes[i])) {
00096
00097 lockedChunks.removeAll();
00098 isLocking = false;
00099 return 0;
00100 }
00101 int numchunks;
00102 IDXL_Share **chunks1;
00103 mmod->fmUtil->getChunkNos(0,nodes[i],&numchunks,&chunks1);
00104 for(int j=0; j<numchunks; j++) {
00105 if(!existsChunk(chunks1[j]->chk)) {
00106 lockedChunks.push_back(chunks1[j]->chk);
00107 }
00108 }
00109 for(int j=0; j<numchunks; j++) {
00110 delete chunks1[j];
00111 }
00112 if(numchunks!=0) free(chunks1);
00113 }
00114 }
00115 for(int i=0; i<numElems; i++) {
00116
00117
00118 if(elems[i] != -1) {
00119 if(elems[i] < -1) {
00120 if(!mmod->fmMesh->elem[elemType].ghost->is_valid(FEM_To_ghost_index(elems[i]))) {
00121
00122 lockedChunks.removeAll();
00123 isLocking = false;
00124 return 0;
00125 }
00126 }
00127 else if(!mmod->fmMesh->elem[elemType].is_valid(elems[i])) {
00128
00129 lockedChunks.removeAll();
00130 isLocking = false;
00131 return 0;
00132 }
00133 int numchunks;
00134 IDXL_Share **chunks1;
00135 mmod->fmUtil->getChunkNos(1,elems[i],&numchunks,&chunks1,elemType);
00136 for(int j=0; j<numchunks; j++) {
00137 if(!existsChunk(chunks1[j]->chk)) {
00138 lockedChunks.push_back(chunks1[j]->chk);
00139 }
00140 }
00141 for(int j=0; j<numchunks; j++) {
00142 delete chunks1[j];
00143 }
00144 if(numchunks!=0) free(chunks1);
00145 }
00146 }
00147
00148
00149 int tmp;
00150 int numLocks = lockedChunks.size();
00151 for(int i=0; i<numLocks; i++) {
00152 for(int j=i+1; j<numLocks; j++) {
00153 if(lockedChunks[i] > lockedChunks[j]) {
00154 tmp = lockedChunks[i];
00155 lockedChunks[i] = lockedChunks[j];
00156 lockedChunks[j] = tmp;
00157 }
00158 }
00159 }
00160
00161
00162 for(int i=0; i<numLocks; i++) {
00163 ret = lock(lockedChunks[i],idx);
00164 CkAssert(ret == 1);
00165 if(ret != 1) {
00166 return -1;
00167 } else {
00168 hasLocks = true;
00169 }
00170 }
00171 done = true;
00172 isLocking = false;
00173 }
00174 else {
00175 CthYield();
00176
00177 }
00178 }
00179 CkAssert(!isLocking && !isUnlocking && hasLocks && lockedChunks.size()>0);
00180 return 1;
00181 }
00182
00186 int FEM_lock::unlock() {
00187 bool done = false;
00188 int ret = 0;
00189 if(!hasLocks && lockedChunks.size()==0) {
00190 return 0;
00191 }
00192 CkAssert(hasLocks && (lockedChunks.size()>0) && !isUnlocking && !isLocking);
00193 while(!done) {
00194 if((!isLocked || (isLocked && isOwner)) && !isLocking && !isUnlocking) {
00195
00196 isUnlocking = true;
00197 if(hasLocks) {
00198 for(int i=0; i<lockedChunks.size(); i++) {
00199 ret = unlock(lockedChunks[i],idx);
00200 CkAssert(ret == 1);
00201 if(ret != 1) return -1;
00202 }
00203 }
00204 hasLocks = false;
00205 lockedChunks.removeAll();
00206 done = true;
00207 isUnlocking = false;
00208 }
00209 else {
00210 CthYield();
00211
00212 }
00213 }
00214 CkAssert(!isUnlocking && !isLocking && !hasLocks && (lockedChunks.size()==0));
00215 return 1;
00216 }
00217
00218 int FEM_lock::lock(int chunkNo, int own) {
00219 intMsg *ret = new intMsg(0);
00220 CkAssert(!(isLocked && (own==owner) && (chunkNo==idx)));
00221 while(true) {
00222 if((!isLocked || (chunkNo != idx)) && !isUnlocking) {
00223 if(chunkNo == idx) {
00224 isLocked = true;
00225 owner = own;
00226 if(owner == idx) {
00227 isOwner = true;
00228 hasLocks = true;
00229 }
00230 else {
00231 isOwner = false;
00232 }
00233 CkPrintf("Chunk %d locked by chunk %d\n",chunkNo, own);
00234 }
00235 else {
00236 int2Msg *imsg = new int2Msg(chunkNo,own);
00237 ret = meshMod[chunkNo].lockRemoteChunk(imsg);
00238 CkAssert(ret->i == 1);
00239 if(ret->i != 1) return -1;
00240 else {
00241 hasLocks = true;
00242 }
00243 }
00244 break;
00245 }
00246 else {
00247 CthYield();
00248 }
00249 }
00250 delete ret;
00251 return 1;
00252 }
00253
00256 int FEM_lock::unlock(int chunkNo, int own) {
00257 intMsg *ret = new intMsg(0);
00258 CkAssert(!(!isLocked && (chunkNo==idx)));
00259 CkAssert(!(isLocked && (chunkNo==idx) && (owner!=own)));
00260 while(true) {
00261 if(isLocked || (chunkNo != idx) && !isLocking) {
00262 if(chunkNo == idx) {
00263 isLocked = false;
00264 owner = -1;
00265 isOwner = false;
00266 CkPrintf("Chunk %d unlocked by chunk %d\n",chunkNo, own);
00267 }
00268 else {
00269 int2Msg *imsg = new int2Msg(chunkNo,own);
00270 ret = meshMod[chunkNo].unlockRemoteChunk(imsg);
00271 CkAssert(ret->i == 1);
00272 if(ret->i != 1) return -1;
00273 }
00274 break;
00275 }
00276 else {
00277 CthYield();
00278 }
00279 }
00280 delete ret;
00281 return 1;
00282 }
00283