123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256 |
- #include "il2cpp-config.h"
- #if IL2CPP_TARGET_LUMIN
- #include <sys/sysinfo.h>
- #include <sys/time.h>
- #include <sys/types.h>
- #include <unistd.h>
- #include <stdio.h>
- #include "os/Process.h"
- #include "utils/Logging.h"
- struct ProcessHandle
- {
- pid_t pid;
- };
- namespace il2cpp
- {
- namespace os
- {
- const int _sc_clk_tck = sysconf(_SC_CLK_TCK);
- typedef struct
- {
- char name[256];
- unsigned long utime;
- unsigned long stime;
- unsigned long long starttime;
- } ProcessStatInfo;
- typedef struct
- {
- unsigned vmpeak;
- unsigned vmsize;
- unsigned vmhwm;
- unsigned vmrss;
- unsigned vmdata;
- unsigned vmstk;
- unsigned vmswap;
- } ProcessStatusInfo;
- static bool GetProcessStatInfo(int pid, ProcessStatInfo *result)
- {
- char buffer[4096], *open_paren, *close_paren;
- FILE *fp;
- sprintf(buffer, "/proc/%d/stat", pid);
- fp = fopen(buffer, "r");
- if (fp == NULL)
- {
- return false;
- }
- fgets(buffer, sizeof(buffer) - 1, fp);
- fclose(fp);
- buffer[sizeof(buffer) - 1] = 0;
- open_paren = strchr(buffer, '(');
- if (open_paren == NULL)
- {
- return false;
- }
- close_paren = strrchr(open_paren + 1, ')');
- if (close_paren == NULL)
- {
- return false;
- }
- *close_paren = 0;
- strncpy(result->name, open_paren + 1, sizeof(result->name) - 1);
- result->name[sizeof(result->name) - 1] = 0;
- sscanf(close_paren + 1, " %*c %*d %*d %*d %*d %*d %*u %*lu %*lu %*lu %*lu %lu %lu %*ld %*ld %*ld %*ld %*ld %*ld %llu",
- &result->utime,
- &result->stime,
- &result->starttime);
- return true;
- }
- #define GPSI_STARTSWITH(s) (strncasecmp(buffer, s, sizeof(s) - 1) == 0)
- static bool GetProcessStatusInfo(int pid, ProcessStatusInfo *result)
- {
- char buffer[1024], *p;
- FILE *fp;
- sprintf(buffer, "/proc/%d/status", pid);
- fp = fopen(buffer, "r");
- if (fp == NULL)
- {
- return false;
- }
- memset(result, 0, sizeof(*result));
- while (fgets(buffer, sizeof(buffer) - 1, fp))
- {
- buffer[sizeof(buffer) - 1] = 0;
- if (GPSI_STARTSWITH("VmPeak:"))
- {
- sscanf(buffer + sizeof("VmPeak:") - 1, "%u", &result->vmpeak);
- }
- else if (GPSI_STARTSWITH("VmSize:"))
- {
- sscanf(buffer + sizeof("VmSize:") - 1, "%u", &result->vmsize);
- }
- else if (GPSI_STARTSWITH("VmHWM:"))
- {
- sscanf(buffer + sizeof("VmHWM:") - 1, "%u", &result->vmhwm);
- }
- else if (GPSI_STARTSWITH("VmRSS:"))
- {
- sscanf(buffer + sizeof("VmRSS:") - 1, "%u", &result->vmrss);
- }
- else if (GPSI_STARTSWITH("VmData:"))
- {
- sscanf(buffer + sizeof("VmData:") - 1, "%u", &result->vmdata);
- }
- else if (GPSI_STARTSWITH("VmStk:"))
- {
- sscanf(buffer + sizeof("VmStk:") - 1, "%u", &result->vmstk);
- }
- else if (GPSI_STARTSWITH("VmSwap:"))
- {
- sscanf(buffer + sizeof("VmSwap:") - 1, "%u", &result->vmswap);
- }
- }
- fclose(fp);
- return true;
- }
- #undef GPSI_STARTSWITH
- int Process::GetCurrentProcessId()
- {
- return getpid();
- }
- utils::Expected<ProcessHandle*> Process::GetProcess(int processId)
- {
- // If/when we implement the CreateProcess_internal icall we will likely
- // need to so something smarter here to find the process if we did
- // not create it and return a known pseudo-handle. For now this
- // is sufficient though.
- return (ProcessHandle*)(intptr_t)processId;
- }
- void Process::FreeProcess(ProcessHandle* handle)
- {
- // We have nothing to do here.
- }
- utils::Expected<std::string> Process::GetProcessName(ProcessHandle* handle)
- {
- intptr_t pid = (intptr_t)handle;
- ProcessStatInfo psi;
- if (GetProcessStatInfo(pid, &psi))
- {
- return std::string(psi.name);
- }
- else
- {
- return std::string();
- }
- }
- int64_t Process::Times(ProcessHandle* handle, int32_t type)
- {
- int pid = (intptr_t)handle;
- ProcessStatInfo psi;
- int64_t result = 0;
- if (GetProcessStatInfo(pid, &psi))
- {
- result = (int64_t)psi.utime * (10000000 / _sc_clk_tck);
- if (type == 2) // Total process time
- {
- result += (int64_t)psi.stime * (10000000 / _sc_clk_tck);
- }
- }
- return result;
- }
- int64_t Process::StartTime(ProcessHandle* handle)
- {
- int pid = (intptr_t)handle;
- ProcessStatInfo psi;
- if (GetProcessStatInfo(pid, &psi))
- {
- struct sysinfo si;
- if (sysinfo(&si) == 0)
- {
- const int64_t unix_time_to_filetime = 11644473600ll;
- int64_t boot_time = (int64_t)time(NULL) - si.uptime + unix_time_to_filetime;
- return (boot_time + psi.starttime / _sc_clk_tck) * 10000000ll;
- }
- }
- return 0;
- }
- int64_t Process::GetProcessData(int32_t pid, int32_t data_type, int32_t* error)
- {
- ProcessStatusInfo psi;
- if (GetProcessStatusInfo(pid, &psi))
- {
- switch (data_type)
- {
- case 4: // WorkingSet64
- return (int64_t)psi.vmrss * 1024;
- case 5: // PeakWorkingSet64
- return (int64_t)psi.vmhwm * 1024;
- case 6: // PrivateMemorySize64
- return (int64_t)(psi.vmdata + psi.vmstk) * 1024;
- case 7: // VirtualMemorySize64
- return (int64_t)psi.vmsize * 1024;
- case 8: // PeakVirtualMemorySize64
- return (int64_t)psi.vmpeak * 1024;
- default:
- {
- char buf[256];
- sprintf(buf, "Process::GetProcessData: Unknown data_type %d", data_type);
- utils::Logging::Write(buf);
- break;
- }
- }
- }
- return 0;
- }
- intptr_t Process::GetMainWindowHandle(int32_t pid)
- {
- return 0;
- }
- }
- }
- #endif
|