void testLock(void) { gslLockMode_t mode1 = PERPROC(curProc)->testMode1; bool mode1DontWait = PERPROC(curProc)->testMode1DontWait; gslLockMode_t mode2 = PERPROC(curProc)->testMode2; bool mode2DontWait = PERPROC(curProc)->testMode2DontWait; bool got1 = false, got2 = false; got1 = gslAcquire(&theLock, mode1, mode1DontWait, NULL); if (got1) holderCounts = lcAdd(holderCounts, lcActive(mode1)); swtch(); if (mode2 != -1) { got2 = gslAcquire(&theLock, mode2, mode2DontWait, NULL); if (got2) holderCounts = lcAdd(holderCounts, lcActive(mode2)); swtch(); } // Check for conflicting held locks lockCounts_t otherCounts = lcSubtract(holderCounts, PERPROC(curProc)->perLock.holding); for (int i = 0; i < LC_MAX_MODES; ++i) { if (lcGetActive(otherCounts, i)) { if ((got1 && CONFLICTS(i, mode1)) || (got2 && CONFLICTS(i, mode2))) { fail("Conflicting lock held"); } else if ((got1 && i == mode1) || (got2 && i == mode2)) { observedSharing[i] = true; } } } // I release mode1 first so that my tests for observed sharing // remain simple. Otherwise, if mode1 overshadows mode2, then // it could prevent sharing of mode2, even if mode2 would // otherwise be sharable. (This isn't entirely reliable, but // takes care of most cases) if (got1) { holderCounts = lcSubtract(holderCounts, lcActive(mode1)); // XXX Check lastlocalhold and lasthold gslRelease(&theLock, mode1, NULL, NULL); } if (got2) { holderCounts = lcSubtract(holderCounts, lcActive(mode2)); gslRelease(&theLock, mode2, NULL, NULL); } }
/** * @fn int CacheMissComputation::computation(FrameWork *ws, AST *ast); * Compute the number of Miss for each AST node by using annotations coming from other modules. * Furthermore put annotations (ETS::MISSES) of each AST node. * @param ws Container framework. * @param ast AST to process. * @return Miss of the current AST. */ int CacheMissComputation::computation(WorkSpace *ws, AST *ast){ int misses; switch (ast->kind()){ case AST_Call:{ ASTInfo *ast_info = ws->getASTInfo(); Option< FunAST *> fun_res = ast_info->get(ast->toCall()->function()->name()); if (fun_res){ AST *fun_ast = (*fun_res)->ast(); misses = computation(ws, fun_ast); MISSES(ast->toCall()) = misses; CHC_OUT(cout << "|| " << ast->toCall()->function()->name() << " a pour nb de miss : " << ast->toCall()->use<int>(ETS::ID_MISSES)<< '\n'); return MISSES(ast->toCall()); } break; } case AST_Block: CHC_OUT(cout << "|| " << ast->toBlock()->first()->get<String>(File::ID_Label,"unknown ") << " a pour nb de miss : " << ast->toBlock()->use<int>(ETS::ID_MISSES)<< '\n'); return MISSES(ast->toBlock()) + CONFLICTS(ast->toBlock()); break; case AST_Seq: { misses = computation(ws, ast->toSeq()->child1()) + computation(ws, ast->toSeq()->child2()); MISSES(ast->toSeq()) = misses; CHC_OUT(cout << "|| " << ast->toSeq()->first()->get<String>(File::ID_Label,"unknown ") << " a pour nb de miss : " << ast->toSeq()->use<int>(ETS::ID_MISSES)<< '\n'); return MISSES(ast->toSeq()); break; } case AST_If: { misses = computation(ws, ast->toIf()->elsePart()); int misses1 = computation(ws, ast->toIf()->thenPart()); if(misses < misses1) MISSES(ast->toIf()) = misses1 + computation(ws, ast->toIf()->condition()); else MISSES(ast->toIf()) = misses + computation(ws, ast->toIf()->condition()); CHC_OUT(cout << "|| " << ast->toIf()->condition()->first()->get<String>(File::ID_Label,"unknown ") << " a pour nb de miss : " << ast->toIf()->use<int>(ETS::ID_MISSES)<< '\n'); return MISSES(ast->toIf()); break; } case AST_While: { int N = LOOP_COUNT(ast->toWhile()); misses = computation(ws, ast->toWhile()->condition()) + N *( computation(ws, ast->toWhile()->condition()) + computation(ws, ast->toWhile()->body())); int misses_coming_from_first_misses = FIRST_MISSES(ast->toWhile()->condition()) + FIRST_MISSES(ast->toWhile()->body()); MISSES(ast->toWhile()) = misses + misses_coming_from_first_misses; CHC_OUT(cout << "|| " << ast->toWhile()->condition()->first()->get<String>(File::ID_Label,"unknown ") << " a pour nb de miss : " << ast->toWhile()->use<int>(ETS::ID_MISSES)<< '\n'); return MISSES(ast->toWhile()); break; } case AST_For: { int N = LOOP_COUNT(ast->toFor()); misses = computation(ws, ast->toFor()->condition()) + computation(ws, ast->toFor()->initialization()) + N *( computation(ws, ast->toFor()->condition()) + computation(ws, ast->toFor()->body()) + computation(ws, ast->toFor()->incrementation())); int misses_coming_from_first_misses = FIRST_MISSES(ast->toFor()->condition()) + FIRST_MISSES(ast->toFor()->body()) + FIRST_MISSES(ast->toFor()->incrementation()); MISSES(ast->toFor()) = misses + misses_coming_from_first_misses; CHC_OUT(cout << "|| " << ast->toFor()->condition()->first()->get<String>(File::ID_Label,"unknown ") << " a pour nb de miss : " << ast->toFor()->use<int>(ETS::ID_MISSES)<< '\n'); return MISSES(ast->toFor()); break; } case AST_DoWhile: { int N = LOOP_COUNT(ast->toDoWhile()); misses = computation(ws, ast->toDoWhile()->body()) + N *( computation(ws, ast->toDoWhile()->condition()) + computation(ws, ast->toDoWhile()->body())); int misses_coming_from_first_misses = FIRST_MISSES(ast->toDoWhile()->body()) + FIRST_MISSES(ast->toDoWhile()->condition()); MISSES(ast->toDoWhile()) = misses + misses_coming_from_first_misses; CHC_OUT(cout << "|| " << ast->toDoWhile()->condition()->first()->get<String>(File::ID_Label,"unknown ") << " a pour nb de miss : " << ast->toDoWhile()->use<int>(ETS::ID_MISSES)<< '\n'); return MISSES(ast->toDoWhile()); break; } default : return 0; } return 0; }
void doRun(void) { // Print mode combination for (int i = 0; i < nProcs; ++i) { if (i != 0) printf(" "); printf("%d%s/%d%s", PERPROC(&procs[i])->testMode1, PERPROC(&procs[i])->testMode1DontWait ? "(NB)" : "", PERPROC(&procs[i])->testMode2, PERPROC(&procs[i])->testMode2DontWait ? "(NB)" : ""); } printf("\n"); // Do I *expect* deadlock from this combination? Ideally I // would ignore the particular bad interleavings, but this // will do. if (nProcs == 2) { gslLockMode_t mode01 = PERPROC(&procs[0])->testMode1, mode02 = PERPROC(&procs[0])->testMode2, mode11 = PERPROC(&procs[1])->testMode1, mode12 = PERPROC(&procs[1])->testMode2; if (mode02 != -1 && mode12 != -1) { if (CONFLICTS(mode01, mode12) && CONFLICTS(mode02, mode11)) { printf("SKIPPING\n"); return; } } } // Reset expected sharing tracking memset(observedSharing, 0, sizeof observedSharing); // Reset counters memset(&counters, 0, sizeof counters); // Run every interleaving procRun(); // Count number of threads for each lock mode int modeCounts[LC_MAX_MODES]; memset(modeCounts, 0, sizeof modeCounts); for (int i = 0; i < nProcs; ++i) { modeCounts[PERPROC(&procs[i])->testMode1]++; if (PERPROC(&procs[i])->testMode2 != -1) modeCounts[PERPROC(&procs[i])->testMode2]++; } // Check for expected sharing for (int i = 0; i < LC_MAX_MODES; ++i) { if (modeCounts[i] > 1 && !CONFLICTS(i, i)) { // Expected sharing to show up in some // interleaving if (!observedSharing[i]) printf("WARNING: No sharing observed for mode %d\n", i); } } // Print counters printf("acquireCalls: %d\t releaseCalls: %d\t " "wakeCalls: %d\t spuriousWakes: %d\n", counters.acquireCalls, counters.releaseCalls, counters.wakeCalls, counters.spuriousWakes); }