-static int profil_funneled(struct proc *p, struct profil_args *uap, register_t *retval);
-static int add_profil_funneled(struct proc *p, struct add_profil_args *uap, register_t *retval);
-
-
-int
-profil(struct proc *p, struct profil_args *uap, register_t *retval)
-{
- boolean_t funnel_state;
- int error;
-
- funnel_state = thread_funnel_set(kernel_flock, TRUE);
- error = profil_funneled(p, uap, retval);
- thread_funnel_set(kernel_flock, funnel_state);
- return(error);
-}
-
-static int
-profil_funneled(struct proc *p, struct profil_args *uap, __unused register_t *retval)
-{
- struct uprof *upp = &p->p_stats->p_prof;
- int s;
-
- if (uap->pcscale > (1 << 16))
- return (EINVAL);
-
- if (uap->pcscale == 0) {
- stopprofclock(p);
- return (0);
- }
- /*
- * Block profile interrupts while changing state.
- */
- s = ml_set_interrupts_enabled(FALSE);
-
- if (proc_is64bit(p)) {
- struct user_uprof *user_upp = &p->p_stats->user_p_prof;
- struct user_uprof *upc, *nupc;
-
- PROFILE_LOCK(&user_upp->pr_lock);
-
- user_upp->pr_base = uap->bufbase;
- user_upp->pr_size = uap->bufsize;
- user_upp->pr_off = uap->pcoffset;
- user_upp->pr_scale = uap->pcscale;
- upp->pr_base = NULL;
- upp->pr_size = 0;
- upp->pr_scale = 0;
-
- /*
- * remove buffers previously allocated with add_profil()
- * don't do the kfree's while interrupts disabled
- */
- upc = user_upp->pr_next;
- user_upp->pr_next = 0;
-
- PROFILE_UNLOCK(&user_upp->pr_lock);
-
- startprofclock(p);
- ml_set_interrupts_enabled(s);
-
- while (upc) {
- nupc = upc->pr_next;
- kfree(upc, sizeof (*upc));
- upc = nupc;
- }
-
- } else {
- struct uprof *upc, *nupc;
-
- PROFILE_LOCK(&upp->pr_lock);
-
- upp->pr_base = CAST_DOWN(caddr_t, uap->bufbase);
- upp->pr_size = uap->bufsize;
- upp->pr_off = uap->pcoffset;
- upp->pr_scale = uap->pcscale;
-
- /*
- * remove buffers previously allocated with add_profil()
- * don't do the kfree's while interrupts disabled
- */
- upc = upp->pr_next;
- upp->pr_next = 0;
-
- PROFILE_UNLOCK(&upp->pr_lock);
-
- startprofclock(p);
- ml_set_interrupts_enabled(s);
-
- while (upc) {
- nupc = upc->pr_next;
- kfree(upc, sizeof (struct uprof));
- upc = nupc;
- }
- }
- return(0);
-}
-
-int
-add_profil(struct proc *p, struct add_profil_args *uap, register_t *retval)
-{
- boolean_t funnel_state;
- int error;
-
- funnel_state = thread_funnel_set(kernel_flock, TRUE);
- error = add_profil_funneled(p, uap, retval);
- thread_funnel_set(kernel_flock, funnel_state);
- return(error);
-}
-
-
-static int
-add_profil_funneled(struct proc *p, struct add_profil_args *uap, __unused register_t *retval)
-{
- struct uprof *upp = &p->p_stats->p_prof, *upc;
- struct user_uprof *user_upp = NULL, *user_upc;
- int s;
- boolean_t is64bit = proc_is64bit(p);
-
-
- upc = NULL;
- user_upc = NULL;
-
- if (is64bit) {
- user_upp = &p->p_stats->user_p_prof;
-
- if (user_upp->pr_scale == 0)
- return (0);
- }
- else {
- if (upp->pr_scale == 0)
- return (0);
- }
- if (is64bit) {
- user_upc = (struct user_uprof *) kalloc(sizeof (struct user_uprof));
- user_upc->pr_base = uap->bufbase;
- user_upc->pr_size = uap->bufsize;
- user_upc->pr_off = uap->pcoffset;
- user_upc->pr_scale = uap->pcscale;
- } else {
- upc = (struct uprof *) kalloc(sizeof (struct uprof));
- upc->pr_base = CAST_DOWN(caddr_t, uap->bufbase);
- upc->pr_size = uap->bufsize;
- upc->pr_off = uap->pcoffset;
- upc->pr_scale = uap->pcscale;
- }
- s = ml_set_interrupts_enabled(FALSE);
-
- if (is64bit) {
- PROFILE_LOCK(&user_upp->pr_lock);
- if (user_upp->pr_scale) {
- user_upc->pr_next = user_upp->pr_next;
- user_upp->pr_next = user_upc;
- user_upc = NULL;
- }
- PROFILE_UNLOCK(&user_upp->pr_lock);
- } else {
- PROFILE_LOCK(&upp->pr_lock);
- if (upp->pr_scale) {
- upc->pr_next = upp->pr_next;
- upp->pr_next = upc;
- upc = NULL;
- }
- PROFILE_UNLOCK(&upp->pr_lock);
- }
- ml_set_interrupts_enabled(s);
-
- if (upc)
- kfree(upc, sizeof(struct uprof));
- if (user_upc)
- kfree(user_upc, sizeof(struct user_uprof));
-
- return(0);
-}