Path: blob/master/runtime/gc_realtime/MetronomeAlarmThread.cpp
5985 views
1/*******************************************************************************2* Copyright (c) 1991, 2019 IBM Corp. and others3*4* This program and the accompanying materials are made available under5* the terms of the Eclipse Public License 2.0 which accompanies this6* distribution and is available at https://www.eclipse.org/legal/epl-2.0/7* or the Apache License, Version 2.0 which accompanies this distribution and8* is available at https://www.apache.org/licenses/LICENSE-2.0.9*10* This Source Code may also be made available under the following11* Secondary Licenses when the conditions for such availability set12* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU13* General Public License, version 2 with the GNU Classpath14* Exception [1] and GNU General Public License, version 2 with the15* OpenJDK Assembly Exception [2].16*17* [1] https://www.gnu.org/software/classpath/license.html18* [2] http://openjdk.java.net/legal/assembly-exception.html19*20* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception21*******************************************************************************/2223/**24* @file25*/2627#include "omrutil.h"2829#include "MetronomeAlarmThread.hpp"30#include "MetronomeDelegate.hpp"31#include "OSInterface.hpp"32#include "RealtimeGC.hpp"33#include "Timer.hpp"3435#if defined(LINUX)36#if !defined(J9ZTPF)37#include <sys/signal.h>38#include <linux/unistd.h>39#endif /* !defined(J9ZTPF) */40#include <sys/types.h>41#endif424344MM_MetronomeAlarmThread *45MM_MetronomeAlarmThread::newInstance(MM_EnvironmentBase *env)46{47MM_MetronomeAlarmThread *alarmThread;4849alarmThread = (MM_MetronomeAlarmThread *)env->getForge()->allocate(sizeof(MM_MetronomeAlarmThread), MM_AllocationCategory::FIXED, OMR_GET_CALLSITE());50if (alarmThread) {51new(alarmThread) MM_MetronomeAlarmThread(env);52if (!alarmThread->initialize(env)) {53alarmThread->kill(env);54return NULL;55}56}57return alarmThread;58}5960void61MM_MetronomeAlarmThread::kill(MM_EnvironmentBase *env)62{63tearDown(env);64env->getForge()->free(this);65}6667void68MM_MetronomeAlarmThread::tearDown(MM_EnvironmentBase *env)69{70/* Shut down the alarm thread, if there is one running */71omrthread_monitor_enter(_mutex);7273/* Set shutdown thread flag */74_shutdown = true;7576while (_alarmThreadActive == ALARM_THREAD_ACTIVE) {77omrthread_monitor_wait(_mutex);78}7980omrthread_monitor_exit(_mutex);8182/* Kill the alarm only after the alarm thread is killed */83if (NULL != _alarm) {84_alarm->kill(env);85_alarm = NULL;86}8788if (NULL != _mutex) {89omrthread_monitor_destroy(_mutex);90_mutex = NULL;91}92}9394bool95MM_MetronomeAlarmThread::initialize(MM_EnvironmentBase *env)96{97if (0 != omrthread_monitor_init_with_name(&_mutex, 0, "Metronome Alarm Thread")) {98return false;99}100101/* TODO: The MM_Alarm classes don't quite have the newInstance/initialize102* pattern right, so we have to manually call initialize.103*/104_alarm = MM_Alarm::factory(env, _scheduler->_osInterface);105if (!_alarm || !_alarm->initialize(env, this)) {106return false;107}108109return true;110}111112/**113* C entrypoint for the newly created alarm thread.114*/115int J9THREAD_PROC116MM_MetronomeAlarmThread::metronomeAlarmThreadWrapper(void* userData)117{118return MM_MetronomeDelegate::metronomeAlarmThreadWrapper(userData);119}120121/**122* Fork a separate thread to perform the periodic alarms.123* Some may instantiate this class without actually calling this method124* to create a separate thread.125* @todo Clean up the abstraction so it makes a bit more sense. Probably126* merging most of the code in this class into MM_Alarm.127* @return true if the thread was successfully created, false otherwise128*/129bool130MM_MetronomeAlarmThread::startThread(MM_EnvironmentBase *env)131{132uintptr_t startPriority;133bool retCode;134135startPriority = J9THREAD_PRIORITY_MAX;136137if (J9THREAD_SUCCESS != createThreadWithCategory(138&_thread,13964 * 1024,140startPriority,1410,142MM_MetronomeAlarmThread::metronomeAlarmThreadWrapper,143this,144J9THREAD_CATEGORY_SYSTEM_GC_THREAD)) {145return false;146}147148omrthread_monitor_enter(_mutex);149while (_alarmThreadActive == ALARM_THREAD_INACTIVE) {150omrthread_monitor_wait(_mutex);151}152retCode = (_alarmThreadActive == ALARM_THREAD_ACTIVE);153omrthread_monitor_exit(_mutex);154155return retCode;156}157158/**159* C++ entrypoint for the newly-created alarm thread.160*/161void162MM_MetronomeAlarmThread::run(MM_EnvironmentRealtime *env)163{164omrthread_monitor_enter(_mutex);165166_alarmThreadActive = ALARM_THREAD_ACTIVE;167omrthread_monitor_notify(_mutex);168169while (!_shutdown) {170omrthread_monitor_exit(_mutex);171172_alarm->sleep();173174if (env->getTimer()->hasTimeElapsed(_scheduler->getStartTimeOfCurrentMutatorSlice(), _scheduler->beatNanos)) {175_scheduler->continueGC(env, TIME_TRIGGER, 0, NULL, true);176}177178omrthread_monitor_enter(_mutex);179}180omrthread_monitor_exit(_mutex);181}182183184185