Skip site navigation (1)Skip section navigation (2)
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>