|
|
@@ -495,10 +495,12 @@ bool dso__data_status_seen(struct dso *dso, enum dso_data_status_seen by)
|
|
|
}
|
|
|
|
|
|
static void
|
|
|
-dso_cache__free(struct rb_root *root)
|
|
|
+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;
|
|
|
|
|
|
@@ -507,10 +509,12 @@ dso_cache__free(struct rb_root *root)
|
|
|
rb_erase(&cache->rb_node, root);
|
|
|
free(cache);
|
|
|
}
|
|
|
+ pthread_mutex_unlock(&dso->lock);
|
|
|
}
|
|
|
|
|
|
-static struct dso_cache *dso_cache__find(const struct rb_root *root, u64 offset)
|
|
|
+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;
|
|
|
@@ -529,17 +533,20 @@ static struct dso_cache *dso_cache__find(const struct rb_root *root, u64 offset)
|
|
|
else
|
|
|
return cache;
|
|
|
}
|
|
|
+
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
-static void
|
|
|
-dso_cache__insert(struct rb_root *root, struct dso_cache *new)
|
|
|
+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;
|
|
|
|
|
|
@@ -551,10 +558,17 @@ dso_cache__insert(struct rb_root *root, struct dso_cache *new)
|
|
|
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;
|
|
|
}
|
|
|
|
|
|
static ssize_t
|
|
|
@@ -572,6 +586,7 @@ static ssize_t
|
|
|
dso_cache__read(struct dso *dso, u64 offset, u8 *data, ssize_t size)
|
|
|
{
|
|
|
struct dso_cache *cache;
|
|
|
+ struct dso_cache *old;
|
|
|
ssize_t ret;
|
|
|
|
|
|
do {
|
|
|
@@ -591,7 +606,12 @@ dso_cache__read(struct dso *dso, u64 offset, u8 *data, ssize_t size)
|
|
|
|
|
|
cache->offset = cache_offset;
|
|
|
cache->size = ret;
|
|
|
- dso_cache__insert(&dso->data.cache, cache);
|
|
|
+ old = dso_cache__insert(dso, cache);
|
|
|
+ if (old) {
|
|
|
+ /* we lose the race */
|
|
|
+ free(cache);
|
|
|
+ cache = old;
|
|
|
+ }
|
|
|
|
|
|
ret = dso_cache__memcpy(cache, offset, data, size);
|
|
|
|
|
|
@@ -608,7 +628,7 @@ static ssize_t dso_cache_read(struct dso *dso, u64 offset,
|
|
|
{
|
|
|
struct dso_cache *cache;
|
|
|
|
|
|
- cache = dso_cache__find(&dso->data.cache, offset);
|
|
|
+ cache = dso_cache__find(dso, offset);
|
|
|
if (cache)
|
|
|
return dso_cache__memcpy(cache, offset, data, size);
|
|
|
else
|
|
|
@@ -964,7 +984,7 @@ void dso__delete(struct dso *dso)
|
|
|
|
|
|
dso__data_close(dso);
|
|
|
auxtrace_cache__free(dso->auxtrace_cache);
|
|
|
- dso_cache__free(&dso->data.cache);
|
|
|
+ dso_cache__free(dso);
|
|
|
dso__free_a2l(dso);
|
|
|
zfree(&dso->symsrc_filename);
|
|
|
pthread_mutex_destroy(&dso->lock);
|