void NodeVersionLoader::startDownload() { auto self = shared_from_this(); checkThread(); auto& item = currentDownloadItem(); { std::lock_guard<std::mutex> lock(downloadQueueMutex); --item.retryCount; } state = State::Connecting; log.setChannel("Download:" + item.version); std::string fileName; auto ver = item.version; try { onNeedsDownloadFileName(ver, fileName); if (fileName.empty()) { MSCThrow(InvalidOperationException("File name is empty.")); } } catch (...) { downloadFailed("Failed to determine the downloaded file path.: " + boost::current_exception_diagnostic_information()); return; } try { file.reset(new std::ofstream(fileName.c_str(), std::ios::out | std::ios::trunc | std::ios::binary)); file->exceptions(std::ios::failbit | std::ios::badbit); } catch (...) { file.reset(); downloadFailed("Failed to open the destination file '" + fileName + "'.: " + boost::current_exception_diagnostic_information()); return; } BOOST_LOG_SEV(log, LogLevel::Info) << "Connecting to the master server."; socket.async_connect(endpoint, [this, self, &item](const error_code& error) { checkThread(); if (disposed) { downloadCancelled(); return; } if (error) { downloadFailed(error.message()); return; } sendHeader(); }); }
void NodeVersionLoader::receiveHeader() { auto self = shared_from_this(); checkThread(); auto& item = currentDownloadItem(); state = State::ReceivingHeader; auto buf = std::make_shared<std::uint64_t>(); timer.expires_from_now(boost::posix_time::seconds(8)); timer.async_wait([this, self] (const error_code& error) { if (error) { return; } if (disposed) { return; } if (state == State::ReceivingHeader) { BOOST_LOG_SEV(log, LogLevel::Warn) << "Timed out."; socket.cancel(); } }); asio::async_read(socket, asio::buffer(buf.get(), 8), [this, self, &item, buf](const error_code& error, std::size_t) { checkThread(); if (disposed) { downloadCancelled(); return; } if (error) { downloadFailed(error.message()); return; } timer.cancel(); auto size = *buf; if (size == 0) { downloadFailed("Version cannot be downloaded for some reason."); return; } receiveData(size); }); }
void NodeVersionLoader::setWatchDogTimer() { auto self = shared_from_this(); checkThread(); timer.expires_from_now(boost::posix_time::seconds(3)); timer.async_wait([this, self] (const error_code& error) { if (error) { return; } if (disposed) { return; } if (state == State::ReceivingData) { auto now = boost::posix_time::second_clock::local_time(); if (now - lastReceiveTime > boost::posix_time::seconds(10)) { BOOST_LOG_SEV(log, LogLevel::Warn) << "Timed out."; socket.cancel(); } else { setWatchDogTimer(); } } }); }
ThreadState::ThreadState() : m_thread(currentThread()) , m_persistents(adoptPtr(new PersistentAnchor())) , m_startOfStack(reinterpret_cast<intptr_t*>(getStackStart())) , m_endOfStack(reinterpret_cast<intptr_t*>(getStackStart())) , m_safePointScopeMarker(nullptr) , m_atSafePoint(false) , m_interruptors() , m_didV8GCAfterLastGC(false) , m_sweepForbidden(false) , m_noAllocationCount(0) , m_isTerminating(false) , m_shouldFlushHeapDoesNotContainCache(false) , m_collectionRate(1.0) , m_gcState(NoGCScheduled) , m_traceDOMWrappers(nullptr) #if defined(ADDRESS_SANITIZER) , m_asanFakeStack(__asan_get_current_fake_stack()) #endif { checkThread(); ASSERT(!**s_threadSpecific); **s_threadSpecific = this; if (isMainThread()) { s_mainThreadStackStart = reinterpret_cast<uintptr_t>(m_startOfStack) - sizeof(void*); s_mainThreadUnderestimatedStackSize = getUnderestimatedStackSize() - sizeof(void*); } for (int heapIndex = 0; heapIndex < NumberOfHeaps; heapIndex++) m_heaps[heapIndex] = new ThreadHeap(this, heapIndex); m_weakCallbackStack = new CallbackStack(); }
void NodeVersionLoader::checkQueue() { auto self = shared_from_this(); checkThread(); if (isDownloading()) return; while (true) { { std::lock_guard<std::mutex> lock(downloadQueueMutex); if (downloadQueue.empty()) return; auto& item = downloadQueue.front(); bool cancel = false; try { onVersionAboutToBeDownloaded(item.version, cancel); } catch (...) { BOOST_LOG_SEV(log, LogLevel::Error) << "onVersionAboutToBeDownloaded failed: " << boost::current_exception_diagnostic_information(); cancel = true; } if (cancel) { downloadQueue.erase(downloadQueue.begin()); continue; } } startDownload(); } }
void ThreadState::postGCProcessing() { checkThread(); if (gcState() != EagerSweepScheduled && gcState() != LazySweepScheduled) return; m_didV8GCAfterLastGC = false; if (isMainThread()) m_allocatedObjectSizeBeforeSweeping = Heap::allocatedObjectSize(); #if ENABLE(GC_PROFILE_HEAP) // We snapshot the heap prior to sweeping to get numbers for both resources // that have been allocated since the last GC and for resources that are // going to be freed. bool gcTracingEnabled; TRACE_EVENT_CATEGORY_GROUP_ENABLED("blink_gc", &gcTracingEnabled); if (gcTracingEnabled) snapshot(); #endif { if (isMainThread()) ScriptForbiddenScope::enter(); SweepForbiddenScope forbiddenScope(this); { // Disallow allocation during weak processing. NoAllocationScope noAllocationScope(this); { TRACE_EVENT0("blink_gc", "ThreadState::threadLocalWeakProcessing"); // Perform thread-specific weak processing. while (popAndInvokeWeakPointerCallback(Heap::s_markingVisitor)) { } } { TRACE_EVENT0("blink_gc", "ThreadState::invokePreFinalizers"); invokePreFinalizers(*Heap::s_markingVisitor); } } if (isMainThread()) ScriptForbiddenScope::exit(); } #if ENABLE(OILPAN) if (gcState() == EagerSweepScheduled) { // Eager sweeping should happen only in testing. setGCState(Sweeping); completeSweep(); } else { // The default behavior is lazy sweeping. setGCState(Sweeping); } #else // FIXME: For now, we disable lazy sweeping in non-oilpan builds // to avoid unacceptable behavior regressions on trunk. setGCState(Sweeping); completeSweep(); #endif }
void NodeVersionLoader::sendHeader() { auto self = shared_from_this(); checkThread(); auto& item = currentDownloadItem(); state = State::SendingHeader; PacketGenerator gen; gen.write(VersionDownloadRequestMagic); gen.writeString(item.version); auto buf = std::make_shared<std::vector<char>>(std::move(gen.vector())); timer.expires_from_now(boost::posix_time::seconds(8)); timer.async_wait([this, self] (const error_code& error) { if (error) { return; } if (disposed) { return; } if (state == State::SendingHeader) { BOOST_LOG_SEV(log, LogLevel::Warn) << "Timed out."; socket.cancel(); } }); asio::async_write(socket, asio::buffer(buf->data(), buf->size()), [this, self, &item](const error_code& error, std::size_t) { checkThread(); if (disposed) { downloadCancelled(); return; } if (error) { downloadFailed(error.message()); return; } timer.cancel(); receiveHeader(); }); }
void Server::remove(Connection* connection) { checkThread(); epoll_event event = { 0, { connection } }; if (epoll_ctl(_epollFd, EPOLL_CTL_DEL, connection->getFd(), &event) == -1) { LS_ERROR(_logger, "Unable to remove from epoll: " << getLastError()); } _connections.erase(connection); }
/* * Class: com_Revsoft_Wabbitemu_CalcInterface * Method: CreateRom * Signature: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V */ JNIEXPORT jint JNICALL Java_com_Revsoft_Wabbitemu_calc_CalcInterface_CreateRom (JNIEnv *env, jclass classObj, jstring jOsPath, jstring jBootPath, jstring jRomPath, jint model) { checkThread(); const char *osPath = env->GetStringUTFChars(jOsPath, JNI_FALSE); const char *bootPath = env->GetStringUTFChars(jBootPath, JNI_FALSE); const char *romPath = env->GetStringUTFChars(jRomPath, JNI_FALSE); //Do not allow more than one calc currently if (lpCalc) { calc_slot_free(lpCalc); } lpCalc = calc_slot_new(); calc_init_model(lpCalc, model, NULL); //slot stuff strcpy(lpCalc->rom_path, romPath); lpCalc->active = TRUE; lpCalc->model = (CalcModel) model; lpCalc->cpu.pio.model = model; FILE *file = fopen(bootPath, "rb"); if (file == NULL) { calc_slot_free(lpCalc); lpCalc = NULL; return -1; } writeboot(file, &lpCalc->mem_c, -1); fclose(file); remove(bootPath); TIFILE_t *tifile = importvar(osPath, FALSE); if (tifile == NULL) { calc_slot_free(lpCalc); lpCalc = NULL; return -2; } int link_error = forceload_os(&lpCalc->cpu, tifile); if (link_error != LERR_SUCCESS) { calc_slot_free(lpCalc); lpCalc = NULL; return -2; } calc_erase_certificate(lpCalc->mem_c.flash,lpCalc->mem_c.flash_size); calc_reset(lpCalc); //write the output from file MFILE *romfile = ExportRom((char *) romPath, lpCalc); if (romfile != NULL) { mclose(romfile); calc_slot_free(lpCalc); lpCalc = NULL; return 0; } calc_slot_free(lpCalc); lpCalc = NULL; return -3; }
void ThreadState::addInterruptor(Interruptor* interruptor) { checkThread(); SafePointScope scope(HeapPointersOnStack, SafePointScope::AllowNesting); { MutexLocker locker(threadAttachMutex()); m_interruptors.append(interruptor); } }
/* * Class: com_Revsoft_Wabbitemu_CalcInterface * Method: ReleaseKey * Signature: (II)V */ JNIEXPORT void JNICALL Java_com_Revsoft_Wabbitemu_calc_CalcInterface_ReleaseKey (JNIEnv *env, jclass classObj, jint group, jint bit) { checkThread(); if (!lpCalc) { return; } keypad_release(&lpCalc->cpu, (int) group, (int) bit); }
/* * Class: com_Revsoft_Wabbitemu_CalcInterface * Method: ClearKeys * Signature: ()V */ JNIEXPORT void JNICALL Java_com_Revsoft_Wabbitemu_calc_CalcInterface_ClearKeys (JNIEnv *env, jclass classObj) { checkThread(); for (int i = 0; i < 7; i++) { for (int j = 0; j < 8; j++) { } } }
/* * Class: com_Revsoft_Wabbitemu_CalcInterface * Method: UnpauseCalc * Signature: ()V */ JNIEXPORT void JNICALL Java_com_Revsoft_Wabbitemu_calc_CalcInterface_UnpauseCalc (JNIEnv *env, jclass classObj) { checkThread(); if (!lpCalc) { return; } lpCalc->running = TRUE; }
void ThreadState::leaveSafePoint(SafePointAwareMutexLocker* locker) { checkThread(); ASSERT(m_atSafePoint); s_safePointBarrier->leaveSafePoint(this, locker); m_atSafePoint = false; m_stackState = HeapPointersOnStack; clearSafePointScopeMarker(); postGCProcessing(); }
JNIEXPORT void JNICALL Java_com_Revsoft_Wabbitemu_calc_CalcInterface_ResetCalc (JNIEnv *env, jclass classObj) { checkThread(); if (!lpCalc) { return; } lpCalc->fake_running = TRUE; calc_reset(lpCalc); lpCalc->fake_running = FALSE; }
void ThreadState::runScheduledGC(StackState stackState) { checkThread(); if (stackState == NoHeapPointersOnStack) { if (gcState() == GCScheduledForTesting) { Heap::collectAllGarbage(); } else if (gcState() == GCScheduled) { Heap::collectGarbage(NoHeapPointersOnStack, GCWithoutSweep); } } }
void ThreadState::removeInterruptor(Interruptor* interruptor) { checkThread(); SafePointScope scope(HeapPointersOnStack, SafePointScope::AllowNesting); { MutexLocker locker(threadAttachMutex()); size_t index = m_interruptors.find(interruptor); RELEASE_ASSERT(index >= 0); m_interruptors.remove(index); } }
JNIEXPORT jint JNICALL Java_com_Revsoft_Wabbitemu_calc_CalcInterface_LoadFile (JNIEnv *env, jclass classObj, jstring filePath) { checkThread(); const char *path = env->GetStringUTFChars(filePath, JNI_FALSE); TIFILE_t *tifile = importvar(path, TRUE); if (!tifile || !lpCalc) { return (jint) LERR_FILE; } int result = SendFile(lpCalc, path, SEND_CUR); return result; }
void NodeVersionLoader::receiveData(std::uint64_t size) { auto self = shared_from_this(); checkThread(); state = State::ReceivingData; remainingBytes = size; lastReceiveTime = boost::posix_time::second_clock::local_time(); setWatchDogTimer(); receiveChunk(); }
void ThreadState::cleanup() { checkThread(); // Finish sweeping. completeSweep(); { // Grab the threadAttachMutex to ensure only one thread can shutdown at // a time and that no other thread can do a global GC. It also allows // safe iteration of the attachedThreads set which happens as part of // thread local GC asserts. We enter a safepoint while waiting for the // lock to avoid a dead-lock where another thread has already requested // GC. SafePointAwareMutexLocker locker(threadAttachMutex(), NoHeapPointersOnStack); // From here on ignore all conservatively discovered // pointers into the heap owned by this thread. m_isTerminating = true; // Set the terminate flag on all heap pages of this thread. This is used to // ensure we don't trace pages on other threads that are not part of the // thread local GC. prepareHeapForTermination(); // Do thread local GC's as long as the count of thread local Persistents // changes and is above zero. PersistentAnchor* anchor = static_cast<PersistentAnchor*>(m_persistents.get()); int oldCount = -1; int currentCount = anchor->numberOfPersistents(); ASSERT(currentCount >= 0); while (currentCount != oldCount) { Heap::collectGarbageForTerminatingThread(this); oldCount = currentCount; currentCount = anchor->numberOfPersistents(); } // We should not have any persistents left when getting to this point, // if we have it is probably a bug so adding a debug ASSERT to catch this. ASSERT(!currentCount); // All of pre-finalizers should be consumed. ASSERT(m_preFinalizers.isEmpty()); RELEASE_ASSERT(gcState() == NoGCScheduled); // Add pages to the orphaned page pool to ensure any global GCs from this point // on will not trace objects on this thread's heaps. cleanupPages(); ASSERT(attachedThreads().contains(this)); attachedThreads().remove(this); } for (auto& task : m_cleanupTasks) task->postCleanup(); m_cleanupTasks.clear(); }
void ThreadState::safePoint(StackState stackState) { checkThread(); runScheduledGC(stackState); ASSERT(!m_atSafePoint); m_stackState = stackState; m_atSafePoint = true; s_safePointBarrier->checkAndPark(this); m_atSafePoint = false; m_stackState = HeapPointersOnStack; postGCProcessing(); }
void ThreadState::setGCState(GCState gcState) { switch (gcState) { case NoGCScheduled: checkThread(); RELEASE_ASSERT(m_gcState == Sweeping); break; case GCScheduled: case GCScheduledForTesting: checkThread(); RELEASE_ASSERT(m_gcState == NoGCScheduled || m_gcState == GCScheduled || m_gcState == GCScheduledForTesting || m_gcState == StoppingOtherThreads || m_gcState == SweepingAndNextGCScheduled); completeSweep(); break; case StoppingOtherThreads: checkThread(); RELEASE_ASSERT(m_gcState == NoGCScheduled || m_gcState == GCScheduled || m_gcState == GCScheduledForTesting || m_gcState == Sweeping || m_gcState == SweepingAndNextGCScheduled); completeSweep(); break; case GCRunning: ASSERT(!isInGC()); RELEASE_ASSERT(m_gcState != GCRunning); break; case EagerSweepScheduled: case LazySweepScheduled: ASSERT(isInGC()); RELEASE_ASSERT(m_gcState == GCRunning); break; case Sweeping: checkThread(); RELEASE_ASSERT(m_gcState == EagerSweepScheduled || m_gcState == LazySweepScheduled); break; case SweepingAndNextGCScheduled: checkThread(); RELEASE_ASSERT(m_gcState == Sweeping || m_gcState == SweepingAndNextGCScheduled); break; default: ASSERT_NOT_REACHED(); } m_gcState = gcState; }
int main (int argc, const char * argv[]) { int port = DEFAULT_PORT; int bufferSize = DEFAULT_BUFFER_SIZE; bool isQuiet = DEFAULT_QUIET; bool isDebug = DEFAULT_DEBUG; int maxClient = DEFAULT_MAXCLIENT; signal(SIGINT, signalHandler); signal(SIGTERM, signalHandler); readArgs(argc,argv,&port,&bufferSize,&isQuiet,&isDebug,&maxClient); logger.setQuiet(isQuiet); logger.setDebug(isDebug); if(!isQuiet) { printInfo(port,bufferSize,isDebug,maxClient); } List<Client*> list; sf::Mutex listMutex; sf::SocketSelector selector; Buffer exchangeBuffer; setupExchangeBuffer(&exchangeBuffer, bufferSize); logger.printLog("Init'ed ..."); ClientsContainer container(&list,&listMutex,&selector); sf::Thread answerThread(&answerToClient,AnswerDataSet(&container,port,maxClient)); answerThread.launch(); sf::Thread checkThread(&checkForInputs,CheckDataSet(&container,&exchangeBuffer)); checkThread.launch(); while(1) //TODO graphic stats { if(checkStopThreads()) { break; } sf::sleep(sf::milliseconds(5)); } return 0; }
void NodeVersionLoader::downloadFailed(const std::string& msg) { auto self = shared_from_this(); checkThread(); auto& item = currentDownloadItem(); file.reset(); int retryCount; { std::lock_guard<std::mutex> lock(downloadQueueMutex); retryCount = item.retryCount; } if (retryCount == 0) { BOOST_LOG_SEV(log, LogLevel::Error) << "Failed to download.: " << msg; auto ver = item.version; { std::lock_guard<std::mutex> lock(downloadQueueMutex); downloadQueue.pop_front(); // note: `item` is a dangling reference now } onVersionDownloadFailed(ver); } else { BOOST_LOG_SEV(log, LogLevel::Warn) << "Failed to download. Retrying.: " << msg; } log.setChannel(std::string("(none)")); state = State::Waiting; timer.expires_from_now(boost::posix_time::seconds(3)); timer.async_wait([this, self] (const error_code& error) { if (error) { return; } if (disposed) { BOOST_LOG_SEV(log, LogLevel::Debug) << "Retry timer aborted.: Disposed."; return; } state = State::Idle; checkQueue(); }); }
ThreadState::~ThreadState() { checkThread(); delete m_weakCallbackStack; m_weakCallbackStack = nullptr; for (int i = 0; i < NumberOfHeaps; ++i) delete m_heaps[i]; deleteAllValues(m_interruptors); **s_threadSpecific = nullptr; if (isMainThread()) { s_mainThreadStackStart = 0; s_mainThreadUnderestimatedStackSize = 0; } }
/* * Class: com_Revsoft_Wabbitemu_CalcInterface * Method: SetCacheDir * Signature: (Ljava/lang/String;)V */ JNIEXPORT void JNICALL Java_com_Revsoft_Wabbitemu_calc_CalcInterface_Initialize (JNIEnv *env, jclass classObj, jstring filePath) { checkThread(); const char *path = env->GetStringUTFChars(filePath, JNI_FALSE); strcpy(cache_dir, path); lpCalc = calc_slot_new(); lpCalc->model = INVALID_MODEL; calc_register_event(lpCalc, ROM_LOAD_EVENT, &load_settings, NULL); for (int i = 0; i < 256; i++) { redPalette[i] = (0x9E * (256 - i)) / 255; bluePalette[i] = (0x88 * (256 - i)) / 255; greenPalette[i] = (0xAB * (256 - i)) / 255; } }
void ThreadState::enterSafePoint(StackState stackState, void* scopeMarker) { checkThread(); #ifdef ADDRESS_SANITIZER if (stackState == HeapPointersOnStack) scopeMarker = adjustScopeMarkerForAdressSanitizer(scopeMarker); #endif ASSERT(stackState == NoHeapPointersOnStack || scopeMarker); runScheduledGC(stackState); ASSERT(!m_atSafePoint); m_atSafePoint = true; m_stackState = stackState; m_safePointScopeMarker = scopeMarker; s_safePointBarrier->enterSafePoint(this); }
void ThreadState::scheduleGCOrForceConservativeGCIfNeeded() { checkThread(); // Allocation is allowed during sweeping, but those allocations should not // trigger nested GCs if (isSweepingInProgress()) return; ASSERT(!sweepForbidden()); if (!shouldGC()) return; if (shouldForceConservativeGC()) Heap::collectGarbage(ThreadState::HeapPointersOnStack, ThreadState::GCWithoutSweep); else scheduleGC(); }
/* * Class: com_Revsoft_Wabbitemu_CalcInterface * Method: SaveCalcState * Signature: (Ljava/lang/String;)V */ JNIEXPORT jboolean JNICALL Java_com_Revsoft_Wabbitemu_calc_CalcInterface_SaveCalcState (JNIEnv *env, jclass classObj, jstring filePath) { checkThread(); const char *path = env->GetStringUTFChars(filePath, JNI_FALSE); SAVESTATE_t *save; try { save = SaveSlot(lpCalc, "Wabbitemu", "Automatic save state"); } catch (std::exception &e) { _tprintf_s(_T("Exception loading save state: %s"), e.what()); return FALSE; } if (save != NULL) { WriteSave(path, save, ZLIB_CMP); FreeSave(save); } return (jboolean) (save != NULL); }
void Thread::waitForThread() { //waits for thread if(checkThread()) pthread_join(handle, NULL); //if a thread has been created wait for it to die }