23c23
< * $FreeBSD: head/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c 258311 2013-11-18 16:51:56Z asomers $
---
> * $FreeBSD: head/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c 264434 2014-04-14 00:22:42Z markj $
64d63
< #include <sys/user.h>
65a65,70
> #include <sys/eventhandler.h>
> #include <sys/user.h>
> #include <vm/vm.h>
> #include <vm/pmap.h>
> #include <vm/vm_map.h>
> #include <vm/vm_param.h>
208a214,217
> #if !defined(sun)
> static void fasttrap_thread_dtor(void *, struct thread *);
> #endif
>
215a225
> static eventhandler_tag fasttrap_thread_dtor_tag;
291a302
> #if !defined(sun)
292a304,414
> * Obtain a chunk of scratch space in the address space of the target process.
> */
> fasttrap_scrspace_t *
> fasttrap_scraddr(struct thread *td, fasttrap_proc_t *fprc)
> {
> fasttrap_scrblock_t *scrblk;
> fasttrap_scrspace_t *scrspc;
> struct proc *p;
> vm_offset_t addr;
> int error, i;
>
> scrspc = NULL;
> if (td->t_dtrace_sscr != NULL) {
> /* If the thread already has scratch space, we're done. */
> scrspc = (fasttrap_scrspace_t *)td->t_dtrace_sscr;
> return (scrspc);
> }
>
> p = td->td_proc;
>
> mutex_enter(&fprc->ftpc_mtx);
> if (LIST_EMPTY(&fprc->ftpc_fscr)) {
> /*
> * No scratch space is available, so we'll map a new scratch
> * space block into the traced process' address space.
> */
> addr = 0;
> error = vm_map_find(&p->p_vmspace->vm_map, NULL, 0, &addr,
> FASTTRAP_SCRBLOCK_SIZE, 0, VMFS_ANY_SPACE, VM_PROT_ALL,
> VM_PROT_ALL, 0);
> if (error != KERN_SUCCESS)
> goto done;
>
> scrblk = malloc(sizeof(*scrblk), M_SOLARIS, M_WAITOK);
> scrblk->ftsb_addr = addr;
> LIST_INSERT_HEAD(&fprc->ftpc_scrblks, scrblk, ftsb_next);
>
> /*
> * Carve the block up into chunks and put them on the free list.
> */
> for (i = 0;
> i < FASTTRAP_SCRBLOCK_SIZE / FASTTRAP_SCRSPACE_SIZE; i++) {
> scrspc = malloc(sizeof(*scrspc), M_SOLARIS, M_WAITOK);
> scrspc->ftss_addr = addr +
> i * FASTTRAP_SCRSPACE_SIZE;
> LIST_INSERT_HEAD(&fprc->ftpc_fscr, scrspc,
> ftss_next);
> }
> }
>
> /*
> * Take the first scratch chunk off the free list, put it on the
> * allocated list, and return its address.
> */
> scrspc = LIST_FIRST(&fprc->ftpc_fscr);
> LIST_REMOVE(scrspc, ftss_next);
> LIST_INSERT_HEAD(&fprc->ftpc_ascr, scrspc, ftss_next);
>
> /*
> * This scratch space is reserved for use by td until the thread exits.
> */
> td->t_dtrace_sscr = scrspc;
>
> done:
> mutex_exit(&fprc->ftpc_mtx);
>
> return (scrspc);
> }
>
> /*
> * Return any allocated per-thread scratch space chunks back to the process'
> * free list.
> */
> static void
> fasttrap_thread_dtor(void *arg __unused, struct thread *td)
> {
> fasttrap_bucket_t *bucket;
> fasttrap_proc_t *fprc;
> fasttrap_scrspace_t *scrspc;
> pid_t pid;
>
> if (td->t_dtrace_sscr == NULL)
> return;
>
> pid = td->td_proc->p_pid;
> bucket = &fasttrap_procs.fth_table[FASTTRAP_PROCS_INDEX(pid)];
> fprc = NULL;
>
> /* Look up the fasttrap process handle for this process. */
> mutex_enter(&bucket->ftb_mtx);
> for (fprc = bucket->ftb_data; fprc != NULL; fprc = fprc->ftpc_next) {
> if (fprc->ftpc_pid == pid) {
> mutex_enter(&fprc->ftpc_mtx);
> mutex_exit(&bucket->ftb_mtx);
> break;
> }
> }
> if (fprc == NULL) {
> mutex_exit(&bucket->ftb_mtx);
> return;
> }
>
> scrspc = (fasttrap_scrspace_t *)td->t_dtrace_sscr;
> LIST_REMOVE(scrspc, ftss_next);
> LIST_INSERT_HEAD(&fprc->ftpc_fscr, scrspc, ftss_next);
>
> mutex_exit(&fprc->ftpc_mtx);
> }
> #endif
>
> /*
451a574,577
> #if !defined(sun)
> fasttrap_scrblock_t *scrblk;
> fasttrap_proc_t *fprc = NULL;
> #endif
536a663,665
> #if !defined(sun)
> fprc = tp->ftt_proc;
> #endif
539a669,684
>
> #if !defined(sun)
> /*
> * Unmap any scratch space inherited from the parent's address
> * space.
> */
> if (fprc != NULL) {
> mutex_enter(&fprc->ftpc_mtx);
> LIST_FOREACH(scrblk, &fprc->ftpc_scrblks, ftsb_next) {
> vm_map_remove(&cp->p_vmspace->vm_map,
> scrblk->ftsb_addr,
> scrblk->ftsb_addr + FASTTRAP_SCRBLOCK_SIZE);
> }
> mutex_exit(&fprc->ftpc_mtx);
> }
> #endif
559a705,708
> #if !defined(sun)
> struct thread *td;
> #endif
>
562c711
< #endif
---
> #else
564a714,720
> /*
> * Since struct threads may be recycled, we cannot rely on t_dtrace_sscr
> * fields to be zeroed by kdtrace_thread_ctor. Thus we must zero it
> * ourselves when a process exits.
> */
> FOREACH_THREAD_IN_PROC(p, td)
> td->t_dtrace_sscr = NULL;
565a722
> #endif
575d731
< #endif
577a734
> #endif
1369a1527,1532
> #if !defined(sun)
> fasttrap_scrblock_t *scrblk, *scrblktmp;
> fasttrap_scrspace_t *scrspc, *scrspctmp;
> struct proc *p;
> struct thread *td;
> #endif
1380a1544,1568
> #if !defined(sun)
> /*
> * Free all structures used to manage per-thread scratch space.
> */
> LIST_FOREACH_SAFE(scrblk, &proc->ftpc_scrblks, ftsb_next,
> scrblktmp) {
> LIST_REMOVE(scrblk, ftsb_next);
> free(scrblk, M_SOLARIS);
> }
> LIST_FOREACH_SAFE(scrspc, &proc->ftpc_fscr, ftss_next, scrspctmp) {
> LIST_REMOVE(scrspc, ftss_next);
> free(scrspc, M_SOLARIS);
> }
> LIST_FOREACH_SAFE(scrspc, &proc->ftpc_ascr, ftss_next, scrspctmp) {
> LIST_REMOVE(scrspc, ftss_next);
> free(scrspc, M_SOLARIS);
> }
>
> if ((p = pfind(pid)) != NULL) {
> FOREACH_THREAD_IN_PROC(p, td)
> td->t_dtrace_sscr = NULL;
> PROC_UNLOCK(p);
> }
> #endif
>
2365a2554,2560
>
> /*
> * This event handler must run before kdtrace_thread_dtor() since it
> * accesses the thread's struct kdtrace_thread.
> */
> fasttrap_thread_dtor_tag = EVENTHANDLER_REGISTER(thread_dtor,
> fasttrap_thread_dtor, NULL, EVENTHANDLER_PRI_FIRST);
2466a2662,2663
> EVENTHANDLER_DEREGISTER(thread_dtor, fasttrap_thread_dtor_tag);
>
< * $FreeBSD: head/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c 258311 2013-11-18 16:51:56Z asomers $
---
> * $FreeBSD: head/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c 264434 2014-04-14 00:22:42Z markj $
64d63
< #include <sys/user.h>
65a65,70
> #include <sys/eventhandler.h>
> #include <sys/user.h>
> #include <vm/vm.h>
> #include <vm/pmap.h>
> #include <vm/vm_map.h>
> #include <vm/vm_param.h>
208a214,217
> #if !defined(sun)
> static void fasttrap_thread_dtor(void *, struct thread *);
> #endif
>
215a225
> static eventhandler_tag fasttrap_thread_dtor_tag;
291a302
> #if !defined(sun)
292a304,414
> * Obtain a chunk of scratch space in the address space of the target process.
> */
> fasttrap_scrspace_t *
> fasttrap_scraddr(struct thread *td, fasttrap_proc_t *fprc)
> {
> fasttrap_scrblock_t *scrblk;
> fasttrap_scrspace_t *scrspc;
> struct proc *p;
> vm_offset_t addr;
> int error, i;
>
> scrspc = NULL;
> if (td->t_dtrace_sscr != NULL) {
> /* If the thread already has scratch space, we're done. */
> scrspc = (fasttrap_scrspace_t *)td->t_dtrace_sscr;
> return (scrspc);
> }
>
> p = td->td_proc;
>
> mutex_enter(&fprc->ftpc_mtx);
> if (LIST_EMPTY(&fprc->ftpc_fscr)) {
> /*
> * No scratch space is available, so we'll map a new scratch
> * space block into the traced process' address space.
> */
> addr = 0;
> error = vm_map_find(&p->p_vmspace->vm_map, NULL, 0, &addr,
> FASTTRAP_SCRBLOCK_SIZE, 0, VMFS_ANY_SPACE, VM_PROT_ALL,
> VM_PROT_ALL, 0);
> if (error != KERN_SUCCESS)
> goto done;
>
> scrblk = malloc(sizeof(*scrblk), M_SOLARIS, M_WAITOK);
> scrblk->ftsb_addr = addr;
> LIST_INSERT_HEAD(&fprc->ftpc_scrblks, scrblk, ftsb_next);
>
> /*
> * Carve the block up into chunks and put them on the free list.
> */
> for (i = 0;
> i < FASTTRAP_SCRBLOCK_SIZE / FASTTRAP_SCRSPACE_SIZE; i++) {
> scrspc = malloc(sizeof(*scrspc), M_SOLARIS, M_WAITOK);
> scrspc->ftss_addr = addr +
> i * FASTTRAP_SCRSPACE_SIZE;
> LIST_INSERT_HEAD(&fprc->ftpc_fscr, scrspc,
> ftss_next);
> }
> }
>
> /*
> * Take the first scratch chunk off the free list, put it on the
> * allocated list, and return its address.
> */
> scrspc = LIST_FIRST(&fprc->ftpc_fscr);
> LIST_REMOVE(scrspc, ftss_next);
> LIST_INSERT_HEAD(&fprc->ftpc_ascr, scrspc, ftss_next);
>
> /*
> * This scratch space is reserved for use by td until the thread exits.
> */
> td->t_dtrace_sscr = scrspc;
>
> done:
> mutex_exit(&fprc->ftpc_mtx);
>
> return (scrspc);
> }
>
> /*
> * Return any allocated per-thread scratch space chunks back to the process'
> * free list.
> */
> static void
> fasttrap_thread_dtor(void *arg __unused, struct thread *td)
> {
> fasttrap_bucket_t *bucket;
> fasttrap_proc_t *fprc;
> fasttrap_scrspace_t *scrspc;
> pid_t pid;
>
> if (td->t_dtrace_sscr == NULL)
> return;
>
> pid = td->td_proc->p_pid;
> bucket = &fasttrap_procs.fth_table[FASTTRAP_PROCS_INDEX(pid)];
> fprc = NULL;
>
> /* Look up the fasttrap process handle for this process. */
> mutex_enter(&bucket->ftb_mtx);
> for (fprc = bucket->ftb_data; fprc != NULL; fprc = fprc->ftpc_next) {
> if (fprc->ftpc_pid == pid) {
> mutex_enter(&fprc->ftpc_mtx);
> mutex_exit(&bucket->ftb_mtx);
> break;
> }
> }
> if (fprc == NULL) {
> mutex_exit(&bucket->ftb_mtx);
> return;
> }
>
> scrspc = (fasttrap_scrspace_t *)td->t_dtrace_sscr;
> LIST_REMOVE(scrspc, ftss_next);
> LIST_INSERT_HEAD(&fprc->ftpc_fscr, scrspc, ftss_next);
>
> mutex_exit(&fprc->ftpc_mtx);
> }
> #endif
>
> /*
451a574,577
> #if !defined(sun)
> fasttrap_scrblock_t *scrblk;
> fasttrap_proc_t *fprc = NULL;
> #endif
536a663,665
> #if !defined(sun)
> fprc = tp->ftt_proc;
> #endif
539a669,684
>
> #if !defined(sun)
> /*
> * Unmap any scratch space inherited from the parent's address
> * space.
> */
> if (fprc != NULL) {
> mutex_enter(&fprc->ftpc_mtx);
> LIST_FOREACH(scrblk, &fprc->ftpc_scrblks, ftsb_next) {
> vm_map_remove(&cp->p_vmspace->vm_map,
> scrblk->ftsb_addr,
> scrblk->ftsb_addr + FASTTRAP_SCRBLOCK_SIZE);
> }
> mutex_exit(&fprc->ftpc_mtx);
> }
> #endif
559a705,708
> #if !defined(sun)
> struct thread *td;
> #endif
>
562c711
< #endif
---
> #else
564a714,720
> /*
> * Since struct threads may be recycled, we cannot rely on t_dtrace_sscr
> * fields to be zeroed by kdtrace_thread_ctor. Thus we must zero it
> * ourselves when a process exits.
> */
> FOREACH_THREAD_IN_PROC(p, td)
> td->t_dtrace_sscr = NULL;
565a722
> #endif
575d731
< #endif
577a734
> #endif
1369a1527,1532
> #if !defined(sun)
> fasttrap_scrblock_t *scrblk, *scrblktmp;
> fasttrap_scrspace_t *scrspc, *scrspctmp;
> struct proc *p;
> struct thread *td;
> #endif
1380a1544,1568
> #if !defined(sun)
> /*
> * Free all structures used to manage per-thread scratch space.
> */
> LIST_FOREACH_SAFE(scrblk, &proc->ftpc_scrblks, ftsb_next,
> scrblktmp) {
> LIST_REMOVE(scrblk, ftsb_next);
> free(scrblk, M_SOLARIS);
> }
> LIST_FOREACH_SAFE(scrspc, &proc->ftpc_fscr, ftss_next, scrspctmp) {
> LIST_REMOVE(scrspc, ftss_next);
> free(scrspc, M_SOLARIS);
> }
> LIST_FOREACH_SAFE(scrspc, &proc->ftpc_ascr, ftss_next, scrspctmp) {
> LIST_REMOVE(scrspc, ftss_next);
> free(scrspc, M_SOLARIS);
> }
>
> if ((p = pfind(pid)) != NULL) {
> FOREACH_THREAD_IN_PROC(p, td)
> td->t_dtrace_sscr = NULL;
> PROC_UNLOCK(p);
> }
> #endif
>
2365a2554,2560
>
> /*
> * This event handler must run before kdtrace_thread_dtor() since it
> * accesses the thread's struct kdtrace_thread.
> */
> fasttrap_thread_dtor_tag = EVENTHANDLER_REGISTER(thread_dtor,
> fasttrap_thread_dtor, NULL, EVENTHANDLER_PRI_FIRST);
2466a2662,2663
> EVENTHANDLER_DEREGISTER(thread_dtor, fasttrap_thread_dtor_tag);
>