qsp.c (48008198270e3ebcc9394401d676c54ed5ac139c) | qsp.c (d73415a315471ac0b127ed3fad45c8ec5d711de1) |
---|---|
1/* 2 * qsp.c - QEMU Synchronization Profiler 3 * 4 * Copyright (C) 2018, Emilio G. Cota <cota@braap.org> 5 * 6 * License: GNU GPL, version 2 or later. 7 * See the COPYING file in the top-level directory. 8 * --- 231 unchanged lines hidden (view full) --- 240 qht_init(&qsp_ht, qsp_entry_cmp, QSP_INITIAL_SIZE, 241 QHT_MODE_AUTO_RESIZE | QHT_MODE_RAW_MUTEXES); 242 qht_init(&qsp_callsite_ht, qsp_callsite_cmp, QSP_INITIAL_SIZE, 243 QHT_MODE_AUTO_RESIZE | QHT_MODE_RAW_MUTEXES); 244} 245 246static __attribute__((noinline)) void qsp_init__slowpath(void) 247{ | 1/* 2 * qsp.c - QEMU Synchronization Profiler 3 * 4 * Copyright (C) 2018, Emilio G. Cota <cota@braap.org> 5 * 6 * License: GNU GPL, version 2 or later. 7 * See the COPYING file in the top-level directory. 8 * --- 231 unchanged lines hidden (view full) --- 240 qht_init(&qsp_ht, qsp_entry_cmp, QSP_INITIAL_SIZE, 241 QHT_MODE_AUTO_RESIZE | QHT_MODE_RAW_MUTEXES); 242 qht_init(&qsp_callsite_ht, qsp_callsite_cmp, QSP_INITIAL_SIZE, 243 QHT_MODE_AUTO_RESIZE | QHT_MODE_RAW_MUTEXES); 244} 245 246static __attribute__((noinline)) void qsp_init__slowpath(void) 247{ |
248 if (atomic_cmpxchg(&qsp_initializing, false, true) == false) { | 248 if (qatomic_cmpxchg(&qsp_initializing, false, true) == false) { |
249 qsp_do_init(); | 249 qsp_do_init(); |
250 atomic_set(&qsp_initialized, true); | 250 qatomic_set(&qsp_initialized, true); |
251 } else { | 251 } else { |
252 while (!atomic_read(&qsp_initialized)) { | 252 while (!qatomic_read(&qsp_initialized)) { |
253 cpu_relax(); 254 } 255 } 256} 257 258/* qsp_init() must be called from _all_ exported functions */ 259static inline void qsp_init(void) 260{ | 253 cpu_relax(); 254 } 255 } 256} 257 258/* qsp_init() must be called from _all_ exported functions */ 259static inline void qsp_init(void) 260{ |
261 if (likely(atomic_read(&qsp_initialized))) { | 261 if (likely(qatomic_read(&qsp_initialized))) { |
262 return; 263 } 264 qsp_init__slowpath(); 265} 266 267static QSPCallSite *qsp_callsite_find(const QSPCallSite *orig) 268{ 269 QSPCallSite *callsite; --- 71 unchanged lines hidden (view full) --- 341} 342 343/* 344 * @e is in the global hash table; it is only written to by the current thread, 345 * so we write to it atomically (as in "write once") to prevent torn reads. 346 */ 347static inline void do_qsp_entry_record(QSPEntry *e, int64_t delta, bool acq) 348{ | 262 return; 263 } 264 qsp_init__slowpath(); 265} 266 267static QSPCallSite *qsp_callsite_find(const QSPCallSite *orig) 268{ 269 QSPCallSite *callsite; --- 71 unchanged lines hidden (view full) --- 341} 342 343/* 344 * @e is in the global hash table; it is only written to by the current thread, 345 * so we write to it atomically (as in "write once") to prevent torn reads. 346 */ 347static inline void do_qsp_entry_record(QSPEntry *e, int64_t delta, bool acq) 348{ |
349 atomic_set_u64(&e->ns, e->ns + delta); | 349 qatomic_set_u64(&e->ns, e->ns + delta); |
350 if (acq) { | 350 if (acq) { |
351 atomic_set_u64(&e->n_acqs, e->n_acqs + 1); | 351 qatomic_set_u64(&e->n_acqs, e->n_acqs + 1); |
352 } 353} 354 355static inline void qsp_entry_record(QSPEntry *e, int64_t delta) 356{ 357 do_qsp_entry_record(e, delta, true); 358} 359 --- 67 unchanged lines hidden (view full) --- 427 428 e = qsp_entry_get(cond, file, line, QSP_CONDVAR); 429 qsp_entry_record(e, t1 - t0); 430 return ret; 431} 432 433bool qsp_is_enabled(void) 434{ | 352 } 353} 354 355static inline void qsp_entry_record(QSPEntry *e, int64_t delta) 356{ 357 do_qsp_entry_record(e, delta, true); 358} 359 --- 67 unchanged lines hidden (view full) --- 427 428 e = qsp_entry_get(cond, file, line, QSP_CONDVAR); 429 qsp_entry_record(e, t1 - t0); 430 return ret; 431} 432 433bool qsp_is_enabled(void) 434{ |
435 return atomic_read(&qemu_mutex_lock_func) == qsp_mutex_lock; | 435 return qatomic_read(&qemu_mutex_lock_func) == qsp_mutex_lock; |
436} 437 438void qsp_enable(void) 439{ | 436} 437 438void qsp_enable(void) 439{ |
440 atomic_set(&qemu_mutex_lock_func, qsp_mutex_lock); 441 atomic_set(&qemu_mutex_trylock_func, qsp_mutex_trylock); 442 atomic_set(&qemu_bql_mutex_lock_func, qsp_bql_mutex_lock); 443 atomic_set(&qemu_rec_mutex_lock_func, qsp_rec_mutex_lock); 444 atomic_set(&qemu_rec_mutex_trylock_func, qsp_rec_mutex_trylock); 445 atomic_set(&qemu_cond_wait_func, qsp_cond_wait); 446 atomic_set(&qemu_cond_timedwait_func, qsp_cond_timedwait); | 440 qatomic_set(&qemu_mutex_lock_func, qsp_mutex_lock); 441 qatomic_set(&qemu_mutex_trylock_func, qsp_mutex_trylock); 442 qatomic_set(&qemu_bql_mutex_lock_func, qsp_bql_mutex_lock); 443 qatomic_set(&qemu_rec_mutex_lock_func, qsp_rec_mutex_lock); 444 qatomic_set(&qemu_rec_mutex_trylock_func, qsp_rec_mutex_trylock); 445 qatomic_set(&qemu_cond_wait_func, qsp_cond_wait); 446 qatomic_set(&qemu_cond_timedwait_func, qsp_cond_timedwait); |
447} 448 449void qsp_disable(void) 450{ | 447} 448 449void qsp_disable(void) 450{ |
451 atomic_set(&qemu_mutex_lock_func, qemu_mutex_lock_impl); 452 atomic_set(&qemu_mutex_trylock_func, qemu_mutex_trylock_impl); 453 atomic_set(&qemu_bql_mutex_lock_func, qemu_mutex_lock_impl); 454 atomic_set(&qemu_rec_mutex_lock_func, qemu_rec_mutex_lock_impl); 455 atomic_set(&qemu_rec_mutex_trylock_func, qemu_rec_mutex_trylock_impl); 456 atomic_set(&qemu_cond_wait_func, qemu_cond_wait_impl); 457 atomic_set(&qemu_cond_timedwait_func, qemu_cond_timedwait_impl); | 451 qatomic_set(&qemu_mutex_lock_func, qemu_mutex_lock_impl); 452 qatomic_set(&qemu_mutex_trylock_func, qemu_mutex_trylock_impl); 453 qatomic_set(&qemu_bql_mutex_lock_func, qemu_mutex_lock_impl); 454 qatomic_set(&qemu_rec_mutex_lock_func, qemu_rec_mutex_lock_impl); 455 qatomic_set(&qemu_rec_mutex_trylock_func, qemu_rec_mutex_trylock_impl); 456 qatomic_set(&qemu_cond_wait_func, qemu_cond_wait_impl); 457 qatomic_set(&qemu_cond_timedwait_func, qemu_cond_timedwait_impl); |
458} 459 460static gint qsp_tree_cmp(gconstpointer ap, gconstpointer bp, gpointer up) 461{ 462 const QSPEntry *a = ap; 463 const QSPEntry *b = bp; 464 enum QSPSortBy sort_by = *(enum QSPSortBy *)up; 465 const QSPCallSite *ca; --- 67 unchanged lines hidden (view full) --- 533 uint32_t hash; 534 535 hash = qsp_entry_no_thread_hash(e); 536 agg = qsp_entry_find(ht, e, hash); 537 /* 538 * The entry is in the global hash table; read from it atomically (as in 539 * "read once"). 540 */ | 458} 459 460static gint qsp_tree_cmp(gconstpointer ap, gconstpointer bp, gpointer up) 461{ 462 const QSPEntry *a = ap; 463 const QSPEntry *b = bp; 464 enum QSPSortBy sort_by = *(enum QSPSortBy *)up; 465 const QSPCallSite *ca; --- 67 unchanged lines hidden (view full) --- 533 uint32_t hash; 534 535 hash = qsp_entry_no_thread_hash(e); 536 agg = qsp_entry_find(ht, e, hash); 537 /* 538 * The entry is in the global hash table; read from it atomically (as in 539 * "read once"). 540 */ |
541 agg->ns += atomic_read_u64(&e->ns); 542 agg->n_acqs += atomic_read_u64(&e->n_acqs); | 541 agg->ns += qatomic_read_u64(&e->ns); 542 agg->n_acqs += qatomic_read_u64(&e->n_acqs); |
543} 544 545static void qsp_iter_diff(void *p, uint32_t hash, void *htp) 546{ 547 struct qht *ht = htp; 548 QSPEntry *old = p; 549 QSPEntry *new; 550 --- 54 unchanged lines hidden (view full) --- 605 * First, see if there's a prior snapshot, so that we read the global hash 606 * table _after_ the snapshot has been created, which guarantees that 607 * the entries we'll read will be a superset of the snapshot's entries. 608 * 609 * We must remain in an RCU read-side critical section until we're done 610 * with the snapshot. 611 */ 612 WITH_RCU_READ_LOCK_GUARD() { | 543} 544 545static void qsp_iter_diff(void *p, uint32_t hash, void *htp) 546{ 547 struct qht *ht = htp; 548 QSPEntry *old = p; 549 QSPEntry *new; 550 --- 54 unchanged lines hidden (view full) --- 605 * First, see if there's a prior snapshot, so that we read the global hash 606 * table _after_ the snapshot has been created, which guarantees that 607 * the entries we'll read will be a superset of the snapshot's entries. 608 * 609 * We must remain in an RCU read-side critical section until we're done 610 * with the snapshot. 611 */ 612 WITH_RCU_READ_LOCK_GUARD() { |
613 QSPSnapshot *snap = atomic_rcu_read(&qsp_snapshot); | 613 QSPSnapshot *snap = qatomic_rcu_read(&qsp_snapshot); |
614 615 /* Aggregate all results from the global hash table into a local one */ 616 qht_init(&ht, qsp_entry_no_thread_cmp, QSP_INITIAL_SIZE, 617 QHT_MODE_AUTO_RESIZE | QHT_MODE_RAW_MUTEXES); 618 qht_iter(&qsp_ht, qsp_aggregate, &ht); 619 620 /* compute the difference wrt the snapshot, if any */ 621 if (snap) { --- 179 unchanged lines hidden (view full) --- 801 802 qht_init(&new->ht, qsp_entry_cmp, QSP_INITIAL_SIZE, 803 QHT_MODE_AUTO_RESIZE | QHT_MODE_RAW_MUTEXES); 804 805 /* take a snapshot of the current state */ 806 qht_iter(&qsp_ht, qsp_aggregate, &new->ht); 807 808 /* replace the previous snapshot, if any */ | 614 615 /* Aggregate all results from the global hash table into a local one */ 616 qht_init(&ht, qsp_entry_no_thread_cmp, QSP_INITIAL_SIZE, 617 QHT_MODE_AUTO_RESIZE | QHT_MODE_RAW_MUTEXES); 618 qht_iter(&qsp_ht, qsp_aggregate, &ht); 619 620 /* compute the difference wrt the snapshot, if any */ 621 if (snap) { --- 179 unchanged lines hidden (view full) --- 801 802 qht_init(&new->ht, qsp_entry_cmp, QSP_INITIAL_SIZE, 803 QHT_MODE_AUTO_RESIZE | QHT_MODE_RAW_MUTEXES); 804 805 /* take a snapshot of the current state */ 806 qht_iter(&qsp_ht, qsp_aggregate, &new->ht); 807 808 /* replace the previous snapshot, if any */ |
809 old = atomic_xchg(&qsp_snapshot, new); | 809 old = qatomic_xchg(&qsp_snapshot, new); |
810 if (old) { 811 call_rcu(old, qsp_snapshot_destroy, rcu); 812 } 813} | 810 if (old) { 811 call_rcu(old, qsp_snapshot_destroy, rcu); 812 } 813} |