src/hotspot/os/linux/osContainer_linux.cpp
changeset 58874 c440a6b4e096
parent 58655 21a92562f0c2
equal deleted inserted replaced
58873:5f1fe5971ff9 58874:c440a6b4e096
    52  */
    52  */
    53 #define PER_CPU_SHARES 1024
    53 #define PER_CPU_SHARES 1024
    54 
    54 
    55 bool  OSContainer::_is_initialized   = false;
    55 bool  OSContainer::_is_initialized   = false;
    56 bool  OSContainer::_is_containerized = false;
    56 bool  OSContainer::_is_containerized = false;
       
    57 int   OSContainer::_active_processor_count = 1;
    57 julong _unlimited_memory;
    58 julong _unlimited_memory;
    58 
    59 
    59 class CgroupSubsystem: CHeapObj<mtInternal> {
    60 class CgroupSubsystem: CHeapObj<mtInternal> {
    60  friend class OSContainer;
    61  friend class OSContainer;
    61 
    62 
       
    63 
    62  private:
    64  private:
       
    65     volatile jlong _next_check_counter;
       
    66 
    63     /* mountinfo contents */
    67     /* mountinfo contents */
    64     char *_root;
    68     char *_root;
    65     char *_mount_point;
    69     char *_mount_point;
    66 
    70 
    67     /* Constructed subsystem directory */
    71     /* Constructed subsystem directory */
    70  public:
    74  public:
    71     CgroupSubsystem(char *root, char *mountpoint) {
    75     CgroupSubsystem(char *root, char *mountpoint) {
    72       _root = os::strdup(root);
    76       _root = os::strdup(root);
    73       _mount_point = os::strdup(mountpoint);
    77       _mount_point = os::strdup(mountpoint);
    74       _path = NULL;
    78       _path = NULL;
       
    79       _next_check_counter = min_jlong;
    75     }
    80     }
    76 
    81 
    77     /*
    82     /*
    78      * Set directory to subsystem specific files based
    83      * Set directory to subsystem specific files based
    79      * on the contents of the mountinfo and cgroup files.
    84      * on the contents of the mountinfo and cgroup files.
   119         }
   124         }
   120       }
   125       }
   121     }
   126     }
   122 
   127 
   123     char *subsystem_path() { return _path; }
   128     char *subsystem_path() { return _path; }
       
   129 
       
   130     bool cache_has_expired() {
       
   131       return os::elapsed_counter() > _next_check_counter;
       
   132     }
       
   133 
       
   134     void set_cache_expiry_time(jlong timeout) {
       
   135       _next_check_counter = os::elapsed_counter() + timeout;
       
   136     }
   124 };
   137 };
   125 
   138 
   126 class CgroupMemorySubsystem: CgroupSubsystem {
   139 class CgroupMemorySubsystem: CgroupSubsystem {
   127  friend class OSContainer;
   140  friend class OSContainer;
   128 
   141 
   130     /* Some container runtimes set limits via cgroup
   143     /* Some container runtimes set limits via cgroup
   131      * hierarchy. If set to true consider also memory.stat
   144      * hierarchy. If set to true consider also memory.stat
   132      * file if everything else seems unlimited */
   145      * file if everything else seems unlimited */
   133     bool _uses_mem_hierarchy;
   146     bool _uses_mem_hierarchy;
   134     volatile jlong _memory_limit_in_bytes;
   147     volatile jlong _memory_limit_in_bytes;
   135     volatile jlong _next_check_counter;
       
   136 
   148 
   137  public:
   149  public:
   138     CgroupMemorySubsystem(char *root, char *mountpoint) : CgroupSubsystem::CgroupSubsystem(root, mountpoint) {
   150     CgroupMemorySubsystem(char *root, char *mountpoint) : CgroupSubsystem::CgroupSubsystem(root, mountpoint) {
   139       _uses_mem_hierarchy = false;
   151       _uses_mem_hierarchy = false;
   140       _memory_limit_in_bytes = -1;
   152       _memory_limit_in_bytes = -1;
   141       _next_check_counter = min_jlong;
       
   142 
   153 
   143     }
   154     }
   144 
   155 
   145     bool is_hierarchical() { return _uses_mem_hierarchy; }
   156     bool is_hierarchical() { return _uses_mem_hierarchy; }
   146     void set_hierarchical(bool value) { _uses_mem_hierarchy = value; }
   157     void set_hierarchical(bool value) { _uses_mem_hierarchy = value; }
   147 
   158 
   148     bool should_check_memory_limit() {
       
   149       return os::elapsed_counter() > _next_check_counter;
       
   150     }
       
   151     jlong memory_limit_in_bytes() { return _memory_limit_in_bytes; }
   159     jlong memory_limit_in_bytes() { return _memory_limit_in_bytes; }
   152     void set_memory_limit_in_bytes(jlong value) {
   160     void set_memory_limit_in_bytes(jlong value) {
   153       _memory_limit_in_bytes = value;
   161       _memory_limit_in_bytes = value;
   154       // max memory limit is unlikely to change, but we want to remain
   162       // max memory limit is unlikely to change, but we want to remain
   155       // responsive to configuration changes. A very short (20ms) grace time
   163       // responsive to configuration changes. A very short grace time
   156       // between re-read avoids excessive overhead during startup without
   164       // between re-read avoids excessive overhead during startup without
   157       // significantly reducing the VMs ability to promptly react to reduced
   165       // significantly reducing the VMs ability to promptly react to reduced
   158       // memory availability
   166       // memory availability
   159       _next_check_counter = os::elapsed_counter() + (NANOSECS_PER_SEC/50);
   167       set_cache_expiry_time(OSCONTAINER_CACHE_TIMEOUT);
   160     }
   168     }
   161 
   169 
   162 };
   170 };
   163 
   171 
   164 CgroupMemorySubsystem* memory = NULL;
   172 CgroupMemorySubsystem* memory = NULL;
   479  *    memory limit in bytes or
   487  *    memory limit in bytes or
   480  *    -1 for unlimited
   488  *    -1 for unlimited
   481  *    OSCONTAINER_ERROR for not supported
   489  *    OSCONTAINER_ERROR for not supported
   482  */
   490  */
   483 jlong OSContainer::memory_limit_in_bytes() {
   491 jlong OSContainer::memory_limit_in_bytes() {
   484   if (!memory->should_check_memory_limit()) {
   492   if (!memory->cache_has_expired()) {
   485     return memory->memory_limit_in_bytes();
   493     return memory->memory_limit_in_bytes();
   486   }
   494   }
   487   jlong memory_limit = read_memory_limit_in_bytes();
   495   jlong memory_limit = read_memory_limit_in_bytes();
   488   // Update CgroupMemorySubsystem to avoid re-reading container settings too often
   496   // Update CgroupMemorySubsystem to avoid re-reading container settings too often
   489   memory->set_memory_limit_in_bytes(memory_limit);
   497   memory->set_memory_limit_in_bytes(memory_limit);
   615 int OSContainer::active_processor_count() {
   623 int OSContainer::active_processor_count() {
   616   int quota_count = 0, share_count = 0;
   624   int quota_count = 0, share_count = 0;
   617   int cpu_count, limit_count;
   625   int cpu_count, limit_count;
   618   int result;
   626   int result;
   619 
   627 
       
   628   // We use a cache with a timeout to avoid performing expensive
       
   629   // computations in the event this function is called frequently.
       
   630   // [See 8227006].
       
   631   if (!cpu->cache_has_expired()) {
       
   632     log_trace(os, container)("OSContainer::active_processor_count (cached): %d", OSContainer::_active_processor_count);
       
   633     return OSContainer::_active_processor_count;
       
   634   }
       
   635 
   620   cpu_count = limit_count = os::Linux::active_processor_count();
   636   cpu_count = limit_count = os::Linux::active_processor_count();
   621   int quota  = cpu_quota();
   637   int quota  = cpu_quota();
   622   int period = cpu_period();
   638   int period = cpu_period();
   623   int share  = cpu_shares();
   639   int share  = cpu_shares();
   624 
   640 
   647     limit_count = share_count;
   663     limit_count = share_count;
   648   }
   664   }
   649 
   665 
   650   result = MIN2(cpu_count, limit_count);
   666   result = MIN2(cpu_count, limit_count);
   651   log_trace(os, container)("OSContainer::active_processor_count: %d", result);
   667   log_trace(os, container)("OSContainer::active_processor_count: %d", result);
       
   668 
       
   669   // Update the value and reset the cache timeout
       
   670   OSContainer::_active_processor_count = result;
       
   671   cpu->set_cache_expiry_time(OSCONTAINER_CACHE_TIMEOUT);
       
   672 
   652   return result;
   673   return result;
   653 }
   674 }
   654 
   675 
   655 char * OSContainer::cpu_cpuset_cpus() {
   676 char * OSContainer::cpu_cpuset_cpus() {
   656   GET_CONTAINER_INFO_CPTR(cptr, cpuset, "/cpuset.cpus",
   677   GET_CONTAINER_INFO_CPTR(cptr, cpuset, "/cpuset.cpus",