Path: blob/master/runtime/gc_realtime/ProcessorInfo.cpp
5985 views
/*******************************************************************************1* Copyright (c) 1991, 2019 IBM Corp. and others2*3* This program and the accompanying materials are made available under4* the terms of the Eclipse Public License 2.0 which accompanies this5* distribution and is available at https://www.eclipse.org/legal/epl-2.0/6* or the Apache License, Version 2.0 which accompanies this distribution and7* is available at https://www.apache.org/licenses/LICENSE-2.0.8*9* This Source Code may also be made available under the following10* Secondary Licenses when the conditions for such availability set11* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU12* General Public License, version 2 with the GNU Classpath13* Exception [1] and GNU General Public License, version 2 with the14* OpenJDK Assembly Exception [2].15*16* [1] https://www.gnu.org/software/classpath/license.html17* [2] http://openjdk.java.net/legal/assembly-exception.html18*19* 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-exception20*******************************************************************************/2122#include "omr.h"23#include "omrcfg.h"2425#include <string.h>2627#include "EnvironmentBase.hpp"28#include "ModronAssertions.h"29#include "ProcessorInfo.hpp"3031/**32* Initialization.33*/34MM_ProcessorInfo*35MM_ProcessorInfo::newInstance(MM_EnvironmentBase *env)36{37MM_ProcessorInfo *processorInfo = (MM_ProcessorInfo *)env->getForge()->allocate(sizeof(MM_ProcessorInfo), MM_AllocationCategory::FIXED, OMR_GET_CALLSITE());38if (processorInfo) {39new(processorInfo) MM_ProcessorInfo();40if (!processorInfo->initialize(env)) {41processorInfo->kill(env);42processorInfo = NULL;43}44}45return processorInfo;46}4748/**49* Initialization.50*/51bool52MM_ProcessorInfo::initialize(MM_EnvironmentBase *env)53{54#if defined(AIXPPC) || defined(WIN32)55/* on AIX and Windows we don't use tick based timer so no need to calculate CPU clock frequency */56return true;57#else58_freq = readFrequency();59return (_freq != 0);60#endif61}6263/**64* Initialization.65*/66void67MM_ProcessorInfo::kill(MM_EnvironmentBase *env)68{69tearDown(env);70env->getForge()->free(this);71}7273/**74* Teardown75*/76void77MM_ProcessorInfo::tearDown(MM_EnvironmentBase *env)78{79}8081U_6482MM_ProcessorInfo::secondToTick(double s)83{84return (U_64) (s * _freq);85}8687double88MM_ProcessorInfo::tickToSecond(U_64 t)89{90return t / _freq;91}9293double94MM_ProcessorInfo::readFrequency()95{96double freq = 0;97#if (defined(LINUX) && (defined(J9X86) || defined(J9HAMMER) || defined(LINUXPPC)))98char buffer[256];99FILE *file = fopen("/proc/cpuinfo", "r");100if (file != NULL) {101while (!feof(file)) {102if (NULL == fgets(buffer, sizeof(buffer), file)) {103break;104}105#if (defined(J9X86) || defined(J9HAMMER))106/* the RTC on x86 is synchronized with the core clock so find the frequency in MHz then multiply by 10^6 to determine the ticks in a second */107if (sscanf(buffer, "cpu MHz : %lf", &freq) == 1) {108freq *= 1e6;109break;110}111#elif defined(LINUXPPC)112/* the timebase register on PPC is potentially lower frequency than the core clock so get the kernel's estimation of its frequency */113U_64 tempBase = 0;114if (sscanf(buffer, "timebase : %llu", (unsigned long long*)&tempBase) == 1) {115/* PPC timebase is already in ticks per second so just convert it to a double for consistency with x86 implementation */116freq = (double)tempBase;117break;118}119#else120/* missing linux proc parsing logic */121Assert_MM_unimplemented();122#endif123}124fclose(file);125}126#elif defined(WIN32)127/* Should read this via Windows API */128#elif defined(AIXPPC)129/* Figure out the right thing to do */130freq = 1000;131#else132/* Hi-res tick implementation required */133Assert_MM_unimplemented();134#endif135return freq;136}137138139