struct btp_distances * btp_threads_compare(struct btp_thread **threads, int m, int n, btp_dist_thread_type dist_func) { struct btp_distances *distances; struct btp_thread *thread1, *thread2; int i, j, ok, all; distances = btp_distances_new(m, n); for (i = 0; i < m; i++) for (j = i + 1; j < n; j++) { ok = all = 0; btp_thread_quality_counts(threads[i], &ok, &all); btp_thread_quality_counts(threads[j], &ok, &all); if (ok == all) { thread1 = threads[i]; thread2 = threads[j]; } else { /* There are some unknown function names, try to pair them, but * the threads need to be copied first. */ thread1 = btp_thread_dup(threads[i], false); thread2 = btp_thread_dup(threads[j], false); btp_normalize_paired_unknown_function_names(thread1, thread2); } distances->distances[get_distance_position(distances, i, j)] = dist_func(thread1, thread2); if (ok != all) { btp_thread_free(thread1); btp_thread_free(thread2); } } return distances; }
struct btp_backtrace * btp_backtrace_dup(struct btp_backtrace *backtrace) { struct btp_backtrace *result = btp_backtrace_new(); memcpy(result, backtrace, sizeof(struct btp_backtrace)); if (backtrace->crash) result->crash = btp_frame_dup(backtrace->crash, false); if (backtrace->threads) result->threads = btp_thread_dup(backtrace->threads, true); if (backtrace->libs) result->libs = btp_sharedlib_dup(backtrace->libs, true); return result; }
/* methods */ PyObject *p_btp_thread_dup(PyObject *self, PyObject *args) { ThreadObject *this = (ThreadObject *)self; if (thread_prepare_linked_list(this) < 0) return NULL; ThreadObject *to = (ThreadObject *)PyObject_New(ThreadObject, &ThreadTypeObject); if (!to) return PyErr_NoMemory(); to->thread = btp_thread_dup(this->thread, false); if (!to->thread) return NULL; to->frames = frame_linked_list_to_python_list(to->thread); return (PyObject *)to; }
struct btp_thread * btp_thread_dup(struct btp_thread *thread, bool siblings) { struct btp_thread *result = btp_thread_new(); memcpy(result, thread, sizeof(struct btp_thread)); /* Handle siblings. */ if (siblings) { if (result->next) result->next = btp_thread_dup(result->next, true); } else result->next = NULL; /* Do not copy that. */ result->frames = btp_frame_dup(result->frames, true); return result; }
struct btp_thread * btp_backtrace_get_optimized_thread(struct btp_backtrace *backtrace, int max_frames) { struct btp_thread *crash_thread; backtrace = btp_backtrace_dup(backtrace); crash_thread = btp_backtrace_find_crash_thread(backtrace); if (!crash_thread) { btp_backtrace_free(backtrace); return NULL; } btp_backtrace_remove_threads_except_one(backtrace, crash_thread); btp_backtrace_set_libnames(backtrace); btp_normalize_thread(crash_thread); btp_normalize_optimize_thread(crash_thread); /* Remove frames with no function name (i.e. signal handlers). */ struct btp_frame *frame = crash_thread->frames, *frame_next; while (frame) { frame_next = frame->next; if (!frame->function_name) btp_thread_remove_frame(crash_thread, frame); frame = frame_next; } if (max_frames > 0) btp_thread_remove_frames_below_n(crash_thread, max_frames); crash_thread = btp_thread_dup(crash_thread, false); btp_backtrace_free(backtrace); return crash_thread; }