Release 4.10 tools/perf/util/dso.c
#include <asm/bug.h>
#include <sys/time.h>
#include <sys/resource.h>
#include "symbol.h"
#include "dso.h"
#include "machine.h"
#include "auxtrace.h"
#include "util.h"
#include "debug.h"
#include "vdso.h"
char dso__symtab_origin(const struct dso *dso)
{
static const char origin[] = {
[DSO_BINARY_TYPE__KALLSYMS] = 'k',
[DSO_BINARY_TYPE__VMLINUX] = 'v',
[DSO_BINARY_TYPE__JAVA_JIT] = 'j',
[DSO_BINARY_TYPE__DEBUGLINK] = 'l',
[DSO_BINARY_TYPE__BUILD_ID_CACHE] = 'B',
[DSO_BINARY_TYPE__FEDORA_DEBUGINFO] = 'f',
[DSO_BINARY_TYPE__UBUNTU_DEBUGINFO] = 'u',
[DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO] = 'o',
[DSO_BINARY_TYPE__BUILDID_DEBUGINFO] = 'b',
[DSO_BINARY_TYPE__SYSTEM_PATH_DSO] = 'd',
[DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE] = 'K',
[DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP] = 'm',
[DSO_BINARY_TYPE__GUEST_KALLSYMS] = 'g',
[DSO_BINARY_TYPE__GUEST_KMODULE] = 'G',
[DSO_BINARY_TYPE__GUEST_KMODULE_COMP] = 'M',
[DSO_BINARY_TYPE__GUEST_VMLINUX] = 'V',
};
if (dso == NULL || dso->symtab_type == DSO_BINARY_TYPE__NOT_FOUND)
return '!';
return origin[dso->symtab_type];
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
jiri olsa | jiri olsa | 120 | 86.96% | 1 | 33.33% |
namhyung kim | namhyung kim | 12 | 8.70% | 1 | 33.33% |
ricardo ribalda | ricardo ribalda | 6 | 4.35% | 1 | 33.33% |
| Total | 138 | 100.00% | 3 | 100.00% |
int dso__read_binary_type_filename(const struct dso *dso,
enum dso_binary_type type,
char *root_dir, char *filename, size_t size)
{
char build_id_hex[SBUILD_ID_SIZE];
int ret = 0;
size_t len;
switch (type) {
case DSO_BINARY_TYPE__DEBUGLINK: {
char *debuglink;
len = __symbol__join_symfs(filename, size, dso->long_name);
debuglink = filename + len;
while (debuglink != filename && *debuglink != '/')
debuglink--;
if (*debuglink == '/')
debuglink++;
ret = -1;
if (!is_regular_file(filename))
break;
ret = filename__read_debuglink(filename, debuglink,
size - (debuglink - filename));
}
break;
case DSO_BINARY_TYPE__BUILD_ID_CACHE:
if (dso__build_id_filename(dso, filename, size) == NULL)
ret = -1;
break;
case DSO_BINARY_TYPE__FEDORA_DEBUGINFO:
len = __symbol__join_symfs(filename, size, "/usr/lib/debug");
snprintf(filename + len, size - len, "%s.debug", dso->long_name);
break;
case DSO_BINARY_TYPE__UBUNTU_DEBUGINFO:
len = __symbol__join_symfs(filename, size, "/usr/lib/debug");
snprintf(filename + len, size - len, "%s", dso->long_name);
break;
case DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO:
{
const char *last_slash;
size_t dir_size;
last_slash = dso->long_name + dso->long_name_len;
while (last_slash != dso->long_name && *last_slash != '/')
last_slash--;
len = __symbol__join_symfs(filename, size, "");
dir_size = last_slash - dso->long_name + 2;
if (dir_size > (size - len)) {
ret = -1;
break;
}
len += scnprintf(filename + len, dir_size, "%s", dso->long_name);
len += scnprintf(filename + len , size - len, ".debug%s",
last_slash);
break;
}
case DSO_BINARY_TYPE__BUILDID_DEBUGINFO:
if (!dso->has_build_id) {
ret = -1;
break;
}
build_id__sprintf(dso->build_id,
sizeof(dso->build_id),
build_id_hex);
len = __symbol__join_symfs(filename, size, "/usr/lib/debug/.build-id/");
snprintf(filename + len, size - len, "%.2s/%s.debug",
build_id_hex, build_id_hex + 2);
break;
case DSO_BINARY_TYPE__VMLINUX:
case DSO_BINARY_TYPE__GUEST_VMLINUX:
case DSO_BINARY_TYPE__SYSTEM_PATH_DSO:
__symbol__join_symfs(filename, size, dso->long_name);
break;
case DSO_BINARY_TYPE__GUEST_KMODULE:
case DSO_BINARY_TYPE__GUEST_KMODULE_COMP:
path__join3(filename, size, symbol_conf.symfs,
root_dir, dso->long_name);
break;
case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE:
case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP:
__symbol__join_symfs(filename, size, dso->long_name);
break;
case DSO_BINARY_TYPE__KCORE:
case DSO_BINARY_TYPE__GUEST_KCORE:
snprintf(filename, size, "%s", dso->long_name);
break;
default:
case DSO_BINARY_TYPE__KALLSYMS:
case DSO_BINARY_TYPE__GUEST_KALLSYMS:
case DSO_BINARY_TYPE__JAVA_JIT:
case DSO_BINARY_TYPE__NOT_FOUND:
ret = -1;
break;
}
return ret;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
jiri olsa | jiri olsa | 276 | 55.31% | 2 | 14.29% |
ricardo ribalda | ricardo ribalda | 107 | 21.44% | 1 | 7.14% |
arnaldo carvalho de melo | arnaldo carvalho de melo | 75 | 15.03% | 5 | 35.71% |
adrian hunter | adrian hunter | 25 | 5.01% | 2 | 14.29% |
victor kamensky | victor kamensky | 7 | 1.40% | 1 | 7.14% |
namhyung kim | namhyung kim | 6 | 1.20% | 1 | 7.14% |
stephane eranian | stephane eranian | 2 | 0.40% | 1 | 7.14% |
masami hiramatsu | masami hiramatsu | 1 | 0.20% | 1 | 7.14% |
| Total | 499 | 100.00% | 14 | 100.00% |
static const struct {
const char *fmt;
int (*decompress)(const char *input, int output);
}
compressions[] = {
#ifdef HAVE_ZLIB_SUPPORT
{ "gz", gzip_decompress_to_file },
#endif
#ifdef HAVE_LZMA_SUPPORT
{ "xz", lzma_decompress_to_file },
#endif
{ NULL, NULL },
};
bool is_supported_compression(const char *ext)
{
unsigned i;
for (i = 0; compressions[i].fmt; i++) {
if (!strcmp(ext, compressions[i].fmt))
return true;
}
return false;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
namhyung kim | namhyung kim | 52 | 100.00% | 1 | 100.00% |
| Total | 52 | 100.00% | 1 | 100.00% |
bool is_kernel_module(const char *pathname, int cpumode)
{
struct kmod_path m;
int mode = cpumode & PERF_RECORD_MISC_CPUMODE_MASK;
WARN_ONCE(mode != cpumode,
"Internal error: passing unmasked cpumode (%x) to is_kernel_module",
cpumode);
switch (mode) {
case PERF_RECORD_MISC_USER:
case PERF_RECORD_MISC_HYPERVISOR:
case PERF_RECORD_MISC_GUEST_USER:
return false;
/* Treat PERF_RECORD_MISC_CPUMODE_UNKNOWN as kernel */
default:
if (kmod_path__parse(&m, pathname)) {
pr_err("Failed to check whether %s is a kernel module or not. Assume it is.",
pathname);
return true;
}
}
return m.kmod;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
wang nan | wang nan | 51 | 62.20% | 1 | 33.33% |
namhyung kim | namhyung kim | 18 | 21.95% | 1 | 33.33% |
jiri olsa | jiri olsa | 13 | 15.85% | 1 | 33.33% |
| Total | 82 | 100.00% | 3 | 100.00% |
bool decompress_to_file(const char *ext, const char *filename, int output_fd)
{
unsigned i;
for (i = 0; compressions[i].fmt; i++) {
if (!strcmp(ext, compressions[i].fmt))
return !compressions[i].decompress(filename,
output_fd);
}
return false;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
namhyung kim | namhyung kim | 71 | 100.00% | 1 | 100.00% |
| Total | 71 | 100.00% | 1 | 100.00% |
bool dso__needs_decompress(struct dso *dso)
{
return dso->symtab_type == DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP ||
dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE_COMP;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
namhyung kim | namhyung kim | 23 | 100.00% | 1 | 100.00% |
| Total | 23 | 100.00% | 1 | 100.00% |
/*
* Parses kernel module specified in @path and updates
* @m argument like:
*
* @comp - true if @path contains supported compression suffix,
* false otherwise
* @kmod - true if @path contains '.ko' suffix in right position,
* false otherwise
* @name - if (@alloc_name && @kmod) is true, it contains strdup-ed base name
* of the kernel module without suffixes, otherwise strudup-ed
* base name of @path
* @ext - if (@alloc_ext && @comp) is true, it contains strdup-ed string
* the compression suffix
*
* Returns 0 if there's no strdup error, -ENOMEM otherwise.
*/
int __kmod_path__parse(struct kmod_path *m, const char *path,
bool alloc_name, bool alloc_ext)
{
const char *name = strrchr(path, '/');
const char *ext = strrchr(path, '.');
bool is_simple_name = false;
memset(m, 0x0, sizeof(*m));
name = name ? name + 1 : path;
/*
* '.' is also a valid character for module name. For example:
* [aaa.bbb] is a valid module name. '[' should have higher
* priority than '.ko' suffix.
*
* The kernel names are from machine__mmap_name. Such
* name should belong to kernel itself, not kernel module.
*/
if (name[0] == '[') {
is_simple_name = true;
if ((strncmp(name, "[kernel.kallsyms]", 17) == 0) ||
(strncmp(name, "[guest.kernel.kallsyms", 22) == 0) ||
(strncmp(name, "[vdso]", 6) == 0) ||
(strncmp(name, "[vsyscall]", 10) == 0)) {
m->kmod = false;
} else
m->kmod = true;
}
/* No extension, just return name. */
if ((ext == NULL) || is_simple_name) {
if (alloc_name) {
m->name = strdup(name);
return m->name ? 0 : -ENOMEM;
}
return 0;
}
if (is_supported_compression(ext + 1)) {
m->comp = true;
ext -= 3;
}
/* Check .ko extension only if there's enough name left. */
if (ext > name)
m->kmod = !strncmp(ext, ".ko", 3);
if (alloc_name) {
if (m->kmod) {
if (asprintf(&m->name, "[%.*s]", (int) (ext - name), name) == -1)
return -ENOMEM;
} else {
if (asprintf(&m->name, "%s", name) == -1)
return -ENOMEM;
}
strxfrchar(m->name, '-', '_');
}
if (alloc_ext && m->comp) {
m->ext = strdup(ext + 4);
if (!m->ext) {
free((void *) m->name);
return -ENOMEM;
}
}
return 0;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
jiri olsa | jiri olsa | 274 | 74.46% | 1 | 50.00% |
wang nan | wang nan | 94 | 25.54% | 1 | 50.00% |
| Total | 368 | 100.00% | 2 | 100.00% |
/*
* Global list of open DSOs and the counter.
*/
static LIST_HEAD(dso__data_open);
static long dso__data_open_cnt;
static pthread_mutex_t dso__data_open_lock = PTHREAD_MUTEX_INITIALIZER;
static void dso__list_add(struct dso *dso)
{
list_add_tail(&dso->data.open_entry, &dso__data_open);
dso__data_open_cnt++;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
jiri olsa | jiri olsa | 27 | 100.00% | 2 | 100.00% |
| Total | 27 | 100.00% | 2 | 100.00% |
static void dso__list_del(struct dso *dso)
{
list_del(&dso->data.open_entry);
WARN_ONCE(dso__data_open_cnt <= 0,
"DSO data fd counter out of bounds.");
dso__data_open_cnt--;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
jiri olsa | jiri olsa | 33 | 100.00% | 2 | 100.00% |
| Total | 33 | 100.00% | 2 | 100.00% |
static void close_first_dso(void);
static int do_open(char *name)
{
int fd;
char sbuf[STRERR_BUFSIZE];
do {
fd = open(name, O_RDONLY);
if (fd >= 0)
return fd;
pr_debug("dso open failed: %s\n",
str_error_r(errno, sbuf, sizeof(sbuf)));
if (!dso__data_open_cnt || errno != EMFILE)
break;
close_first_dso();
} while (1);
return -1;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
jiri olsa | jiri olsa | 64 | 81.01% | 1 | 25.00% |
masami hiramatsu | masami hiramatsu | 13 | 16.46% | 1 | 25.00% |
arnaldo carvalho de melo | arnaldo carvalho de melo | 1 | 1.27% | 1 | 25.00% |
namhyung kim | namhyung kim | 1 | 1.27% | 1 | 25.00% |
| Total | 79 | 100.00% | 4 | 100.00% |
static int __open_dso(struct dso *dso, struct machine *machine)
{
int fd;
char *root_dir = (char *)"";
char *name = malloc(PATH_MAX);
if (!name)
return -ENOMEM;
if (machine)
root_dir = machine->root_dir;
if (dso__read_binary_type_filename(dso, dso->binary_type,
root_dir, name, PATH_MAX)) {
free(name);
return -EINVAL;
}
if (!is_regular_file(name))
return -EINVAL;
fd = do_open(name);
free(name);
return fd;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
jiri olsa | jiri olsa | 105 | 93.75% | 4 | 66.67% |
arnaldo carvalho de melo | arnaldo carvalho de melo | 7 | 6.25% | 2 | 33.33% |
| Total | 112 | 100.00% | 6 | 100.00% |
static void check_data_close(void);
/**
* dso_close - Open DSO data file
* @dso: dso object
*
* Open @dso's data file descriptor and updates
* list/count of open DSO objects.
*/
static int open_dso(struct dso *dso, struct machine *machine)
{
int fd = __open_dso(dso, machine);
if (fd >= 0) {
dso__list_add(dso);
/*
* Check if we crossed the allowed number
* of opened DSOs and close one if needed.
*/
check_data_close();
}
return fd;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
jiri olsa | jiri olsa | 45 | 97.83% | 2 | 66.67% |
adrian hunter | adrian hunter | 1 | 2.17% | 1 | 33.33% |
| Total | 46 | 100.00% | 3 | 100.00% |
static void close_data_fd(struct dso *dso)
{
if (dso->data.fd >= 0) {
close(dso->data.fd);
dso->data.fd = -1;
dso->data.file_size = 0;
dso__list_del(dso);
}
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
jiri olsa | jiri olsa | 54 | 100.00% | 3 | 100.00% |
| Total | 54 | 100.00% | 3 | 100.00% |
/**
* dso_close - Close DSO data file
* @dso: dso object
*
* Close @dso's data file descriptor and updates
* list/count of open DSO objects.
*/
static void close_dso(struct dso *dso)
{
close_data_fd(dso);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
jiri olsa | jiri olsa | 16 | 100.00% | 1 | 100.00% |
| Total | 16 | 100.00% | 1 | 100.00% |
static void close_first_dso(void)
{
struct dso *dso;
dso = list_first_entry(&dso__data_open, struct dso, data.open_entry);
close_dso(dso);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
jiri olsa | jiri olsa | 33 | 100.00% | 1 | 100.00% |
| Total | 33 | 100.00% | 1 | 100.00% |
static rlim_t get_fd_limit(void)
{
struct rlimit l;
rlim_t limit = 0;
/* Allow half of the current open fd limit. */
if (getrlimit(RLIMIT_NOFILE, &l) == 0) {
if (l.rlim_cur == RLIM_INFINITY)
limit = l.rlim_cur;
else
limit = l.rlim_cur / 2;
} else {
pr_err("failed to get fd limit\n");
limit = 1;
}
return limit;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
jiri olsa | jiri olsa | 70 | 100.00% | 1 | 100.00% |
| Total | 70 | 100.00% | 1 | 100.00% |
static rlim_t fd_limit;
/*
* Used only by tests/dso-data.c to reset the environment
* for tests. I dont expect we should change this during
* standard runtime.
*/
void reset_fd_limit(void)
{
fd_limit = 0;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
jiri olsa | jiri olsa | 11 | 100.00% | 1 | 100.00% |
| Total | 11 | 100.00% | 1 | 100.00% |
static bool may_cache_fd(void)
{
if (!fd_limit)
fd_limit = get_fd_limit();
if (fd_limit == RLIM_INFINITY)
return true;
return fd_limit > (rlim_t) dso__data_open_cnt;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
jiri olsa | jiri olsa | 35 | 100.00% | 2 | 100.00% |
| Total | 35 | 100.00% | 2 | 100.00% |
/*
* Check and close LRU dso if we crossed allowed limit
* for opened dso file descriptors. The limit is half
* of the RLIMIT_NOFILE files opened.
*/
static void check_data_close(void)
{
bool cache_fd = may_cache_fd();
if (!cache_fd)
close_first_dso();
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
jiri olsa | jiri olsa | 22 | 100.00% | 1 | 100.00% |
| Total | 22 | 100.00% | 1 | 100.00% |
/**
* dso__data_close - Close DSO data file
* @dso: dso object
*
* External interface to close @dso's data file descriptor.
*/
void dso__data_close(struct dso *dso)
{
pthread_mutex_lock(&dso__data_open_lock);
close_dso(dso);
pthread_mutex_unlock(&dso__data_open_lock);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
jiri olsa | jiri olsa | 15 | 55.56% | 1 | 50.00% |
namhyung kim | namhyung kim | 12 | 44.44% | 1 | 50.00% |
| Total | 27 | 100.00% | 2 | 100.00% |
static void try_to_open_dso(struct dso *dso, struct machine *machine)
{
enum dso_binary_type binary_type_data[] = {
DSO_BINARY_TYPE__BUILD_ID_CACHE,
DSO_BINARY_TYPE__SYSTEM_PATH_DSO,
DSO_BINARY_TYPE__NOT_FOUND,
};
int i = 0;
if (dso->data.fd >= 0)
return;
if (dso->binary_type != DSO_BINARY_TYPE__NOT_FOUND) {
dso->data.fd = open_dso(dso, machine);
goto out;
}
do {
dso->binary_type = binary_type_data[i++];
dso->data.fd = open_dso(dso, machine);
if (dso->data.fd >= 0)
goto out;
} while (dso->binary_type != DSO_BINARY_TYPE__NOT_FOUND);
out:
if (dso->data.fd >= 0)
dso->data.status = DSO_DATA_STATUS_OK;
else
dso->data.status = DSO_DATA_STATUS_ERROR;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
jiri olsa | jiri olsa | 95 | 64.19% | 2 | 40.00% |
adrian hunter | adrian hunter | 45 | 30.41% | 1 | 20.00% |
namhyung kim | namhyung kim | 5 | 3.38% | 1 | 20.00% |
arnaldo carvalho de melo | arnaldo carvalho de melo | 3 | 2.03% | 1 | 20.00% |
| Total | 148 | 100.00% | 5 | 100.00% |
/**
* dso__data_get_fd - Get dso's data file descriptor
* @dso: dso object
* @machine: machine object
*
* External interface to find dso's file, open it and
* returns file descriptor. It should be paired with
* dso__data_put_fd() if it returns non-negative value.
*/
int dso__data_get_fd(struct dso *dso, struct machine *machine)
{
if (dso->data.status == DSO_DATA_STATUS_ERROR)
return -1;
if (pthread_mutex_lock(&dso__data_open_lock) < 0)
return -1;
try_to_open_dso(dso, machine);
if (dso->data.fd < 0)
pthread_mutex_unlock(&dso__data_open_lock);
return dso->data.fd;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
namhyung kim | namhyung kim | 65 | 89.04% | 3 | 60.00% |
adrian hunter | adrian hunter | 5 | 6.85% | 1 | 20.00% |
jiri olsa | jiri olsa | 3 | 4.11% | 1 | 20.00% |
| Total | 73 | 100.00% | 5 | 100.00% |
void dso__data_put_fd(struct dso *dso __maybe_unused)
{
pthread_mutex_unlock(&dso__data_open_lock);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
namhyung kim | namhyung kim | 17 | 100.00% | 1 | 100.00% |
| Total | 17 | 100.00% | 1 | 100.00% |
bool dso__data_status_seen(struct dso *dso, enum dso_data_status_seen by)
{
u32 flag = 1 << by;
if (dso->data.status_seen & flag)
return true;
dso->data.status_seen |= flag;
return false;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
adrian hunter | adrian hunter | 45 | 100.00% | 1 | 100.00% |
| Total | 45 | 100.00% | 1 | 100.00% |
static void
dso_cache__free(struct dso *dso)
{
struct rb_root *root = &dso->data.cache;
struct rb_node *next = rb_first(root);
pthread_mutex_lock(&dso->lock);
while (next) {
struct dso_cache *cache;
cache = rb_entry(next, struct dso_cache, rb_node);
next = rb_next(&cache->rb_node);
rb_erase(&cache->rb_node, root);
free(cache);
}
pthread_mutex_unlock(&dso->lock);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
jiri olsa | jiri olsa | 67 | 69.07% | 1 | 50.00% |
namhyung kim | namhyung kim | 30 | 30.93% | 1 | 50.00% |
| Total | 97 | 100.00% | 2 | 100.00% |
static struct dso_cache *dso_cache__find(struct dso *dso, u64 offset)
{
const struct rb_root *root = &dso->data.cache;
struct rb_node * const *p = &root->rb_node;
const struct rb_node *parent = NULL;
struct dso_cache *cache;
while (*p != NULL) {
u64 end;
parent = *p;
cache = rb_entry(parent, struct dso_cache, rb_node);
end = cache->offset + DSO__DATA_CACHE_SIZE;
if (offset < cache->offset)
p = &(*p)->rb_left;
else if (offset >= end)
p = &(*p)->rb_right;
else
return cache;
}
return NULL;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
jiri olsa | jiri olsa | 116 | 87.22% | 1 | 33.33% |
namhyung kim | namhyung kim | 15 | 11.28% | 1 | 33.33% |
arnaldo carvalho de melo | arnaldo carvalho de melo | 2 | 1.50% | 1 | 33.33% |
| Total | 133 | 100.00% | 3 | 100.00% |
static struct dso_cache *
dso_cache__insert(struct dso *dso, struct dso_cache *new)
{
struct rb_root *root = &dso->data.cache;
struct rb_node **p = &root->rb_node;
struct rb_node *parent = NULL;
struct dso_cache *cache;
u64 offset = new->offset;
pthread_mutex_lock(&dso->lock);
while (*p != NULL) {
u64 end;
parent = *p;
cache = rb_entry(parent, struct dso_cache, rb_node);
end = cache->offset + DSO__DATA_CACHE_SIZE;
if (offset < cache->offset)
p = &(*p)->rb_left;
else if (offset >= end)
p = &(*p)->rb_right;
else
goto out;
}
rb_link_node(&new->rb_node, parent, p);
rb_insert_color(&new->rb_node, root);
cache = NULL;
out:
pthread_mutex_unlock(&dso->lock);
return cache;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
jiri olsa | jiri olsa | 137 | 74.86% | 1 | 50.00% |
namhyung kim | namhyung kim | 46 | 25.14% | 1 | 50.00% |
| Total | 183 | 100.00% | 2 | 100.00% |
static ssize_t
dso_cache__memcpy(struct dso_cache *cache, u64 offset,
u8 *data, u64 size)
{
u64 cache_offset = offset - cache->offset;
u64 cache_size = min(cache->size - cache_offset, size);
memcpy(data, cache->data + cache_offset, cache_size);
return cache_size;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
jiri olsa | jiri olsa | 60 | 100.00% | 1 | 100.00% |
| Total | 60 | 100.00% | 1 | 100.00% |
static ssize_t
dso_cache__read(struct dso *dso, struct machine *machine,
u64 offset, u8 *data, ssize_t size)
{
struct dso_cache *cache;
struct dso_cache *old;
ssize_t ret;
do {
u64 cache_offset;
cache = zalloc(sizeof(*cache) + DSO__DATA_CACHE_SIZE);
if (!cache)
return -ENOMEM;
pthread_mutex_lock(&dso__data_open_lock);
/*
* dso->data.fd might be closed if other thread opened another
* file (dso) due to open file limit (RLIMIT_NOFILE).
*/
try_to_open_dso(dso, machine);
if (dso->data.fd < 0) {
ret = -errno;
dso->data.status = DSO_DATA_STATUS_ERROR;
break;
}
cache_offset = offset & DSO__DATA_CACHE_MASK;
ret = pread(dso->data.fd, cache->data, DSO__DATA_CACHE_SIZE, cache_offset);
if (ret <= 0)
break;
cache->offset = cache_offset;
cache->size = ret;
} while (0);
pthread_mutex_unlock(&dso__data_open_lock);
if (ret > 0) {
old = dso_cache__insert(dso, cache);
if (old) {
/* we lose the race */
free(cache);
cache = old