aboutsummaryrefslogblamecommitdiffstats
path: root/util/system/info.cpp
blob: cf6681e89a91e0bb12a27d7daaf9e5a07201a5c9 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
                 
                  








                                         
     











                                                   
                                          
                          

                                           





                              
                                    














                                                                                                                
                                                

















                                       
                                         



























                                                           
                             

                                                         
                              





















                                             
                                                         









                                                          
                 

                                      
                                  
      



















                                          
 
                                            

                            
 
                              
                                 
      
 
 
                                       










                                                                                                                      

                         
                       










                                                                          
                    




                                                                                        












                                            
#include "info.h"

#include "error.h"

#include <cstdlib>

#if defined(_linux_) || defined(_cygwin_)
    #include <fcntl.h>
    #include <sys/sysinfo.h>
#endif

#if defined(_win_)
    #include "winint.h"
    #include <stdio.h>
#else
    #include <unistd.h>
#endif

#if defined(_bionic_)
//TODO
#elif defined(_cygwin_)
static int getloadavg(double* loadavg, int nelem) {
    for (int i = 0; i < nelem; ++i) {
        loadavg[i] = 0.0;
    }

    return nelem;
}
#elif defined(_unix_) || defined(_darwin_)
    #include <sys/types.h>
#endif

#if defined(_freebsd_) || defined(_darwin_)
    #include <sys/sysctl.h>
#endif

#include <util/string/ascii.h>
#include <util/string/cast.h>
#include <util/string/strip.h>
#include <util/stream/file.h>
#include <util/generic/yexception.h>

#if defined(_linux_)
static inline size_t CgroupCpus() {
    try {
        auto q = FromString<ssize_t>(StripString(TFileInput("/sys/fs/cgroup/cpu/cpu.cfs_quota_us").ReadAll()));

        if (q <= 0) {
            return 0;
        }

        auto p = FromString<ssize_t>(StripString(TFileInput("/sys/fs/cgroup/cpu/cpu.cfs_period_us").ReadAll()));

        if (p <= 0) {
            return 0;
        }

        return Max<ssize_t>(1, (q + p / 2) / p);
    } catch (...) {
        return 0;
    }
}
#endif

size_t NSystemInfo::NumberOfCpus() {
#if defined(_linux_)
    if (auto res = CgroupCpus(); res) {
        return res;
    }
#endif

#if defined(_win_)
    SYSTEM_INFO info;

    GetSystemInfo(&info);

    return info.dwNumberOfProcessors;
#elif defined(_SC_NPROCESSORS_ONLN)
    return sysconf(_SC_NPROCESSORS_ONLN);
#elif defined(_linux_)
    unsigned ret;
    int fd, nread, column;
    char buf[512];
    static const char matchstr[] = "processor\t:";

    fd = open("/proc/cpuinfo", O_RDONLY);

    if (fd == -1) {
        abort();
    }

    column = 0;
    ret = 0;

    while (true) {
        nread = read(fd, buf, sizeof(buf));

        if (nread <= 0) {
            break;
        }

        for (int i = 0; i < nread; ++i) {
            const char ch = buf[i];

            if (ch == '\n') {
                column = 0;
            } else if (column != -1) {
                if (AsciiToLower(ch) == matchstr[column]) {
                    ++column;

                    if (column == sizeof(matchstr) - 1) {
                        column = -1;
                        ++ret;
                    }
                } else {
                    column = -1;
                }
            }
        }
    }

    if (ret == 0) {
        abort();
    }

    close(fd);

    return ret;
#elif defined(_freebsd_) || defined(_darwin_)
    int mib[2];
    size_t len;
    unsigned ncpus = 1;

    mib[0] = CTL_HW;
    mib[1] = HW_NCPU;
    len = sizeof(ncpus);
    if (sysctl(mib, 2, &ncpus, &len, nullptr, 0) == -1) {
        abort();
    }

    return ncpus;
#else
    #error todo
#endif
}

size_t NSystemInfo::LoadAverage(double* la, size_t len) {
#if defined(_win_) || defined(_musl_) || defined(_bionic_)
    int ret = -1;
#else
    for (size_t i = 0; i < len; ++i) {
        la[i] = 0;
    }

    int ret = getloadavg(la, len);
#endif

    if (ret < 0) {
        for (size_t i = 0; i < len; ++i) {
            la[i] = 0;
        }

        ret = len;
    }

    return (size_t)ret;
}

static size_t NCpus;

size_t NSystemInfo::CachedNumberOfCpus() {
    if (!NCpus) {
        NCpus = NumberOfCpus();
    }

    return NCpus;
}

size_t NSystemInfo::GetPageSize() noexcept {
#if defined(_win_)
    SYSTEM_INFO sysInfo;
    GetSystemInfo(&sysInfo);

    return sysInfo.dwPageSize;
#else
    return sysconf(_SC_PAGESIZE);
#endif
}

size_t NSystemInfo::TotalMemorySize() {
#if defined(_linux_) && defined(_64_)
    try {
        auto q = FromString<size_t>(StripString(TFileInput("/sys/fs/cgroup/memory/memory.limit_in_bytes").ReadAll()));

        if (q < (((size_t)1) << 60)) {
            return q;
        }
    } catch (...) {
    }
#endif

#if defined(_linux_) || defined(_cygwin_)
    struct sysinfo info;
    sysinfo(&info);
    return info.totalram;
#elif defined(_darwin_)
    int mib[2];
    int64_t memSize;
    size_t length;

    // Get the Physical memory size
    mib[0] = CTL_HW;
    mib[1] = HW_MEMSIZE;
    length = sizeof(int64_t);
    if (sysctl(mib, 2, &memSize, &length, NULL, 0) != 0) {
        ythrow yexception() << "sysctl failed: " << LastSystemErrorText();
    }
    return (size_t)memSize;
#elif defined(_win_)
    MEMORYSTATUSEX memoryStatusEx;
    memoryStatusEx.dwLength = sizeof(memoryStatusEx);
    if (!GlobalMemoryStatusEx(&memoryStatusEx)) {
        ythrow yexception() << "GlobalMemoryStatusEx failed: " << LastSystemErrorText();
    }
    return (size_t)memoryStatusEx.ullTotalPhys;
#else
    return 0;
#endif
}

size_t NSystemInfo::MaxOpenFiles() {
#if defined(ANDROID) || defined(__ANDROID__)
    return sysconf(_SC_OPEN_MAX);
#elif defined(_win_)
    return _getmaxstdio();
#else
    return getdtablesize();
#endif
}