random_product_constrained_sequence(unsigned n, T p, const std::vector<T>& mn) { TBLIS_ASSERT(n > 0); TBLIS_ASSERT(p >= 1); TBLIS_ASSERT(mn.size() == n); std::vector<double> mnd(n); for (unsigned i = 0;i < n;i++) { mnd[i] = std::max(T(1), mn[i]); } std::vector<double> sd = random_product_constrained_sequence<double>(n, p, mnd); std::vector<T> si(n); for (unsigned i = 0;i < n;i++) { switch (Mode) { case ROUND_UP: si[i] = lrint( ceil(sd[i])); break; case ROUND_DOWN: si[i] = lrint(floor(sd[i])); break; case ROUND_NEAREST: si[i] = lrint( sd[i] ); break; } si[i] = std::max(si[i], mn[i]); } //cout << p << si << accumulate(si.begin(), si.end(), T(1), multiplies<T>()) << endl; return si; }
static void executeOneCommand(JNIEnv* env) { switch (saCmdType) { case SA_CMD_SUSPEND_ALL: { if (suspended) { reportErrorToSA("Target process already suspended"); return; } // We implement this by getting all of the threads and calling // SuspendThread on each one, except for the thread object // corresponding to this thread. Each thread for which the call // succeeded (i.e., did not return JVMDI_ERROR_INVALID_THREAD) // is added to a list which is remembered for later resumption. // Note that this currently has race conditions since a thread // might be started after we call GetAllThreads and since a // thread for which we got an error earlier might be resumed by // the VM while we are busy suspending other threads. We could // solve this by looping until there are no more threads we can // suspend, but a more robust and scalable solution is to add // this functionality to the JVMDI interface (i.e., // "suspendAll"). Probably need to provide an exclude list for // such a routine. jint threadCount; jthread* threads; if (jvmdi->GetAllThreads(&threadCount, &threads) != JVMDI_ERROR_NONE) { reportErrorToSA("Error while getting thread list"); return; } for (int i = 0; i < threadCount; i++) { jthread thr = threads[i]; if (!env->IsSameObject(thr, debugThreadObj)) { jvmdiError err = jvmdi->SuspendThread(thr); if (err == JVMDI_ERROR_NONE) { // Remember this thread and do not free it suspendedThreads.push_back(thr); continue; } else { fprintf(stderr, " SA: Error %d while suspending thread\n", err); // FIXME: stop, resume all threads, report error } } env->DeleteGlobalRef(thr); } // Free up threads jvmdi->Deallocate((jbyte*) threads); // Suspension is complete suspended = true; break; } case SA_CMD_RESUME_ALL: { if (!suspended) { reportErrorToSA("Target process already suspended"); return; } saCmdResult = 0; bool errorOccurred = false; jvmdiError firstError; for (int i = 0; i < suspendedThreads.size(); i++) { jthread thr = suspendedThreads[i]; jvmdiError err = jvmdi->ResumeThread(thr); env->DeleteGlobalRef(thr); if (err != JVMDI_ERROR_NONE) { if (!errorOccurred) { errorOccurred = true; firstError = err; } } } suspendedThreads.clear(); suspended = false; if (errorOccurred) { reportErrorToSA("Error %d while resuming threads", firstError); return; } break; } case SA_CMD_TOGGLE_BREAKPOINT: { saCmdBkptResWasError = 1; // Search line number info for all loaded classes jint classCount; jclass* classes; jvmdiError glcRes = jvmdi->GetLoadedClasses(&classCount, &classes); if (glcRes != JVMDI_ERROR_NONE) { reportErrorToSA("Error %d while getting loaded classes", glcRes); return; } JvmdiRefListDeallocator rld(env, (jobject*) classes, classCount); bool done = false; bool gotOne = false; jclass targetClass; jmethodID targetMethod; jlocation targetLocation; jint targetLineNumber; for (int i = 0; i < classCount && !done; i++) { fflush(stderr); jclass clazz = classes[i]; char* srcName; jvmdiError sfnRes = jvmdi->GetSourceFileName(clazz, &srcName); if (sfnRes == JVMDI_ERROR_NONE) { JvmdiDeallocator de1(srcName); if (!strcmp(srcName, saCmdBkptSrcFileName)) { // Got a match. Now see whether the package name of the class also matches char* clazzName; jvmdiError sigRes = jvmdi->GetClassSignature(clazz, &clazzName); if (sigRes != JVMDI_ERROR_NONE) { reportErrorToSA("Error %d while getting a class's signature", sigRes); return; } JvmdiDeallocator de2(clazzName); if (packageNameMatches(clazzName + 1, saCmdBkptPkgName)) { // Iterate through all methods jint methodCount; jmethodID* methods; if (jvmdi->GetClassMethods(clazz, &methodCount, &methods) != JVMDI_ERROR_NONE) { reportErrorToSA("Error while getting methods of class %s", clazzName); return; } JvmdiDeallocator de3(methods); for (int j = 0; j < methodCount && !done; j++) { jmethodID m = methods[j]; jint entryCount; JVMDI_line_number_entry* table; jvmdiError lnRes = jvmdi->GetLineNumberTable(clazz, m, &entryCount, &table); if (lnRes == JVMDI_ERROR_NONE) { JvmdiDeallocator de4(table); // Look for line number greater than or equal to requested line for (int k = 0; k < entryCount && !done; k++) { JVMDI_line_number_entry& entry = table[k]; if (entry.line_number >= saCmdBkptLineNumber && (!gotOne || entry.line_number < targetLineNumber)) { gotOne = true; targetClass = clazz; targetMethod = m; targetLocation = entry.start_location; targetLineNumber = entry.line_number; done = (targetLineNumber == saCmdBkptLineNumber); } } } else if (lnRes != JVMDI_ERROR_ABSENT_INFORMATION) { reportErrorToSA("Unexpected error %d while fetching line number table", lnRes); return; } } } } } else if (sfnRes != JVMDI_ERROR_ABSENT_INFORMATION) { reportErrorToSA("Unexpected error %d while fetching source file name", sfnRes); return; } } bool wasSet = true; if (gotOne) { // Really toggle this breakpoint jvmdiError bpRes; bpRes = jvmdi->SetBreakpoint(targetClass, targetMethod, targetLocation); if (bpRes == JVMDI_ERROR_DUPLICATE) { bpRes = jvmdi->ClearBreakpoint(targetClass, targetMethod, targetLocation); wasSet = false; } if (bpRes != JVMDI_ERROR_NONE) { reportErrorToSA("Unexpected error %d while setting or clearing breakpoint at bci %d, line %d", bpRes, targetLocation, targetLineNumber); return; } } else { saCmdBkptResWasError = 0; reportErrorToSA("No debug information found covering this line"); return; } // Provide result saCmdBkptResLineNumber = targetLineNumber; saCmdBkptResBCI = targetLocation; saCmdBkptResWasSet = (wasSet ? 1 : 0); { char* methodName; char* methodSig; if (jvmdi->GetMethodName(targetClass, targetMethod, &methodName, &methodSig) == JVMDI_ERROR_NONE) { JvmdiDeallocator mnd(methodName); JvmdiDeallocator msd(methodSig); strncpy(saCmdBkptResMethodName, methodName, SA_CMD_BUF_SIZE); strncpy(saCmdBkptResMethodSig, methodSig, SA_CMD_BUF_SIZE); } else { strncpy(saCmdBkptResMethodName, "<error>", SA_CMD_BUF_SIZE); strncpy(saCmdBkptResMethodSig, "<error>", SA_CMD_BUF_SIZE); } } break; } default: reportErrorToSA("Command %d not yet supported", saCmdType); return; } // Successful command execution saCmdResult = 0; saCmdPending = 0; }