From 2b035cbe5a817f7c86a12d30997ab134c2cf4e3f Mon Sep 17 00:00:00 2001 From: Julian Elischer Date: Wed, 4 Jun 2003 00:12:57 +0000 Subject: [PATCH] Remove un-needed code. Don't copyin() data we are about to overwrite. Add a flag to tell userland that KSE is officially "DONE" with the mailbox and has gone away. Obtained from: davidxu@ --- sys/kern/kern_kse.c | 76 +++++++++++++++--------------------------- sys/kern/kern_thread.c | 76 +++++++++++++++--------------------------- sys/sys/kse.h | 1 + sys/sys/proc.h | 3 +- 4 files changed, 56 insertions(+), 100 deletions(-) diff --git a/sys/kern/kern_kse.c b/sys/kern/kern_kse.c index 34ebffbc33a..33bf61985a6 100644 --- a/sys/kern/kern_kse.c +++ b/sys/kern/kern_kse.c @@ -422,21 +422,36 @@ kse_exit(struct thread *td, struct kse_exit_args *uap) struct proc *p; struct ksegrp *kg; struct kse *ke; + struct kse_upcall *ku, *ku2; + int error, count; p = td->td_proc; - if (td->td_upcall == NULL || TD_CAN_UNBIND(td)) + if ((ku = td->td_upcall) == NULL || TD_CAN_UNBIND(td)) return (EINVAL); kg = td->td_ksegrp; - /* Serialize removing upcall */ + count = 0; PROC_LOCK(p); mtx_lock_spin(&sched_lock); - if ((kg->kg_numupcalls == 1) && (kg->kg_numthreads > 1)) { + FOREACH_UPCALL_IN_GROUP(kg, ku2) { + if (ku2->ku_flags & KUF_EXITING) + count++; + } + if ((kg->kg_numupcalls - count) == 1 && + (kg->kg_numthreads > 1)) { mtx_unlock_spin(&sched_lock); PROC_UNLOCK(p); return (EDEADLK); } - ke = td->td_kse; + ku->ku_flags |= KUF_EXITING; + mtx_unlock_spin(&sched_lock); + PROC_UNLOCK(p); + error = suword(&ku->ku_mailbox->km_flags, ku->ku_mflags|KMF_DONE); + PROC_LOCK(p); + if (error) + psignal(p, SIGSEGV); + mtx_lock_spin(&sched_lock); upcall_remove(td); + ke = td->td_kse; if (p->p_numthreads == 1) { kse_purge(p, td); p->p_flag &= ~P_THREADED; @@ -720,41 +735,6 @@ kse_create(struct thread *td, struct kse_create_args *uap) return (0); } -/* - * Fill a ucontext_t with a thread's context information. - * - * This is an analogue to getcontext(3). - */ -void -thread_getcontext(struct thread *td, ucontext_t *uc) -{ - - get_mcontext(td, &uc->uc_mcontext, 0); - PROC_LOCK(td->td_proc); - uc->uc_sigmask = td->td_sigmask; - PROC_UNLOCK(td->td_proc); -} - -/* - * Set a thread's context from a ucontext_t. - * - * This is an analogue to setcontext(3). - */ -int -thread_setcontext(struct thread *td, ucontext_t *uc) -{ - int ret; - - ret = set_mcontext(td, &uc->uc_mcontext); - if (ret == 0) { - SIG_CANTMASK(uc->uc_sigmask); - PROC_LOCK(td->td_proc); - td->td_sigmask = uc->uc_sigmask; - PROC_UNLOCK(td->td_proc); - } - return (ret); -} - /* * Initialize global thread allocation resources. */ @@ -948,27 +928,25 @@ thread_export_context(struct thread *td) uintptr_t mbx; void *addr; int error,temp; - ucontext_t uc; + mcontext_t mc; p = td->td_proc; kg = td->td_ksegrp; /* Export the user/machine context. */ - addr = (void *)(&td->td_mailbox->tm_context); - error = copyin(addr, &uc, sizeof(ucontext_t)); - if (error) - goto bad; - - thread_getcontext(td, &uc); - error = copyout(&uc, addr, sizeof(ucontext_t)); - if (error) + get_mcontext(td, &mc, 0); + addr = (void *)(&td->td_mailbox->tm_context.uc_mcontext); + error = copyout(&mc, addr, sizeof(mcontext_t)); + if (error) goto bad; /* Exports clock ticks in kernel mode */ addr = (caddr_t)(&td->td_mailbox->tm_sticks); temp = fuword(addr) + td->td_usticks; - if (suword(addr, temp)) + if (suword(addr, temp)) { + error = EFAULT; goto bad; + } /* Get address in latest mbox of list pointer */ addr = (void *)(&td->td_mailbox->tm_next); diff --git a/sys/kern/kern_thread.c b/sys/kern/kern_thread.c index 34ebffbc33a..33bf61985a6 100644 --- a/sys/kern/kern_thread.c +++ b/sys/kern/kern_thread.c @@ -422,21 +422,36 @@ kse_exit(struct thread *td, struct kse_exit_args *uap) struct proc *p; struct ksegrp *kg; struct kse *ke; + struct kse_upcall *ku, *ku2; + int error, count; p = td->td_proc; - if (td->td_upcall == NULL || TD_CAN_UNBIND(td)) + if ((ku = td->td_upcall) == NULL || TD_CAN_UNBIND(td)) return (EINVAL); kg = td->td_ksegrp; - /* Serialize removing upcall */ + count = 0; PROC_LOCK(p); mtx_lock_spin(&sched_lock); - if ((kg->kg_numupcalls == 1) && (kg->kg_numthreads > 1)) { + FOREACH_UPCALL_IN_GROUP(kg, ku2) { + if (ku2->ku_flags & KUF_EXITING) + count++; + } + if ((kg->kg_numupcalls - count) == 1 && + (kg->kg_numthreads > 1)) { mtx_unlock_spin(&sched_lock); PROC_UNLOCK(p); return (EDEADLK); } - ke = td->td_kse; + ku->ku_flags |= KUF_EXITING; + mtx_unlock_spin(&sched_lock); + PROC_UNLOCK(p); + error = suword(&ku->ku_mailbox->km_flags, ku->ku_mflags|KMF_DONE); + PROC_LOCK(p); + if (error) + psignal(p, SIGSEGV); + mtx_lock_spin(&sched_lock); upcall_remove(td); + ke = td->td_kse; if (p->p_numthreads == 1) { kse_purge(p, td); p->p_flag &= ~P_THREADED; @@ -720,41 +735,6 @@ kse_create(struct thread *td, struct kse_create_args *uap) return (0); } -/* - * Fill a ucontext_t with a thread's context information. - * - * This is an analogue to getcontext(3). - */ -void -thread_getcontext(struct thread *td, ucontext_t *uc) -{ - - get_mcontext(td, &uc->uc_mcontext, 0); - PROC_LOCK(td->td_proc); - uc->uc_sigmask = td->td_sigmask; - PROC_UNLOCK(td->td_proc); -} - -/* - * Set a thread's context from a ucontext_t. - * - * This is an analogue to setcontext(3). - */ -int -thread_setcontext(struct thread *td, ucontext_t *uc) -{ - int ret; - - ret = set_mcontext(td, &uc->uc_mcontext); - if (ret == 0) { - SIG_CANTMASK(uc->uc_sigmask); - PROC_LOCK(td->td_proc); - td->td_sigmask = uc->uc_sigmask; - PROC_UNLOCK(td->td_proc); - } - return (ret); -} - /* * Initialize global thread allocation resources. */ @@ -948,27 +928,25 @@ thread_export_context(struct thread *td) uintptr_t mbx; void *addr; int error,temp; - ucontext_t uc; + mcontext_t mc; p = td->td_proc; kg = td->td_ksegrp; /* Export the user/machine context. */ - addr = (void *)(&td->td_mailbox->tm_context); - error = copyin(addr, &uc, sizeof(ucontext_t)); - if (error) - goto bad; - - thread_getcontext(td, &uc); - error = copyout(&uc, addr, sizeof(ucontext_t)); - if (error) + get_mcontext(td, &mc, 0); + addr = (void *)(&td->td_mailbox->tm_context.uc_mcontext); + error = copyout(&mc, addr, sizeof(mcontext_t)); + if (error) goto bad; /* Exports clock ticks in kernel mode */ addr = (caddr_t)(&td->td_mailbox->tm_sticks); temp = fuword(addr) + td->td_usticks; - if (suword(addr, temp)) + if (suword(addr, temp)) { + error = EFAULT; goto bad; + } /* Get address in latest mbox of list pointer */ addr = (void *)(&td->td_mailbox->tm_next); diff --git a/sys/sys/kse.h b/sys/sys/kse.h index a69adcdcde8..6a173ccf44f 100644 --- a/sys/sys/kse.h +++ b/sys/sys/kse.h @@ -88,6 +88,7 @@ struct kse_mailbox { /* These flags are kept in km_flags */ #define KMF_NOUPCALL 0x01 #define KMF_NOCOMPLETED 0x02 +#define KMF_DONE 0x04 #ifndef _KERNEL int kse_create(struct kse_mailbox *, int); diff --git a/sys/sys/proc.h b/sys/sys/proc.h index 77c56539985..75cde85cd69 100644 --- a/sys/sys/proc.h +++ b/sys/sys/proc.h @@ -459,6 +459,7 @@ struct kse_upcall { }; #define KUF_DOUPCALL 0x00001 /* Do upcall now, don't wait */ +#define KUF_EXITING 0x00002 /* Upcall structure is exiting */ /* * Kernel-scheduled entity group (KSEG). The scheduler considers each KSEG to @@ -900,11 +901,9 @@ struct thread *thread_alloc(void); void thread_exit(void) __dead2; int thread_export_context(struct thread *td); void thread_free(struct thread *td); -void thread_getcontext(struct thread *td, ucontext_t *uc); void thread_link(struct thread *td, struct ksegrp *kg); void thread_reap(void); struct thread *thread_schedule_upcall(struct thread *td, struct kse_upcall *ku); -int thread_setcontext(struct thread *td, ucontext_t *uc); int thread_single(int how); #define SINGLE_NO_EXIT 0 /* values for 'how' */ #define SINGLE_EXIT 1