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