00001
00015 #include "converse.h"
00016 #include "quiescence.h"
00017 #include <stdio.h>
00018 #include <stdlib.h>
00019 #ifndef DEBUGF
00020 #define DEBUGF(x)
00021 #endif
00022
00023 CpvDeclare(CQdState, cQdState);
00024 unsigned int _CQdHandlerIdx;
00025 unsigned int _CQdAnnounceHandlerIdx;
00026
00027
00028 int CQdMsgGetPhase(CQdMsg msg)
00029 { return msg->phase; }
00030
00031 void CQdMsgSetPhase(CQdMsg msg, int p)
00032 { msg->phase = p; }
00033
00034 int CQdMsgGetCreated(CQdMsg msg)
00035 { CmiAssert(msg->phase==1); return msg->u.p1.created; }
00036
00037 void CQdMsgSetCreated(CQdMsg msg, int c)
00038 { CmiAssert(msg->phase==1); msg->u.p1.created = c; }
00039
00040 int CQdMsgGetProcessed(CQdMsg msg)
00041 { CmiAssert(msg->phase==1); return msg->u.p1.processed; }
00042
00043 void CQdMsgSetProcessed(CQdMsg msg, int p)
00044 { CmiAssert(msg->phase==1); msg->u.p1.processed = p; }
00045
00046 int CQdMsgGetDirty(CQdMsg msg)
00047 { CmiAssert(msg->phase==2); return msg->u.p2.dirty; }
00048
00049 void CQdMsgSetDirty(CQdMsg msg, int d)
00050 { CmiAssert(msg->phase==2); msg->u.p2.dirty = d; }
00051
00052
00053 int CQdGetCreated(CQdState state)
00054 { return state->mCreated; }
00055
00056 void CQdCreate(CQdState state, int n)
00057 { state->mCreated += n; }
00058
00059 int CQdGetProcessed(CQdState state)
00060 { return state->mProcessed; }
00061
00062 void CQdProcess(CQdState state, int n)
00063 { state->mProcessed += n; }
00064
00065 void CQdPropagate(CQdState state, CQdMsg msg)
00066 {
00067 int i;
00068 CmiSetHandler(msg, _CQdHandlerIdx);
00069 for(i=0; i<state->nChildren; i++) {
00070 CQdCreate(state, -1);
00071 CmiSyncSend(state->children[i], sizeof(struct ConvQdMsg), (char *)msg);
00072 }
00073 }
00074
00075 int CQdGetParent(CQdState state)
00076 { return state->parent; }
00077
00078 int CQdGetCCreated(CQdState state)
00079 { return state->cCreated; }
00080
00081 int CQdGetCProcessed(CQdState state)
00082 { return state->cProcessed; }
00083
00084 void CQdSubtreeCreate(CQdState state, int c)
00085 { state->cCreated += c; }
00086
00087 void CQdSubtreeProcess(CQdState state, int p)
00088 { state->cProcessed += p; }
00089
00090 int CQdGetStage(CQdState state)
00091 { return state->stage; }
00092
00093 void CQdSetStage(CQdState state, int p)
00094 { state->stage = p; }
00095
00096 void CQdReported(CQdState state)
00097 { state->nReported++; }
00098
00099 int CQdAllReported(CQdState state)
00100 { return state->nReported==(state->nChildren+1);}
00101
00102 void CQdReset(CQdState state)
00103 {
00104 state->nReported=0; state->cCreated=0;
00105 state->cProcessed=0; state->cDirty=0;
00106 }
00107
00108 void CQdMarkProcessed(CQdState state)
00109 { state->oProcessed = state->mProcessed; }
00110
00111 int CQdIsDirty(CQdState state)
00112 { return ((state->mProcessed > state->oProcessed) || state->cDirty); }
00113
00114 void CQdSubtreeSetDirty(CQdState state, int d)
00115 { state->cDirty = state->cDirty || d; }
00116
00117 CQdState CQdStateCreate(void)
00118 {
00119 CQdState state = (CQdState) malloc(sizeof(struct ConvQdState));
00120 _MEMCHECK(state);
00121 state->mCreated = 0;
00122 state->mProcessed = 0;
00123 state->stage = 0;
00124 state->nReported = 0;
00125 state->oProcessed = 0;
00126 state->cCreated = 0;
00127 state->cProcessed = 0;
00128 state->cDirty = 0;
00129 state->nChildren = CmiNumSpanTreeChildren(CmiMyPe());
00130 state->parent = CmiSpanTreeParent(CmiMyPe());
00131
00132 if (state->nChildren) {
00133 state->children = (int *) malloc(state->nChildren*sizeof(int));
00134 _MEMCHECK(state->children);
00135 }
00136 else
00137 state->children = NULL;
00138 CmiSpanTreeChildren(CmiMyPe(), state->children);
00139
00140 return state;
00141 }
00142
00143
00144 static void CQdBcastQD1(CQdState state, CQdMsg msg)
00145 {
00146 CQdMsgSetPhase(msg, 0);
00147 CQdPropagate(state, msg);
00148 CQdMsgSetPhase(msg, 1);
00149 CQdMsgSetCreated(msg, CQdGetCreated(state));
00150 CQdMsgSetProcessed(msg, CQdGetProcessed(state));
00151 CQdCreate(state, -1);
00152 CmiSyncSendAndFree(CmiMyPe(), sizeof(struct ConvQdMsg), (char *) msg);
00153 CQdMarkProcessed(state);
00154 CQdReset(state);
00155 CQdSetStage(state, 1);
00156 }
00157
00158
00159 static void CQdBcastQD2(CQdState state, CQdMsg msg)
00160 {
00161 CQdMsgSetPhase(msg, 1);
00162 CQdPropagate(state, msg);
00163 CQdMsgSetPhase(msg, 2);
00164 CQdMsgSetDirty(msg, CQdIsDirty(state));
00165 CQdCreate(state, -1);
00166 CmiSyncSendAndFree(CmiMyPe(), sizeof(struct ConvQdMsg), (char *) msg);
00167 CQdReset(state);
00168 CQdSetStage(state, 2);
00169 }
00170
00171
00172 static void CQdHandlePhase0(CQdState state, CQdMsg msg)
00173 {
00174 CmiAssert(CmiMyPe()==0 || CQdGetStage(state)==0);
00175 if(CQdGetStage(state)==0)
00176 CQdBcastQD1(state, msg);
00177 else
00178 CmiFree(msg);
00179 }
00180
00181
00182 static void CQdHandlePhase1(CQdState state, CQdMsg msg)
00183 {
00184 switch(CQdGetStage(state)) {
00185 case 0 :
00186 CmiAssert(CmiMyPe()!=0);
00187 CQdBcastQD2(state, msg);
00188 break;
00189 case 1 :
00190 CQdSubtreeCreate(state, CQdMsgGetCreated(msg));
00191 CQdSubtreeProcess(state, CQdMsgGetProcessed(msg));
00192 CQdReported(state);
00193
00194 if(CQdAllReported(state)) {
00195 if(CmiMyPe()==0) {
00196 if(CQdGetCCreated(state) == CQdGetCProcessed(state))
00197 CQdBcastQD2(state, msg);
00198 else
00199 CQdBcastQD1(state, msg);
00200 }
00201 else {
00202 CQdMsgSetCreated(msg, CQdGetCCreated(state));
00203 CQdMsgSetProcessed(msg, CQdGetCProcessed(state));
00204 CQdCreate(state, -1);
00205 CmiSyncSendAndFree(CQdGetParent(state),
00206 sizeof(struct ConvQdMsg), (char *) msg);
00207 DEBUGF(("PE = %d, My parent = %d\n", CmiMyPe(), CQdGetParent(state)));
00208 CQdReset(state);
00209 CQdSetStage(state, 0);
00210 }
00211 }
00212 else
00213 CmiFree(msg);
00214 break;
00215 default:
00216 CmiAbort("Internal QD Error. Contact Developers.!\n");
00217 }
00218 }
00219
00220
00221 static void CQdHandlePhase2(CQdState state, CQdMsg msg)
00222 {
00223 CmiAssert(CQdGetStage(state)==2);
00224 CQdSubtreeSetDirty(state, CQdMsgGetDirty(msg));
00225 CQdReported(state);
00226 if(CQdAllReported(state)) {
00227 if(CmiMyPe()==0) {
00228 if(CQdIsDirty(state))
00229 CQdBcastQD1(state, msg);
00230 else {
00231 CmiSetHandler(msg, _CQdAnnounceHandlerIdx);
00232 CQdCreate(state, 0-CmiNumPes());
00233 CmiSyncBroadcastAllAndFree(sizeof(struct ConvQdMsg), (char *) msg);
00234 CQdReset(state);
00235 CQdSetStage(state, 0);
00236 }
00237 }
00238 else {
00239 CQdMsgSetDirty(msg, CQdIsDirty(state));
00240 CQdCreate(state, -1);
00241 CmiSyncSendAndFree(CQdGetParent(state),
00242 sizeof(struct ConvQdMsg), (char *) msg);
00243 CQdReset(state);
00244 CQdSetStage(state, 0);
00245 }
00246 }
00247 else
00248 CmiFree(msg);
00249 }
00250
00251
00252 static void CQdCallWhenIdle(CQdMsg msg)
00253 {
00254 CQdState state = CpvAccess(cQdState);
00255
00256 switch(CQdMsgGetPhase(msg)) {
00257 case 0 : CQdHandlePhase0(state, msg); break;
00258 case 1 : CQdHandlePhase1(state, msg); break;
00259 case 2 : CQdHandlePhase2(state, msg); break;
00260 default: CmiAbort("Internal QD Error. Contact Developers.!\n");
00261 }
00262 }
00263
00264
00265 void CQdHandler(CQdMsg msg)
00266 {
00267 CQdProcess(CpvAccess(cQdState), -1);
00268 CcdCallOnCondition(CcdPROCESSOR_STILL_IDLE,
00269 (CcdVoidFn)CQdCallWhenIdle, (void*) msg);
00270 }
00271
00272
00273 void CQdRegisterCallback(CQdVoidFn fn, void *arg)
00274 {
00275 CcdCallOnCondition(CcdQUIESCENCE, fn, arg);
00276 }
00277
00278 void CQdAnnounceHandler(CQdMsg msg)
00279 {
00280 CQdProcess(CpvAccess(cQdState), -1);
00281 CcdRaiseCondition(CcdQUIESCENCE);
00282 }
00283
00284 void CQdCpvInit(void) {
00285 CpvInitialize(CQdState, cQdState);
00286 CpvAccess(cQdState) = CQdStateCreate();
00287 }
00288
00289 void CQdInit(void)
00290 {
00291 CQdCpvInit();
00292 _CQdHandlerIdx = CmiRegisterHandler((CmiHandler)CQdHandler);
00293 _CQdAnnounceHandlerIdx =
00294 CmiRegisterHandler((CmiHandler)CQdAnnounceHandler);
00295 }
00296
00297 void CmiStartQD(CQdVoidFn fn, void *arg)
00298 {
00299 register CQdMsg msg = (CQdMsg) CmiAlloc(sizeof(struct ConvQdMsg));
00300 CQdRegisterCallback(fn, arg);
00301 CQdMsgSetPhase(msg, 0);
00302 CmiSetHandler(msg, _CQdHandlerIdx);
00303 CQdCreate(CpvAccess(cQdState), -1);
00304 CmiSyncSendAndFree(0, sizeof(struct ConvQdMsg), (char *)msg);
00305 }
00306
00307
00308