diff options
Diffstat (limited to 'tools/perf/util/dso.c')
-rw-r--r-- | tools/perf/util/dso.c | 37 |
1 files changed, 36 insertions, 1 deletions
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c index ff0204ac4321..7c0c08386a1d 100644 --- a/tools/perf/util/dso.c +++ b/tools/perf/util/dso.c @@ -1049,6 +1049,7 @@ struct dso *dso__new(const char *name) INIT_LIST_HEAD(&dso->node); INIT_LIST_HEAD(&dso->data.open_entry); pthread_mutex_init(&dso->lock, NULL); + atomic_set(&dso->refcnt, 1); } return dso; @@ -1083,6 +1084,19 @@ void dso__delete(struct dso *dso) free(dso); } +struct dso *dso__get(struct dso *dso) +{ + if (dso) + atomic_inc(&dso->refcnt); + return dso; +} + +void dso__put(struct dso *dso) +{ + if (dso && atomic_dec_and_test(&dso->refcnt)) + dso__delete(dso); +} + void dso__set_build_id(struct dso *dso, void *build_id) { memcpy(dso->build_id, build_id, sizeof(dso->build_id)); @@ -1153,6 +1167,27 @@ void __dsos__add(struct dsos *dsos, struct dso *dso) { list_add_tail(&dso->node, &dsos->head); __dso__findlink_by_longname(&dsos->root, dso, NULL); + /* + * It is now in the linked list, grab a reference, then garbage collect + * this when needing memory, by looking at LRU dso instances in the + * list with atomic_read(&dso->refcnt) == 1, i.e. no references + * anywhere besides the one for the list, do, under a lock for the + * list: remove it from the list, then a dso__put(), that probably will + * be the last and will then call dso__delete(), end of life. + * + * That, or at the end of the 'struct machine' lifetime, when all + * 'struct dso' instances will be removed from the list, in + * dsos__exit(), if they have no other reference from some other data + * structure. + * + * E.g.: after processing a 'perf.data' file and storing references + * to objects instantiated while processing events, we will have + * references to the 'thread', 'map', 'dso' structs all from 'struct + * hist_entry' instances, but we may not need anything not referenced, + * so we might as well call machines__exit()/machines__delete() and + * garbage collect it. + */ + dso__get(dso); } void dsos__add(struct dsos *dsos, struct dso *dso) @@ -1206,7 +1241,7 @@ struct dso *dsos__findnew(struct dsos *dsos, const char *name) { struct dso *dso; pthread_rwlock_wrlock(&dsos->lock); - dso = __dsos__findnew(dsos, name); + dso = dso__get(__dsos__findnew(dsos, name)); pthread_rwlock_unlock(&dsos->lock); return dso; } |