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
9c40c9a0
Commit
9c40c9a0
authored
Feb 04, 2018
by
Hisham Muhammad
Browse files
Add perf counter object
parent
c55c8c23
Changes
2
Show whitespace changes
Inline
Side-by-side
linux/PerfCounter.c
0 → 100644
View file @
9c40c9a0
/*
* This file is based on tiptop.
* by Erven ROHOU
* Copyright (c) 2011, 2012, 2014 Inria
* License: GNU General Public License version 2.
*/
#include "PerfCounter.h"
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include "XAlloc.h"
/*{
#include <config.h>
#include <sys/types.h>
#include <unistd.h>
#include <asm/unistd.h>
#include <inttypes.h>
#include <stdbool.h>
// The sys_perf_counter_open syscall and header files changed names
// between Linux 2.6.31 and 2.6.32. Do the mangling here.
#ifdef HAVE_LINUX_PERF_COUNTER_H
#include <linux/perf_counter.h>
#define STRUCT_NAME perf_counter_attr
#define SYSCALL_NUM __NR_perf_counter_open
#elif HAVE_LINUX_PERF_EVENT_H
#include <linux/perf_event.h>
#define STRUCT_NAME perf_event_attr
#define SYSCALL_NUM __NR_perf_event_open
#else
#error Sorry, performance counters not supported on this system.
#endif
typedef struct PerfCounter_ {
struct STRUCT_NAME events;
pid_t pid;
int fd;
uint64_t prevValue;
uint64_t value;
} PerfCounter;
#define PerfCounter_delta(pc_) ((pc_)->value - (pc_)->prevValue)
}*/
int
PerfCounter_openFds
=
0
;
static
int
PerfCounter_fdLimit
=
-
1
;
static
void
PerfCounter_initFdLimit
()
{
char
name
[
100
]
=
{
0
};
/* needs to fit the name /proc/xxxx/limits */
snprintf
(
name
,
sizeof
(
name
)
-
1
,
"/proc/%d/limits"
,
getpid
());
FILE
*
f
=
fopen
(
name
,
"r"
);
if
(
f
)
{
char
line
[
100
];
while
(
fgets
(
line
,
100
,
f
))
{
int
n
=
sscanf
(
line
,
"Max open files %d"
,
&
PerfCounter_fdLimit
);
if
(
n
)
{
break
;
}
}
fclose
(
f
);
}
PerfCounter_fdLimit
-=
20
;
/* keep some slack */
if
(
PerfCounter_fdLimit
==
0
)
{
/* something went wrong */
PerfCounter_fdLimit
=
200
;
/* reasonable default? */
}
}
static
long
perf_event_open
(
struct
STRUCT_NAME
*
hw_event
,
pid_t
pid
,
int
cpu
,
int
group_fd
,
unsigned
long
flags
)
{
int
ret
=
syscall
(
SYSCALL_NUM
,
hw_event
,
pid
,
cpu
,
group_fd
,
flags
);
#if defined(__x86_64__) || defined(__i386__)
if
(
ret
<
0
&&
ret
>
-
4096
)
{
errno
=
-
ret
;
ret
=
-
1
;
}
#endif
return
ret
;
}
PerfCounter
*
PerfCounter_new
(
pid_t
pid
,
uint32_t
type
,
uint64_t
config
)
{
if
(
PerfCounter_fdLimit
==
-
1
)
{
PerfCounter_initFdLimit
();
}
PerfCounter
*
this
=
xCalloc
(
sizeof
(
PerfCounter
),
1
);
this
->
pid
=
pid
;
this
->
events
.
disabled
=
0
;
this
->
events
.
pinned
=
1
;
this
->
events
.
exclude_hv
=
1
;
this
->
events
.
exclude_kernel
=
1
;
this
->
events
.
type
=
type
;
this
->
events
.
config
=
config
;
if
(
PerfCounter_openFds
<
PerfCounter_fdLimit
)
{
this
->
fd
=
perf_event_open
(
&
this
->
events
,
pid
,
-
1
,
-
1
,
0
);
}
else
{
this
->
fd
=
-
1
;
}
if
(
this
->
fd
!=
-
1
)
{
PerfCounter_openFds
++
;
}
return
this
;
}
void
PerfCounter_delete
(
PerfCounter
*
this
)
{
if
(
!
this
)
{
return
;
}
if
(
this
->
fd
!=
-
1
)
{
PerfCounter_openFds
--
;
}
close
(
this
->
fd
);
free
(
this
);
}
bool
PerfCounter_read
(
PerfCounter
*
this
)
{
if
(
this
->
fd
==
-
1
)
{
return
false
;
}
uint64_t
value
;
int
r
=
read
(
this
->
fd
,
&
value
,
sizeof
(
value
));
if
(
r
!=
sizeof
(
value
))
{
close
(
this
->
fd
);
this
->
fd
=
perf_event_open
(
&
this
->
events
,
this
->
pid
,
-
1
,
-
1
,
0
);
return
false
;
}
this
->
prevValue
=
this
->
value
;
this
->
value
=
value
;
return
true
;
}
linux/PerfCounter.h
0 → 100644
View file @
9c40c9a0
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_PerfCounter
#define HEADER_PerfCounter
/*
* This file is based on tiptop.
* by Erven ROHOU
* Copyright (c) 2011, 2012, 2014 Inria
* License: GNU General Public License version 2.
*/
#include <config.h>
#include <sys/types.h>
#include <unistd.h>
#include <asm/unistd.h>
#include <inttypes.h>
#include <stdbool.h>
// The sys_perf_counter_open syscall and header files changed names
// between Linux 2.6.31 and 2.6.32. Do the mangling here.
#ifdef HAVE_LINUX_PERF_COUNTER_H
#include <linux/perf_counter.h>
#define STRUCT_NAME perf_counter_attr
#define SYSCALL_NUM __NR_perf_counter_open
#elif HAVE_LINUX_PERF_EVENT_H
#include <linux/perf_event.h>
#define STRUCT_NAME perf_event_attr
#define SYSCALL_NUM __NR_perf_event_open
#else
#error Sorry, performance counters not supported on this system.
#endif
typedef
struct
PerfCounter_
{
struct
STRUCT_NAME
events
;
pid_t
pid
;
int
fd
;
uint64_t
prevValue
;
uint64_t
value
;
}
PerfCounter
;
#define PerfCounter_delta(pc_) ((pc_)->value - (pc_)->prevValue)
extern
int
PerfCounter_openFds
;
PerfCounter
*
PerfCounter_new
(
pid_t
pid
,
uint32_t
type
,
uint64_t
config
);
void
PerfCounter_delete
(
PerfCounter
*
this
);
bool
PerfCounter_read
(
PerfCounter
*
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