# HG changeset patch # User Yasumasa Suenaga # Date 1516338387 -32400 # Node ID 9a13d070bb77287cbd1ef66947b6aae0e88f51d7 # Parent bec923d3aeb68c7cd2326ee79c8e91db58e2aa29 Bug 3511: Migrate to Intel TBB Reviewed-by: ykubota https://github.com/HeapStats/heapstats/pull/128 diff -r bec923d3aeb6 -r 9a13d070bb77 ChangeLog --- a/ChangeLog Tue Dec 05 16:18:49 2017 +0900 +++ b/ChangeLog Fri Jan 19 14:06:27 2018 +0900 @@ -1,3 +1,7 @@ +2018-01-19 Yasumasa Suenaga + + * Bug 3511: Migrate to Intel TBB + 2017-12-05 Yasumasa Suenaga * Bug 3498: Agent cannot work on brandnew glibc diff -r bec923d3aeb6 -r 9a13d070bb77 INSTALL --- a/INSTALL Tue Dec 05 16:18:49 2017 +0900 +++ b/INSTALL Fri Jan 19 14:06:27 2018 +0900 @@ -11,6 +11,9 @@ - pcre-devel 6 or later - net-snmp-devel 5.3 or later - binutils 2 or later + - Intel(R) Threading Building Blocks (TBB) + * If you compile the agent for Raspberry Pi 2, you have to install + libtbb2 and libtbb-dev in official Debian repository. Analyzer: - Java SE 8 or later diff -r bec923d3aeb6 -r 9a13d070bb77 Makefile.in --- a/Makefile.in Tue Dec 05 16:18:49 2017 +0900 +++ b/Makefile.in Fri Jan 19 14:06:27 2018 +0900 @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.15 from Makefile.am. +# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2014 Free Software Foundation, Inc. +# Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, diff -r bec923d3aeb6 -r 9a13d070bb77 aclocal.m4 --- a/aclocal.m4 Tue Dec 05 16:18:49 2017 +0900 +++ b/aclocal.m4 Fri Jan 19 14:06:27 2018 +0900 @@ -1,6 +1,6 @@ -# generated automatically by aclocal 1.15 -*- Autoconf -*- +# generated automatically by aclocal 1.15.1 -*- Autoconf -*- -# Copyright (C) 1996-2014 Free Software Foundation, Inc. +# Copyright (C) 1996-2017 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -20,7 +20,7 @@ If you have problems, you may need to regenerate the build system entirely. To do so, use the procedure documented by the package, typically 'autoreconf'.])]) -# Copyright (C) 2002-2014 Free Software Foundation, Inc. +# Copyright (C) 2002-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -35,7 +35,7 @@ [am__api_version='1.15' dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to dnl require some minimum version. Point them to the right macro. -m4_if([$1], [1.15], [], +m4_if([$1], [1.15.1], [], [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl ]) @@ -51,14 +51,14 @@ # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. # This function is AC_REQUIREd by AM_INIT_AUTOMAKE. AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], -[AM_AUTOMAKE_VERSION([1.15])dnl +[AM_AUTOMAKE_VERSION([1.15.1])dnl m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) # Figure out how to run the assembler. -*- Autoconf -*- -# Copyright (C) 2001-2014 Free Software Foundation, Inc. +# Copyright (C) 2001-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -78,7 +78,7 @@ # AM_AUX_DIR_EXPAND -*- Autoconf -*- -# Copyright (C) 2001-2014 Free Software Foundation, Inc. +# Copyright (C) 2001-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -130,7 +130,7 @@ # AM_CONDITIONAL -*- Autoconf -*- -# Copyright (C) 1997-2014 Free Software Foundation, Inc. +# Copyright (C) 1997-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -161,7 +161,7 @@ Usually this means the macro was only invoked conditionally.]]) fi])]) -# Copyright (C) 1999-2014 Free Software Foundation, Inc. +# Copyright (C) 1999-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -352,7 +352,7 @@ # Generate code to set up dependency tracking. -*- Autoconf -*- -# Copyright (C) 1999-2014 Free Software Foundation, Inc. +# Copyright (C) 1999-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -428,7 +428,7 @@ # Do all the work for Automake. -*- Autoconf -*- -# Copyright (C) 1996-2014 Free Software Foundation, Inc. +# Copyright (C) 1996-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -625,7 +625,7 @@ done echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) -# Copyright (C) 2001-2014 Free Software Foundation, Inc. +# Copyright (C) 2001-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -646,7 +646,7 @@ fi AC_SUBST([install_sh])]) -# Copyright (C) 2003-2014 Free Software Foundation, Inc. +# Copyright (C) 2003-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -668,7 +668,7 @@ # Add --enable-maintainer-mode option to configure. -*- Autoconf -*- # From Jim Meyering -# Copyright (C) 1996-2014 Free Software Foundation, Inc. +# Copyright (C) 1996-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -703,7 +703,7 @@ # Check to see how 'make' treats includes. -*- Autoconf -*- -# Copyright (C) 2001-2014 Free Software Foundation, Inc. +# Copyright (C) 2001-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -753,7 +753,7 @@ # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- -# Copyright (C) 1997-2014 Free Software Foundation, Inc. +# Copyright (C) 1997-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -792,7 +792,7 @@ # Helper functions for option handling. -*- Autoconf -*- -# Copyright (C) 2001-2014 Free Software Foundation, Inc. +# Copyright (C) 2001-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -821,7 +821,7 @@ AC_DEFUN([_AM_IF_OPTION], [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) -# Copyright (C) 1999-2014 Free Software Foundation, Inc. +# Copyright (C) 1999-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -868,7 +868,7 @@ # For backward compatibility. AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])]) -# Copyright (C) 2001-2014 Free Software Foundation, Inc. +# Copyright (C) 2001-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -887,7 +887,7 @@ # Check to make sure that the build environment is sane. -*- Autoconf -*- -# Copyright (C) 1996-2014 Free Software Foundation, Inc. +# Copyright (C) 1996-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -968,7 +968,7 @@ rm -f conftest.file ]) -# Copyright (C) 2009-2014 Free Software Foundation, Inc. +# Copyright (C) 2009-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -1028,7 +1028,7 @@ _AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl ]) -# Copyright (C) 2001-2014 Free Software Foundation, Inc. +# Copyright (C) 2001-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -1056,7 +1056,7 @@ INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" AC_SUBST([INSTALL_STRIP_PROGRAM])]) -# Copyright (C) 2006-2014 Free Software Foundation, Inc. +# Copyright (C) 2006-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -1075,7 +1075,7 @@ # Check how to create a tarball. -*- Autoconf -*- -# Copyright (C) 2004-2014 Free Software Foundation, Inc. +# Copyright (C) 2004-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, diff -r bec923d3aeb6 -r 9a13d070bb77 agent/Makefile.in --- a/agent/Makefile.in Tue Dec 05 16:18:49 2017 +0900 +++ b/agent/Makefile.in Fri Jan 19 14:06:27 2018 +0900 @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.15 from Makefile.am. +# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2014 Free Software Foundation, Inc. +# Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, diff -r bec923d3aeb6 -r 9a13d070bb77 agent/attacher/Makefile.in --- a/agent/attacher/Makefile.in Tue Dec 05 16:18:49 2017 +0900 +++ b/agent/attacher/Makefile.in Fri Jan 19 14:06:27 2018 +0900 @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.15 from Makefile.am. +# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2014 Free Software Foundation, Inc. +# Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, diff -r bec923d3aeb6 -r 9a13d070bb77 agent/src/Makefile.in --- a/agent/src/Makefile.in Tue Dec 05 16:18:49 2017 +0900 +++ b/agent/src/Makefile.in Fri Jan 19 14:06:27 2018 +0900 @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.15 from Makefile.am. +# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2014 Free Software Foundation, Inc. +# Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, diff -r bec923d3aeb6 -r 9a13d070bb77 agent/src/heapstats-engines/Makefile.in --- a/agent/src/heapstats-engines/Makefile.in Tue Dec 05 16:18:49 2017 +0900 +++ b/agent/src/heapstats-engines/Makefile.in Fri Jan 19 14:06:27 2018 +0900 @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.15 from Makefile.am. +# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2014 Free Software Foundation, Inc. +# Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, diff -r bec923d3aeb6 -r 9a13d070bb77 agent/src/heapstats-engines/classContainer.cpp --- a/agent/src/heapstats-engines/classContainer.cpp Tue Dec 05 16:18:49 2017 +0900 +++ b/agent/src/heapstats-engines/classContainer.cpp Fri Jan 19 14:06:27 2018 +0900 @@ -78,7 +78,6 @@ static char ORDER_USAGE[6] = "USAGE"; static TClassInfoSet unloadedList; -volatile int unloadedList_lock = 0; /*! * \briefString of DELTA order. @@ -87,81 +86,21 @@ /*! * \brief TClassContainer constructor. - * \param base [in] Parent class container instance. - * \param needToClr [in] Flag of deallocate all data on destructor. */ -TClassContainer::TClassContainer(TClassContainer *base, bool needToClr) - : localContainers() { - /* Initialize each field. */ - lockval = 0; - queueLock = 0; - needToClear = needToClr; - classMap = NULL; - pSender = NULL; - - if (likely(base != NULL)) { - /* Get parent container's spin lock. */ - spinLockWait(&base->lockval); - } - - try { - if (unlikely(base == NULL)) { - classMap = new TClassMap(); - } else { - classMap = new TClassMap(*base->classMap); - } - } catch (...) { - /* - * This statement is for release lock. So allocate check is after. - */ - } - - if (likely(base != NULL)) { - /* Release parent container's spin lock. */ - spinLockRelease(&base->lockval); - } - - try { - /* Check classMap. */ - if (unlikely(classMap == NULL)) { - throw 1; - } - - /* Create trap sender. */ - pSender = conf->SnmpSend()->get() ? new TTrapSender() : NULL; - - /* Create thread storage key. */ - if (unlikely(pthread_key_create(&clsContainerKey, NULL) != 0)) { - throw 1; - } - } catch (...) { - delete classMap; - delete pSender; - throw "TClassContainer initialize failed!"; - } +TClassContainer::TClassContainer(void) : classMap(), updatedClassList() { + /* Create trap sender. */ + pSender = conf->SnmpSend()->get() ? new TTrapSender() : NULL; } /*! * \brief TClassContainer destructor. */ TClassContainer::~TClassContainer(void) { - if (needToClear) { - /* Cleanup class information. */ - this->allClear(); - } - - /* Cleanup ClassContainer in TLS. */ - for (TLocalClassContainer::iterator it = localContainers.begin(); - it != localContainers.end(); it++) { - delete *it; - } + /* Cleanup class information. */ + this->allClear(); /* Cleanup instances. */ - delete classMap; delete pSender; - - /* Cleanup thread storage key. */ - pthread_key_delete(clsContainerKey); } /*! @@ -231,70 +170,26 @@ */ TObjectData *TClassContainer::pushNewClass(void *klassOop, TObjectData *objData) { - TObjectData *existData = NULL; - /* Get class container's spin lock. */ - spinLockWait(&lockval); - { - /* - * Jvmti extension event "classUnload" is loose once in a while. - * The event forget callback occasionally when class unloading. - * So we need to check klassOop that was doubling. - */ - - /* Check klassOop doubling. */ - TClassMap::iterator it = classMap->find(klassOop); - if (likely(it != classMap->end())) { - /* Store data to return value as result. */ - TObjectData *expectData = (*it).second; - if (likely(expectData != NULL)) { - /* If adding class data is already exists. */ - if (unlikely(expectData->className != NULL && - strcmp(objData->className, expectData->className) == 0 && - objData->clsLoaderId == expectData->clsLoaderId)) { - /* Return existing data on map. */ - existData = expectData; - } else { - /* klass oop is doubling for another class. */ - spinLockWait(&unloadedList_lock); - { - unloadedList.insert(expectData); - } - spinLockRelease(&unloadedList_lock); - } - } - } - - if (likely(existData == NULL)) { - try { - /* Append class data. */ - (*classMap)[klassOop] = objData; - } catch (...) { - /* - * Maybe failed to allocate memory at "std::map::operator[]". - */ + /* + * Jvmti extension event "classUnload" is loose once in a while. + * The event forget callback occasionally when class unloading. + * So we need to check klassOop that was doubling. + */ + TClassMap::accessor acc; + if (!classMap.insert(acc, std::make_pair(klassOop, objData))) { + TObjectData *expectData = acc->second; + if (likely(expectData != NULL)) { + /* If adding class data for another class is already exists. */ + if (unlikely((expectData->className == NULL) || + (strcmp(objData->className, expectData->className) != 0) || + (objData->clsLoaderId != expectData->clsLoaderId))) { + acc->second = objData; + unloadedList.push(expectData); } } } - /* Release class container's spin lock. */ - spinLockRelease(&lockval); - /* If already exist class data. */ - if (unlikely(existData != NULL)) { - return existData; - } - - /* Get spin lock of containers queue. */ - spinLockWait(&queueLock); - { - /* Broadcast to each local container. */ - for (TLocalClassContainer::iterator it = localContainers.begin(); - it != localContainers.end(); it++) { - (*it)->pushNewClass(klassOop, objData); - } - } - /* Release spin lock of containers queue. */ - spinLockRelease(&queueLock); - return objData; + return acc->second; } /*! @@ -302,43 +197,19 @@ * \param target [in] Remove class data. */ void TClassContainer::removeClass(TObjectData *target) { - /* Remove item from map. Please callee has container's lock. */ - classMap->erase(target->klassOop); - - /* Get spin lock of containers queue. */ - spinLockWait(&queueLock); - { - /* Broadcast to each local container. */ - for (TLocalClassContainer::iterator it = localContainers.begin(); - it != localContainers.end(); it++) { - /* Get local container's spin lock. */ - spinLockWait(&(*it)->lockval); - { (*it)->classMap->erase(target->klassOop); } - /* Release local container's spin lock. */ - spinLockRelease(&(*it)->lockval); - } - } - /* Release spin lock of containers queue. */ - spinLockRelease(&queueLock); + classMap.erase(target->klassOop); } /*! * \brief Remove all-class from container. * This function will be called from d'tor of TClassContainer. - * So we do not get any lock because d'tor calls at Agent_OnUnload. */ void TClassContainer::allClear(void) { - /* Add all TObjectData pointers in parent container map to unloadedList */ - for (TClassMap::iterator cur = classMap->begin(); cur != classMap->end(); - ++cur) { - unloadedList.insert(cur->second); - } - - /* Release all memory for TObjectData. */ - for (TClassInfoSet::iterator itr = unloadedList.begin(); - itr != unloadedList.end(); itr++) { - free((*itr)->className); - free(*itr); + /* Add all TObjectData pointers in container map to unloadedList */ + for (auto cur = classMap.begin(); cur != classMap.end(); cur++) { + TObjectData *objData = cur->second; + free(objData->className); + free(objData); } } @@ -566,11 +437,12 @@ * \param fd [in] Target file descriptor. * \param objData [in] The class information. * \param cur [in] The class size counter. + * \param snapshot[in] SnapShot container. * \return Value is zero, if process is succeed.
* Value is error number a.k.a. "errno", if process is failure. */ inline int writeClassData(const int fd, const TObjectData *objData, - const TClassCounter *cur) { + TClassCounter *cur, TSnapShotContainer *snapshot) { int result = 0; /* Output class-information. */ try { @@ -700,27 +572,10 @@ } /* Class map used snapshot output. */ - TClassMap *workClsMap = NULL; - /* Get class container's spin lock. */ - spinLockWait(&lockval); - { - try { - workClsMap = new TClassMap(*this->classMap); - } catch (...) { - workClsMap = NULL; - } - } - /* Release class container's spin lock. */ - spinLockRelease(&lockval); - - if (unlikely(workClsMap == NULL)) { - int raisedErrNum = errno; - logger->printWarnMsgWithErrno("Couldn't allocate working memory!"); - return raisedErrNum; - } + auto workClsMap(classMap); /* Allocate return array. */ - jlong rankCnt = workClsMap->size(); + jlong rankCnt = workClsMap.size(); rankCnt = (rankCnt < conf->RankLevel()->get()) ? rankCnt : conf->RankLevel()->get(); @@ -734,7 +589,6 @@ } catch (...) { int raisedErrNum = errno; logger->printWarnMsgWithErrno("Couldn't allocate working memory!"); - delete workClsMap; return raisedErrNum; } @@ -746,7 +600,6 @@ int raisedErrNum = errno; logger->printWarnMsgWithErrno("Could not open %s", conf->FileName()->get()); delete sortArray; - delete workClsMap; return raisedErrNum; } @@ -770,7 +623,6 @@ logger->printWarnMsg("Could not write snapshot"); close(fd); delete sortArray; - delete workClsMap; return raisedErrNum; } @@ -782,9 +634,8 @@ register jlong AlertThreshold = conf->getAlertThreshold(); /* Loop each class. */ - for (TClassMap::iterator it = workClsMap->begin(); it != workClsMap->end(); - ++it) { - TObjectData *objData = (*it).second; + for (auto it = workClsMap.begin(); it != workClsMap.end(); it++) { + TObjectData *objData = it->second; TClassCounter *cur = snapshot->findClass(objData); /* If don't registed class yet. */ if (unlikely(cur == NULL)) { @@ -808,7 +659,7 @@ if (!conf->ReduceSnapShot()->get() || (result.usage > 0)) { /* Output class-information. */ if (likely(raiseErrorCode == 0)) { - raiseErrorCode = writeClassData(fd, objData, cur); + raiseErrorCode = writeClassData(fd, objData, cur, snapshot); } numEntries++; @@ -848,7 +699,6 @@ } } } - delete workClsMap; /* Set output entry count. */ hdr.size = numEntries; @@ -923,7 +773,7 @@ * because class unloading is single-threaded process. * So we can lock-free access. */ - unloadedList.insert(counter); + unloadedList.push(counter); } } } @@ -942,16 +792,15 @@ TSnapShotContainer::removeObjectDataFromAllSnapShots(unloadedList); /* Remove targets from class container. */ - for (TClassInfoSet::iterator itr = unloadedList.begin(); - itr != unloadedList.end(); itr++) { - TObjectData *objData = *itr; + TObjectData *objData; + while (unloadedList.try_pop(objData)) { clsContainer->removeClass(objData); free(objData->className); free(objData); } + } - /* Clear unloaded list. */ - unloadedList.clear(); - } + /* Clear updated data */ + clsContainer->removeBeforeUpdatedData(); } diff -r bec923d3aeb6 -r 9a13d070bb77 agent/src/heapstats-engines/classContainer.hpp --- a/agent/src/heapstats-engines/classContainer.hpp Tue Dec 05 16:18:49 2017 +0900 +++ b/agent/src/heapstats-engines/classContainer.hpp Fri Jan 19 14:06:27 2018 +0900 @@ -22,12 +22,13 @@ #ifndef CLASS_CONTAINER_HPP #define CLASS_CONTAINER_HPP -#include -#include +#include +#include +#include -#include "snapShotContainer.hpp" #include "sorter.hpp" #include "trapSender.hpp" +#include "oopUtil.hpp" #if PROCESSOR_ARCH == X86 #include "arch/x86/lock.inline.hpp" @@ -36,6 +37,31 @@ #endif /*! + * \brief Pointer type of klassOop. + */ +typedef void* PKlassOop; + +/*! + * \brief Forward declaration in snapShotContainer.hpp + */ +class TSnapShotContainer; + +/*! + * \brief This structure stored class information. + */ +typedef struct { + jlong tag; /*!< Class tag. */ + jlong classNameLen; /*!< Class name. */ + char *className; /*!< Class name length. */ + PKlassOop klassOop; /*!< Java inner class object. */ + jlong oldTotalSize; /*!< Class old total use size. */ + TOopType oopType; /*!< Type of class. */ + jlong clsLoaderId; /*!< Class loader instance id. */ + jlong clsLoaderTag; /*!< Class loader class tag. */ + jlong instanceSize; /*!< Class size if this class is instanceKlass. */ +} TObjectData; + +/*! * \brief This structure stored size of a class used in heap. */ typedef struct { @@ -45,27 +71,20 @@ } THeapDelta; /*! - * \brief This type is for map stored class information. - */ -typedef std::tr1::unordered_map > TClassMap; - -/*! * \brief Memory usage alert types. */ typedef enum { ALERT_JAVA_HEAP, ALERT_METASPACE } TMemoryUsageAlertType; /*! - * \brief This class is stored class information.
- * e.g. class-name, class instance count, size, etc... + * \brief Type is for unloaded class information. */ -class TClassContainer; +typedef tbb::concurrent_queue TClassInfoSet; /*! - * \brief This type is for TClassContainer in Thread-Local-Storage. + * \brief Type is for storing class information. */ -typedef std::deque TLocalClassContainer; - +typedef tbb::concurrent_hash_map > TClassMap; /*! * \brief This class is stored class information.
* e.g. class-name, class instance count, size, etc... @@ -74,10 +93,8 @@ public: /*! * \brief TClassContainer constructor. - * \param base [in] Parent class container instance. - * \param needToClr [in] Flag of deallocate all data on destructor. */ - TClassContainer(TClassContainer *base = NULL, bool needToClr = true); + TClassContainer(void); /*! * \brief TClassContainer destructor. */ @@ -88,7 +105,7 @@ * \param klassOop [in] New class oop. * \return New-class data. */ - virtual TObjectData *pushNewClass(void *klassOop); + virtual TObjectData *pushNewClass(PKlassOop klassOop); /*! * \brief Append new-class to container. @@ -98,7 +115,7 @@ * This value isn't equal param "objData", * if already registered equivalence class. */ - virtual TObjectData *pushNewClass(void *klassOop, TObjectData *objData); + virtual TObjectData *pushNewClass(PKlassOop klassOop, TObjectData *objData); /*! * \brief Remove class from container. @@ -111,23 +128,9 @@ * \param klassOop [in] Target class oop. * \return Class data of target class. */ - inline TObjectData *findClass(void *klassOop) { - /* Search class data. */ - TObjectData *result = NULL; - - /* Get class container's spin lock. */ - spinLockWait(&lockval); - { - /* Search class data. */ - TClassMap::iterator it = classMap->find(klassOop); - if (it != classMap->end()) { - result = (*it).second; - } - } - /* Release class container's spin lock. */ - spinLockRelease(&lockval); - - return result; + inline TObjectData *findClass(PKlassOop klassOop) { + TClassMap::const_accessor acc; + return classMap.find(acc, klassOop) ? acc->second : NULL; } /*! @@ -136,44 +139,20 @@ * \param newKlassOop [in] Target new class oop. * \return Class data of target class. */ - inline void updateClass(void *oldKlassOop, void *newKlassOop) { - /* Get class container's spin lock. */ - spinLockWait(&lockval); - { - /* Search class data. */ - TClassMap::iterator it = classMap->find(oldKlassOop); - if (it != classMap->end()) { - TObjectData *cur = (*it).second; - - /* Remove old klassOop. */ - classMap->erase(it); + inline void updateClass(PKlassOop oldKlassOop, PKlassOop newKlassOop) { + TClassMap::const_accessor acc; + if (classMap.find(acc, oldKlassOop)) { + TObjectData *cur = acc->second; + acc.release(); - try { - /* Update class data. */ - (*classMap)[newKlassOop] = cur; - cur->klassOop = newKlassOop; - } catch (...) { - /* - * Maybe failed to allocate memory - * at "std::map::operator[]". - */ - } - } + cur->klassOop = newKlassOop; + TClassMap::accessor new_acc; + classMap.insert(new_acc, std::make_pair(newKlassOop, cur)); + new_acc.release(); + + classMap.erase(oldKlassOop); + updatedClassList.push(oldKlassOop); } - /* Release class container's spin lock. */ - spinLockRelease(&lockval); - - /* Get spin lock of containers queue. */ - spinLockWait(&queueLock); - { - TLocalClassContainer::iterator it = localContainers.begin(); - /* Broadcast to each local container. */ - for (; it != localContainers.end(); it++) { - (*it)->updateClass(oldKlassOop, newKlassOop); - } - } - /* Release spin lock of containers queue. */ - spinLockRelease(&queueLock); } /*! @@ -181,14 +160,7 @@ * \return Entries count of class information. */ inline size_t getContainerSize(void) { - size_t result = 0; - - /* Get class container's spin lock. */ - spinLockWait(&lockval); - { result = this->classMap->size(); } - /* Release class container's spin lock. */ - spinLockRelease(&lockval); - return result; + return classMap.size(); } /*! @@ -205,55 +177,14 @@ virtual int afterTakeSnapShot(TSnapShotContainer *snapshot, TSorter **rank); - /*! - * \brief Get local class container with each threads. - * \return Local class container instance for this thread. - */ - inline TClassContainer *getLocalContainer(void) { - /* Get container for this thread. */ - TClassContainer *result = - (TClassContainer *)pthread_getspecific(clsContainerKey); - - /* If container isn't exists yet. */ - if (unlikely(result == NULL)) { - try { - result = new TClassContainer(this, false); - } catch (...) { - /* Maybe raised badalloc exception. */ - return NULL; - } - pthread_setspecific(clsContainerKey, result); - - bool isFailure = false; - /* Get spin lock of containers queue. */ - spinLockWait(&queueLock); - { - try { - localContainers.push_back(result); - } catch (...) { - /* Maybe failed to add queue. */ - isFailure = true; - } - } - /* Release spin lock of containers queue. */ - spinLockRelease(&queueLock); - - if (unlikely(isFailure)) { - delete result; - result = NULL; - } + void removeBeforeUpdatedData(void) { + PKlassOop klass; + while (updatedClassList.try_pop(klass)) { + classMap.erase(klass); } - - return result; } - protected: - /*! - * \brief ClassContainer in TLS of each threads. - */ - TLocalClassContainer localContainers; - - RELEASE_ONLY(private :) + private: /*! * \brief SNMP trap sender. */ @@ -262,27 +193,12 @@ /*! * \brief Maps of class counting record. */ - TClassMap *classMap; - - /*! - * \brief The thread storage key for each local class container. - */ - pthread_key_t clsContainerKey; + TClassMap classMap; /*! - * \brief SpinLock variable for class container instance. - */ - volatile int lockval; - - /*! - * \brief SpinLock variable for queue of local class containers. + * \brief Updated class list. */ - volatile int queueLock; - - /*! - * \brief Do we need to clear at destructor? - */ - bool needToClear; + tbb::concurrent_queue updatedClassList; }; /*! diff -r bec923d3aeb6 -r 9a13d070bb77 agent/src/heapstats-engines/libmain.cpp --- a/agent/src/heapstats-engines/libmain.cpp Tue Dec 05 16:18:49 2017 +0900 +++ b/agent/src/heapstats-engines/libmain.cpp Fri Jan 19 14:06:27 2018 +0900 @@ -454,6 +454,7 @@ TThreadRecorder::setCapabilities(&capabilities); /* Setup GarbageCollectionFinish callback for class unloading. */ + TGarbageCollectionFinishCallback::mergeCapabilities(&capabilities); TGarbageCollectionFinishCallback::registerCallback( &OnGarbageCollectionFinishForUnload); @@ -472,7 +473,6 @@ /* FullGC on G1, we handle it at callbackForG1Full() */ if (!vmVal->getUseG1()) { TGarbageCollectionStartCallback::mergeCapabilities(&capabilities); - TGarbageCollectionFinishCallback::mergeCapabilities(&capabilities); if (vmVal->getUseCMS()) { TGarbageCollectionStartCallback::registerCallback(&OnCMSGCStart); diff -r bec923d3aeb6 -r 9a13d070bb77 agent/src/heapstats-engines/snapShotContainer.cpp --- a/agent/src/heapstats-engines/snapShotContainer.cpp Tue Dec 05 16:18:49 2017 +0900 +++ b/agent/src/heapstats-engines/snapShotContainer.cpp Fri Jan 19 14:06:27 2018 +0900 @@ -19,25 +19,18 @@ * */ +#include +#include + #include "globals.hpp" #include "snapShotContainer.hpp" - -/*! - * \brief Pthread mutex for instance control.
- *
- * This mutex used in below process.
- * - TSnapShotContainer::getInstance @ snapShotContainer.cpp
- * To get older snapShotContainer instance from stockQueue.
- * - TSnapShotContainer::releaseInstance @ snapShotContainer.cpp
- * To add used snapShotContainer instance to stockQueue.
- */ -pthread_mutex_t TSnapShotContainer::instanceLocker = - PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP; +#include "classContainer.hpp" /*! * \brief Snapshot container instance stock queue. */ -TSnapShotQueue *TSnapShotContainer::stockQueue = NULL; +tbb::concurrent_queue + *TSnapShotContainer::stockQueue = NULL; /*! * \brief Set of active TSnapShotContainer set @@ -67,13 +60,12 @@ */ void TSnapShotContainer::globalFinalize(void) { if (likely(stockQueue != NULL)) { - /* Clear snapshot in queue. */ - while (!stockQueue->empty()) { - TSnapShotContainer *item = stockQueue->front(); + TSnapShotContainer *item; + /* Clear snapshots in queue. */ + while (stockQueue->try_pop(item)) { /* Deallocate snapshot instance. */ delete item; - stockQueue->pop(); } /* Deallocate stock queue. */ @@ -90,26 +82,12 @@ */ TSnapShotContainer *TSnapShotContainer::getInstance(void) { TSnapShotContainer *result = NULL; - - ENTER_PTHREAD_SECTION(&instanceLocker) { - if (!stockQueue->empty()) { - /* Reuse snapshot container instance. */ - result = stockQueue->front(); - stockQueue->pop(); - } - - /* If need create new instance. */ - if (result == NULL) { - /* Create new snapshot container instance. */ - try { - result = new TSnapShotContainer(); - activeSnapShots.insert(result); - } catch (...) { - result = NULL; - } - } + if (!stockQueue->try_pop(result)) { + /* Create new snapshot container instance. */ + result = new TSnapShotContainer(); + TActiveSnapShots::accessor acc; + activeSnapShots.insert(acc, result); } - EXIT_PTHREAD_SECTION(&instanceLocker) return result; } @@ -125,53 +103,27 @@ return; } - bool existStockSpace = false; - ENTER_PTHREAD_SECTION(&instanceLocker) { - existStockSpace = (stockQueue->size() < MAX_STOCK_COUNT); - } - EXIT_PTHREAD_SECTION(&instanceLocker) - - if (likely(existStockSpace)) { - /* - * We reset this flag. - * Because we need deallocating if failed to store to stock. - * E.g. Failed to get mutex at "pthread_mutex_lock/unlock" - * or no more memory at "std::queue::push()". - */ - existStockSpace = false; - + /* + * unsafe_size() might return actual size if it is accessed concurrently. + * However we use this function because we can use to decide cache count. + * SnapShot cache means best effort. + */ + if (likely(stockQueue->unsafe_size() < MAX_STOCK_COUNT)) { /* Clear data. */ instance->clear(false); - - ENTER_PTHREAD_SECTION(&instanceLocker) { - try { - /* Store instance. */ - stockQueue->push(instance); - - existStockSpace = true; - } catch (...) { - /* Maybe faield to allocate memory. So we release instance. */ - } - } - EXIT_PTHREAD_SECTION(&instanceLocker) + /* Store instance. */ + stockQueue->push(instance); + } else { + /* Deallocate instance. */ + activeSnapShots.erase(instance); + delete instance; } - - ENTER_PTHREAD_SECTION(&instanceLocker) - { - if (unlikely(!existStockSpace)) { - /* Deallocate instance. */ - activeSnapShots.erase(instance); - delete instance; - } - } - EXIT_PTHREAD_SECTION(&instanceLocker) } /*! * \brief TSnapshotContainer constructor. */ -TSnapShotContainer::TSnapShotContainer(bool isParent) - : counterMap(), containerMap() { +TSnapShotContainer::TSnapShotContainer(void) : counterMap(), childrenMap() { /* Header setting. */ this->_header.magicNumber = conf->CollectRefTree()->get() ? EXTENDED_REFTREE_SNAPSHOT @@ -181,16 +133,6 @@ this->_header.size = 0; memset((void *)&this->_header.gcCause[0], 0, 80); - /* Initialize each field. */ - lockval = 0; - isParentContainer = isParent; - - /* Create thread storage key. */ - if (unlikely(isParent && - pthread_key_create(&snapShotContainerKey, NULL) != 0)) { - throw "Failed to create pthread key"; - } - this->isCleared = true; } @@ -199,45 +141,18 @@ */ TSnapShotContainer::~TSnapShotContainer(void) { /* Cleanup elements on counter map. */ - for (TSizeMap::iterator it = counterMap.begin(); it != counterMap.end(); - ++it) { - TClassCounter *clsCounter = (*it).second; - if (unlikely(clsCounter == NULL)) { - continue; - } - - /* Deallocate field block cache. */ + for (auto itr = counterMap.begin(); itr != counterMap.end(); itr++) { + TClassCounter *clsCounter = itr->second; free(clsCounter->offsets); - - /* Deallocate children class list. */ - TChildClassCounter *counter = clsCounter->child; - while (counter != NULL) { - TChildClassCounter *aCounter = counter; - counter = counter->next; - - /* Deallocate TChildClassCounter. */ - free(aCounter->counter); - free(aCounter); - } - - /* Deallocate TClassCounter. */ free(clsCounter->counter); free(clsCounter); } - /* Cleanup elements on snapshot container map. */ - for (TLocalSnapShotContainer::iterator it = containerMap.begin(); - it != containerMap.end(); ++it) { - delete (*it).second; - } - - /* Clean maps. */ - counterMap.clear(); - containerMap.clear(); - - if (isParentContainer) { - /* Clean thread storage key. */ - pthread_key_delete(snapShotContainerKey); + /* Cleanup elements on children map. */ + for (auto itr = childrenMap.begin(); itr != childrenMap.end(); itr++) { + TChildClassCounter *childCounter = itr->second; + free(childCounter->counter); + free(childCounter); } } @@ -271,19 +186,15 @@ this->clearObjectCounter(cur->counter); - try { - /* Set counter map. */ - counterMap[objData] = cur; - } catch (...) { - /* - * Maybe failed to allocate memory at "std::map::operator[]". - */ + /* Set to counter map. */ + TSizeMap::accessor acc; + if (!counterMap.insert(acc, std::make_pair(objData, cur))) { free(cur->counter); free(cur); cur = NULL; } - return cur; + return acc->second; } /*! @@ -313,17 +224,27 @@ this->clearObjectCounter(newCounter->counter); newCounter->objData = objData; - /* Chain children list. */ - TChildClassCounter *counter = clsCounter->child; - if (unlikely(counter == NULL)) { - clsCounter->child = newCounter; - } else { - /* Get last counter. */ - while (counter->next != NULL) { - counter = counter->next; + /* Set to children map. */ + TChildrenMapKey key = std::make_pair(clsCounter, objData->klassOop); + TChildrenMap::accessor acc; + childrenMap.insert(acc, std::make_pair(key, newCounter)); + acc.release(); + + /* Add new counter to children list */ + spinLockWait(&clsCounter->spinlock); + { + TChildClassCounter *counter = clsCounter->child; + if (unlikely(counter == NULL)) { + clsCounter->child = newCounter; + } else { + /* Get last counter. */ + while (counter->next != NULL) { + counter = counter->next; + } + counter->next = newCounter; } - counter->next = newCounter; } + spinLockRelease(&clsCounter->spinlock); return newCounter; } @@ -378,36 +299,16 @@ return; } - /* Get snapshot container's spin lock. */ - spinLockWait(&lockval); - { - /* Clean heap usage information. */ - for (TSizeMap::iterator it = counterMap.begin(); it != counterMap.end(); - ++it) { - TClassCounter *clsCounter = (*it).second; - if (unlikely(clsCounter == NULL)) { - continue; - } + /* Cleanup elements on counter map. */ + for (auto itr = counterMap.begin(); itr != counterMap.end(); itr++) { + TClassCounter *clsCounter = itr->second; + free(clsCounter->offsets); + clsCounter->offsets = NULL; + clsCounter->offsetCount = -1; - /* Deallocate field block cache. */ - free(clsCounter->offsets); - clsCounter->offsets = NULL; - clsCounter->offsetCount = -1; - - /* Reset counters. */ - this->clearChildClassCounters(clsCounter); - } - - /* Clean local snapshots. */ - for (TLocalSnapShotContainer::iterator it = containerMap.begin(); - it != containerMap.end(); ++it) { - (*it).second->clear(true); - } - - this->isCleared = true; + /* Reset counters. */ + clearChildClassCounters(clsCounter); } - /* Release snapshot container's spin lock. */ - spinLockRelease(&lockval); } /*! @@ -448,122 +349,34 @@ } /*! - * \brief Merge children data. - */ -void TSnapShotContainer::mergeChildren(void) { - /* Get snapshot container's spin lock. */ - spinLockWait(&lockval); - { - /* Loop each local snapshot container. */ - for (TLocalSnapShotContainer::iterator it = this->containerMap.begin(); - it != this->containerMap.end(); it++) { - /* Loop each class in snapshot container. */ - TSizeMap *srcCounterMap = &(*it).second->counterMap; - for (TSizeMap::iterator it2 = srcCounterMap->begin(); - it2 != srcCounterMap->end(); it2++) { - TClassCounter *srcClsCounter = (*it2).second; - - /* Search or register class. */ - TClassCounter *clsCounter = this->findClass((*it2).first); - if (unlikely(clsCounter == NULL)) { - clsCounter = this->pushNewClass((*it2).first); - - /* If failed to search and register class. */ - if (unlikely(clsCounter == NULL)) { - continue; /* Skip merge this class. */ - } - } - - /* Marge class heap usage. */ - this->addInc(clsCounter->counter, srcClsCounter->counter); - - /* Loop each children class. */ - TChildClassCounter *counter = srcClsCounter->child; - while (counter != NULL) { - TObjectData *objData = counter->objData; - - /* Search child class. */ - TChildClassCounter *childClsData = - this->findChildClass(clsCounter, objData->klassOop); - - /* Register class as child class. */ - if (unlikely(childClsData == NULL)) { - childClsData = this->pushNewChildClass(clsCounter, objData); - } - - if (likely(childClsData != NULL)) { - /* Marge children class heap usage. */ - this->addInc(childClsData->counter, counter->counter); - } - - counter = counter->next; - } - } - } - } - /* Release snapshot container's spin lock. */ - spinLockRelease(&lockval); -} - -/*! * \brief Remove unloaded TObjectData in this snapshot container. * This function should be called at safepoint. * \param unloadedList Set of unloaded TObjectData. */ void TSnapShotContainer::removeObjectData(TClassInfoSet &unloadedList) { - TSizeMap::iterator itr; - - /* Remove the target from parent container. */ - for (TClassInfoSet::iterator target = unloadedList.begin(); - target != unloadedList.end(); target++) { - itr = counterMap.find(*target); - if (itr != counterMap.end()) { - TClassCounter *clsCounter = itr->second; - TChildClassCounter *childCounter = clsCounter->child; - - while (childCounter != NULL) { - TChildClassCounter *nextCounter = childCounter->next; - free(childCounter->counter); - free(childCounter); - childCounter = nextCounter; - } - - free(clsCounter->counter); - free(clsCounter); - counterMap.erase(itr); - } - } + /* + * This function is called at safepoint. + * (from OnGarbageCollectionFinishForUnload() in classContainer.cpp) + * So we can use *unsafe* iterator access in tbb::concurrent_queue. + */ + for (auto itr = unloadedList.unsafe_begin(); + itr != unloadedList.unsafe_end(); itr++) { + TSizeMap::const_accessor acc; + if (counterMap.find(acc, *itr)) { + TClassCounter *clsCounter = acc->second; + counterMap.erase(acc); + acc.release(); - /* Remove the target from all children in counterMap. */ - for (itr = counterMap.begin(); itr != counterMap.end(); itr++) { - TClassCounter *clsCounter = itr->second; - TChildClassCounter *childCounter = clsCounter->child; - TChildClassCounter *prevChildCounter = NULL; - - while (childCounter != NULL) { - TChildClassCounter *nextCounter = childCounter->next; - - if (unloadedList.find(childCounter->objData) != unloadedList.end()) { - free(childCounter->counter); - free(childCounter); - if (prevChildCounter == NULL) { - clsCounter->child = nextCounter; - } else { - prevChildCounter->next = nextCounter; - } - } else { - prevChildCounter = childCounter; + TChildClassCounter *child = clsCounter->child; + while (child != NULL) { + TChildClassCounter *next = child->next; + childrenMap.erase(std::make_pair(clsCounter, child->objData->klassOop)); + free(child->counter); + free(child); + child = next; } - - childCounter = nextCounter; } } - - /* Remove the target from local containers. */ - for (TLocalSnapShotContainer::iterator container = containerMap.begin(); - container != containerMap.end(); container++) { - container->second->removeObjectData(unloadedList); - } } /*! @@ -572,13 +385,9 @@ */ void TSnapShotContainer::removeObjectDataFromAllSnapShots( TClassInfoSet &unloadedList) { - ENTER_PTHREAD_SECTION(&instanceLocker) - { - for (TActiveSnapShots::iterator itr = activeSnapShots.begin(); - itr != activeSnapShots.end(); itr++) { - (*itr)->removeObjectData(unloadedList); - } + for (auto itr = activeSnapShots.begin(); + itr != activeSnapShots.end(); itr++) { + itr->first->removeObjectData(unloadedList); } - EXIT_PTHREAD_SECTION(&instanceLocker) } diff -r bec923d3aeb6 -r 9a13d070bb77 agent/src/heapstats-engines/snapShotContainer.hpp --- a/agent/src/heapstats-engines/snapShotContainer.hpp Tue Dec 05 16:18:49 2017 +0900 +++ b/agent/src/heapstats-engines/snapShotContainer.hpp Fri Jan 19 14:06:27 2018 +0900 @@ -22,14 +22,14 @@ #ifndef _SNAPSHOT_CONTAINER_HPP #define _SNAPSHOT_CONTAINER_HPP -#include +#include +#include -#include -#include -#include +#include #include "jvmInfo.hpp" #include "oopUtil.hpp" +#include "classContainer.hpp" #if PROCESSOR_ARCH == X86 #include "arch/x86/lock.inline.hpp" @@ -66,34 +66,12 @@ } TObjectCounter; /*! - * \brief This structure stored class information. - */ -typedef struct { - jlong tag; /*!< Class tag. */ - jlong classNameLen; /*!< Class name. */ - char *className; /*!< Class name length. */ - void *klassOop; /*!< Java inner class object. */ - jlong oldTotalSize; /*!< Class old total use size. */ - TOopType oopType; /*!< Type of class. */ - jlong clsLoaderId; /*!< Class loader instance id. */ - jlong clsLoaderTag; /*!< Class loader class tag. */ - jlong instanceSize; /*!< Class size if this class is instanceKlass. */ -} TObjectData; - -/*! - * \brief This type is for storing unloaded class information. - */ -typedef std::tr1::unordered_set > TClassInfoSet; - -/*! * \brief This structure stored child class size information. */ struct TChildClassCounter { TObjectCounter *counter; /*!< Java inner class object. */ TObjectData *objData; /*!< Class information. */ TChildClassCounter *next; /*!< Pointer of next object. */ - unsigned int callCount; /*!< Call count. */ }; /*! @@ -136,31 +114,25 @@ class TSnapShotContainer; /*! - * \brief This type is for queue store snapshot information. + * \brief Type is for map of storing object counters. */ -typedef std::queue TSnapShotQueue; - -/*! - * \brief This type is for map stored size information. - */ -typedef std::tr1::unordered_map > TSizeMap; +typedef tbb::concurrent_hash_map > TSizeMap; /*! - * \brief This class is stored class object usage on heap. + * \brief Container of active snapshot list. */ -class TSnapShotContainer; +typedef tbb::concurrent_hash_map TActiveSnapShots; + +typedef std::pair TChildrenMapKey; + +typedef tbb::concurrent_hash_map + TChildrenMap; /*! - * \brief This type is for TSnapShotContainer in Thread-Local-Storage. + * \brief Snapshot container instance stock queue. */ -typedef std::tr1::unordered_map > - TLocalSnapShotContainer; - -typedef std::tr1::unordered_set > TActiveSnapShots; - +typedef tbb::concurrent_queue TSnapShotQueue; /*! * \brief This class is stored class object usage on heap. @@ -265,8 +237,8 @@ * Value is null, if class is not found. */ inline TClassCounter *findClass(TObjectData *objData) { - TSizeMap::iterator it = counterMap.find(objData); - return (it != counterMap.end()) ? (*it).second : NULL; + TSizeMap::const_accessor acc; + return counterMap.find(acc, objData) ? acc->second : NULL; } /*! @@ -277,44 +249,10 @@ * Value is null, if class is not found. */ inline TChildClassCounter *findChildClass(TClassCounter *clsCounter, - void *klassOop) { - TChildClassCounter *prevCounter = NULL; - TChildClassCounter *morePrevCounter = NULL; - TChildClassCounter *counter = clsCounter->child; - - if (counter == NULL) { - return NULL; - } - - /* Search children class list. */ - while (counter->objData->klassOop != klassOop) { - morePrevCounter = prevCounter; - prevCounter = counter; - counter = counter->next; - - if (counter == NULL) { - return NULL; - } - } - - /* LFU (Least Frequently Used). */ - if (counter != NULL) { - counter->callCount++; - - /* If counter need move to list head. */ - if (prevCounter != NULL && prevCounter->callCount <= counter->callCount) { - prevCounter->next = counter->next; - if (morePrevCounter != NULL) { - /* Move to near list head. */ - morePrevCounter->next = counter; - } else { - /* Move list head. */ - clsCounter->child = counter; - } - counter->next = prevCounter; - } - } - return counter; + PKlassOop klassOop) { + TChildrenMapKey key = std::make_pair(clsCounter, klassOop); + TChildrenMap::const_accessor acc; + return childrenMap.find(acc, key) ? acc->second : NULL; } /*! @@ -344,65 +282,6 @@ void clear(bool isForce); /*! - * \brief Get local snapshot container with each threads. - * \return Local snapshot container instance for this thread. - */ - inline TSnapShotContainer *getLocalContainer(void) { - TSnapShotContainer *result = NULL; - - /* Get root and local snapshot conatiner. */ - result = (TSnapShotContainer *)pthread_getspecific(snapShotContainerKey); - - /* If not exists local container. */ - if (unlikely(result == NULL)) { - pthread_t selfThreadId = pthread_self(); - - /* Get snapshot container's spin lock. */ - spinLockWait(&lockval); - { - TLocalSnapShotContainer::iterator it = containerMap.find(selfThreadId); - if (it != containerMap.end()) { - result = (*it).second; - } - } - /* Release snapshot container's spin lock. */ - spinLockRelease(&lockval); - - if (unlikely(result == NULL)) { - try { - result = new TSnapShotContainer(false); - } catch (...) { - /* Maybe raise badalloc exception. */ - return NULL; - } - - /* Get snapshot container's spin lock. */ - spinLockWait(&lockval); - { - try { - containerMap[selfThreadId] = result; - } catch (...) { - /* Failed to add map. Maybe no more free memory. */ - delete result; - result = NULL; - } - } - /* Release snapshot container's spin lock. */ - spinLockRelease(&lockval); - } - - /* Set local snapshot conatiner. */ - pthread_setspecific(snapShotContainerKey, result); - } - return result; - } - - /*! - * \brief Merge children data. - */ - virtual void mergeChildren(void); - - /*! * \brief Set "isCleared" flag. */ inline void setIsCleared(bool flag) { this->isCleared = flag; } @@ -424,7 +303,7 @@ /*! * \brief TSnapshotContainer constructor. */ - TSnapShotContainer(bool isParent = true); + TSnapShotContainer(void); /*! * \brief TSnapshotContainer destructor. */ @@ -449,17 +328,6 @@ void clearChildClassCounters(TClassCounter *counter); /*! - * \brief Pthread mutex for instance control.
- *
- * This mutex used in below process.
- * - TSnapShotContainer::getInstance @ snapShotContainer.cpp
- * To get older snapShotContainer instance from stockQueue.
- * - TSnapShotContainer::releaseInstance @ snapShotContainer.cpp
- * To add used snapShotContainer instance to stockQueue.
- */ - static pthread_mutex_t instanceLocker; - - /*! * \brief Snapshot container instance stock queue. */ static TSnapShotQueue *stockQueue; @@ -470,16 +338,16 @@ const static unsigned int MAX_STOCK_COUNT = 2; /*! - * \brief Maps of counter of each java class. + * \brief Map for TClassCounter. */ TSizeMap counterMap; /*! - * \brief Maps of TSnapShotContainer and thread. + * \brief Map for TChildClassCounter. */ - TLocalSnapShotContainer containerMap; + TChildrenMap childrenMap; - RELEASE_ONLY(private :) + private: /*! * \brief Snapshot header. @@ -487,21 +355,6 @@ volatile TSnapShotFileHeader _header; /*! - * \brief SpinLock variable for each snapshot class container. - */ - volatile int lockval; - - /*! - * \brief The thread key for map of local snapshot containers. - */ - pthread_key_t snapShotContainerKey; - - /*! - * \brief Is this container is parent container ? - */ - bool isParentContainer; - - /*! * \brief Is this container is cleared ? */ volatile bool isCleared; @@ -562,7 +415,6 @@ child_counter->counter->count = 0; child_counter->counter->total_size = 0; - // child_counter->callCount >>= 1; child_counter = child_counter->next; } diff -r bec923d3aeb6 -r 9a13d070bb77 agent/src/heapstats-engines/snapShotMain.cpp --- a/agent/src/heapstats-engines/snapShotMain.cpp Tue Dec 05 16:18:49 2017 +0900 +++ b/agent/src/heapstats-engines/snapShotMain.cpp Fri Jan 19 14:06:27 2018 +0900 @@ -42,7 +42,6 @@ typedef struct { TSnapShotContainer *snapshot; /*!< Container of taking snapshot. */ TClassCounter *counter; /*!< Counter of class heap usage. */ - TClassContainer *clsContainer; /*!< Container of class data. */ } TCollectContainers; /* Variable defines. */ @@ -74,19 +73,6 @@ pthread_mutex_t dumpMutex = PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP; /*! - * \brief Pthread mutex for change snapshot queue.
- *
- * This mutex used in below process.
- * - TakeSnapShot @ snapShotMain.cpp
- * To add snapshot by JVMTI to output wait queue.
- * - popSnapShotQueue @ snapShotMain.cpp
- * To get snapshot from output wait queue.
- * - addSnapShotQueue @ snapShotMain.cpp
- * To add snapshot by GC to output wait queue.
- */ -pthread_mutex_t queueMutex = PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP; - -/*! * \brief Pthread mutex for JVMTI IterateOverHeap calling.
*
* This mutex used in below process.
@@ -194,24 +180,8 @@ * So that, you should be additionally handling snapshot instance. */ inline bool addSnapShotQueue(TSnapShotContainer *snapshot) { - bool isSucceed = false; - /* Push output waiting queue. */ - ENTER_PTHREAD_SECTION(&queueMutex) { - try { - snapStockQueue.push(snapshot); - - /* Reset exception flag. */ - isSucceed = true; - } catch (...) { - /* - * Maybe faield to allocate memory at "std:queue::push()". - * So we throw exception again at after release lock. - */ - } - } - EXIT_PTHREAD_SECTION(&queueMutex) - - return isSucceed; + snapStockQueue.push(snapshot); + return true; } /*! @@ -221,17 +191,8 @@ */ inline TSnapShotContainer *popSnapShotQueue(void) { TSnapShotContainer *snapshot = NULL; - - /* Get snapshot data from waiting queue. */ - ENTER_PTHREAD_SECTION(&queueMutex) { - if (likely(!snapStockQueue.empty())) { - snapshot = snapStockQueue.front(); - snapStockQueue.pop(); - } - } - EXIT_PTHREAD_SECTION(&queueMutex) - - return snapshot; + bool succeeded = snapStockQueue.try_pop(snapshot); + return succeeded ? snapshot : NULL; } /*! @@ -329,26 +290,14 @@ /*! * \brief Get class information. - * \param aClsContainer [in] Search target class container. * \param klassOop [in] Pointer of child java class object(KlassOopDesc). * \return Pointer of information of expceted class by klassOop. */ -inline TObjectData *getObjectDataFromKlassOop(TClassContainer *aClsContainer, - void *klassOop) { - TObjectData *clsData = NULL; - - /* Search child class at local class container. */ - clsData = aClsContainer->findClass(klassOop); +inline TObjectData *getObjectDataFromKlassOop(void *klassOop) { + TObjectData *clsData = clsContainer->findClass(klassOop); if (unlikely(clsData == NULL)) { - /* Search child class at root class container. */ - clsData = clsContainer->findClass(klassOop); - if (unlikely(clsData == NULL)) { - /* Push new loaded class to root class container. */ - clsData = clsContainer->pushNewClass(klassOop); - } else { - /* Push a loaded class to local class container. */ - aClsContainer->pushNewClass(klassOop, clsData); - } + /* Push new loaded class to root class container. */ + clsData = clsContainer->pushNewClass(klassOop); } return clsData; @@ -367,21 +316,19 @@ return; } - TSnapShotContainer *localSnapshot = containerInfo->snapshot; + TSnapShotContainer *snapshot = containerInfo->snapshot; TClassCounter *parentCounter = containerInfo->counter; - TClassContainer *localClsContainer = containerInfo->clsContainer; TChildClassCounter *clsCounter = NULL; /* Search child class. */ - clsCounter = localSnapshot->findChildClass(parentCounter, klassOop); + clsCounter = snapshot->findChildClass(parentCounter, klassOop); if (unlikely(clsCounter == NULL)) { /* Get child class information. */ - TObjectData *clsData = - getObjectDataFromKlassOop(localClsContainer, klassOop); + TObjectData *clsData = getObjectDataFromKlassOop(klassOop); /* Push new child loaded class. */ - clsCounter = localSnapshot->pushNewChildClass(parentCounter, clsData); + clsCounter = snapshot->pushNewChildClass(parentCounter, clsData); } if (unlikely(clsCounter == NULL)) { @@ -404,7 +351,7 @@ } /* Count perent class size and instance count. */ - localSnapshot->FastInc(clsCounter->counter, size); + snapshot->FastInc(clsCounter->counter, size); } /*! @@ -414,16 +361,8 @@ */ inline void calculateObjectUsage(TSnapShotContainer *snapshot, void *oop) { void *klassOop = getKlassOopFromOop(oop); - TClassContainer *workClsContainer = clsContainer->getLocalContainer(); /* Sanity check. */ - if (unlikely(snapshot == NULL || klassOop == NULL || - workClsContainer == NULL)) { - return; - } - - TSnapShotContainer *localSnapshot = snapshot->getLocalContainer(); - if (unlikely(localSnapshot == NULL)) { - logger->printCritMsg("Couldn't get local snapshot container!"); + if (unlikely(snapshot == NULL || klassOop == NULL)) { return; } @@ -433,17 +372,17 @@ TObjectData *clsData = NULL; /* Get class information. */ - clsData = getObjectDataFromKlassOop(workClsContainer, klassOop); + clsData = getObjectDataFromKlassOop(klassOop); if (unlikely(clsData == NULL)) { logger->printCritMsg("Couldn't get ObjectData!"); return; } /* Search class. */ - clsCounter = localSnapshot->findClass(clsData); + clsCounter = snapshot->findClass(clsData); if (unlikely(clsCounter == NULL)) { /* Push new loaded class. */ - clsCounter = localSnapshot->pushNewClass(clsData); + clsCounter = snapshot->pushNewClass(clsData); } if (unlikely(clsCounter == NULL)) { @@ -468,7 +407,7 @@ } /* Count perent class size and instance count. */ - localSnapshot->FastInc(clsCounter->counter, size); + snapshot->FastInc(clsCounter->counter, size); /* If we should not collect reftree or oop has no field. */ if (!conf->CollectRefTree()->get() || !hasOopField(oopType)) { @@ -476,9 +415,8 @@ } TCollectContainers containerInfo; - containerInfo.snapshot = localSnapshot; + containerInfo.snapshot = snapshot; containerInfo.counter = clsCounter; - containerInfo.clsContainer = workClsContainer; TOopMapBlock *offsets = NULL; int offsetCount = 0; diff -r bec923d3aeb6 -r 9a13d070bb77 agent/src/heapstats-engines/snapShotProcessor.cpp --- a/agent/src/heapstats-engines/snapShotProcessor.cpp Tue Dec 05 16:18:49 2017 +0900 +++ b/agent/src/heapstats-engines/snapShotProcessor.cpp Fri Jan 19 14:06:27 2018 +0900 @@ -87,10 +87,7 @@ if (likely(controller->_numRequests > 0)) { controller->_numRequests--; needProcess = true; - if (likely(!controller->snapQueue.empty())) { - snapshot = controller->snapQueue.front(); - controller->snapQueue.pop(); - } + controller->snapQueue.try_pop(snapshot); } /* Check remaining work. */ @@ -106,9 +103,6 @@ static const char *label = "Write SnapShot and calculation"; TElapsedTimer elapsedTime(label); - /* Marge children snapshot's data to parent snapshot. */ - snapshot->mergeChildren(); - /* Output class-data. */ result = controller->_container->afterTakeSnapShot(snapshot, &ranking); } diff -r bec923d3aeb6 -r 9a13d070bb77 agent/src/heapstats-engines/threadRecorder.cpp --- a/agent/src/heapstats-engines/threadRecorder.cpp Tue Dec 05 16:18:49 2017 +0900 +++ b/agent/src/heapstats-engines/threadRecorder.cpp Fri Jan 19 14:06:27 2018 +0900 @@ -353,7 +353,6 @@ TThreadRecorder::TThreadRecorder(size_t buffer_size) : threadIDMap() { aligned_buffer_size = ALIGN_SIZE_UP(buffer_size, systemPageSize); bufferLockVal = 0; - idmapLockVal = 0; /* manpage of mmap(2): * @@ -380,17 +379,9 @@ munmap(record_buffer, aligned_buffer_size); /* Deallocate memory for thread name. */ - spinLockWait(&idmapLockVal); - { - for (std::tr1::unordered_map >::iterator itr = - threadIDMap.begin(); - itr != threadIDMap.end(); itr++) { - free(itr->second); - } + for (auto itr = threadIDMap.begin(); itr != threadIDMap.end(); itr++) { + free(itr->second); } - spinLockRelease(&idmapLockVal); - } /*! @@ -655,27 +646,21 @@ char bom = BOM; write(fd, &bom, sizeof(char)); - spinLockWait(&idmapLockVal); - { - /* Dump thread list. */ - int threadIDMapSize = threadIDMap.size(); - write(fd, &threadIDMapSize, sizeof(int)); + /* Dump thread list. */ + auto workIDMap(threadIDMap); + int threadIDMapSize = workIDMap.size(); + write(fd, &threadIDMapSize, sizeof(int)); - for (std::tr1::unordered_map >::iterator itr = - threadIDMap.begin(); - itr != threadIDMap.end(); itr++) { - jlong id = itr->first; - int classname_length = strlen(itr->second); - write(fd, &id, sizeof(jlong)); - write(fd, &classname_length, sizeof(int)); - write(fd, itr->second, classname_length); - } + for (auto itr = workIDMap.begin(); itr != workIDMap.end(); itr++) { + jlong id = itr->first; + int classname_length = strlen(itr->second); + write(fd, &id, sizeof(jlong)); + write(fd, &classname_length, sizeof(int)); + write(fd, itr->second, classname_length); + } - /* Dump thread event. */ - write(fd, record_buffer, aligned_buffer_size); - } - spinLockRelease(&idmapLockVal); + /* Dump thread event. */ + write(fd, record_buffer, aligned_buffer_size); close(fd); } @@ -760,17 +745,13 @@ jvmtiThreadInfo threadInfo; jvmti->GetThreadInfo(thread, &threadInfo); - spinLockWait(&idmapLockVal); { - char *current_val = threadIDMap[id]; - - if (unlikely(current_val != NULL)) { - free(current_val); + TThreadIDMap::accessor acc; + if (!threadIDMap.insert(acc, id)) { + free(acc->second); } - - threadIDMap[id] = strdup(threadInfo.name); + acc->second = strdup(threadInfo.name); } - spinLockRelease(&idmapLockVal); jvmti->Deallocate((unsigned char *)threadInfo.name); } @@ -814,17 +795,11 @@ eventRecord.additionalData = additionalData; if (unlikely(top_of_buffer->event == ThreadEnd)) { - spinLockWait(&idmapLockVal); - { - std::tr1::unordered_map > - ::iterator entry = threadIDMap.find(top_of_buffer->thread_id); - - if (likely(entry != threadIDMap.end())) { - free(entry->second); - threadIDMap.erase(entry); - } + TThreadIDMap::accessor acc; + if (threadIDMap.find(acc, top_of_buffer->thread_id)) { + free(acc->second); + threadIDMap.erase(acc); } - spinLockRelease(&idmapLockVal); } spinLockWait(&bufferLockVal); diff -r bec923d3aeb6 -r 9a13d070bb77 agent/src/heapstats-engines/threadRecorder.hpp --- a/agent/src/heapstats-engines/threadRecorder.hpp Tue Dec 05 16:18:49 2017 +0900 +++ b/agent/src/heapstats-engines/threadRecorder.hpp Fri Jan 19 14:06:27 2018 +0900 @@ -27,7 +27,7 @@ #include -#include +#include /*! * \brief Header of recording data. @@ -79,6 +79,12 @@ } TThreadEvent; /*! + * \brief Type of ThreadID-ThreadName map. + */ +typedef tbb::concurrent_hash_map > + TThreadIDMap; + +/*! * \brief Implementation of HeapStats Thread Recorder. * This instance must be singleton. */ @@ -111,7 +117,7 @@ * \brief ThreadID-ThreadName map. * Key is thread ID, Value is thread name. */ - std::tr1::unordered_map > threadIDMap; + TThreadIDMap threadIDMap; /*! * \brief SpinLock variable for Ring Buffer operation. @@ -119,11 +125,6 @@ volatile int bufferLockVal; /*! - * \brief SpinLock variable for Thread ID map operation. - */ - volatile int idmapLockVal; - - /*! * \brief Instance of TThreadRecorder. */ static TThreadRecorder *inst; diff -r bec923d3aeb6 -r 9a13d070bb77 agent/src/heapstats-engines/util.hpp --- a/agent/src/heapstats-engines/util.hpp Tue Dec 05 16:18:49 2017 +0900 +++ b/agent/src/heapstats-engines/util.hpp Fri Jan 19 14:06:27 2018 +0900 @@ -361,20 +361,33 @@ /* Classes. */ /*! - * \brief Hasher class for std::tr1::unordered_map. - * This template class will be used when key is numeric type. - * (int, pointer, etc) + * \brief Hasher class for tbb::concurrent_hash_map. + * This template class is for number type except pointers. */ template class TNumericalHasher { - public: - /*! - * \brief Get hash value from designated value. - * This function always return convert to integer only. - * \param val [in] Hash source data. - * \return Hash value. - */ - size_t operator()(const T &val) const { return (size_t)val; }; + public: + + static size_t hash(const T v) { + return v; + } + + static bool equal(const T v1, const T v2) { + return v1 == v2; + } + +}; + +/*! + * \brief Hasher class for tbb::concurrent_hash_map. + * This template class is for pointer type. + */ +template +class TPointerHasher : public TNumericalHasher { + public: + static size_t hash(const T v) { + return reinterpret_cast(v) / sizeof(T); + } }; /*! diff -r bec923d3aeb6 -r 9a13d070bb77 agent/src/iotracer/Makefile.in --- a/agent/src/iotracer/Makefile.in Tue Dec 05 16:18:49 2017 +0900 +++ b/agent/src/iotracer/Makefile.in Fri Jan 19 14:06:27 2018 +0900 @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.15 from Makefile.am. +# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2014 Free Software Foundation, Inc. +# Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, diff -r bec923d3aeb6 -r 9a13d070bb77 configure --- a/configure Tue Dec 05 16:18:49 2017 +0900 +++ b/configure Fri Jan 19 14:06:27 2018 +0900 @@ -5600,6 +5600,47 @@ as_fn_error $? "BFD library was not found." "$LINENO" 5 fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lpthread" >&5 +$as_echo_n "checking for main in -lpthread... " >&6; } +if ${ac_cv_lib_pthread_main+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lpthread $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + +int +main () +{ +return main (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_pthread_main=yes +else + ac_cv_lib_pthread_main=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_main" >&5 +$as_echo "$ac_cv_lib_pthread_main" >&6; } +if test "x$ac_cv_lib_pthread_main" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBPTHREAD 1 +_ACEOF + + LIBS="-lpthread $LIBS" + +else + as_fn_error $? "Posix thread library was not found." "$LINENO" 5 +fi + cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure @@ -6501,6 +6542,19 @@ fi +for ac_header in sys/auxv.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "sys/auxv.h" "ac_cv_header_sys_auxv_h" "$ac_includes_default" +if test "x$ac_cv_header_sys_auxv_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SYS_AUXV_H 1 +_ACEOF + +fi + +done + # Supplemental headers + # Check Container insert/erase and iterator constness (N2350) { $as_echo "$as_me:${as_lineno-$LINENO}: checking for N2350" >&5 $as_echo_n "checking for N2350... " >&6; } @@ -8110,7 +8164,70 @@ if test -n "$ARCH"; then CXXFLAGS+=" -march=$ARCH"; CCASFLAGS+=" -march=$ARCH" -fi +elif test x"$PROCESSOR_TYPE" = "xarm"; then # Raspberry Pi 2 support + CXXFLAGS+=" -march=armv7-a" + CCASFLAGS+=" -march=armv7-a" +fi + +# check TBB -------------------------------------------------------------------- +for ac_header in \ + tbb/concurrent_hash_map.h tbb/concurrent_queue.h \ + +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_cxx_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +else + as_fn_error $? "Not found common header files." "$LINENO" 5 +fi + +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -ltbb" >&5 +$as_echo_n "checking for main in -ltbb... " >&6; } +if ${ac_cv_lib_tbb_main+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ltbb $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + +int +main () +{ +return main (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_tbb_main=yes +else + ac_cv_lib_tbb_main=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_tbb_main" >&5 +$as_echo "$ac_cv_lib_tbb_main" >&6; } +if test "x$ac_cv_lib_tbb_main" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBTBB 1 +_ACEOF + + LIBS="-ltbb $LIBS" + +else + as_fn_error $? "TBB library was not found." "$LINENO" 5 +fi + # end processor type ----------------------------------------------------------- diff -r bec923d3aeb6 -r 9a13d070bb77 configure.ac --- a/configure.ac Tue Dec 05 16:18:49 2017 +0900 +++ b/configure.ac Fri Jan 19 14:06:27 2018 +0900 @@ -54,6 +54,8 @@ AC_CHECK_LIB([iberty], [main], [], []) AC_CHECK_LIB([bfd], [main], [], [AC_MSG_ERROR([BFD library was not found.])]) +AC_CHECK_LIB([pthread], [main], [], + [AC_MSG_ERROR([Posix thread library was not found.])]) AC_CACHE_SAVE # Checks for common header files. @@ -110,6 +112,8 @@ ) AM_CONDITIONAL(USE_PCRE, test -n "${ac_cv_header_pcre_h}") +AC_CHECK_HEADERS([sys/auxv.h], [], []) # Supplemental headers + # Check Container insert/erase and iterator constness (N2350) AC_MSG_CHECKING([for N2350]) @@ -218,8 +222,17 @@ if test -n "$ARCH"; then CXXFLAGS+=" -march=$ARCH"; CCASFLAGS+=" -march=$ARCH" +elif test x"$PROCESSOR_TYPE" = "xarm"; then # Raspberry Pi 2 support + CXXFLAGS+=" -march=armv7-a" + CCASFLAGS+=" -march=armv7-a" fi +# check TBB -------------------------------------------------------------------- +AC_CHECK_HEADERS([ \ + tbb/concurrent_hash_map.h tbb/concurrent_queue.h \ + ], [], [AC_MSG_ERROR([Not found common header files.])]) +AC_CHECK_LIB([tbb], [main], [], [AC_MSG_ERROR([TBB library was not found.])]) + # end processor type ----------------------------------------------------------- # get JDK path ----------------------------------------------------------------- diff -r bec923d3aeb6 -r 9a13d070bb77 mbean/Makefile.in --- a/mbean/Makefile.in Tue Dec 05 16:18:49 2017 +0900 +++ b/mbean/Makefile.in Fri Jan 19 14:06:27 2018 +0900 @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.15 from Makefile.am. +# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2014 Free Software Foundation, Inc. +# Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, diff -r bec923d3aeb6 -r 9a13d070bb77 mbean/native/Makefile.in --- a/mbean/native/Makefile.in Tue Dec 05 16:18:49 2017 +0900 +++ b/mbean/native/Makefile.in Fri Jan 19 14:06:27 2018 +0900 @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.15 from Makefile.am. +# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2014 Free Software Foundation, Inc. +# Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, diff -r bec923d3aeb6 -r 9a13d070bb77 specs/heapstats.spec --- a/specs/heapstats.spec Tue Dec 05 16:18:49 2017 +0900 +++ b/specs/heapstats.spec Fri Jan 19 14:06:27 2018 +0900 @@ -19,6 +19,7 @@ # Requires for running Requires: pcre >= 6 +Requires: tbb # Requires for building BuildRequires: pcre-devel >= 6 @@ -28,6 +29,7 @@ BuildRequires: binutils-devel BuildRequires: autoconf BuildRequires: automake +BuildRequires: tbb-devel %if 0%{?WITH_ANALYZER:1} BuildRequires: java-1.8.0-openjdk-openjfx-devel @@ -166,6 +168,8 @@ %endif %changelog +* Thu Jan 18 2018 Yasumasa Suenaga +- Add dependencies to TBB * Tue Jul 11 2017 Yasumasa Suenaga - Add Analyzer package. * Tue Feb 09 2016 KUBOTA Yuji