2015-07-12 18:47:43 +00:00
/*
htop - DarwinProcess . c
( C ) 2015 Hisham H . Muhammad
2021-09-22 09:33:00 +00:00
Released under the GNU GPLv2 + , see the COPYING file
2015-07-12 18:47:43 +00:00
in the source distribution for its full text .
*/
2021-04-29 18:13:36 +00:00
# include "darwin/DarwinProcess.h"
2015-07-13 06:17:14 +00:00
# include <libproc.h>
2015-07-14 16:46:16 +00:00
# include <stdio.h>
2020-11-17 18:41:22 +00:00
# include <stdlib.h>
# include <string.h>
2016-02-18 16:57:09 +00:00
# include <mach/mach.h>
2020-10-15 20:37:02 +00:00
# include "CRT.h"
2020-11-17 18:41:22 +00:00
# include "Process.h"
2021-04-29 18:13:36 +00:00
# include "darwin/Platform.h"
2020-10-15 20:37:02 +00:00
2015-07-12 18:47:43 +00:00
2020-12-15 18:44:52 +00:00
const ProcessFieldData Process_fields [ LAST_PROCESSFIELD ] = {
2020-12-13 14:52:58 +00:00
[ 0 ] = { . name = " " , . title = NULL , . description = NULL , . flags = 0 , } ,
2020-12-15 18:44:52 +00:00
[ PID ] = { . name = " PID " , . title = " PID " , . description = " Process/thread ID " , . flags = 0 , . pidColumn = true , } ,
2020-12-13 14:52:58 +00:00
[ COMM ] = { . name = " Command " , . title = " Command " , . description = " Command line " , . flags = 0 , } ,
[ STATE ] = { . name = " STATE " , . title = " S " , . description = " Process state (S sleeping, R running, D disk, Z zombie, T traced, W paging) " , . flags = 0 , } ,
2020-12-15 18:44:52 +00:00
[ PPID ] = { . name = " PPID " , . title = " PPID " , . description = " Parent process ID " , . flags = 0 , . pidColumn = true , } ,
[ PGRP ] = { . name = " PGRP " , . title = " PGRP " , . description = " Process group ID " , . flags = 0 , . pidColumn = true , } ,
[ SESSION ] = { . name = " SESSION " , . title = " SID " , . description = " Process's session ID " , . flags = 0 , . pidColumn = true , } ,
2021-03-21 18:40:56 +00:00
[ TTY ] = { . name = " TTY " , . title = " TTY " , . description = " Controlling terminal " , . flags = 0 , } ,
2020-12-15 18:44:52 +00:00
[ TPGID ] = { . name = " TPGID " , . title = " TPGID " , . description = " Process ID of the fg process group of the controlling terminal " , . flags = 0 , . pidColumn = true , } ,
2021-01-21 13:27:23 +00:00
[ MINFLT ] = { . name = " MINFLT " , . title = " MINFLT " , . description = " Number of minor faults which have not required loading a memory page from disk " , . flags = 0 , . defaultSortDesc = true , } ,
[ MAJFLT ] = { . name = " MAJFLT " , . title = " MAJFLT " , . description = " Number of major faults which have required loading a memory page from disk " , . flags = 0 , . defaultSortDesc = true , } ,
2020-12-13 14:52:58 +00:00
[ PRIORITY ] = { . name = " PRIORITY " , . title = " PRI " , . description = " Kernel's internal priority for the process " , . flags = 0 , } ,
[ NICE ] = { . name = " NICE " , . title = " NI " , . description = " Nice value (the higher the value, the more it lets other processes take priority) " , . flags = 0 , } ,
[ STARTTIME ] = { . name = " STARTTIME " , . title = " START " , . description = " Time the process was started " , . flags = 0 , } ,
2021-05-02 11:29:39 +00:00
[ ELAPSED ] = { . name = " ELAPSED " , . title = " ELAPSED " , . description = " Time since the process was started " , . flags = 0 , } ,
2020-12-13 14:52:58 +00:00
[ PROCESSOR ] = { . name = " PROCESSOR " , . title = " CPU " , . description = " Id of the CPU the process last executed on " , . flags = 0 , } ,
2021-01-21 13:27:23 +00:00
[ M_VIRT ] = { . name = " M_VIRT " , . title = " VIRT " , . description = " Total program size in virtual memory " , . flags = 0 , . defaultSortDesc = true , } ,
[ M_RESIDENT ] = { . name = " M_RESIDENT " , . title = " RES " , . description = " Resident set size, size of the text and data sections, plus stack usage " , . flags = 0 , . defaultSortDesc = true , } ,
2021-08-16 20:50:36 +00:00
[ ST_UID ] = { . name = " ST_UID " , . title = " UID " , . description = " User ID of the process owner " , . flags = 0 , } ,
2021-01-21 13:27:23 +00:00
[ PERCENT_CPU ] = { . name = " PERCENT_CPU " , . title = " CPU% " , . description = " Percentage of the CPU time the process used in the last sampling " , . flags = 0 , . defaultSortDesc = true , } ,
2021-03-02 20:07:20 +00:00
[ PERCENT_NORM_CPU ] = { . name = " PERCENT_NORM_CPU " , . title = " NCPU% " , . description = " Normalized percentage of the CPU time the process used in the last sampling (normalized by cpu count) " , . flags = 0 , . defaultSortDesc = true , } ,
2021-01-21 13:27:23 +00:00
[ PERCENT_MEM ] = { . name = " PERCENT_MEM " , . title = " MEM% " , . description = " Percentage of the memory the process is using, based on resident memory size " , . flags = 0 , . defaultSortDesc = true , } ,
2021-08-16 20:50:36 +00:00
[ USER ] = { . name = " USER " , . title = " USER " , . description = " Username of the process owner (or user ID if name cannot be determined) " , . flags = 0 , } ,
2021-01-21 13:27:23 +00:00
[ TIME ] = { . name = " TIME " , . title = " TIME+ " , . description = " Total time the process has spent in user and system time " , . flags = 0 , . defaultSortDesc = true , } ,
2020-12-13 14:52:58 +00:00
[ NLWP ] = { . name = " NLWP " , . title = " NLWP " , . description = " Number of threads in the process " , . flags = 0 , } ,
2020-12-15 18:44:52 +00:00
[ TGID ] = { . name = " TGID " , . title = " TGID " , . description = " Thread group ID (i.e. process ID) " , . flags = 0 , . pidColumn = true , } ,
2021-05-25 17:03:54 +00:00
[ PROC_EXE ] = { . name = " EXE " , . title = " EXE " , . description = " Basename of exe of the process from /proc/[pid]/exe " , . flags = 0 , } ,
[ CWD ] = { . name = " CWD " , . title = " CWD " , . description = " The current working directory of the process " , . flags = PROCESS_FLAG_CWD , } ,
2020-12-13 14:54:13 +00:00
[ TRANSLATED ] = { . name = " TRANSLATED " , . title = " T " , . description = " Translation info (T translated, N native) " , . flags = 0 , } ,
2020-12-13 14:52:58 +00:00
} ;
2020-10-21 19:26:05 +00:00
Process * DarwinProcess_new ( const Settings * settings ) {
2016-02-02 14:53:02 +00:00
DarwinProcess * this = xCalloc ( 1 , sizeof ( DarwinProcess ) ) ;
2015-07-14 16:46:16 +00:00
Object_setClass ( this , Class ( DarwinProcess ) ) ;
Process_init ( & this - > super , settings ) ;
this - > utime = 0 ;
this - > stime = 0 ;
2016-03-31 03:18:42 +00:00
this - > taskAccess = true ;
2020-12-13 14:54:13 +00:00
this - > translated = false ;
2015-07-14 16:46:16 +00:00
2020-10-21 19:26:05 +00:00
return & this - > super ;
2015-07-12 18:47:43 +00:00
}
2015-07-13 06:17:14 +00:00
void Process_delete ( Object * cast ) {
2015-07-14 16:46:16 +00:00
DarwinProcess * this = ( DarwinProcess * ) cast ;
Process_done ( & this - > super ) ;
2015-07-12 18:47:43 +00:00
// free platform-specific fields here
free ( this ) ;
}
2020-12-13 14:54:13 +00:00
static void DarwinProcess_writeField ( const Process * this , RichString * str , ProcessField field ) {
const DarwinProcess * dp = ( const DarwinProcess * ) this ;
char buffer [ 256 ] ; buffer [ 255 ] = ' \0 ' ;
int attr = CRT_colors [ DEFAULT_COLOR ] ;
int n = sizeof ( buffer ) - 1 ;
2020-12-15 18:44:48 +00:00
switch ( field ) {
2020-12-13 14:54:13 +00:00
// add Platform-specific fields here
case TRANSLATED : xSnprintf ( buffer , n , " %c " , dp - > translated ? ' T ' : ' N ' ) ; break ;
default :
Process_writeField ( this , str , field ) ;
return ;
}
RichString_appendWide ( str , attr , buffer ) ;
}
2020-12-23 12:02:32 +00:00
static int DarwinProcess_compareByKey ( const Process * v1 , const Process * v2 , ProcessField key ) {
2020-12-17 23:09:55 +00:00
const DarwinProcess * p1 = ( const DarwinProcess * ) v1 ;
const DarwinProcess * p2 = ( const DarwinProcess * ) v2 ;
2020-12-13 14:54:13 +00:00
2020-12-15 18:44:48 +00:00
switch ( key ) {
2020-12-13 14:54:13 +00:00
// add Platform-specific fields here
case TRANSLATED :
return SPACESHIP_NUMBER ( p1 - > translated , p2 - > translated ) ;
default :
2020-12-18 21:12:26 +00:00
return Process_compareByKey_Base ( v1 , v2 , key ) ;
2020-12-13 14:54:13 +00:00
}
}
2021-05-18 21:29:57 +00:00
static void DarwinProcess_updateExe ( pid_t pid , Process * proc ) {
char path [ PROC_PIDPATHINFO_MAXSIZE ] ;
int r = proc_pidpath ( pid , path , sizeof ( path ) ) ;
if ( r < = 0 )
return ;
Process_updateExe ( proc , path ) ;
}
2021-05-25 17:03:54 +00:00
static void DarwinProcess_updateCwd ( pid_t pid , Process * proc ) {
struct proc_vnodepathinfo vpi ;
int r = proc_pidinfo ( pid , PROC_PIDVNODEPATHINFO , 0 , & vpi , sizeof ( vpi ) ) ;
if ( r < = 0 ) {
free ( proc - > procCwd ) ;
proc - > procCwd = NULL ;
return ;
}
if ( ! vpi . pvi_cdir . vip_path [ 0 ] ) {
free ( proc - > procCwd ) ;
proc - > procCwd = NULL ;
return ;
}
free_and_xStrdup ( & proc - > procCwd , vpi . pvi_cdir . vip_path ) ;
}
2021-05-18 21:29:57 +00:00
static void DarwinProcess_updateCmdLine ( const struct kinfo_proc * k , Process * proc ) {
Process_updateComm ( proc , k - > kp_proc . p_comm ) ;
2015-07-13 06:17:14 +00:00
/* This function is from the old Mac version of htop. Originally from ps? */
int mib [ 3 ] , argmax , nargs , c = 0 ;
size_t size ;
2021-05-18 21:29:57 +00:00
char * procargs , * sp , * np , * cp ;
2015-07-13 06:17:14 +00:00
/* Get the maximum process arguments size. */
mib [ 0 ] = CTL_KERN ;
mib [ 1 ] = KERN_ARGMAX ;
size = sizeof ( argmax ) ;
if ( sysctl ( mib , 2 , & argmax , & size , NULL , 0 ) = = - 1 ) {
goto ERROR_A ;
}
/* Allocate space for the arguments. */
2021-10-02 22:52:39 +00:00
procargs = ( char * ) malloc ( argmax ) ;
2015-07-13 06:17:14 +00:00
if ( procargs = = NULL ) {
goto ERROR_A ;
}
/*
* Make a sysctl ( ) call to get the raw argument space of the process .
* The layout is documented in start . s , which is part of the Csu
* project . In summary , it looks like :
*
* / - - - - - - - - - - - - - - - \ 0x00000000
* : :
* : :
* | - - - - - - - - - - - - - - - |
* | argc |
* | - - - - - - - - - - - - - - - |
* | arg [ 0 ] |
* | - - - - - - - - - - - - - - - |
* : :
* : :
* | - - - - - - - - - - - - - - - |
* | arg [ argc - 1 ] |
* | - - - - - - - - - - - - - - - |
* | 0 |
* | - - - - - - - - - - - - - - - |
* | env [ 0 ] |
* | - - - - - - - - - - - - - - - |
* : :
* : :
* | - - - - - - - - - - - - - - - |
* | env [ n ] |
* | - - - - - - - - - - - - - - - |
* | 0 |
* | - - - - - - - - - - - - - - - | < - - Beginning of data returned by sysctl ( ) is here .
* | argc |
* | - - - - - - - - - - - - - - - |
* | exec_path |
* | : : : : : : : : : : : : : : : |
* | |
* | String area . |
* | |
* | - - - - - - - - - - - - - - - | < - - Top of stack .
* : :
* : :
* \ - - - - - - - - - - - - - - - / 0xffffffff
*/
mib [ 0 ] = CTL_KERN ;
mib [ 1 ] = KERN_PROCARGS2 ;
mib [ 2 ] = k - > kp_proc . p_pid ;
size = ( size_t ) argmax ;
if ( sysctl ( mib , 3 , procargs , & size , NULL , 0 ) = = - 1 ) {
goto ERROR_B ;
}
memcpy ( & nargs , procargs , sizeof ( nargs ) ) ;
cp = procargs + sizeof ( nargs ) ;
/* Skip the saved exec_path. */
for ( ; cp < & procargs [ size ] ; cp + + ) {
if ( * cp = = ' \0 ' ) {
/* End of exec_path reached. */
break ;
}
}
if ( cp = = & procargs [ size ] ) {
goto ERROR_B ;
}
/* Skip trailing '\0' characters. */
for ( ; cp < & procargs [ size ] ; cp + + ) {
if ( * cp ! = ' \0 ' ) {
/* Beginning of first argument reached. */
break ;
}
}
if ( cp = = & procargs [ size ] ) {
goto ERROR_B ;
}
/* Save where the argv[0] string starts. */
sp = cp ;
2021-05-18 21:29:57 +00:00
int end = 0 ;
2015-07-13 06:17:14 +00:00
for ( np = NULL ; c < nargs & & cp < & procargs [ size ] ; cp + + ) {
if ( * cp = = ' \0 ' ) {
c + + ;
if ( np ! = NULL ) {
/* Convert previous '\0'. */
* np = ' ' ;
}
2020-10-31 21:14:27 +00:00
/* Note location of current '\0'. */
np = cp ;
2021-05-18 21:29:57 +00:00
if ( end = = 0 ) {
end = cp - sp ;
2020-10-31 21:14:27 +00:00
}
}
2015-10-23 15:46:21 +00:00
}
2015-07-13 06:17:14 +00:00
/*
* sp points to the beginning of the arguments / environment string , and
* np should point to the ' \0 ' terminator for the string .
*/
if ( np = = NULL | | np = = sp ) {
/* Empty or unterminated string. */
goto ERROR_B ;
}
2021-05-18 21:29:57 +00:00
if ( end = = 0 ) {
end = np - sp ;
2016-02-19 01:45:17 +00:00
}
2015-07-13 06:17:14 +00:00
2021-05-18 21:29:57 +00:00
Process_updateCmdline ( proc , sp , 0 , end ) ;
2015-07-13 06:17:14 +00:00
/* Clean up. */
free ( procargs ) ;
2021-05-18 21:29:57 +00:00
return ;
2015-07-13 06:17:14 +00:00
ERROR_B :
free ( procargs ) ;
2021-02-01 21:24:42 +00:00
2015-07-13 06:17:14 +00:00
ERROR_A :
2021-05-18 21:29:57 +00:00
Process_updateCmdline ( proc , k - > kp_proc . p_comm , 0 , strlen ( k - > kp_proc . p_comm ) ) ;
2015-07-13 06:17:14 +00:00
}
2021-09-18 13:55:21 +00:00
// Converts nanoseconds to hundredths of a second (centiseconds) as needed by the "time" field of the Process struct.
2021-08-20 21:52:07 +00:00
static long long int nanosecondsToCentiseconds ( uint64_t nanoseconds ) {
2021-08-23 14:37:37 +00:00
const uint64_t centiseconds_per_second = 100 ;
const uint64_t nanoseconds_per_second = 1e9 ;
2021-08-20 21:52:07 +00:00
return nanoseconds / nanoseconds_per_second * centiseconds_per_second ;
}
2020-11-17 18:41:22 +00:00
void DarwinProcess_setFromKInfoProc ( Process * proc , const struct kinfo_proc * ps , bool exists ) {
2020-12-13 14:54:13 +00:00
DarwinProcess * dp = ( DarwinProcess * ) proc ;
2020-11-17 18:41:22 +00:00
const struct extern_proc * ep = & ps - > kp_proc ;
2015-08-19 16:56:46 +00:00
/* UNSET HERE :
*
* processor
* user ( set at ProcessList level )
* nlwp
* percent_cpu
* percent_mem
2020-11-20 16:09:34 +00:00
* m_virt
2015-08-19 16:56:46 +00:00
* m_resident
* minflt
* majflt
*/
/* First, the "immutable" parts */
2020-10-31 19:52:20 +00:00
if ( ! exists ) {
2015-08-19 16:56:46 +00:00
/* Set the PID/PGID/etc. */
proc - > pid = ep - > p_pid ;
proc - > ppid = ps - > kp_eproc . e_ppid ;
proc - > pgrp = ps - > kp_eproc . e_pgid ;
proc - > session = 0 ; /* TODO Get the session id */
2016-02-18 16:14:45 +00:00
proc - > tpgid = ps - > kp_eproc . e_tpgid ;
proc - > tgid = proc - > pid ;
2021-04-10 12:08:26 +00:00
proc - > isKernelThread = false ;
proc - > isUserlandThread = false ;
2020-12-13 14:54:13 +00:00
dp - > translated = ps - > kp_proc . p_flag & P_TRANSLATED ;
2015-08-19 16:56:46 +00:00
2021-03-21 18:40:56 +00:00
proc - > tty_nr = ps - > kp_eproc . e_tdev ;
const char * name = ( ps - > kp_eproc . e_tdev ! = NODEV ) ? devname ( ps - > kp_eproc . e_tdev , S_IFCHR ) : NULL ;
if ( ! name ) {
free ( proc - > tty_name ) ;
proc - > tty_name = NULL ;
} else {
free_and_xStrdup ( & proc - > tty_name , name ) ;
}
2020-10-13 12:26:40 +00:00
proc - > starttime_ctime = ep - > p_starttime . tv_sec ;
Process_fillStarttimeBuffer ( proc ) ;
2021-05-18 21:29:57 +00:00
DarwinProcess_updateExe ( ep - > p_pid , proc ) ;
DarwinProcess_updateCmdLine ( ps , proc ) ;
2021-05-25 17:03:54 +00:00
2021-08-31 05:38:52 +00:00
if ( proc - > settings - > ss - > flags & PROCESS_FLAG_CWD ) {
2021-05-25 17:03:54 +00:00
DarwinProcess_updateCwd ( ep - > p_pid , proc ) ;
}
2015-08-19 16:56:46 +00:00
}
/* Mutable information */
proc - > nice = ep - > p_nice ;
proc - > priority = ep - > p_priority ;
2021-10-11 22:45:09 +00:00
proc - > state = ( ep - > p_stat = = SZOMB ) ? ZOMBIE : UNKNOWN ;
2015-08-19 16:56:46 +00:00
/* Make sure the updated flag is set */
proc - > updated = true ;
2015-07-13 06:17:14 +00:00
}
2021-08-23 14:37:37 +00:00
void DarwinProcess_setFromLibprocPidinfo ( DarwinProcess * proc , DarwinProcessList * dpl , double timeIntervalNS ) {
2015-08-19 16:56:46 +00:00
struct proc_taskinfo pti ;
2015-07-13 06:17:14 +00:00
2020-10-31 19:52:20 +00:00
if ( sizeof ( pti ) = = proc_pidinfo ( proc - > super . pid , PROC_PIDTASKINFO , 0 , & pti , sizeof ( pti ) ) ) {
2021-08-20 21:52:07 +00:00
uint64_t total_existing_time_ns = proc - > stime + proc - > utime ;
2021-08-22 14:47:11 +00:00
uint64_t user_time_ns = Platform_machTicksToNanoseconds ( pti . pti_total_user ) ;
uint64_t system_time_ns = Platform_machTicksToNanoseconds ( pti . pti_total_system ) ;
2021-08-20 21:52:07 +00:00
uint64_t total_current_time_ns = user_time_ns + system_time_ns ;
2020-12-09 04:12:44 +00:00
2021-08-23 14:37:37 +00:00
if ( total_existing_time_ns & & 1E-6 < timeIntervalNS ) {
2021-08-20 21:52:07 +00:00
uint64_t total_time_diff_ns = total_current_time_ns - total_existing_time_ns ;
2021-08-23 14:37:37 +00:00
proc - > super . percent_cpu = ( ( double ) total_time_diff_ns / timeIntervalNS ) * 100.0 ;
2020-12-09 04:12:44 +00:00
} else {
proc - > super . percent_cpu = 0.0 ;
2015-08-19 16:56:46 +00:00
}
2015-07-14 16:46:16 +00:00
2021-08-20 21:52:07 +00:00
proc - > super . time = nanosecondsToCentiseconds ( total_current_time_ns ) ;
2015-08-19 16:56:46 +00:00
proc - > super . nlwp = pti . pti_threadnum ;
2020-12-10 00:57:48 +00:00
proc - > super . m_virt = pti . pti_virtual_size / ONE_K ;
proc - > super . m_resident = pti . pti_resident_size / ONE_K ;
2015-08-19 16:56:46 +00:00
proc - > super . majflt = pti . pti_faults ;
proc - > super . percent_mem = ( double ) pti . pti_resident_size * 100.0
2020-10-31 21:14:27 +00:00
/ ( double ) dpl - > host_info . max_mem ;
2015-08-19 16:56:46 +00:00
2021-08-20 21:52:07 +00:00
proc - > stime = system_time_ns ;
proc - > utime = user_time_ns ;
2015-08-19 16:56:46 +00:00
dpl - > super . kernelThreads + = 0 ; /*pti.pti_threads_system;*/
dpl - > super . userlandThreads + = pti . pti_threadnum ; /*pti.pti_threads_user;*/
dpl - > super . totalTasks + = pti . pti_threadnum ;
dpl - > super . runningTasks + = pti . pti_numrunning ;
}
2015-07-13 06:17:14 +00:00
}
2016-02-18 16:57:09 +00:00
/*
* Scan threads for process state information .
* Based on : http : //stackoverflow.com/questions/6788274/ios-mac-cpu-usage-for-thread
* and https : //github.com/max-horvath/htop-osx/blob/e86692e869e30b0bc7264b3675d2a4014866ef46/ProcessList.c
*/
2020-10-31 22:28:02 +00:00
void DarwinProcess_scanThreads ( DarwinProcess * dp ) {
2016-02-18 16:57:09 +00:00
Process * proc = ( Process * ) dp ;
kern_return_t ret ;
2019-10-31 16:39:12 +00:00
2016-03-31 03:18:42 +00:00
if ( ! dp - > taskAccess ) {
return ;
}
2019-10-31 16:39:12 +00:00
2021-10-11 22:45:09 +00:00
if ( proc - > state = = ZOMBIE ) {
2016-02-18 16:57:09 +00:00
return ;
}
task_t port ;
ret = task_for_pid ( mach_task_self ( ) , proc - > pid , & port ) ;
if ( ret ! = KERN_SUCCESS ) {
2016-03-31 03:18:42 +00:00
dp - > taskAccess = false ;
2016-02-18 16:57:09 +00:00
return ;
}
2019-10-31 16:39:12 +00:00
2016-02-18 16:57:09 +00:00
task_info_data_t tinfo ;
mach_msg_type_number_t task_info_count = TASK_INFO_MAX ;
ret = task_info ( port , TASK_BASIC_INFO , ( task_info_t ) tinfo , & task_info_count ) ;
if ( ret ! = KERN_SUCCESS ) {
2016-03-31 03:18:42 +00:00
dp - > taskAccess = false ;
2016-02-18 16:57:09 +00:00
return ;
}
2019-10-31 16:39:12 +00:00
2016-02-18 16:57:09 +00:00
thread_array_t thread_list ;
mach_msg_type_number_t thread_count ;
ret = task_threads ( port , & thread_list , & thread_count ) ;
if ( ret ! = KERN_SUCCESS ) {
2016-03-31 03:18:42 +00:00
dp - > taskAccess = false ;
2016-02-18 16:57:09 +00:00
mach_port_deallocate ( mach_task_self ( ) , port ) ;
return ;
}
2019-10-31 16:39:12 +00:00
2016-02-18 16:57:09 +00:00
integer_t run_state = 999 ;
for ( unsigned int i = 0 ; i < thread_count ; i + + ) {
thread_info_data_t thinfo ;
mach_msg_type_number_t thread_info_count = THREAD_BASIC_INFO_COUNT ;
ret = thread_info ( thread_list [ i ] , THREAD_BASIC_INFO , ( thread_info_t ) thinfo , & thread_info_count ) ;
if ( ret = = KERN_SUCCESS ) {
thread_basic_info_t basic_info_th = ( thread_basic_info_t ) thinfo ;
if ( basic_info_th - > run_state < run_state ) {
run_state = basic_info_th - > run_state ;
}
mach_port_deallocate ( mach_task_self ( ) , thread_list [ i ] ) ;
}
}
vm_deallocate ( mach_task_self ( ) , ( vm_address_t ) thread_list , sizeof ( thread_port_array_t ) * thread_count ) ;
mach_port_deallocate ( mach_task_self ( ) , port ) ;
2021-10-11 22:45:09 +00:00
/* Taken from: https://github.com/apple/darwin-xnu/blob/2ff845c2e033bd0ff64b5b6aa6063a1f8f65aa32/osfmk/mach/thread_info.h#L129 */
2016-02-18 16:57:09 +00:00
switch ( run_state ) {
2021-10-11 22:45:09 +00:00
case TH_STATE_RUNNING : proc - > state = RUNNING ; break ;
case TH_STATE_STOPPED : proc - > state = STOPPED ; break ;
case TH_STATE_WAITING : proc - > state = WAITING ; break ;
case TH_STATE_UNINTERRUPTIBLE : proc - > state = UNINTERRUPTIBLE_WAIT ; break ;
case TH_STATE_HALTED : proc - > state = BLOCKED ; break ;
default : proc - > state = UNKNOWN ;
2016-02-18 16:57:09 +00:00
}
}
2020-12-13 14:54:13 +00:00
const ProcessClass DarwinProcess_class = {
. super = {
. extends = Class ( Process ) ,
. display = Process_display ,
. delete = Process_delete ,
2020-12-17 23:09:55 +00:00
. compare = Process_compare
2020-12-13 14:54:13 +00:00
} ,
. writeField = DarwinProcess_writeField ,
2020-12-17 23:09:55 +00:00
. compareByKey = DarwinProcess_compareByKey ,
2020-12-13 14:54:13 +00:00
} ;