[lttng-dev] [PATCH lttng-ust] Fix: Make deadlocks with baddr statedump unlikely
Paul Woegerer
paul_woegerer at mentor.com
Mon Mar 17 05:22:01 EDT 2014
Signed-off-by: Paul Woegerer <paul_woegerer at mentor.com>
---
liblttng-ust/lttng-ust-baddr.c | 95 ++++++++++++++++++++++++++++++++----------
1 file changed, 74 insertions(+), 21 deletions(-)
diff --git a/liblttng-ust/lttng-ust-baddr.c b/liblttng-ust/lttng-ust-baddr.c
index dec7e82..0e8ff24 100644
--- a/liblttng-ust/lttng-ust-baddr.c
+++ b/liblttng-ust/lttng-ust-baddr.c
@@ -39,17 +39,50 @@
#define TP_SESSION_CHECK
#include "ust_baddr_statedump.h"
+struct baddr_entry {
+ void *base_addr_ptr;
+ char resolved_path[PATH_MAX];
+ int vdso;
+};
+
struct extract_data {
- void *owner;
void *exec_baddr; /* executable base address */
+ struct baddr_entry *baddrs; /* other base addresses */
+ size_t num_baddrs; /* number of other base addresses */
+ size_t idx_baddrs; /* current base addresse index */
};
+static
+int add_baddr(void *base_addr_ptr,
+ const char *resolved_path,
+ int vdso,
+ struct extract_data *data)
+{
+ struct baddr_entry *baddr;
+
+ if (data->num_baddrs < data->idx_baddrs + 1) {
+ data->num_baddrs *= 2;
+ data->baddrs = realloc(data->baddrs,
+ data->num_baddrs * sizeof(struct baddr_entry));
+ if (!data->baddrs)
+ return 1;
+ }
+
+ baddr = data->baddrs + data->idx_baddrs;
+ baddr->base_addr_ptr = base_addr_ptr;
+ strncpy(baddr->resolved_path, resolved_path, PATH_MAX - 1);
+ baddr->vdso = vdso;
+
+ data->idx_baddrs += 1;
+ return 0;
+}
+
/*
* Trace baddr into all sessions for which statedump is pending owned by
* the caller thread.
*/
static
-int trace_baddr(void *base_addr_ptr,
+void trace_baddr(void *base_addr_ptr,
const char *resolved_path,
int vdso,
void *owner)
@@ -62,16 +95,6 @@ int trace_baddr(void *base_addr_ptr,
sostat.st_size = 0;
sostat.st_mtime = -1;
}
- /*
- * UST lock nests within dynamic loader lock.
- */
- if (ust_lock()) {
- /*
- * Stop iteration on headers if need to exit.
- */
- ust_unlock();
- return 1;
- }
sessionsp = _lttng_get_sessions();
cds_list_for_each_entry(session, sessionsp, node) {
@@ -84,8 +107,6 @@ int trace_baddr(void *base_addr_ptr,
resolved_path, sostat.st_size,
sostat.st_mtime);
}
- ust_unlock();
- return 0;
}
static
@@ -93,7 +114,6 @@ int extract_soinfo_events(struct dl_phdr_info *info, size_t size, void *_data)
{
int j;
struct extract_data *data = _data;
- void *owner = data->owner;
for (j = 0; j < info->dlpi_phnum; j++) {
char resolved_path[PATH_MAX];
@@ -138,9 +158,8 @@ int extract_soinfo_events(struct dl_phdr_info *info, size_t size, void *_data)
vdso = 1;
}
}
- if (trace_baddr(base_addr_ptr, resolved_path, vdso, owner)) {
+ if (add_baddr(base_addr_ptr, resolved_path, vdso, data))
return 1;
- }
/*
* We are only interested in the base address (lowest virtual
* address associated with the memory image), skip the rest
@@ -151,9 +170,8 @@ int extract_soinfo_events(struct dl_phdr_info *info, size_t size, void *_data)
}
static
-void dump_exec_baddr(struct extract_data *data)
+void dump_exec_baddr(struct extract_data *data, void *owner)
{
- void *owner = data->owner;
void *base_addr_ptr;
char exe_path[PATH_MAX];
ssize_t exe_len;
@@ -172,6 +190,38 @@ void dump_exec_baddr(struct extract_data *data)
trace_baddr(base_addr_ptr, exe_path, 0, owner);
}
+static
+void dump_baddrs(struct extract_data *data, void *owner)
+{
+ /* Emit tracepoints for shared objects */
+ struct baddr_entry *baddrs = data->baddrs;
+ size_t idx_baddrs = data->idx_baddrs;
+ size_t i = 0;
+
+ /*
+ * UST lock nests within dynamic loader lock.
+ */
+ if (ust_lock()) {
+ /*
+ * Stop if need to exit.
+ */
+ ust_unlock();
+ return;
+ }
+
+ while (i < idx_baddrs) {
+ struct baddr_entry *baddr = baddrs + i;
+ trace_baddr(baddr->base_addr_ptr,
+ baddr->resolved_path,
+ baddr->vdso, owner);
+ i += 1;
+ }
+ /* Emit tracepoint for executable */
+ dump_exec_baddr(data, owner);
+
+ ust_unlock();
+}
+
int lttng_ust_baddr_statedump(void *owner)
{
struct extract_data data;
@@ -179,8 +229,10 @@ int lttng_ust_baddr_statedump(void *owner)
if (!getenv("LTTNG_UST_WITH_EXPERIMENTAL_BADDR_STATEDUMP"))
return 0;
- data.owner = owner;
data.exec_baddr = NULL;
+ data.num_baddrs = 32;
+ data.baddrs = malloc(data.num_baddrs * sizeof(struct baddr_entry));
+ data.idx_baddrs = 0;
/*
* Iterate through the list of currently loaded shared objects and
* generate events for loadable segments using
@@ -193,7 +245,8 @@ int lttng_ust_baddr_statedump(void *owner)
* deadlocks, so dump the executable outside of the phdr
* iteration.
*/
- dump_exec_baddr(&data);
+ dump_baddrs(&data, owner);
+ free(data.baddrs);
return 0;
}
--
1.9.0
More information about the lttng-dev
mailing list