Date: Sat, 27 Jan 2001 00:33:23 -0800 (PST) From: Root Dude <julian@elischer.org> To: current@freebsd.org Subject: kernel threading: the first steps [patch] Message-ID: <200101270833.AAA75738@InterJet.elischer.org>
next in thread | raw e-mail | index | archive | help
Here's a first step. I've broken the proc structure into 4 structures. At this moment the proc structure includes the other three, so there is no problem with allocation, and there is always a 1:1 correlation between them at this time so this is safe. SOme of the fields are probably in the wrong structs but it doesn't matter for his patch. The aim of this patch is to make people think about which fields go to which structures and what new fields are needed. Remarkably the kernel compiles and runs! The purposes of the structs in this setting are: 1/ The kse struct is known to the scheduler, associated with a CPU and scheduled whenever there as a context to run. 2/The ksec is a stored context that is associated with a kse, but for some reason cannot be running now. 3/The KSEG has a priority, nice value, etc. KSECs tha complete may be reported back to the userland scheduler on he next KSE within the same KSEG. Timers are in KSEG scope. Signals are in KSEG scope too? 4/Al resorces and permissions are owned by the original proc sruct. these definitions are open for discussion but they give some grounds to work on regarding which fields go where After deciding what the semantics are and assigning fields to structures, (and how they are linked), we can then work out which functions in the kernel take which structure as arguments, and them work towards divorcing them so that the 1:1 relationship is broken. At that stage we have threads. thoughts?. -- __--_|\ Julian Elischer / \ julian@elischer.org ( OZ ) World tour 2000-2001 ---> X_.---._/ v Index: kern/kern_fork.c =================================================================== RCS file: /unused/cvs/freebsd/src/sys/kern/kern_fork.c,v retrieving revision 1.94 diff -u -r1.94 kern_fork.c --- kern/kern_fork.c 2001/01/24 10:47:14 1.94 +++ kern/kern_fork.c 2001/01/27 03:53:12 @@ -371,6 +371,24 @@ bcopy(&p1->p_startcopy, &p2->p_startcopy, (unsigned) ((caddr_t)&p2->p_endcopy - (caddr_t)&p2->p_startcopy)); + bzero(&p2->kse0.kse_startzero, + (unsigned) ((caddr_t)&p2->kse0.kse_endzero + - (caddr_t)&p2->kse0.kse_startzero)); + bcopy(&p1->kse0.kse_startcopy, &p2->kse0.kse_startcopy, + (unsigned) ((caddr_t)&p2->kse0.kse_endcopy + - (caddr_t)&p2->kse0.kse_startcopy)); + + bzero(&p2->ksec0.ksec_startzero, + (unsigned) ((caddr_t)&p2->ksec0.ksec_endzero + - (caddr_t)&p2->ksec0.ksec_startzero)); + bcopy(&p1->ksec0.ksec_startcopy, &p2->ksec0.ksec_startcopy, + (unsigned) ((caddr_t)&p2->ksec0.ksec_endcopy + - (caddr_t)&p2->ksec0.ksec_startcopy)); + + bcopy(&p1->kseg0.kseg_startcopy, &p2->kseg0.kseg_startcopy, + (unsigned) ((caddr_t)&p2->kseg0.kseg_endcopy + - (caddr_t)&p2->kseg0.kseg_startcopy)); + mtx_init(&p2->p_mtx, "process lock", MTX_DEF); p2->p_aioinfo = NULL; Index: sys/proc.h =================================================================== RCS file: /unused/cvs/freebsd/src/sys/sys/proc.h,v retrieving revision 1.141 diff -u -r1.141 proc.h --- sys/proc.h 2001/01/24 09:41:03 1.141 +++ sys/proc.h 2001/01/27 03:52:53 @@ -141,18 +141,157 @@ * m - Giant * n - not locked, lazy */ +struct proc; /* forward decl. */ + +/* + * The schedulable entity that can be given a context to run. + * A process may have several of these. Probably one per processor + * but posibly a few more. In this universe they are grouped + * with a KSEG that contains the priority and niceness + * for the group. + */ +struct kse { + /***** individualy set up */ + struct pstats *kse_stats; /* (bk) Accounting/statistics (CPU). */ +#define kse_startzero kse_estcpu + /***** start zero */ + u_int kse_estcpu; /* (jk) Time averaged value of kse_cpticks. */ + int kse_cpticks; /* (jk) Ticks of cpu time. */ + fixpt_t kse_pctcpu; /* (jk) %cpu during p_swtime. */ + u_int64_t kse_uu; /* (jk) Previous user time in microsec. */ + u_int64_t kse_su; /* (jk) Previous system time in microsec. */ + u_int64_t kse_iu; /* (jk) Previous interrupt time in microsec. */ + u_int64_t kse_uticks; /* (jk) Statclock hits in user mode. */ + u_int64_t kse_sticks; /* (jk) Statclock hits in system mode. */ + u_int64_t kse_iticks; /* (jk) Statclock hits processing intr. */ + u_int kse_slptime; /* (jk) Time since last blocked. */ + u_char kse_oncpu; /* (jk) Which cpu we are on. */ + char kse_rqindex; /* (jk) Run queue index. */ + register_t kse_retval[2]; /* (kk) Syscall aux returns. */ + /***** end zero */ +#define kse_endzero kse_priority +#define kse_startcopy kse_priority + /***** start copy */ + u_char kse_priority; /* (jk) Process priority. */ + u_char kse_usrpri; /* (jk) User priority based on p_cpu and p_nice. */ +#define kse_endcopy kse_ithd + /***** end copy */ + struct ithd *kse_ithd; /* (bk) For interrupt threads only. */ + struct kseg *kse_ourkseg; + struct proc *kse_ourproc; +}; +/* + * Compatibility defines for while we are using a + * single one in the proc struct during development. + */ +#define p_stats kse0.kse_stats +#define p_estcpu kse0.kse_estcpu +#define p_cpticks kse0.kse_cpticks +#define p_pctcpu kse0.kse_pctcpu +#define p_uu kse0.kse_uu +#define p_su kse0.kse_su +#define p_iu kse0.kse_iu +#define p_uticks kse0.kse_uticks +#define p_sticks kse0.kse_sticks +#define p_iticks kse0.kse_iticks +#define p_slptime kse0.kse_slptime +#define p_oncpu kse0.kse_oncpu +#define p_rqindex kse0.kse_rqindex +#define p_retval kse0.kse_retval +#define p_priority kse0.kse_priority +#define p_usrpri kse0.kse_usrpri +#define p_ithd kse0.kse_ithd + +/* + * Kernel runnable context. This is what is put to sleep and reactivated. + * (Kernel Schedulable Entity Context) + * The first KSE available in the correct group will run this context. + * If several are available, use the one on the same CPU as last time. + */ +struct ksec { + /***** individualy set up */ + TAILQ_ENTRY(proc) ksec_procq; /* (jc) Run/mutex queue. */ + TAILQ_ENTRY(proc) ksec_slpq; /* (jc) Sleep queue. */ + int ksec_intr_nesting_level; /* (nc?) Interrupt recursion. */ +#define ksec_startzero ksec_dupfd + /***** start zero */ + int ksec_dupfd; /* (cc) Sideways ret value from fdopen. XXX */ + void *ksec_wchan; /* (jc) Sleep address. */ + const char *ksec_wmesg; /* (jc) Reason for sleep. */ + u_char ksec_lastcpu; /* (jc) Last cpu we were on. */ + short ksec_locks; /* (*c) DEBUG: lockmgr count of held locks */ + short ksec_simple_locks; /* (*c) DEBUG: count of held simple locks */ + u_int ksec_stops; /* (cc?) Procfs event bitmask. */ + u_int ksec_stype; /* (cc?) Procfs stop event type. */ + char ksec_step; /* (cc?) Procfs stop *once* flag. */ + u_char ksec_pfsflags; /* (cc?) Procfs flags. */ + struct mtx *ksec_blocked; /* (jc) Mutex process is blocked on. */ + const char *ksec_mtxname; /* (jc) Name of mutex blocked on. */ + LIST_HEAD(, mtx) ksec_contested;/* (jc) Contested locks. */ + /***** end zero */ +#define ksec_endzero ksec_slpcallout +#define ksec_startcopy ksec_slpcallout + /***** start copy */ + struct callout ksec_slpcallout;/* (hc) Callout for sleep. */ + struct mdproc ksec_md; /* (kc) Any machine-dependent fields. */ + /***** end copy */ +#define ksec_endcopy ksec_ourkse + struct kse *ksec_ourkse; +}; +/* + * Compatibility defines for while we are using a + * single one in the proc struct during development. + */ +#define p_procq ksec0.ksec_procq +#define p_slpq ksec0.ksec_slpq +#define p_intr_nesting_level ksec0.ksec_intr_nesting_level +#define p_dupfd ksec0.ksec_dupfd +#define p_wchan ksec0.ksec_wchan +#define p_wmesg ksec0.ksec_wmesg +#define p_lastcpu ksec0.ksec_lastcpu +#define p_locks ksec0.ksec_locks +#define p_simple_locks ksec0.ksec_simple_locks +#define p_stops ksec0.ksec_stops +#define p_stype ksec0.ksec_stype +#define p_step ksec0.ksec_step +#define p_pfsflags ksec0.ksec_pfsflags +#define p_blocked ksec0.ksec_blocked +#define p_mtxname ksec0.ksec_mtxname +#define p_contested ksec0.ksec_contested +#define p_slpcallout ksec0.ksec_slpcallout +#define p_md ksec0.ksec_md + +/* + * store KSE group common information such as priority + */ +struct kseg { /* all copied */ +#define kseg_startcopy kseg_itcallout + struct callout kseg_itcallout; /* (hg) Interval timer callout. */ + char kseg_nice; /* (j?/k?g) Process "nice" value. */ + struct rtprio kseg_rtprio; /* (jg) Realtime priority. */ +#define kseg_endcopy kseg_ourproc + struct proc *kseg_ourproc; +}; +/* + * Compatibility defines for while we are using a + * single one in the proc struct during development. + */ +#define p_itcallout kseg0.kseg_itcallout +#define p_nice kseg0.kseg_nice +#define p_rtprio kseg0.kseg_rtprio + struct proc { - TAILQ_ENTRY(proc) p_procq; /* (j) Run/mutex queue. */ - TAILQ_ENTRY(proc) p_slpq; /* (j) Sleep queue. */ - LIST_ENTRY(proc) p_list; /* (d) List of all processes. */ + LIST_ENTRY(proc) p_list; /* (dp) List of all processes. */ + struct kse kse0; + struct kseg kseg0; + struct ksec ksec0; /* substructures: */ - struct pcred *p_cred; /* (c) Process owner's identity. */ - struct filedesc *p_fd; /* (b) Ptr to open files structure. */ - struct pstats *p_stats; /* (b) Accounting/statistics (CPU). */ - struct plimit *p_limit; /* (m) Process limits. */ - struct vm_object *p_upages_obj;/* (c) Upages object. */ - struct procsig *p_procsig; /* (c) Signal actions, state (CPU). */ + struct pcred *p_cred; /* (cp) Process owner's identity. */ + struct filedesc *p_fd; /* (bp) Ptr to open files structure. */ + struct plimit *p_limit; /* (mp) Process limits. */ + struct vm_object *p_upages_obj;/* (cp) Upages object. */ + struct procsig *p_procsig; /* (cp) Signal actions, state (CPU). */ #define p_sigacts p_procsig->ps_sigacts #define p_sigignore p_procsig->ps_sigignore #define p_sigcatch p_procsig->ps_sigcatch @@ -160,77 +299,47 @@ #define p_ucred p_cred->pc_ucred #define p_rlimit p_limit->pl_rlimit - int p_flag; /* (c) P_* flags. */ - int p_sflag; /* (j) PS_* flags. */ - int p_intr_nesting_level; /* (n) Interrupt recursion. */ - char p_stat; /* (j) S* process status. */ + int p_flag; /* (cp) P_* flags. */ + int p_sflag; /* (jp) PS_* flags. */ + char p_stat; /* (jp) S* process status. */ char p_pad1[3]; - pid_t p_pid; /* (b) Process identifier. */ - LIST_ENTRY(proc) p_hash; /* (d) Hash chain. */ - LIST_ENTRY(proc) p_pglist; /* (c) List of processes in pgrp. */ - struct proc *p_pptr; /* (e) Pointer to parent process. */ - LIST_ENTRY(proc) p_sibling; /* (e) List of sibling processes. */ - LIST_HEAD(, proc) p_children; /* (e) Pointer to list of children. */ + pid_t p_pid; /* (bp) Process identifier. */ + LIST_ENTRY(proc) p_hash; /* (dp) Hash chain. */ + LIST_ENTRY(proc) p_pglist; /* (cp) List of processes in pgrp. */ + struct proc *p_pptr; /* (ep) Pointer to parent process. */ + LIST_ENTRY(proc) p_sibling; /* (ep) List of sibling processes. */ + LIST_HEAD(, proc) p_children; /* (ep) Pointer to list of children. */ /* The following fields are all zeroed upon creation in fork. */ #define p_startzero p_oppid - pid_t p_oppid; /* (c) Save parent pid during ptrace. XXX */ - int p_dupfd; /* (c) Sideways ret value from fdopen. XXX */ - struct vmspace *p_vmspace; /* (b) Address space. */ + pid_t p_oppid; /* (cp) Save parent pid during ptrace. XXX */ + struct vmspace *p_vmspace; /* (bp) Address space. */ /* scheduling */ - u_int p_estcpu; /* (j) Time averaged value of p_cpticks. */ - int p_cpticks; /* (j) Ticks of cpu time. */ - fixpt_t p_pctcpu; /* (j) %cpu during p_swtime. */ - struct callout p_slpcallout; /* (h) Callout for sleep. */ - void *p_wchan; /* (j) Sleep address. */ - const char *p_wmesg; /* (j) Reason for sleep. */ - u_int p_swtime; /* (j) Time swapped in or out. */ - u_int p_slptime; /* (j) Time since last blocked. */ + u_int p_swtime; /* (jp) Time swapped in or out. */ - struct callout p_itcallout; /* (h) Interval timer callout. */ struct itimerval p_realtimer; /* (h?/k?) Alarm timer. */ - u_int64_t p_runtime; /* (j) Real time in microsec. */ - u_int64_t p_uu; /* (j) Previous user time in microsec. */ - u_int64_t p_su; /* (j) Previous system time in microsec. */ - u_int64_t p_iu; /* (j) Previous interrupt time in microsec. */ - u_int64_t p_uticks; /* (j) Statclock hits in user mode. */ - u_int64_t p_sticks; /* (j) Statclock hits in system mode. */ - u_int64_t p_iticks; /* (j) Statclock hits processing intr. */ - - int p_traceflag; /* (j?) Kernel trace points. */ - struct vnode *p_tracep; /* (j?) Trace to vnode. */ - - sigset_t p_siglist; /* (c) Signals arrived but not delivered. */ - - struct vnode *p_textvp; /* (b) Vnode of executable. */ - - char p_lock; /* (c) Process lock (prevent swap) count. */ - struct mtx p_mtx; /* (k) Lock for this struct. */ - u_char p_oncpu; /* (j) Which cpu we are on. */ - u_char p_lastcpu; /* (j) Last cpu we were on. */ - char p_rqindex; /* (j) Run queue index. */ - - short p_locks; /* (*) DEBUG: lockmgr count of held locks */ - short p_simple_locks; /* (*) DEBUG: count of held simple locks */ - u_int p_stops; /* (c) Procfs event bitmask. */ - u_int p_stype; /* (c) Procfs stop event type. */ - char p_step; /* (c) Procfs stop *once* flag. */ - u_char p_pfsflags; /* (c) Procfs flags. */ + u_int64_t p_runtime; /* (jp) Real time in microsec. */ + + int p_traceflag; /* (j?p) Kernel trace points. */ + struct vnode *p_tracep; /* (j?p) Trace to vnode. */ + + sigset_t p_siglist; /* (cp) Signals arrived but not delivered. */ + + struct vnode *p_textvp; /* (bp) Vnode of executable. */ + + char p_lock; /* (cp) Process lock (prevent swap) count. */ + struct mtx p_mtx; /* (kp) Lock for this struct. */ char p_pad3[2]; /* Alignment. */ - register_t p_retval[2]; /* (k) Syscall aux returns. */ - struct sigiolst p_sigiolst; /* (c) List of sigio sources. */ - int p_sigparent; /* (c) Signal to parent on exit. */ - sigset_t p_oldsigmask; /* (c) Saved mask from before sigpause. */ - int p_sig; /* (n) For core dump/debugger XXX. */ - u_long p_code; /* (n) For core dump/debugger XXX. */ - struct klist p_klist; /* (c) Knotes attached to this process. */ - LIST_HEAD(, mtx) p_heldmtx; /* (j) For debugging code. */ - struct mtx *p_blocked; /* (j) Mutex process is blocked on. */ - const char *p_mtxname; /* (j) Name of mutex blocked on. */ - LIST_HEAD(, mtx) p_contested; /* (j) Contested locks. */ + struct sigiolst p_sigiolst; /* (cp) List of sigio sources. */ + int p_sigparent; /* (cp) Signal to parent on exit. */ + sigset_t p_oldsigmask; /* (cp) Saved mask from before sigpause. */ + int p_sig; /* (np) For core dump/debugger XXX. */ + u_long p_code; /* (np) For core dump/debugger XXX. */ + struct klist p_klist; /* (cp) Knotes attached to this process. */ + LIST_HEAD(, mtx) p_heldmtx; /* (jp) For debugging code. */ /* End area that is zeroed on creation. */ #define p_endzero p_startcopy @@ -238,38 +347,32 @@ /* The following fields are all copied upon creation in fork. */ #define p_startcopy p_sigmask - sigset_t p_sigmask; /* (c) Current signal mask. */ - stack_t p_sigstk; /* (c) Stack pointer and on-stack flag. */ + sigset_t p_sigmask; /* (cp) Current signal mask. */ + stack_t p_sigstk; /* (cp) Stack pointer and on-stack flag. */ - int p_magic; /* (b) Magic number. */ - u_char p_priority; /* (j) Process priority. */ - u_char p_usrpri; /* (j) User priority based on p_cpu and p_nice. */ - u_char p_nativepri; /* (j) Priority before propagation. */ - char p_nice; /* (j?/k?) Process "nice" value. */ - char p_comm[MAXCOMLEN + 1]; /* (b) Process name. */ - - struct pgrp *p_pgrp; /* (e?/c?) Pointer to process group. */ - struct sysentvec *p_sysent; /* (b) System call dispatch information. */ - struct rtprio p_rtprio; /* (j) Realtime priority. */ - struct prison *p_prison; /* (b?) jail(4). */ - struct pargs *p_args; /* (b?) Process arguments. */ + int p_magic; /* (bp) Magic number. */ + u_char p_nativepri; /* (jp) Priority before propagation. */ + char p_comm[MAXCOMLEN + 1]; /* (bp) Process name. */ + + struct pgrp *p_pgrp; /* (e?/c?p) Pointer to process group. */ + struct sysentvec *p_sysent; /* (pb) System call dispatch information. */ + struct prison *p_prison; /* (b?p) jail(4). */ + struct pargs *p_args; /* (b?p) Process arguments. */ /* End area that is copied on creation. */ #define p_endcopy p_addr - struct user *p_addr; /* (k) Kernel virtual addr of u-area (CPU). */ - struct mdproc p_md; /* (k) Any machine-dependent fields. */ + struct user *p_addr; /* (kp) Kernel virtual addr of u-area (CPU). */ - u_short p_xstat; /* (c) Exit status for wait; also stop sig. */ - u_short p_acflag; /* (c) Accounting flags. */ - struct rusage *p_ru; /* (a) Exit information. XXX */ - - void *p_aioinfo; /* (c) ASYNC I/O info. */ - struct proc *p_peers; /* (c) */ - struct proc *p_leader; /* (c) */ - struct pasleep p_asleep; /* (k) Used by asleep()/await(). */ - void *p_emuldata; /* (c) Emulator state data. */ - struct ithd *p_ithd; /* (b) For interrupt threads only. */ + u_short p_xstat; /* (cp) Exit status for wait; also stop sig. */ + u_short p_acflag; /* (cp) Accounting flags. */ + struct rusage *p_ru; /* (ap) Exit information. XXX */ + + void *p_aioinfo; /* (cp) ASYNC I/O info. */ + struct proc *p_peers; /* (cp) */ + struct proc *p_leader; /* (cp) */ + struct pasleep p_asleep; /* (kc) Used by asleep()/await(). */ + void *p_emuldata; /* (cp) Emulator state data. */ }; #define p_session p_pgrp->pg_session To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-current" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200101270833.AAA75738>