1/* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE --- 6 unchanged lines hidden (view full) --- 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 * 21 * Portions Copyright 2010 The FreeBSD Foundation 22 * |
23 * $FreeBSD: head/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c 264434 2014-04-14 00:22:42Z markj $ |
24 */ 25 26/* 27 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 28 * Use is subject to license terms. 29 */ 30 31#if defined(sun) --- 24 unchanged lines hidden (view full) --- 56#include <sys/proc.h> 57#include <sys/policy.h> 58#if defined(sun) 59#include <util/qsort.h> 60#endif 61#include <sys/mutex.h> 62#include <sys/kernel.h> 63#if !defined(sun) |
64#include <sys/dtrace_bsd.h> |
65#include <sys/eventhandler.h> 66#include <sys/user.h> 67#include <vm/vm.h> 68#include <vm/pmap.h> 69#include <vm/vm_map.h> 70#include <vm/vm_param.h> |
71#include <cddl/dev/dtrace/dtrace_cddl.h> 72#endif 73 74/* 75 * User-Land Trap-Based Tracing 76 * ---------------------------- 77 * 78 * The fasttrap provider allows DTrace consumers to instrument any user-level --- 127 unchanged lines hidden (view full) --- 206static fasttrap_provider_t *fasttrap_provider_lookup(pid_t, const char *, 207 const dtrace_pattr_t *); 208static void fasttrap_provider_retire(pid_t, const char *, int); 209static void fasttrap_provider_free(fasttrap_provider_t *); 210 211static fasttrap_proc_t *fasttrap_proc_lookup(pid_t); 212static void fasttrap_proc_release(fasttrap_proc_t *); 213 |
214#if !defined(sun) 215static void fasttrap_thread_dtor(void *, struct thread *); 216#endif 217 |
218#define FASTTRAP_PROVS_INDEX(pid, name) \ 219 ((fasttrap_hash_str(name) + (pid)) & fasttrap_provs.fth_mask) 220 221#define FASTTRAP_PROCS_INDEX(pid) ((pid) & fasttrap_procs.fth_mask) 222 223#if !defined(sun) 224static kmutex_t fasttrap_cpuc_pid_lock[MAXCPU]; |
225static eventhandler_tag fasttrap_thread_dtor_tag; |
226#endif 227 228static int 229fasttrap_highbit(ulong_t i) 230{ 231 int h = 1; 232 233 if (i == 0) --- 60 unchanged lines hidden (view full) --- 294 ksi->ksi_code = TRAP_DTRACE; 295 ksi->ksi_addr = (caddr_t)pc; 296 PROC_LOCK(p); 297 (void) tdksignal(t, SIGTRAP, ksi); 298 PROC_UNLOCK(p); 299#endif 300} 301 |
302#if !defined(sun) |
303/* |
304 * Obtain a chunk of scratch space in the address space of the target process. 305 */ 306fasttrap_scrspace_t * 307fasttrap_scraddr(struct thread *td, fasttrap_proc_t *fprc) 308{ 309 fasttrap_scrblock_t *scrblk; 310 fasttrap_scrspace_t *scrspc; 311 struct proc *p; 312 vm_offset_t addr; 313 int error, i; 314 315 scrspc = NULL; 316 if (td->t_dtrace_sscr != NULL) { 317 /* If the thread already has scratch space, we're done. */ 318 scrspc = (fasttrap_scrspace_t *)td->t_dtrace_sscr; 319 return (scrspc); 320 } 321 322 p = td->td_proc; 323 324 mutex_enter(&fprc->ftpc_mtx); 325 if (LIST_EMPTY(&fprc->ftpc_fscr)) { 326 /* 327 * No scratch space is available, so we'll map a new scratch 328 * space block into the traced process' address space. 329 */ 330 addr = 0; 331 error = vm_map_find(&p->p_vmspace->vm_map, NULL, 0, &addr, 332 FASTTRAP_SCRBLOCK_SIZE, 0, VMFS_ANY_SPACE, VM_PROT_ALL, 333 VM_PROT_ALL, 0); 334 if (error != KERN_SUCCESS) 335 goto done; 336 337 scrblk = malloc(sizeof(*scrblk), M_SOLARIS, M_WAITOK); 338 scrblk->ftsb_addr = addr; 339 LIST_INSERT_HEAD(&fprc->ftpc_scrblks, scrblk, ftsb_next); 340 341 /* 342 * Carve the block up into chunks and put them on the free list. 343 */ 344 for (i = 0; 345 i < FASTTRAP_SCRBLOCK_SIZE / FASTTRAP_SCRSPACE_SIZE; i++) { 346 scrspc = malloc(sizeof(*scrspc), M_SOLARIS, M_WAITOK); 347 scrspc->ftss_addr = addr + 348 i * FASTTRAP_SCRSPACE_SIZE; 349 LIST_INSERT_HEAD(&fprc->ftpc_fscr, scrspc, 350 ftss_next); 351 } 352 } 353 354 /* 355 * Take the first scratch chunk off the free list, put it on the 356 * allocated list, and return its address. 357 */ 358 scrspc = LIST_FIRST(&fprc->ftpc_fscr); 359 LIST_REMOVE(scrspc, ftss_next); 360 LIST_INSERT_HEAD(&fprc->ftpc_ascr, scrspc, ftss_next); 361 362 /* 363 * This scratch space is reserved for use by td until the thread exits. 364 */ 365 td->t_dtrace_sscr = scrspc; 366 367done: 368 mutex_exit(&fprc->ftpc_mtx); 369 370 return (scrspc); 371} 372 373/* 374 * Return any allocated per-thread scratch space chunks back to the process' 375 * free list. 376 */ 377static void 378fasttrap_thread_dtor(void *arg __unused, struct thread *td) 379{ 380 fasttrap_bucket_t *bucket; 381 fasttrap_proc_t *fprc; 382 fasttrap_scrspace_t *scrspc; 383 pid_t pid; 384 385 if (td->t_dtrace_sscr == NULL) 386 return; 387 388 pid = td->td_proc->p_pid; 389 bucket = &fasttrap_procs.fth_table[FASTTRAP_PROCS_INDEX(pid)]; 390 fprc = NULL; 391 392 /* Look up the fasttrap process handle for this process. */ 393 mutex_enter(&bucket->ftb_mtx); 394 for (fprc = bucket->ftb_data; fprc != NULL; fprc = fprc->ftpc_next) { 395 if (fprc->ftpc_pid == pid) { 396 mutex_enter(&fprc->ftpc_mtx); 397 mutex_exit(&bucket->ftb_mtx); 398 break; 399 } 400 } 401 if (fprc == NULL) { 402 mutex_exit(&bucket->ftb_mtx); 403 return; 404 } 405 406 scrspc = (fasttrap_scrspace_t *)td->t_dtrace_sscr; 407 LIST_REMOVE(scrspc, ftss_next); 408 LIST_INSERT_HEAD(&fprc->ftpc_fscr, scrspc, ftss_next); 409 410 mutex_exit(&fprc->ftpc_mtx); 411} 412#endif 413 414/* |
415 * This function ensures that no threads are actively using the memory 416 * associated with probes that were formerly live. 417 */ 418static void 419fasttrap_mod_barrier(uint64_t gen) 420{ 421 int i; 422 --- 143 unchanged lines hidden (view full) --- 566 * This is called from cfork() via dtrace_fasttrap_fork(). The child 567 * process's address space is (roughly) a copy of the parent process's so 568 * we have to remove all the instrumentation we had previously enabled in the 569 * parent. 570 */ 571static void 572fasttrap_fork(proc_t *p, proc_t *cp) 573{ |
574#if !defined(sun) 575 fasttrap_scrblock_t *scrblk; 576 fasttrap_proc_t *fprc = NULL; 577#endif |
578 pid_t ppid = p->p_pid; 579 int i; 580 581#if defined(sun) 582 ASSERT(curproc == p); 583 ASSERT(p->p_proc_flag & P_PR_LOCK); 584#else 585 PROC_LOCK_ASSERT(p, MA_OWNED); --- 69 unchanged lines hidden (view full) --- 655 /* 656 * The count of active providers can only be 657 * decremented (i.e. to zero) during exec, 658 * exit, and removal of a meta provider so it 659 * should be impossible to drop the count 660 * mid-fork. 661 */ 662 ASSERT(tp->ftt_proc->ftpc_acount != 0); |
663#if !defined(sun) 664 fprc = tp->ftt_proc; 665#endif |
666 } 667 } 668 mutex_exit(&bucket->ftb_mtx); |
669 670#if !defined(sun) 671 /* 672 * Unmap any scratch space inherited from the parent's address 673 * space. 674 */ 675 if (fprc != NULL) { 676 mutex_enter(&fprc->ftpc_mtx); 677 LIST_FOREACH(scrblk, &fprc->ftpc_scrblks, ftsb_next) { 678 vm_map_remove(&cp->p_vmspace->vm_map, 679 scrblk->ftsb_addr, 680 scrblk->ftsb_addr + FASTTRAP_SCRBLOCK_SIZE); 681 } 682 mutex_exit(&fprc->ftpc_mtx); 683 } 684#endif |
685 } 686 687#if defined(sun) 688 mutex_enter(&cp->p_lock); 689 sprunlock(cp); 690#else 691 PROC_LOCK(p); 692 PROC_LOCK(cp); --- 4 unchanged lines hidden (view full) --- 697/* 698 * This is called from proc_exit() or from exec_common() if p_dtrace_probes 699 * is set on the proc structure to indicate that there is a pid provider 700 * associated with this process. 701 */ 702static void 703fasttrap_exec_exit(proc_t *p) 704{ |
705#if !defined(sun) 706 struct thread *td; 707#endif 708 |
709#if defined(sun) 710 ASSERT(p == curproc); |
711#else |
712 PROC_LOCK_ASSERT(p, MA_OWNED); 713 _PHOLD(p); |
714 /* 715 * Since struct threads may be recycled, we cannot rely on t_dtrace_sscr 716 * fields to be zeroed by kdtrace_thread_ctor. Thus we must zero it 717 * ourselves when a process exits. 718 */ 719 FOREACH_THREAD_IN_PROC(p, td) 720 td->t_dtrace_sscr = NULL; |
721 PROC_UNLOCK(p); |
722#endif |
723 724 /* 725 * We clean up the pid provider for this process here; user-land 726 * static probes are handled by the meta-provider remove entry point. 727 */ 728 fasttrap_provider_retire(p->p_pid, FASTTRAP_PID_NAME, 0); 729#if !defined(sun) 730 if (p->p_dtrace_helpers) 731 dtrace_helpers_destroy(p); |
732 PROC_LOCK(p); 733 _PRELE(p); |
734#endif |
735} 736 737 738/*ARGSUSED*/ 739static void 740fasttrap_pid_provide(void *arg, dtrace_probedesc_t *desc) 741{ 742 /* --- 776 unchanged lines hidden (view full) --- 1519} 1520 1521static void 1522fasttrap_proc_release(fasttrap_proc_t *proc) 1523{ 1524 fasttrap_bucket_t *bucket; 1525 fasttrap_proc_t *fprc, **fprcp; 1526 pid_t pid = proc->ftpc_pid; |
1527#if !defined(sun) 1528 fasttrap_scrblock_t *scrblk, *scrblktmp; 1529 fasttrap_scrspace_t *scrspc, *scrspctmp; 1530 struct proc *p; 1531 struct thread *td; 1532#endif |
1533 1534 mutex_enter(&proc->ftpc_mtx); 1535 1536 ASSERT(proc->ftpc_rcount != 0); 1537 ASSERT(proc->ftpc_acount <= proc->ftpc_rcount); 1538 1539 if (--proc->ftpc_rcount != 0) { 1540 mutex_exit(&proc->ftpc_mtx); 1541 return; 1542 } 1543 |
1544#if !defined(sun) 1545 /* 1546 * Free all structures used to manage per-thread scratch space. 1547 */ 1548 LIST_FOREACH_SAFE(scrblk, &proc->ftpc_scrblks, ftsb_next, 1549 scrblktmp) { 1550 LIST_REMOVE(scrblk, ftsb_next); 1551 free(scrblk, M_SOLARIS); 1552 } 1553 LIST_FOREACH_SAFE(scrspc, &proc->ftpc_fscr, ftss_next, scrspctmp) { 1554 LIST_REMOVE(scrspc, ftss_next); 1555 free(scrspc, M_SOLARIS); 1556 } 1557 LIST_FOREACH_SAFE(scrspc, &proc->ftpc_ascr, ftss_next, scrspctmp) { 1558 LIST_REMOVE(scrspc, ftss_next); 1559 free(scrspc, M_SOLARIS); 1560 } 1561 1562 if ((p = pfind(pid)) != NULL) { 1563 FOREACH_THREAD_IN_PROC(p, td) 1564 td->t_dtrace_sscr = NULL; 1565 PROC_UNLOCK(p); 1566 } 1567#endif 1568 |
1569 mutex_exit(&proc->ftpc_mtx); 1570 1571 /* 1572 * There should definitely be no live providers associated with this 1573 * process at this point. 1574 */ 1575 ASSERT(proc->ftpc_acount == 0); 1576 --- 969 unchanged lines hidden (view full) --- 2546 for (i = 0; i < fasttrap_procs.fth_nent; i++) 2547 mutex_init(&fasttrap_procs.fth_table[i].ftb_mtx, 2548 "processes bucket mtx", MUTEX_DEFAULT, NULL); 2549 2550 CPU_FOREACH(i) { 2551 mutex_init(&fasttrap_cpuc_pid_lock[i], "fasttrap barrier", 2552 MUTEX_DEFAULT, NULL); 2553 } |
2554 2555 /* 2556 * This event handler must run before kdtrace_thread_dtor() since it 2557 * accesses the thread's struct kdtrace_thread. 2558 */ 2559 fasttrap_thread_dtor_tag = EVENTHANDLER_REGISTER(thread_dtor, 2560 fasttrap_thread_dtor, NULL, EVENTHANDLER_PRI_FIRST); |
2561#endif 2562 2563 /* 2564 * Install our hooks into fork(2), exec(2), and exit(2). 2565 */ 2566 dtrace_fasttrap_fork = &fasttrap_fork; 2567 dtrace_fasttrap_exit = &fasttrap_exec_exit; 2568 dtrace_fasttrap_exec = &fasttrap_exec_exit; --- 85 unchanged lines hidden (view full) --- 2654 2655#ifdef DEBUG 2656 mutex_enter(&fasttrap_count_mtx); 2657 ASSERT(fasttrap_pid_count == 0); 2658 mutex_exit(&fasttrap_count_mtx); 2659#endif 2660 2661#if !defined(sun) |
2662 EVENTHANDLER_DEREGISTER(thread_dtor, fasttrap_thread_dtor_tag); 2663 |
2664 for (i = 0; i < fasttrap_tpoints.fth_nent; i++) 2665 mutex_destroy(&fasttrap_tpoints.fth_table[i].ftb_mtx); 2666 for (i = 0; i < fasttrap_provs.fth_nent; i++) 2667 mutex_destroy(&fasttrap_provs.fth_table[i].ftb_mtx); 2668 for (i = 0; i < fasttrap_procs.fth_nent; i++) 2669 mutex_destroy(&fasttrap_procs.fth_table[i].ftb_mtx); 2670#endif 2671 kmem_free(fasttrap_tpoints.fth_table, --- 54 unchanged lines hidden --- |