Date: Mon, 19 Aug 2002 00:19:19 -0700 (PDT) From: Jonathan Mini <mini@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 16252 for review Message-ID: <200208190719.g7J7JJow018343@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://people.freebsd.org/~peter/p4db/chv.cgi?CH=16252 Change 16252 by mini@mini_stylus on 2002/08/19 00:19:18 - Use ucontext_t to store state for threads, as well as for the UTS. - Instead of repeatedly returning to the same location in the UTS, act as if we have swapcontext()'d in. Affected files ... .. //depot/projects/kse/sys/i386/i386/trap.c#60 edit .. //depot/projects/kse/sys/i386/i386/vm_machdep.c#62 edit .. //depot/projects/kse/sys/kern/kern_exit.c#60 edit .. //depot/projects/kse/sys/kern/kern_fork.c#77 edit .. //depot/projects/kse/sys/kern/kern_proc.c#78 edit .. //depot/projects/kse/sys/kern/kern_thread.c#86 edit .. //depot/projects/kse/sys/sys/kse.h#16 edit .. //depot/projects/kse/sys/sys/proc.h#122 edit .. //depot/projects/kse/sys/sys/ucontext.h#3 edit Differences ... ==== //depot/projects/kse/sys/i386/i386/trap.c#60 (text+ko) ==== @@ -971,7 +971,7 @@ * but for now do it every time. */ td->td_mailbox = (void *)fuword((caddr_t)td->td_kse->ke_mailbox - + offsetof(struct kse_mailbox, kmbx_current_thread)); + + offsetof(struct kse_mailbox, km_curthread)); if ((td->td_mailbox == NULL) || (td->td_mailbox == (void *)-1)) { td->td_mailbox = NULL; /* single thread it.. */ ==== //depot/projects/kse/sys/i386/i386/vm_machdep.c#62 (text+ko) ==== @@ -313,132 +313,6 @@ }; void -cpu_save_upcall(struct thread *td, struct kse *newkse) -{ - struct trapframe *tf; - - newkse->ke_mdstorage = malloc(sizeof(struct md_store), M_TEMP, - M_WAITOK); - /* Note: use of M_WAITOK means it won't fail. */ - /* set up shortcuts in MI section */ - newkse->ke_pcb = - &(((struct md_store *)(newkse->ke_mdstorage))->mds_pcb); - newkse->ke_frame = - &(((struct md_store *)(newkse->ke_mdstorage))->mds_frame); - tf = newkse->ke_frame; - - /* Copy the upcall pcb. Kernel mode & fp regs are here. */ - /* XXXKSE this may be un-needed */ - bcopy(td->td_pcb, newkse->ke_pcb, sizeof(struct pcb)); - - /* - * This initialises most of the user mode register values - * to good values. Eventually set them explicitly to know values - */ - bcopy(td->td_frame, newkse->ke_frame, sizeof(struct trapframe)); - tf->tf_edi = 0; - tf->tf_esi = 0; /* trampoline arg */ - tf->tf_ebp = 0; - tf->tf_esp = (int)newkse->ke_stackbase + newkse->ke_stacksize - 16; - tf->tf_ebx = 0; /* trampoline arg */ - tf->tf_eip = (int)newkse->ke_upcall; -} - -void -cpu_set_upcall(struct thread *td, void *pcb) -{ - struct pcb *pcb2; - - td->td_flags |= TDF_UPCALLING; - - /* Point the pcb to the top of the stack. */ - pcb2 = td->td_pcb; - - /* - * Copy the upcall pcb. This loads kernel regs. - * Those not loaded individually below get their default - * values here. - * - * XXXKSE It might be a good idea to simply skip this as - * the values of the other registers may be unimportant. - * This would remove any requirement for knowing the KSE - * at this time (see the matching comment below for - * more analysis) (need a good safe default). - */ - bcopy(pcb, pcb2, sizeof(*pcb2)); - - /* - * Create a new fresh stack for the new thread. - * The -16 is so we can expand the trapframe if we go to vm86. - * Don't forget to set this stack value into whatever supplies - * the address for the fault handlers. - * The contexts are filled in at the time we actually DO the - * upcall as only then do we know which KSE we got. - */ - td->td_frame = (struct trapframe *)((caddr_t)pcb2 - 16) - 1; - - /* - * Set registers for trampoline to user mode. Leave space for the - * return address on stack. These are the kernel mode register values. - */ - pcb2->pcb_cr3 = vtophys(vmspace_pmap(td->td_proc->p_vmspace)->pm_pdir); - pcb2->pcb_edi = 0; - pcb2->pcb_esi = (int)fork_return; /* trampoline arg */ - pcb2->pcb_ebp = 0; - pcb2->pcb_esp = (int)td->td_frame - sizeof(void *); /* trampoline arg */ - pcb2->pcb_ebx = (int)td; /* trampoline arg */ - pcb2->pcb_eip = (int)fork_trampoline; - pcb2->pcb_psl &= ~(PSL_I); /* interrupts must be disabled */ - /* - * If we didn't copy the pcb, we'd need to do the following registers: - * pcb2->pcb_dr*: cloned above. - * pcb2->pcb_savefpu: cloned above. - * pcb2->pcb_flags: cloned above. - * pcb2->pcb_onfault: cloned above (always NULL here?). - * pcb2->pcb_gs: cloned above. XXXKSE ??? - * pcb2->pcb_ext: cleared below. - */ - pcb2->pcb_ext = NULL; -} - -void -cpu_set_args(struct thread *td, struct kse *ke) -{ - suword((void *)(ke->ke_frame->tf_esp + sizeof(void *)), - (int)ke->ke_mailbox); -} - -void -cpu_free_kse_mdstorage(struct kse *kse) -{ - - free(kse->ke_mdstorage, M_TEMP); - kse->ke_mdstorage = NULL; - kse->ke_pcb = NULL; - kse->ke_frame = NULL; -} - -int -cpu_export_context(struct thread *td) -{ - struct trapframe *frame; - struct thread_mailbox *tm; - struct trapframe *uframe; - int error; - - frame = td->td_frame; - tm = td->td_mailbox; - uframe = &tm->ctx.tfrm.tf_tf; - error = copyout(frame, uframe, sizeof(*frame)); - /* - * "What about the fp regs?" I hear you ask.... XXXKSE - * Don't know where gs and "onstack" come from. - * May need to fiddle a few other values too. - */ - return (error); -} - -void cpu_wait(p) struct proc *p; { ==== //depot/projects/kse/sys/kern/kern_exit.c#60 (text+ko) ==== @@ -204,8 +204,6 @@ p->p_flag |= P_WEXIT; PROC_UNLOCK(p); - if (td->td_kse->ke_mdstorage) - cpu_free_kse_mdstorage(td->td_kse); /* Are we a task leader? */ PROC_LOCK(p); ==== //depot/projects/kse/sys/kern/kern_fork.c#77 (text+ko) ==== @@ -490,8 +490,6 @@ bcopy(&p1->p_startcopy, &p2->p_startcopy, (unsigned) RANGEOF(struct proc, p_startcopy, p_endcopy)); - bcopy(&td->td_kse->ke_startcopy, &ke2->ke_startcopy, - (unsigned) RANGEOF(struct kse, ke_startcopy, ke_endcopy)); bcopy(&td->td_startcopy, &td2->td_startcopy, (unsigned) RANGEOF(struct thread, td_startcopy, td_endcopy)); bcopy(&td->td_ksegrp->kg_startcopy, &kg2->kg_startcopy, ==== //depot/projects/kse/sys/kern/kern_proc.c#78 (text+ko) ==== @@ -345,11 +345,7 @@ mtx_lock_spin(&sched_lock); mi_switch(); /* Save current registers to PCB. */ mtx_unlock_spin(&sched_lock); - newkse->ke_upcall = mbx.kmbx_upcall; - newkse->ke_stackbase = mbx.kmbx_stackbase; - newkse->ke_stacksize = mbx.kmbx_stacksize; newkse->ke_mailbox = uap->mbx; - cpu_save_upcall(td, newkse); /* Note that we are the returning syscall */ td->td_retval[0] = 0; td->td_retval[1] = 0; ==== //depot/projects/kse/sys/kern/kern_thread.c#86 (text+ko) ==== @@ -190,6 +190,14 @@ allocated_threads--; /* XXXSMP */ } +void +thread_getcontext(struct thread *td, ucontext_t *uc) +{ + + get_mcontext(td, &uc->uc_mcontext); + uc->uc_sigmask = td->td_proc->p_sigmask; +} + int thread_setcontext(struct thread *td, ucontext_t *uc) { @@ -283,18 +291,29 @@ void *addr1; void *addr2; int error; + ucontext_t uc; #ifdef __ia64__ td2_mbx = 0; /* pacify gcc (!) */ #endif - /* Export the register contents. */ - error = cpu_export_context(td); + /* Export the user/machine context. */ + error = copyin((caddr_t)td->td_mailbox + + offsetof(struct thread_mailbox, tm_context), + &uc, + sizeof(ucontext_t)); + if (error == 0) { + thread_getcontext(td, &uc); + uc.uc_busy = 0; + error = copyout(&uc, (caddr_t)td->td_mailbox + + offsetof(struct thread_mailbox, tm_context), + sizeof(ucontext_t)); + } ke = td->td_kse; addr1 = (caddr_t)ke->ke_mailbox - + offsetof(struct kse_mailbox, kmbx_completed_threads); + + offsetof(struct kse_mailbox, km_completed); addr2 = (caddr_t)td->td_mailbox - + offsetof(struct thread_mailbox , next_completed); + + offsetof(struct thread_mailbox , tm_next); /* Then link it into it's KSE's list of completed threads. */ if (!error) { error = td2_mbx = fuword(addr1); @@ -425,6 +444,8 @@ thread_schedule_upcall(struct thread *td, struct kse *ke) { struct thread *td2; + caddr_t ucp; + ucontext_t uc; mtx_assert(&sched_lock, MA_OWNED); if (ke->ke_tdspare != NULL) { @@ -438,7 +459,17 @@ CTR3(KTR_PROC, "thread_schedule_upcall: thread %p (pid %d, %s)", td, td->td_proc->p_pid, td->td_proc->p_comm); thread_link(td2, ke->ke_ksegrp); - cpu_set_upcall(td2, ke->ke_pcb); + ucp = (caddr_t)ke->ke_mailbox + + offsetof(struct kse_mailbox, km_context); + copyin(ucp, &uc, sizeof(ucontext_t)); + /* + * XXX: It is somewhat bogus to ignore the error + * if copyin fails here, but the end result will be + * that the process will crash from bogus state information, + * which is what we want. + */ + thread_setcontext(td2, &uc); + suword(ucp + offsetof(ucontext_t, uc_busy), 1); td2->td_ucred = crhold(td->td_ucred); td2->td_flags = TDF_UNBOUND|TDF_UPCALLING; td2->td_priority = td->td_priority; @@ -544,6 +575,7 @@ if (td->td_flags & TDF_UPCALLING) { CTR3(KTR_PROC, "userret: upcall thread %p (pid %d, %s)", td, p->p_pid, p->p_comm); +#if 0 /* * Make sure that it has the correct frame loaded. * While we know that we are on the same KSEGRP @@ -569,8 +601,13 @@ */ td->td_flags &= ~TDF_UPCALLING; /* Hmmmm. */ error = suword((caddr_t)td->td_kse->ke_mailbox + - offsetof(struct kse_mailbox, kmbx_current_thread), + offsetof(struct kse_mailbox, km_curthread), 0); +#else + /* + * We are returning to the UTS. + */ +#endif } /* * Stop any chance that we may be separated from ==== //depot/projects/kse/sys/sys/kse.h#16 (text+ko) ==== @@ -9,7 +9,7 @@ * are met: * 1. Redistributions of source code must retain the above copyright * notice(s), this list of conditions and the following disclaimer as - * the first lines of this file unmodified other than the possible + * the first lines of this file unmodified other than the possible * addition of one or more copyright notices. * 2. Redistributions in binary form must reproduce the above copyright * notice(s), this list of conditions and the following disclaimer in the @@ -32,9 +32,11 @@ #ifndef SYS_KSE_H #define SYS_KSE_H + #include <machine/kse.h> #include <sys/ucontext.h> -/* + +/* * This file defines the structures needed for communication between * the userland and the kernel when running a KSE-based threading system. * The only programs that should see this file are the UTS and the kernel. @@ -42,42 +44,34 @@ struct kse_mailbox; typedef void kse_fn_t(struct kse_mailbox *mbx); -/* - * Each userland thread has one of these buried in it's - * Thread control structure somewhere. +/* + * Thread mailbox. + * + * This describes a user thread ot the kernel scheduler. */ -struct thread_mailbox -{ - struct thread_mailbox *next_completed; - unsigned int flags; - void *UTS_handle; /* The UTS can use this for anything */ - union kse_td_ctx ctx; /* thread's saved context goes here. */ +struct thread_mailbox { + unsigned int tm_flags; /* Thread flags */ + struct thread_mailbox *tm_next; /* Next thread in list */ + ucontext_t tm_context; /* User and machine context */ + void *tm_udata; /* For use by the UTS */ + int tm_spare[8]; }; -/* - * You need to supply one of these as the argument to the - * kse_new() system call. +/* + * KSE mailbox. + * + * Cummunication path between the UTS and the kernel scheduler specific to + * a single KSE. */ -struct kse_mailbox -{ - kse_fn_t *kmbx_upcall; - char *kmbx_stackbase; - unsigned long int kmbx_stacksize; - struct thread_mailbox *kmbx_current_thread; - struct thread_mailbox *kmbx_completed_threads; - unsigned int kmbx_flags; - void *kmbx_UTS_handle; /* UTS can use this for anything */ +struct kse_mailbox { + unsigned int km_flags; /* KSE flags */ +#define KSEKMF_CRITICAL 0x00000001 + ucontext_t km_context; /* UTS context */ + struct thread_mailbox *km_curthread; /* Currently running thread */ + struct thread_mailbox *km_completed; /* Threads back from kernel */ + sigset_t km_sigscaught; /* Caught signals */ + void *km_udata; /* For use by the UTS */ + int tm_spare[8]; }; -#define KEMBXF_CRITICAL 0x00000001 - -struct kse_global_mailbox -{ - unsigned int flags; -}; -#define GMBXF_CRITICAL 0x00000001 - -#ifdef _KERNEL -int thread_setcontext(struct thread *td, ucontext_t *uc); -#endif /* _KERNEL */ #endif ==== //depot/projects/kse/sys/sys/proc.h#122 (text+ko) ==== @@ -55,6 +55,7 @@ #else #include <sys/pcpu.h> #endif +#include <sys/ucontext.h> #include <sys/ucred.h> #include <machine/proc.h> /* Machine-dependent proc substruct. */ #include <vm/uma.h> @@ -376,18 +377,7 @@ void *ke_mailbox; /* the userland mailbox address */ struct thread *ke_tdspare; /* spare thread for upcalls */ #define ke_endzero ke_dummy - -#define ke_startcopy ke_endzero - u_char ke_dummy; /* */ -#define ke_endcopy ke_mdstorage - - void *ke_upcall; - void *ke_stackbase; - u_long ke_stacksize; - void *ke_mdstorage; /* where we store the pcb and frame */ - struct pcb *ke_pcb; /* the pcb saved for the upcalls */ - struct trapframe *ke_frame; /* the upcall trapframe */ - void *mdkse; /* eventually you load from this in */ + char ke_dummy; /* switch for our extension PCB x86 */ }; /* flags kept in ke_flags */ @@ -845,11 +835,6 @@ /* New in KSE. */ struct thread *thread_alloc(void); void thread_free(struct thread *td); -int cpu_export_context(struct thread *td); -void cpu_free_kse_mdstorage(struct kse *kse); -void cpu_save_upcall(struct thread *td, struct kse *newkse); -void cpu_set_args(struct thread *, struct kse *); -void cpu_set_upcall(struct thread *td, void *pcb); void cpu_thread_exit(struct thread *); void cpu_thread_setup(struct thread *td); void kse_reassign(struct kse *ke); @@ -862,6 +847,8 @@ void thread_link(struct thread *td, struct ksegrp *kg); void thread_reap(void); struct thread *thread_schedule_upcall(struct thread *td, struct kse *ke); +int thread_setcontext(struct thread *td, ucontext_t *uc); +void thread_getcontext(struct thread *td, ucontext_t *uc); int thread_single(int how); #define SNGLE_NO_EXIT 0 /* values for 'how' */ #define SNGLE_EXIT 1 ==== //depot/projects/kse/sys/sys/ucontext.h#3 (text+ko) ==== @@ -47,7 +47,8 @@ struct __ucontext *uc_link; stack_t uc_stack; - int __spare__[8]; + int uc_busy; + int __spare__[6]; } ucontext_t; #ifndef _KERNEL To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe p4-projects" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200208190719.g7J7JJow018343>