162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci#include <errno.h> 362306a36Sopenharmony_ci#include <stdlib.h> 462306a36Sopenharmony_ci#include <stdio.h> 562306a36Sopenharmony_ci#include <string.h> 662306a36Sopenharmony_ci#include <linux/kernel.h> 762306a36Sopenharmony_ci#include <linux/zalloc.h> 862306a36Sopenharmony_ci#include "dso.h" 962306a36Sopenharmony_ci#include "session.h" 1062306a36Sopenharmony_ci#include "thread.h" 1162306a36Sopenharmony_ci#include "thread-stack.h" 1262306a36Sopenharmony_ci#include "debug.h" 1362306a36Sopenharmony_ci#include "namespaces.h" 1462306a36Sopenharmony_ci#include "comm.h" 1562306a36Sopenharmony_ci#include "map.h" 1662306a36Sopenharmony_ci#include "symbol.h" 1762306a36Sopenharmony_ci#include "unwind.h" 1862306a36Sopenharmony_ci#include "callchain.h" 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci#include <api/fs/fs.h> 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ciint thread__init_maps(struct thread *thread, struct machine *machine) 2362306a36Sopenharmony_ci{ 2462306a36Sopenharmony_ci pid_t pid = thread__pid(thread); 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci if (pid == thread__tid(thread) || pid == -1) { 2762306a36Sopenharmony_ci thread__set_maps(thread, maps__new(machine)); 2862306a36Sopenharmony_ci } else { 2962306a36Sopenharmony_ci struct thread *leader = __machine__findnew_thread(machine, pid, pid); 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci if (leader) { 3262306a36Sopenharmony_ci thread__set_maps(thread, maps__get(thread__maps(leader))); 3362306a36Sopenharmony_ci thread__put(leader); 3462306a36Sopenharmony_ci } 3562306a36Sopenharmony_ci } 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci return thread__maps(thread) ? 0 : -1; 3862306a36Sopenharmony_ci} 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_cistruct thread *thread__new(pid_t pid, pid_t tid) 4162306a36Sopenharmony_ci{ 4262306a36Sopenharmony_ci char *comm_str; 4362306a36Sopenharmony_ci struct comm *comm; 4462306a36Sopenharmony_ci RC_STRUCT(thread) *_thread = zalloc(sizeof(*_thread)); 4562306a36Sopenharmony_ci struct thread *thread; 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci if (ADD_RC_CHK(thread, _thread) != NULL) { 4862306a36Sopenharmony_ci thread__set_pid(thread, pid); 4962306a36Sopenharmony_ci thread__set_tid(thread, tid); 5062306a36Sopenharmony_ci thread__set_ppid(thread, -1); 5162306a36Sopenharmony_ci thread__set_cpu(thread, -1); 5262306a36Sopenharmony_ci thread__set_guest_cpu(thread, -1); 5362306a36Sopenharmony_ci thread__set_lbr_stitch_enable(thread, false); 5462306a36Sopenharmony_ci INIT_LIST_HEAD(thread__namespaces_list(thread)); 5562306a36Sopenharmony_ci INIT_LIST_HEAD(thread__comm_list(thread)); 5662306a36Sopenharmony_ci init_rwsem(thread__namespaces_lock(thread)); 5762306a36Sopenharmony_ci init_rwsem(thread__comm_lock(thread)); 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci comm_str = malloc(32); 6062306a36Sopenharmony_ci if (!comm_str) 6162306a36Sopenharmony_ci goto err_thread; 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci snprintf(comm_str, 32, ":%d", tid); 6462306a36Sopenharmony_ci comm = comm__new(comm_str, 0, false); 6562306a36Sopenharmony_ci free(comm_str); 6662306a36Sopenharmony_ci if (!comm) 6762306a36Sopenharmony_ci goto err_thread; 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci list_add(&comm->list, thread__comm_list(thread)); 7062306a36Sopenharmony_ci refcount_set(thread__refcnt(thread), 1); 7162306a36Sopenharmony_ci /* Thread holds first ref to nsdata. */ 7262306a36Sopenharmony_ci RC_CHK_ACCESS(thread)->nsinfo = nsinfo__new(pid); 7362306a36Sopenharmony_ci srccode_state_init(thread__srccode_state(thread)); 7462306a36Sopenharmony_ci } 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci return thread; 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_cierr_thread: 7962306a36Sopenharmony_ci free(thread); 8062306a36Sopenharmony_ci return NULL; 8162306a36Sopenharmony_ci} 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_cistatic void (*thread__priv_destructor)(void *priv); 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_civoid thread__set_priv_destructor(void (*destructor)(void *priv)) 8662306a36Sopenharmony_ci{ 8762306a36Sopenharmony_ci assert(thread__priv_destructor == NULL); 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci thread__priv_destructor = destructor; 9062306a36Sopenharmony_ci} 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_civoid thread__delete(struct thread *thread) 9362306a36Sopenharmony_ci{ 9462306a36Sopenharmony_ci struct namespaces *namespaces, *tmp_namespaces; 9562306a36Sopenharmony_ci struct comm *comm, *tmp_comm; 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci thread_stack__free(thread); 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci if (thread__maps(thread)) { 10062306a36Sopenharmony_ci maps__put(thread__maps(thread)); 10162306a36Sopenharmony_ci thread__set_maps(thread, NULL); 10262306a36Sopenharmony_ci } 10362306a36Sopenharmony_ci down_write(thread__namespaces_lock(thread)); 10462306a36Sopenharmony_ci list_for_each_entry_safe(namespaces, tmp_namespaces, 10562306a36Sopenharmony_ci thread__namespaces_list(thread), list) { 10662306a36Sopenharmony_ci list_del_init(&namespaces->list); 10762306a36Sopenharmony_ci namespaces__free(namespaces); 10862306a36Sopenharmony_ci } 10962306a36Sopenharmony_ci up_write(thread__namespaces_lock(thread)); 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci down_write(thread__comm_lock(thread)); 11262306a36Sopenharmony_ci list_for_each_entry_safe(comm, tmp_comm, thread__comm_list(thread), list) { 11362306a36Sopenharmony_ci list_del_init(&comm->list); 11462306a36Sopenharmony_ci comm__free(comm); 11562306a36Sopenharmony_ci } 11662306a36Sopenharmony_ci up_write(thread__comm_lock(thread)); 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci nsinfo__zput(RC_CHK_ACCESS(thread)->nsinfo); 11962306a36Sopenharmony_ci srccode_state_free(thread__srccode_state(thread)); 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci exit_rwsem(thread__namespaces_lock(thread)); 12262306a36Sopenharmony_ci exit_rwsem(thread__comm_lock(thread)); 12362306a36Sopenharmony_ci thread__free_stitch_list(thread); 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci if (thread__priv_destructor) 12662306a36Sopenharmony_ci thread__priv_destructor(thread__priv(thread)); 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci RC_CHK_FREE(thread); 12962306a36Sopenharmony_ci} 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_cistruct thread *thread__get(struct thread *thread) 13262306a36Sopenharmony_ci{ 13362306a36Sopenharmony_ci struct thread *result; 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci if (RC_CHK_GET(result, thread)) 13662306a36Sopenharmony_ci refcount_inc(thread__refcnt(thread)); 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci return result; 13962306a36Sopenharmony_ci} 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_civoid thread__put(struct thread *thread) 14262306a36Sopenharmony_ci{ 14362306a36Sopenharmony_ci if (thread && refcount_dec_and_test(thread__refcnt(thread))) 14462306a36Sopenharmony_ci thread__delete(thread); 14562306a36Sopenharmony_ci else 14662306a36Sopenharmony_ci RC_CHK_PUT(thread); 14762306a36Sopenharmony_ci} 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_cistatic struct namespaces *__thread__namespaces(struct thread *thread) 15062306a36Sopenharmony_ci{ 15162306a36Sopenharmony_ci if (list_empty(thread__namespaces_list(thread))) 15262306a36Sopenharmony_ci return NULL; 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ci return list_first_entry(thread__namespaces_list(thread), struct namespaces, list); 15562306a36Sopenharmony_ci} 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_cistruct namespaces *thread__namespaces(struct thread *thread) 15862306a36Sopenharmony_ci{ 15962306a36Sopenharmony_ci struct namespaces *ns; 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci down_read(thread__namespaces_lock(thread)); 16262306a36Sopenharmony_ci ns = __thread__namespaces(thread); 16362306a36Sopenharmony_ci up_read(thread__namespaces_lock(thread)); 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci return ns; 16662306a36Sopenharmony_ci} 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_cistatic int __thread__set_namespaces(struct thread *thread, u64 timestamp, 16962306a36Sopenharmony_ci struct perf_record_namespaces *event) 17062306a36Sopenharmony_ci{ 17162306a36Sopenharmony_ci struct namespaces *new, *curr = __thread__namespaces(thread); 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ci new = namespaces__new(event); 17462306a36Sopenharmony_ci if (!new) 17562306a36Sopenharmony_ci return -ENOMEM; 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ci list_add(&new->list, thread__namespaces_list(thread)); 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci if (timestamp && curr) { 18062306a36Sopenharmony_ci /* 18162306a36Sopenharmony_ci * setns syscall must have changed few or all the namespaces 18262306a36Sopenharmony_ci * of this thread. Update end time for the namespaces 18362306a36Sopenharmony_ci * previously used. 18462306a36Sopenharmony_ci */ 18562306a36Sopenharmony_ci curr = list_next_entry(new, list); 18662306a36Sopenharmony_ci curr->end_time = timestamp; 18762306a36Sopenharmony_ci } 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci return 0; 19062306a36Sopenharmony_ci} 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_ciint thread__set_namespaces(struct thread *thread, u64 timestamp, 19362306a36Sopenharmony_ci struct perf_record_namespaces *event) 19462306a36Sopenharmony_ci{ 19562306a36Sopenharmony_ci int ret; 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci down_write(thread__namespaces_lock(thread)); 19862306a36Sopenharmony_ci ret = __thread__set_namespaces(thread, timestamp, event); 19962306a36Sopenharmony_ci up_write(thread__namespaces_lock(thread)); 20062306a36Sopenharmony_ci return ret; 20162306a36Sopenharmony_ci} 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_cistruct comm *thread__comm(struct thread *thread) 20462306a36Sopenharmony_ci{ 20562306a36Sopenharmony_ci if (list_empty(thread__comm_list(thread))) 20662306a36Sopenharmony_ci return NULL; 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_ci return list_first_entry(thread__comm_list(thread), struct comm, list); 20962306a36Sopenharmony_ci} 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_cistruct comm *thread__exec_comm(struct thread *thread) 21262306a36Sopenharmony_ci{ 21362306a36Sopenharmony_ci struct comm *comm, *last = NULL, *second_last = NULL; 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ci list_for_each_entry(comm, thread__comm_list(thread), list) { 21662306a36Sopenharmony_ci if (comm->exec) 21762306a36Sopenharmony_ci return comm; 21862306a36Sopenharmony_ci second_last = last; 21962306a36Sopenharmony_ci last = comm; 22062306a36Sopenharmony_ci } 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci /* 22362306a36Sopenharmony_ci * 'last' with no start time might be the parent's comm of a synthesized 22462306a36Sopenharmony_ci * thread (created by processing a synthesized fork event). For a main 22562306a36Sopenharmony_ci * thread, that is very probably wrong. Prefer a later comm to avoid 22662306a36Sopenharmony_ci * that case. 22762306a36Sopenharmony_ci */ 22862306a36Sopenharmony_ci if (second_last && !last->start && thread__pid(thread) == thread__tid(thread)) 22962306a36Sopenharmony_ci return second_last; 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ci return last; 23262306a36Sopenharmony_ci} 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_cistatic int ____thread__set_comm(struct thread *thread, const char *str, 23562306a36Sopenharmony_ci u64 timestamp, bool exec) 23662306a36Sopenharmony_ci{ 23762306a36Sopenharmony_ci struct comm *new, *curr = thread__comm(thread); 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci /* Override the default :tid entry */ 24062306a36Sopenharmony_ci if (!thread__comm_set(thread)) { 24162306a36Sopenharmony_ci int err = comm__override(curr, str, timestamp, exec); 24262306a36Sopenharmony_ci if (err) 24362306a36Sopenharmony_ci return err; 24462306a36Sopenharmony_ci } else { 24562306a36Sopenharmony_ci new = comm__new(str, timestamp, exec); 24662306a36Sopenharmony_ci if (!new) 24762306a36Sopenharmony_ci return -ENOMEM; 24862306a36Sopenharmony_ci list_add(&new->list, thread__comm_list(thread)); 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ci if (exec) 25162306a36Sopenharmony_ci unwind__flush_access(thread__maps(thread)); 25262306a36Sopenharmony_ci } 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci thread__set_comm_set(thread, true); 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci return 0; 25762306a36Sopenharmony_ci} 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_ciint __thread__set_comm(struct thread *thread, const char *str, u64 timestamp, 26062306a36Sopenharmony_ci bool exec) 26162306a36Sopenharmony_ci{ 26262306a36Sopenharmony_ci int ret; 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_ci down_write(thread__comm_lock(thread)); 26562306a36Sopenharmony_ci ret = ____thread__set_comm(thread, str, timestamp, exec); 26662306a36Sopenharmony_ci up_write(thread__comm_lock(thread)); 26762306a36Sopenharmony_ci return ret; 26862306a36Sopenharmony_ci} 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_ciint thread__set_comm_from_proc(struct thread *thread) 27162306a36Sopenharmony_ci{ 27262306a36Sopenharmony_ci char path[64]; 27362306a36Sopenharmony_ci char *comm = NULL; 27462306a36Sopenharmony_ci size_t sz; 27562306a36Sopenharmony_ci int err = -1; 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_ci if (!(snprintf(path, sizeof(path), "%d/task/%d/comm", 27862306a36Sopenharmony_ci thread__pid(thread), thread__tid(thread)) >= (int)sizeof(path)) && 27962306a36Sopenharmony_ci procfs__read_str(path, &comm, &sz) == 0) { 28062306a36Sopenharmony_ci comm[sz - 1] = '\0'; 28162306a36Sopenharmony_ci err = thread__set_comm(thread, comm, 0); 28262306a36Sopenharmony_ci } 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_ci return err; 28562306a36Sopenharmony_ci} 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_cistatic const char *__thread__comm_str(struct thread *thread) 28862306a36Sopenharmony_ci{ 28962306a36Sopenharmony_ci const struct comm *comm = thread__comm(thread); 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_ci if (!comm) 29262306a36Sopenharmony_ci return NULL; 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_ci return comm__str(comm); 29562306a36Sopenharmony_ci} 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_ciconst char *thread__comm_str(struct thread *thread) 29862306a36Sopenharmony_ci{ 29962306a36Sopenharmony_ci const char *str; 30062306a36Sopenharmony_ci 30162306a36Sopenharmony_ci down_read(thread__comm_lock(thread)); 30262306a36Sopenharmony_ci str = __thread__comm_str(thread); 30362306a36Sopenharmony_ci up_read(thread__comm_lock(thread)); 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ci return str; 30662306a36Sopenharmony_ci} 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_cistatic int __thread__comm_len(struct thread *thread, const char *comm) 30962306a36Sopenharmony_ci{ 31062306a36Sopenharmony_ci if (!comm) 31162306a36Sopenharmony_ci return 0; 31262306a36Sopenharmony_ci thread__set_comm_len(thread, strlen(comm)); 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_ci return thread__var_comm_len(thread); 31562306a36Sopenharmony_ci} 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_ci/* CHECKME: it should probably better return the max comm len from its comm list */ 31862306a36Sopenharmony_ciint thread__comm_len(struct thread *thread) 31962306a36Sopenharmony_ci{ 32062306a36Sopenharmony_ci int comm_len = thread__var_comm_len(thread); 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_ci if (!comm_len) { 32362306a36Sopenharmony_ci const char *comm; 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ci down_read(thread__comm_lock(thread)); 32662306a36Sopenharmony_ci comm = __thread__comm_str(thread); 32762306a36Sopenharmony_ci comm_len = __thread__comm_len(thread, comm); 32862306a36Sopenharmony_ci up_read(thread__comm_lock(thread)); 32962306a36Sopenharmony_ci } 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_ci return comm_len; 33262306a36Sopenharmony_ci} 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_cisize_t thread__fprintf(struct thread *thread, FILE *fp) 33562306a36Sopenharmony_ci{ 33662306a36Sopenharmony_ci return fprintf(fp, "Thread %d %s\n", thread__tid(thread), thread__comm_str(thread)) + 33762306a36Sopenharmony_ci maps__fprintf(thread__maps(thread), fp); 33862306a36Sopenharmony_ci} 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_ciint thread__insert_map(struct thread *thread, struct map *map) 34162306a36Sopenharmony_ci{ 34262306a36Sopenharmony_ci int ret; 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci ret = unwind__prepare_access(thread__maps(thread), map, NULL); 34562306a36Sopenharmony_ci if (ret) 34662306a36Sopenharmony_ci return ret; 34762306a36Sopenharmony_ci 34862306a36Sopenharmony_ci maps__fixup_overlappings(thread__maps(thread), map, stderr); 34962306a36Sopenharmony_ci return maps__insert(thread__maps(thread), map); 35062306a36Sopenharmony_ci} 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_cistatic int __thread__prepare_access(struct thread *thread) 35362306a36Sopenharmony_ci{ 35462306a36Sopenharmony_ci bool initialized = false; 35562306a36Sopenharmony_ci int err = 0; 35662306a36Sopenharmony_ci struct maps *maps = thread__maps(thread); 35762306a36Sopenharmony_ci struct map_rb_node *rb_node; 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_ci down_read(maps__lock(maps)); 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_ci maps__for_each_entry(maps, rb_node) { 36262306a36Sopenharmony_ci err = unwind__prepare_access(thread__maps(thread), rb_node->map, &initialized); 36362306a36Sopenharmony_ci if (err || initialized) 36462306a36Sopenharmony_ci break; 36562306a36Sopenharmony_ci } 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_ci up_read(maps__lock(maps)); 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_ci return err; 37062306a36Sopenharmony_ci} 37162306a36Sopenharmony_ci 37262306a36Sopenharmony_cistatic int thread__prepare_access(struct thread *thread) 37362306a36Sopenharmony_ci{ 37462306a36Sopenharmony_ci int err = 0; 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_ci if (dwarf_callchain_users) 37762306a36Sopenharmony_ci err = __thread__prepare_access(thread); 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_ci return err; 38062306a36Sopenharmony_ci} 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_cistatic int thread__clone_maps(struct thread *thread, struct thread *parent, bool do_maps_clone) 38362306a36Sopenharmony_ci{ 38462306a36Sopenharmony_ci /* This is new thread, we share map groups for process. */ 38562306a36Sopenharmony_ci if (thread__pid(thread) == thread__pid(parent)) 38662306a36Sopenharmony_ci return thread__prepare_access(thread); 38762306a36Sopenharmony_ci 38862306a36Sopenharmony_ci if (thread__maps(thread) == thread__maps(parent)) { 38962306a36Sopenharmony_ci pr_debug("broken map groups on thread %d/%d parent %d/%d\n", 39062306a36Sopenharmony_ci thread__pid(thread), thread__tid(thread), 39162306a36Sopenharmony_ci thread__pid(parent), thread__tid(parent)); 39262306a36Sopenharmony_ci return 0; 39362306a36Sopenharmony_ci } 39462306a36Sopenharmony_ci /* But this one is new process, copy maps. */ 39562306a36Sopenharmony_ci return do_maps_clone ? maps__clone(thread, thread__maps(parent)) : 0; 39662306a36Sopenharmony_ci} 39762306a36Sopenharmony_ci 39862306a36Sopenharmony_ciint thread__fork(struct thread *thread, struct thread *parent, u64 timestamp, bool do_maps_clone) 39962306a36Sopenharmony_ci{ 40062306a36Sopenharmony_ci if (thread__comm_set(parent)) { 40162306a36Sopenharmony_ci const char *comm = thread__comm_str(parent); 40262306a36Sopenharmony_ci int err; 40362306a36Sopenharmony_ci if (!comm) 40462306a36Sopenharmony_ci return -ENOMEM; 40562306a36Sopenharmony_ci err = thread__set_comm(thread, comm, timestamp); 40662306a36Sopenharmony_ci if (err) 40762306a36Sopenharmony_ci return err; 40862306a36Sopenharmony_ci } 40962306a36Sopenharmony_ci 41062306a36Sopenharmony_ci thread__set_ppid(thread, thread__tid(parent)); 41162306a36Sopenharmony_ci return thread__clone_maps(thread, parent, do_maps_clone); 41262306a36Sopenharmony_ci} 41362306a36Sopenharmony_ci 41462306a36Sopenharmony_civoid thread__find_cpumode_addr_location(struct thread *thread, u64 addr, 41562306a36Sopenharmony_ci struct addr_location *al) 41662306a36Sopenharmony_ci{ 41762306a36Sopenharmony_ci size_t i; 41862306a36Sopenharmony_ci const u8 cpumodes[] = { 41962306a36Sopenharmony_ci PERF_RECORD_MISC_USER, 42062306a36Sopenharmony_ci PERF_RECORD_MISC_KERNEL, 42162306a36Sopenharmony_ci PERF_RECORD_MISC_GUEST_USER, 42262306a36Sopenharmony_ci PERF_RECORD_MISC_GUEST_KERNEL 42362306a36Sopenharmony_ci }; 42462306a36Sopenharmony_ci 42562306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(cpumodes); i++) { 42662306a36Sopenharmony_ci thread__find_symbol(thread, cpumodes[i], addr, al); 42762306a36Sopenharmony_ci if (al->map) 42862306a36Sopenharmony_ci break; 42962306a36Sopenharmony_ci } 43062306a36Sopenharmony_ci} 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_cistruct thread *thread__main_thread(struct machine *machine, struct thread *thread) 43362306a36Sopenharmony_ci{ 43462306a36Sopenharmony_ci if (thread__pid(thread) == thread__tid(thread)) 43562306a36Sopenharmony_ci return thread__get(thread); 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_ci if (thread__pid(thread) == -1) 43862306a36Sopenharmony_ci return NULL; 43962306a36Sopenharmony_ci 44062306a36Sopenharmony_ci return machine__find_thread(machine, thread__pid(thread), thread__pid(thread)); 44162306a36Sopenharmony_ci} 44262306a36Sopenharmony_ci 44362306a36Sopenharmony_ciint thread__memcpy(struct thread *thread, struct machine *machine, 44462306a36Sopenharmony_ci void *buf, u64 ip, int len, bool *is64bit) 44562306a36Sopenharmony_ci{ 44662306a36Sopenharmony_ci u8 cpumode = PERF_RECORD_MISC_USER; 44762306a36Sopenharmony_ci struct addr_location al; 44862306a36Sopenharmony_ci struct dso *dso; 44962306a36Sopenharmony_ci long offset; 45062306a36Sopenharmony_ci 45162306a36Sopenharmony_ci if (machine__kernel_ip(machine, ip)) 45262306a36Sopenharmony_ci cpumode = PERF_RECORD_MISC_KERNEL; 45362306a36Sopenharmony_ci 45462306a36Sopenharmony_ci addr_location__init(&al); 45562306a36Sopenharmony_ci if (!thread__find_map(thread, cpumode, ip, &al)) { 45662306a36Sopenharmony_ci addr_location__exit(&al); 45762306a36Sopenharmony_ci return -1; 45862306a36Sopenharmony_ci } 45962306a36Sopenharmony_ci 46062306a36Sopenharmony_ci dso = map__dso(al.map); 46162306a36Sopenharmony_ci 46262306a36Sopenharmony_ci if (!dso || dso->data.status == DSO_DATA_STATUS_ERROR || map__load(al.map) < 0) { 46362306a36Sopenharmony_ci addr_location__exit(&al); 46462306a36Sopenharmony_ci return -1; 46562306a36Sopenharmony_ci } 46662306a36Sopenharmony_ci 46762306a36Sopenharmony_ci offset = map__map_ip(al.map, ip); 46862306a36Sopenharmony_ci if (is64bit) 46962306a36Sopenharmony_ci *is64bit = dso->is_64_bit; 47062306a36Sopenharmony_ci 47162306a36Sopenharmony_ci addr_location__exit(&al); 47262306a36Sopenharmony_ci 47362306a36Sopenharmony_ci return dso__data_read_offset(dso, machine, offset, buf, len); 47462306a36Sopenharmony_ci} 47562306a36Sopenharmony_ci 47662306a36Sopenharmony_civoid thread__free_stitch_list(struct thread *thread) 47762306a36Sopenharmony_ci{ 47862306a36Sopenharmony_ci struct lbr_stitch *lbr_stitch = thread__lbr_stitch(thread); 47962306a36Sopenharmony_ci struct stitch_list *pos, *tmp; 48062306a36Sopenharmony_ci 48162306a36Sopenharmony_ci if (!lbr_stitch) 48262306a36Sopenharmony_ci return; 48362306a36Sopenharmony_ci 48462306a36Sopenharmony_ci list_for_each_entry_safe(pos, tmp, &lbr_stitch->lists, node) { 48562306a36Sopenharmony_ci list_del_init(&pos->node); 48662306a36Sopenharmony_ci free(pos); 48762306a36Sopenharmony_ci } 48862306a36Sopenharmony_ci 48962306a36Sopenharmony_ci list_for_each_entry_safe(pos, tmp, &lbr_stitch->free_lists, node) { 49062306a36Sopenharmony_ci list_del_init(&pos->node); 49162306a36Sopenharmony_ci free(pos); 49262306a36Sopenharmony_ci } 49362306a36Sopenharmony_ci 49462306a36Sopenharmony_ci zfree(&lbr_stitch->prev_lbr_cursor); 49562306a36Sopenharmony_ci free(thread__lbr_stitch(thread)); 49662306a36Sopenharmony_ci thread__set_lbr_stitch(thread, NULL); 49762306a36Sopenharmony_ci} 498