Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
adam.huang
htop
Commits
43ef703f
Commit
43ef703f
authored
Jul 13, 2015
by
David Hunt
Committed by
Hisham Muhammad
Aug 19, 2015
Browse files
Start supporting actual data
parent
70e7c8db
Changes
7
Hide whitespace changes
Inline
Side-by-side
darwin/DarwinCRT.c
View file @
43ef703f
...
...
@@ -9,6 +9,7 @@ in the source distribution for its full text.
#include "CRT.h"
#include <stdio.h>
#include <stdlib.h>
#include <execinfo.h>
void
CRT_handleSIGSEGV
(
int
sgn
)
{
(
void
)
sgn
;
...
...
darwin/DarwinProcess.c
View file @
43ef703f
...
...
@@ -7,12 +7,14 @@ in the source distribution for its full text.
#include "Process.h"
#include "DarwinProcess.h"
#include <stdlib.h>
#include <libproc.h>
#include <string.h>
/*{
#include "Settings.h"
#define Process_delete UnsupportedProcess_delete
#include <sys/sysctl.h>
}*/
...
...
@@ -23,7 +25,7 @@ Process* DarwinProcess_new(Settings* settings) {
return
this
;
}
void
Darwin
Process_delete
(
Object
*
cast
)
{
void
Process_delete
(
Object
*
cast
)
{
Process
*
this
=
(
Process
*
)
cast
;
Object_setClass
(
this
,
Class
(
Process
));
Process_done
((
Process
*
)
cast
);
...
...
@@ -31,3 +33,281 @@ void DarwinProcess_delete(Object* cast) {
free
(
this
);
}
bool
Process_isThread
(
Process
*
this
)
{
return
false
;
}
void
DarwinProcess_setStartTime
(
Process
*
proc
,
struct
extern_proc
*
ep
,
time_t
now
)
{
struct
tm
date
;
proc
->
starttime_ctime
=
ep
->
p_starttime
.
tv_sec
;
(
void
)
localtime_r
(
&
proc
->
starttime_ctime
,
&
date
);
strftime
(
proc
->
starttime_show
,
7
,
((
proc
->
starttime_ctime
>
now
-
86400
)
?
"%R "
:
"%b%d "
),
&
date
);
}
char
*
DarwinProcessList_getCmdLine
(
struct
kinfo_proc
*
k
,
int
show_args
)
{
/* This function is from the old Mac version of htop. Originally from ps? */
int
mib
[
3
],
argmax
,
nargs
,
c
=
0
;
size_t
size
;
char
*
procargs
,
*
sp
,
*
np
,
*
cp
,
*
retval
;
/* 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. */
procargs
=
(
char
*
)
malloc
(
argmax
);
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
;
/*
* Iterate through the '\0'-terminated strings and convert '\0' to ' '
* until a string is found that has a '=' character in it (or there are
* no more strings in procargs). There is no way to deterministically
* know where the command arguments end and the environment strings
* start, which is why the '=' character is searched for as a heuristic.
*/
for
(
np
=
NULL
;
c
<
nargs
&&
cp
<
&
procargs
[
size
];
cp
++
)
{
if
(
*
cp
==
'\0'
)
{
c
++
;
if
(
np
!=
NULL
)
{
/* Convert previous '\0'. */
*
np
=
' '
;
}
/* Note location of current '\0'. */
np
=
cp
;
if
(
!
show_args
)
{
/*
* Don't convert '\0' characters to ' '.
* However, we needed to know that the
* command name was terminated, which we
* now know.
*/
break
;
}
}
}
#if 0
/*
* If eflg is non-zero, continue converting '\0' characters to ' '
* characters until no more strings that look like environment settings
* follow.
*/
if ( ( eflg != 0 )
&& ( ( getuid( ) == 0 )
|| ( k->kp_eproc.e_pcred.p_ruid == getuid( ) ) ) ) {
for ( ; cp < &procargs[size]; cp++ ) {
if ( *cp == '\0' ) {
if ( np != NULL ) {
if ( &np[1] == cp ) {
/*
* Two '\0' characters in a row.
* This should normally only
* happen after all the strings
* have been seen, but in any
* case, stop parsing.
*/
break;
}
/* Convert previous '\0'. */
*np = ' ';
}
/* Note location of current '\0'. */
np = cp;
}
}
}
#endif
/*
* 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
;
}
/* Make a copy of the string. */
retval
=
strdup
(
sp
);
/* Clean up. */
free
(
procargs
);
return
retval
;
ERROR_B:
free
(
procargs
);
ERROR_A:
retval
=
strdup
(
k
->
kp_proc
.
p_comm
);
return
retval
;
}
void
DarwinProcess_setFromKInfoProc
(
Process
*
proc
,
struct
kinfo_proc
*
ps
,
time_t
now
,
bool
exists
)
{
struct
extern_proc
*
ep
=
&
ps
->
kp_proc
;
/* UNSET HERE :
*
* processor
* user (set at ProcessList level)
* nlwp
* percent_cpu
* percent_mem
* m_size
* m_resident
* minflt
* majflt
*/
/* First, the "immutable" parts */
if
(
!
exists
)
{
/* 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 */
proc
->
tgid
=
ps
->
kp_eproc
.
e_tpgid
;
proc
->
st_uid
=
ps
->
kp_eproc
.
e_ucred
.
cr_uid
;
/* e_tdev = (major << 24) | (minor & 0xffffff) */
/* e_tdev == -1 for "no device" */
proc
->
tty_nr
=
ps
->
kp_eproc
.
e_tdev
&
0xff
;
/* TODO tty_nr is unsigned */
DarwinProcess_setStartTime
(
proc
,
ep
,
now
);
/* The command is from the old Mac htop */
char
*
slash
;
proc
->
comm
=
DarwinProcessList_getCmdLine
(
ps
,
false
);
slash
=
strrchr
(
proc
->
comm
,
'/'
);
proc
->
basenameOffset
=
(
NULL
!=
slash
)
?
(
slash
-
proc
->
comm
)
:
0
;
}
/* Mutable information */
proc
->
nice
=
ep
->
p_nice
;
proc
->
priority
=
ep
->
p_priority
;
/* Set the state */
switch
(
ep
->
p_stat
)
{
case
SIDL
:
proc
->
state
=
'I'
;
break
;
case
SRUN
:
proc
->
state
=
'R'
;
break
;
case
SSLEEP
:
proc
->
state
=
'S'
;
break
;
case
SSTOP
:
proc
->
state
=
'T'
;
break
;
case
SZOMB
:
proc
->
state
=
'Z'
;
break
;
default:
proc
->
state
=
'?'
;
break
;
}
/* Make sure the updated flag is set */
proc
->
updated
=
true
;
}
void
DarwinProcess_setFromLibprocPidinfo
(
Process
*
proc
,
uint64_t
total_memory
,
bool
preExisting
)
{
struct
proc_taskinfo
pti
;
if
(
sizeof
(
pti
)
==
proc_pidinfo
(
proc
->
pid
,
PROC_PIDTASKINFO
,
0
,
&
pti
,
sizeof
(
pti
)))
{
proc
->
nlwp
=
pti
.
pti_threadnum
;
proc
->
m_size
=
pti
.
pti_virtual_size
/
1024
;
proc
->
m_resident
=
pti
.
pti_resident_size
/
1024
;
proc
->
majflt
=
pti
.
pti_faults
;
proc
->
percent_mem
=
(
double
)
pti
.
pti_resident_size
*
100
.
0
/
(
double
)
total_memory
;
}
}
void
DarwinProcess_parseThreads
(
Process
*
proc
,
time_t
now
,
bool
preExisting
)
{
static
const
size_t
IDS_SZ
=
sizeof
(
uint64_t
)
*
2048
;
uint64_t
*
thread_ids
=
(
uint64_t
*
)
malloc
(
IDS_SZ
);
size_t
bytes
=
proc_pidinfo
(
proc
->
pid
,
PROC_PIDLISTTHREADS
,
0
,
thread_ids
,
IDS_SZ
);
if
(
0
<
bytes
)
{
size_t
count
=
bytes
/
sizeof
(
uint64_t
);
proc
->
nlwp
=
count
;
}
free
(
thread_ids
);
/* TODO Keep reusing this block */
}
darwin/DarwinProcess.h
View file @
43ef703f
...
...
@@ -10,13 +10,23 @@ in the source distribution for its full text.
*/
#include "Settings.h"
#define Process_delete DarwinProcess_delete
#include <sys/sysctl.h>
Process
*
DarwinProcess_new
(
Settings
*
settings
);
void
DarwinProcess_delete
(
Object
*
cast
);
void
Process_delete
(
Object
*
cast
);
bool
Process_isThread
(
Process
*
this
);
void
DarwinProcess_setStartTime
(
Process
*
proc
,
struct
extern_proc
*
ep
,
time_t
now
);
char
*
DarwinProcessList_getCmdLine
(
struct
kinfo_proc
*
k
,
int
show_args
);
void
DarwinProcess_setFromKInfoProc
(
Process
*
proc
,
struct
kinfo_proc
*
ps
,
time_t
now
,
bool
exists
);
void
DarwinProcess_setFromLibprocPidinfo
(
Process
*
proc
,
uint64_t
total_memory
,
bool
preExisting
);
void
DarwinProcess_parseThreads
(
Process
*
proc
,
time_t
now
,
bool
preExisting
);
#endif
darwin/DarwinProcessList.c
View file @
43ef703f
...
...
@@ -11,16 +11,85 @@ in the source distribution for its full text.
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <libproc.h>
/*{
#include <mach/mach_host.h>
#include <sys/sysctl.h>
typedef struct DarwinProcessList_ {
ProcessList super;
host_basic_info_data_t prev_hinfo;
processor_info_data_t prev_cpus;
} DarwinProcessList;
}*/
void
ProcessList_getHostInfo
(
host_basic_info_data_t
*
p
)
{
mach_msg_type_number_t
info_size
=
HOST_BASIC_INFO_COUNT
;
if
(
0
!=
host_info
(
mach_host_self
(),
HOST_BASIC_INFO
,
(
host_info_t
)
p
,
&
info_size
))
{
fprintf
(
stderr
,
"Unable to retrieve host info
\n
"
);
exit
(
2
);
}
}
unsigned
ProcessList_getCPUInfo
(
processor_info_data_t
*
p
)
{
mach_msg_type_number_t
info_size
=
PROCESSOR_CPU_LOAD_INFO_COUNT
;
unsigned
cpu_count
;
if
(
0
!=
host_processor_info
(
mach_host_self
(),
PROCESSOR_CPU_LOAD_INFO
,
&
cpu_count
,
(
processor_info_array_t
*
)
p
,
&
info_size
))
{
fprintf
(
stderr
,
"Unable to retrieve CPU info
\n
"
);
exit
(
4
);
}
return
cpu_count
;
}
struct
kinfo_proc
*
ProcessList_getKInfoProcs
(
size_t
*
count
)
{
int
mib
[
4
]
=
{
CTL_KERN
,
KERN_PROC
,
KERN_PROC_ALL
,
0
};
struct
kinfo_proc
*
processes
=
NULL
;
/* Note the two calls to sysctl(). One to get length and one to get the
* data. This -does- mean that the second call could end up with a missing
* process entry or two.
*/
*
count
=
0
;
if
(
0
>
sysctl
(
mib
,
4
,
NULL
,
count
,
NULL
,
0
))
{
fprintf
(
stderr
,
"Unable to get size of kproc_infos"
);
exit
(
5
);
}
processes
=
(
struct
kinfo_proc
*
)
malloc
(
*
count
);
if
(
NULL
==
processes
)
{
fprintf
(
stderr
,
"Out of memory for kproc_infos
\n
"
);
exit
(
6
);
}
if
(
0
>
sysctl
(
mib
,
4
,
processes
,
count
,
NULL
,
0
))
{
fprintf
(
stderr
,
"Unable to get kinfo_procs
\n
"
);
exit
(
7
);
}
*
count
=
*
count
/
sizeof
(
struct
kinfo_proc
);
return
processes
;
}
ProcessList
*
ProcessList_new
(
UsersTable
*
usersTable
,
Hashtable
*
pidWhiteList
,
uid_t
userId
)
{
ProcessList
*
this
=
calloc
(
1
,
sizeof
(
ProcessList
));
ProcessList_init
(
this
,
Class
(
Process
),
usersTable
,
pidWhiteList
,
userId
);
DarwinProcessList
*
this
=
calloc
(
1
,
sizeof
(
DarwinProcessList
));
ProcessList_init
(
&
this
->
super
,
Class
(
Process
),
usersTable
,
pidWhiteList
,
userId
);
return
this
;
/* Initialize the previous information */
this
->
super
.
cpuCount
=
ProcessList_getCPUInfo
(
&
this
->
prev_cpus
);
ProcessList_getHostInfo
(
&
this
->
prev_hinfo
);
return
&
this
->
super
;
}
void
ProcessList_delete
(
ProcessList
*
this
)
{
...
...
@@ -29,43 +98,36 @@ void ProcessList_delete(ProcessList* this) {
}
void
ProcessList_goThroughEntries
(
ProcessList
*
super
)
{
DarwinProcessList
*
dpl
=
(
DarwinProcessList
*
)
super
;
bool
preExisting
=
true
;
struct
kinfo_proc
*
ps
;
size_t
count
;
Process
*
proc
;
struct
timeval
tv
;
gettimeofday
(
&
tv
,
NULL
);
/* Start processing time */
/* We use kinfo_procs for initial data since :
*
* 1) They always succeed.
* 2) The contain the basic information.
*
* We attempt to fill-in additional information with libproc.
*/
ps
=
ProcessList_getKInfoProcs
(
&
count
);
for
(
size_t
i
=
0
;
i
<
count
;
++
i
)
{
proc
=
ProcessList_getProcess
(
super
,
ps
[
i
].
kp_proc
.
p_pid
,
&
preExisting
,
DarwinProcess_new
);
DarwinProcess_setFromKInfoProc
(
proc
,
ps
+
i
,
tv
.
tv_sec
,
preExisting
);
DarwinProcess_setFromLibprocPidinfo
(
proc
,
dpl
->
prev_hinfo
.
max_mem
,
preExisting
);
if
(
!
preExisting
)
{
proc
->
user
=
UsersTable_getRef
(
super
->
usersTable
,
proc
->
st_uid
);
ProcessList_add
(
super
,
proc
);
}
}
proc
=
ProcessList_getProcess
(
super
,
1
,
&
preExisting
,
DarwinProcess_new
);
/* Empty values */
proc
->
time
=
proc
->
time
+
10
;
proc
->
pid
=
1
;
proc
->
ppid
=
1
;
proc
->
tgid
=
0
;
proc
->
comm
=
"<unsupported architecture>"
;
proc
->
basenameOffset
=
0
;
proc
->
updated
=
true
;
proc
->
state
=
'R'
;
proc
->
show
=
true
;
/* Reflected in proc->settings-> "hideXXX" really */
proc
->
pgrp
=
0
;
proc
->
session
=
0
;
proc
->
tty_nr
=
0
;
proc
->
tpgid
=
0
;
proc
->
st_uid
=
0
;
proc
->
flags
=
0
;
proc
->
processor
=
0
;
proc
->
percent_cpu
=
2
.
5
;
proc
->
percent_mem
=
2
.
5
;
proc
->
user
=
"nobody"
;
proc
->
priority
=
0
;
proc
->
nice
=
0
;
proc
->
nlwp
=
1
;
strncpy
(
proc
->
starttime_show
,
"Jun 01 "
,
sizeof
(
proc
->
starttime_show
));
proc
->
starttime_ctime
=
1433116800
;
// Jun 01, 2015
proc
->
m_size
=
100
;
proc
->
m_resident
=
100
;
proc
->
minflt
=
20
;
proc
->
majflt
=
20
;
free
(
ps
);
}
darwin/DarwinProcessList.h
View file @
43ef703f
...
...
@@ -9,7 +9,25 @@ Released under the GNU GPL, see the COPYING file
in the source distribution for its full text.
*/
#include <mach/mach_host.h>
#include <sys/sysctl.h>
typedef
struct
DarwinProcessList_
{
ProcessList
super
;
host_basic_info_data_t
prev_hinfo
;
vm_statistics64_data_t
prev_vminfo
;
processor_info_data_t
prev_cpus
;
}
DarwinProcessList
;
void
ProcessList_getHostInfo
(
host_basic_info_data_t
*
p
);
void
ProcessList_getVMInfo
(
vm_statistics64_data_t
*
p
);
unsigned
ProcessList_getCPUInfo
(
processor_info_data_t
*
p
);
struct
kinfo_proc
*
ProcessList_getKInfoProcs
(
size_t
*
count
);
ProcessList
*
ProcessList_new
(
UsersTable
*
usersTable
,
Hashtable
*
pidWhiteList
,
uid_t
userId
);
...
...
darwin/Platform.c
View file @
43ef703f
...
...
@@ -16,6 +16,8 @@ in the source distribution for its full text.
#include "HostnameMeter.h"
#include "UptimeMeter.h"
#include <stdlib.h>
/*{
#include "Action.h"
#include "BatteryMeter.h"
...
...
@@ -87,13 +89,22 @@ int Platform_getUptime() {
}
void
Platform_getLoadAverage
(
double
*
one
,
double
*
five
,
double
*
fifteen
)
{
*
one
=
0
;
*
five
=
0
;
*
fifteen
=
0
;
double
results
[
3
];
if
(
3
==
getloadavg
(
results
,
3
))
{
*
one
=
results
[
0
];
*
five
=
results
[
1
];
*
fifteen
=
results
[
2
];
}
else
{
*
one
=
0
;
*
five
=
0
;
*
fifteen
=
0
;
}
}
int
Platform_getMaxPid
()
{
return
1
;
/* http://opensource.apple.com/source/xnu/xnu-2782.1.97/bsd/sys/proc_internal.hh */
return
99999
;
}
void
Process_setupColumnWidths
()
{
...
...
@@ -121,6 +132,8 @@ void Process_setupColumnWidths() {
}
double
Platform_setCPUValues
(
Meter
*
this
,
int
cpu
)
{
DarwinProcessList
*
dpl
=
(
DarwinProcessList
*
)
this
->
pl
;
return
0
.
0
;
}
...
...
@@ -130,7 +143,3 @@ void Platform_setMemoryValues(Meter* this) {
void
Platform_setSwapValues
(
Meter
*
this
)
{
}
bool
Process_isThread
(
Process
*
this
)
{
return
false
;
}
darwin/Platform.h
View file @
43ef703f
...
...
@@ -40,7 +40,5 @@ void Platform_setMemoryValues(Meter* this);
void
Platform_setSwapValues
(
Meter
*
this
);
bool
Process_isThread
(
Process
*
this
);
#endif
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment