diff -c -N -r /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/lib/libc/sys/sched_setparam.2 /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/lib/libc/sys/sched_setparam.2 *** /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/lib/libc/sys/sched_setparam.2 Fri Aug 27 20:02:34 1999 --- /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/lib/libc/sys/sched_setparam.2 Thu Oct 28 18:06:28 1999 *************** *** 54,63 **** .Fa pid . Higher numerical values for the priority represent higher priorities. .Pp - In this implementation, if the value of - .Fa pid - is negative the function will fail. - .Pp If a process specified by .Fa pid exists and if the calling process has permission, the scheduling --- 54,59 ---- *************** *** 68,78 **** .Fa pid is zero, the scheduling parameters are set for the calling process. .Pp - In this implementation, the policy of when a process can affect - the scheduling parameters of another process is specified in - .Xr p1003_1b - as a write-style operation. - .Pp The target process, whether it is running or not running, will resume execution after all other runnable processes of equal or greater priority have been scheduled to run. --- 64,69 ---- *************** *** 93,106 **** the requested priority change until the higher priority process has executed. .Pp - In this implementation, when the current scheduling policy for the - process specified by - .Fa pid - is normal timesharing (SCHED_OTHER, aka SCHED_NORMAL when not POSIX-source) - or the idle policy (SCHED_IDLE when not POSIX-source) then the behavior - is as if the process had been running under SCHED_RR with a priority - lower than any actual realtime priority. - .Pp The .Fn sched_getparam function will return the scheduling parameters of a process specified --- 84,89 ---- *************** *** 118,141 **** .Fa pid are returned. .Pp - In this implementation, the policy of when a process can obtain the - scheduling parameters of another process are detailed in - .Xr p1003_1b - as a read-style operation. - .Pp If .Fa pid is zero, the scheduling parameters for the calling process will be ! returned. In this implementation, the ! .Fa sched_getparam ! function will fail if ! .Fa pid ! is negative. .Sh RETURN The function will return zero if it completes successfully, or it will return a value of -1 and set .Va errno to indicate the error. .Sh ERRORS On failure .Va errno --- 101,130 ---- .Fa pid are returned. .Pp If .Fa pid is zero, the scheduling parameters for the calling process will be ! returned. .Sh RETURN The function will return zero if it completes successfully, or it will return a value of -1 and set .Va errno to indicate the error. + .Sh IMPLEMENTATION DETAILS + The policy of when a process can access the + scheduling parameters of another process is detailed in + .Xr p1003_1b 9 . + .Fn sched_setparam + is a write style operation and + .Fn sched_getparam + is a read style operation. + .Pp + If the value of + .Fa pid + is negative the functions will fail. + .Pp + For the specifics of the details on the scheduling classes, see + .Xr sched_setscheduler 9 . .Sh ERRORS On failure .Va errno *************** *** 145,151 **** The system is not configured to support this functionality. .It Bq Er EPERM The requesting process doesn not have permission as detailed in ! .Xr p1003_1b . .It Bq Er ESRCH No process can be found corresponding to that specified by .Fa pid . --- 134,140 ---- The system is not configured to support this functionality. .It Bq Er EPERM The requesting process doesn not have permission as detailed in ! .Xr p1003_1b 9 . .It Bq Er ESRCH No process can be found corresponding to that specified by .Fa pid . *************** *** 157,162 **** --- 146,152 ---- .Fa pid . .El .Sh SEE ALSO + .Xr p1003_1b 9 , .Xr sched_get_priority_max 2 , .Xr sched_get_priority_min 2 , .Xr sched_getscheduler 2 , diff -c -N -r /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/lib/libc/sys/sched_setscheduler.2 /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/lib/libc/sys/sched_setscheduler.2 *** /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/lib/libc/sys/sched_setscheduler.2 Fri Aug 27 20:02:34 1999 --- /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/lib/libc/sys/sched_setscheduler.2 Thu Oct 28 18:06:28 1999 *************** *** 57,66 **** the scheduling policy specified by .Fa policy . .Pp - In this implementation, if the value of - .Fa pid - is negative the function will fail. - .Pp If a process specified by .Fa pid exists and if the calling process has permission, the scheduling --- 57,62 ---- *************** *** 73,92 **** is zero, the scheduling policy and scheduling parameters are set for the calling process. .Pp - In this implementation, the policy of when a process can affect - the scheduling parameters of another process is specified in - .Xr p1003_1b - as a write-style operation. - .Pp The scheduling policies are in .Fa : .Bl -tag -width [SCHED_OTHER] ! .It Bq Er SCHED_FIFO First-in-first-out fixed priority scheduling with no round robin scheduling; ! .It Bq Er SCHED_OTHER The standard time sharing scheduler; ! .It Bq Er SCHED_RR Round-robin scheduling across same priority processes. .El .Pp The --- 69,85 ---- is zero, the scheduling policy and scheduling parameters are set for the calling process. .Pp The scheduling policies are in .Fa : .Bl -tag -width [SCHED_OTHER] ! .It Bq Dv SCHED_FIFO First-in-first-out fixed priority scheduling with no round robin scheduling; ! .It Bq Dv SCHED_OTHER The standard time sharing scheduler; ! .It Bq Dv SCHED_RR Round-robin scheduling across same priority processes. + .It Bq Dv SCHED_IDLE + BSD Idle priority scheduling (See IMPLEMENTATION DETAILS). .El .Pp The *************** *** 113,136 **** .Fa pid are returned. .Pp - In this implementation, the policy of when a process can obtain the - scheduling parameters of another process are detailed in - .Xr p1003_1b - as a read-style operation. - .Pp If .Fa pid is zero, the scheduling parameters for the calling process will be ! returned. In this implementation, the ! .Fa sched_getscheduler ! function will fail if ! .Fa pid ! is negative. .Sh RETURN The function will return zero if it completes successfully, or it will return a value of -1 and set .Va errno to indicate the error. .Sh ERRORS On failure .Va errno --- 106,171 ---- .Fa pid are returned. .Pp If .Fa pid is zero, the scheduling parameters for the calling process will be ! returned. .Sh RETURN The function will return zero if it completes successfully, or it will return a value of -1 and set .Va errno to indicate the error. + .Sh IMPLEMENTATION DETAILS + The policy of when a process can access the + scheduling parameters of another process is detailed in + .Xr p1003_1b 9 . + .Fn sched_setscheduler + is a write style operation and + .Fn sched_getscheduler + is a read style operation. + .Pp + If the value of + .Fa pid + is negative the functions will fail. + .Pp + For the + .Fx + soft real-time implementation: + .Bl -tag -width [SCHED_OTHER] + .It Bq Dv SCHED_FIFO + is implemented identically to + .Dv RTP_PRIO_REALTIME ; + see also + .Xr rtprio 2 . + Since + .St -p1003.1b + requires that higher numerical priorities be higher priority, + the priority values are inverted. The scheduling queue is shared with the + .Dv SCHED_RR + function class. + .It Bq Dv SCHED_OTHER + This is implemented via the standard time sharing scheduler. The process + nice value is modified subject to the restrictions in + .Xr setpriority 2 . + The numerical values are offset and inverted + in order to meet the + .St -p1003.1b + requirements. + .It Bq Dv SCHED_RR + This shares the scheduling queue with + .Dv SCHED_FIFO + except that it will yield the processor resource at the end of the + time quantum. + .It Bq Dv SCHED_IDLE + This is an implementation defined class. It will not appear in + the name space when the appropriate defines are in effect. + This is implemented identically to + .Dv RTP_PRIO_IDLE. + Since + .St -p1003.1b + requires that higher numerical priorities be higher priority, + the values are inverted. + .El .Sh ERRORS On failure .Va errno *************** *** 140,146 **** The system is not configured to support this functionality. .It Bq Er EPERM The requesting process doesn not have permission as detailed in ! .Xr p1003_1b . .It Bq Er ESRCH No process can be found corresponding to that specified by .Fa pid . --- 175,181 ---- The system is not configured to support this functionality. .It Bq Er EPERM The requesting process doesn not have permission as detailed in ! .Xr p1003_1b 9 . .It Bq Er ESRCH No process can be found corresponding to that specified by .Fa pid . *************** *** 151,157 **** --- 186,201 ---- .Fa param is outside the valid range for the specified scheduling policy. .El + .Sh NOTES + I see no good direct portable use for + .Dv SCHED_OTHER . + However, a program can use it indirectly and portably revert to + whatever it started out as by using + .Fn sched_getparam + and + .Fn sched_setparam . .Sh SEE ALSO + .Xr p1003_1b 9 , .Xr sched_get_priority_max 2 , .Xr sched_get_priority_min 2 , .Xr sched_getparam 2 , diff -c -N -r /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/share/man/man9/Makefile /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/share/man/man9/Makefile *** /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/share/man/man9/Makefile Sat Sep 25 16:12:01 1999 --- /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/share/man/man9/Makefile Thu Oct 28 18:06:29 1999 *************** *** 16,22 **** devtoname.9 fetch.9 ifnet.9 inittodr.9 intro.9 kernacc.9 malloc.9 \ make_dev.9 microseq.9 mi_switch.9 namei.9 panic.9 physio.9 posix4.9 \ psignal.9 resettodr.9 rtalloc.9 rtentry.9 sleep.9 spl.9 \ ! store.9 style.9 suser.9 time.9 timeout.9 uio.9 \ vget.9 vnode.9 vput.9 vref.9 vrele.9 vslock.9 MAN9+= device.9 device_add_child.9 device_delete_child.9 device_enable.9 \ --- 16,22 ---- devtoname.9 fetch.9 ifnet.9 inittodr.9 intro.9 kernacc.9 malloc.9 \ make_dev.9 microseq.9 mi_switch.9 namei.9 panic.9 physio.9 posix4.9 \ psignal.9 resettodr.9 rtalloc.9 rtentry.9 sleep.9 spl.9 \ ! store.9 style.9 suser.9 synch.9 time.9 timeout.9 uio.9 \ vget.9 vnode.9 vput.9 vref.9 vrele.9 vslock.9 MAN9+= device.9 device_add_child.9 device_delete_child.9 device_enable.9 \ *************** *** 75,80 **** --- 75,94 ---- MLINKS+=spl.9 splnet.9 spl.9 splsoftclock.9 spl.9 splsofttty.9 MLINKS+=spl.9 splstatclock.9 spl.9 spltty.9 spl.9 splvm.9 spl.9 splx.9 MLINKS+=store.9 subyte.9 store.9 suswintr.9 store.9 susword.9 store.9 suword.9 + MLINKS+=synch.9 donice.9 synch.9 dortprio.9 + MLINKS+=synch.9 resched_wanted.9 synch.9 roundrobin_interval.9 + MLINKS+=synch.9 setrunnable.9 synch.9 synch_compare.9 synch.9 synch_fork.9 + MLINKS+=synch.9 synch_proc0_init.9 + MLINKS+=synch.9 synch_proc_force_runnable.9 + MLINKS+=synch.9 synch_proc_isnice.9 + MLINKS+=synch.9 synch_proc_killing.9 + MLINKS+=synch.9 synch_proc_priority.9 + MLINKS+=synch.9 synch_proc_runfast.9 + MLINKS+=synch.9 synch_proc_uninterruptible.9 + MLINKS+=synch.9 synch_proc_unswappable.9 + MLINKS+=synch.9 synch_yield.9 + MLINKS+=synch.9 synch_zombie_charge.9 + MLINKS+=synch.9 update_estcpu.9 MLINKS+=time.9 boottime.9 time.9 mono_time.9 time.9 runtime.9 MLINKS+=timeout.9 untimeout.9 MLINKS+=uio.9 uiomove.9 *************** *** 96,100 **** --- 110,115 ---- MLINKS+=devclass_add_driver.9 devclass_find_driver.9 MLINKS+=BUS_READ_IVAR.9 BUS_WRITE_IVAR.9 MLINKS+=bus_generic_read_ivar.9 bus_generic_write_ivar.9 + .include diff -c -N -r /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/share/man/man9/synch.9 /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/share/man/man9/synch.9 *** /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/share/man/man9/synch.9 Thu Oct 28 18:06:29 1999 --- /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/share/man/man9/synch.9 Thu Oct 28 18:06:29 1999 *************** *** 0 **** --- 1,456 ---- + .\" + .\" Copyright (c) 1999 HD Associates, Inc. + .\" + .\" All rights reserved. + .\" + .\" Redistribution and use in source and binary forms, with or without + .\" modification, are permitted provided that the following conditions + .\" are met: + .\" 1. Redistributions of source code must retain the above copyright + .\" notice, this list of conditions and the following disclaimer. + .\" 2. Redistributions in binary form must reproduce the above copyright + .\" notice, this list of conditions and the following disclaimer in the + .\" documentation and/or other materials provided with the distribution. + .\" + .\" THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY EXPRESS OR + .\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + .\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + .\" IN NO EVENT SHALL THE DEVELOPERS BE LIABLE FOR ANY DIRECT, INDIRECT, + .\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + .\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + .\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + .\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + .\" + .\" $FreeBSD: src/share/man/man9/synch.9,v 1.16 1999/08/28 00:21:32 peter Exp $ + .\" " + .Dd December 17, 1998 + .Os + .Dt SYNCH 9 + .Sh NAME + .Nm donice , + .Nm dortprio , + .Nm resched_wanted , + .Nm roundrobin_interval , + .Nm setrunnable , + .Nm synch_compare , + .Nm synch_fork , + .Nm synch_proc0_init , + .Nm synch_proc_force_runnable , + .Nm synch_proc_isnice , + .Nm synch_proc_killing , + .Nm synch_proc_priority , + .Nm synch_proc_runfast , + .Nm synch_proc_uninterruptible , + .Nm synch_proc_unswappable , + .Nm synch_yield , + .Nm synch_zombie_charge , + .Nm update_estcpu + .Nd synchronization and scheduling primitives + .Sh SYNOPSIS + .Fd #include + .Ft int + .Fn donice "struct proc *changer" "struct proc *changee" "int nice" + .Ft int + .Fn dortprio "struct proc *changer" "struct proc *changee" "struct rtprio *rtp" + .Ft int + .Fn resched_wanted "void" + .Ft int + .Fn roundrobin_interval "void" + .Ft void + .Fn setrunnable "struct proc *p" + .Ft int + .Fn synch_compare "struct proc *p1" "struct proc *p2" + .Ft void + .Fn synch_fork "struct proc *parent" "struct proc *child" + .Ft void + .Fn synch_proc0_init "struct proc *p0" + .Ft int + .Fn synch_proc_force_runnable "struct proc *p" + .Ft int + .Fn synch_proc_isnice "struct proc *p" + .Ft void + .Fn synch_proc_killing "struct proc *p" + .Ft int + .Fn synch_proc_priority "struct proc *p" "struct rtprio *rtp" + .Ft void + .Fn synch_proc_runfast "struct proc *p" + .Ft int + .Fn synch_proc_uninterruptible "struct proc *p" + .Ft int + .Fn synch_proc_unswappable "struct proc *p" + .Ft void + .Fn synch_yield "struct proc *p" "int flag" + .Ft void + .Fn synch_zombie_charge "struct proc *p" + .Sh DESCRIPTION + This documents the current state of the kernel synchronization primitives, + and provides hints about where I think I'm going. + Everything that knows about scheduling policy is now in either + .Pa kern/kern_synch.c + or + .Pa kern/kern_switch.c . + In order to access any of the synchronization and scheduling members + of the proc structure, you must now define + .Dv SCHEDULER_FRIEND + before including any of kernel header files. + By setting the + .Dv NO_RTPRIO + the behavior (almost) reverts to normal 4.4Lite scheduling. There + are still some FreeBSD extensions present in the scheduling as observed + in this document; I anticipate + making it possible to disable those extensions (at least those not + associated with security holes) + via a sysctl to easily revert to a 4.4Lite reference scheduler. + .Pp + Don't be too concerned about the number of entry points documented + in of this document. I'm hoping to collapse a number of them (e.g., + .Fn synch_proc_killing , + .Fn synch_proc_runfast , + and + .Fn synch_proc_force_runnable + together even if they still need a "behavior flag" passed in. + .Pp + .Fn donice + sets the traditional BSD + .Fa nice + value for process + .Fa changee + to the value specified by + .Fa nice + using process + .Fa changer's + credentials. + Out of range + .Fa nice + values are handled by clipping at + .Dv PRIO_MIN + and + .Dv PRIO_MAX . + If process + .Fa changer + is not + .Dv NULL + and it is not permitted to change + .Fa changee's + nice parameter then the value + .Dv EPERM + is returned. + If + .Fa changer + is not + .Dv NULL + and is not the super user and it attempts to lower the + .Fa nice + value then + .Dv EACCESS + is returned. + Note that this + .Dv NULL + behavior is new - previously + .Fn donice + always checked the permissions. + .Pp + If the process is not running the time sharing scheduler class then + this has the guaranteed effect of switching the process to the time sharing + class. + The + .Dv POSIX.4 + system call + .Fn ksched_setscheduler + uses this to revert back to the time sharing scheduler for a + .Dv SCHED_OTHER + scheduler class, and so this behavior must be retained or + .Fn ksched_setscheduler + changed. + .Pp + .Fn dortprio + is the counterpart of + .Fn donice + for the fixed priority scheduling classes. The arguments are the same + except that the final one, + .Fa rtprio , + is a pointer to a + .Fa "struct rtprio" . + .Pp + Currently only the super user can switch to anything other than the + time sharing class. This is to avoid denial of service either by + hogging the CPU using a real time class or indirectly via priority inversion + for the idle class. + .Pp + Note that the connection between the nice value + .Fa proc.p_nice + and the + .Fa rtprio.prio + member is not defined. Currently, the two ways to revert to + a normal time sharing class are either by calling + .Fn donice + with an explicit nice value for + .Fa p_nice + or by calling + .Fn dortprio + specifying + .Fa rtprio.type + as the normal scheduler, in which case the process will revert to + whatever the processes + .Fa p_nice + value happens to be, assumedly the value from before an earlier call to + .Fn dortprio . + This behavior should be defined. Probably the best definition is that the + .Fa rtprio.prio + member to be the nice value subject to appropriate checks, i.e., + we must be sure that the user can't lower + the nice value in a round-about manner + if superuser-only scheduling class restrictions are removed. + .Pp + .Fn resched_wanted + specifies that the current process is hogging the CPU and should give it + up. This was added to avoid DOS hacks via huge kernel moves to + .Fn uio + flavor devices. It is used in + .Pa kern/kern_subr.c + by + .Fn uiomove , + .Fn uiomoveco , + and + .Fn uioread + to decide when it must yield the CPU. Since currently there is always + a + .Fn resched_wanted + followed by a + .Fn synch_yield + if it returns true then perhaps it should be replaced with a single + .Fn hog_check + function that gives up the CPU. + .Pp + Originally + .Fn resched_wanted + simply returned the + .Fa want_resched + flag, however, it has been changed with this bde comment in the log: + .Bd -literal -ragged + Improved scheduling in uiomove(), etc. resched_wanted() is true too + often for it to be a good criterion for switching kernel cpu hogs -- + it is true after most wakeups. Use the criterion "has been running + for >= 2 quanta" instead. + .Ed + Thus resched_wanted returns twice the current scheduling quantum. + .Fn resched_wanted + returns true even if the current process is a real time process. Given + the current gates into fixed priority (i.e., only suser or in the + future something as well thought out) can enter fixed priority this + should be changed. + .Pp + .Fn roundrobin_interval + returns the current scheduling quantum. This defaults at power up to + .Fa hz + over ten, and may be changed using the + .Fa kern.quantum + .Fn sysctl + variable. This determines how frequently the + .Fn roundrobin + round-robin rescheduler is invoked. + .Pp + .Fn setrunnable + sets the state of the process pointed to by + .Fa p + to be runnable. If it is in memory it is placed on the run queue using + .Fn setrunqueue ; + if it is not the swapper is woken up. + .Pp + .Fn synch_compare + compares two runnable processes to decide which is more "interesting". This + function is used by + .Pa kern/tty.c + to decide which of two foreground runnable processes should be + displayed in ttyinfo. + .Pp + .Fn synch_fork + is a hook called in fork that currently only copies the estimated + CPU time of the parent + into that of the child under creation. + This is an early FreeBSD extension, not present in 4.4Lite, + that I believe goes along with the zombie stuff. The estimated + CPU time is in the part of the proc structure that is normally zeroed + at process creation. + .Fn synch_fork + copies the estimated CPU time into the child, + and to quote the original author, "makes a big difference in the + interactive feel of the system". This is a good candidate for disabling + via a sysctl. + .Pp + .Fn synch_proc0_init + is called to initialize the scheduling members during system startup. + .Fa p0 + is of course a pointer to proc0. + .Pp + .Fn synch_proc_force_runnable + is called in + .Pa vm/vm_pageout.c + in + .Fn vm_pageout_scan + when there is no more swap space. After finding the largest resident + process + .Fn vm_pageout_scan + kills the process and calls + .Fn synch_proc_force_runnable + to ensure it runs and exits. + This is not present in 4.4Lite, which did not kill processes in no swap + conditions. I think this has to do with supporting memory overcommit in + FreeBSD - correct me if I'm wrong. + .Fn synch_proc_force_runnable + used to be buggy, I've changed + it to invoke "donice" to properly switch to the fastest normal + priority. It returns 0 if it works otherwise whatever donice returns, + maybe it probably should panic on failure since it shouldn't fail. + This could have been a problem with + .Fa idprio + processes since it wouldn't have affected them before my changes. + .Pp + .Fn synch_proc_isnice + informs us as to whether or not a process is running at a reduced + priority level. How this should behave longterm is questionable since + the long term definition of "niceness" versus fixed priority scheduling, + multiple scheduling classes, and multiple CPU resources is + poorly defined. For now I'm just trying a sensible + treatment by saying that idle priority processes are nice, + thta nice processes are nice, + and that real time processes are not nice. This is used in + .Pa kern/kern_clock.c + as part of the statclock statistics. + .Pp + .Fn synch_proc_killing + is similar in spirit to + .Fn synch_proc_force_runnable. + It is called by + .Fn psignal + to remove any niceness associated with a process. It only changes the + process priority if it is less than + .Dv PZERO , + instead of boosting it to the max. This should be merged with + .Fn synch_proc_force_runnable . + .Pp + .Fn synch_proc_priority + returns the process's nice value and optionally a pointer to the + .Fa "struct rtprio" + for the process indicated by + .Fa p . + Since the nice value means little for the real time processes you + have to be careful using this. For now idle queue processes are + treated as the logically lowest nice value and real time queue + processes the logically highest nice value, however, this behavior + could change. + .Pp + Since the swapper uses this to decide what + to swap in and out and idle priority processes are now treated as + fair game and can also be killed, this may fix some of the previous + problems with idle priority, but I wouldn't count on it. + At least it is no longer trivial to create a growing unswappable idle + priority process. + .Pp + .Fn synch_proc_runfast + is similar to + .Fn synch_proc_killing + and + .Fn synch_proc_force_runnable + except that it + changes the process's kernel scheduling priority + by boosting it to at least + .Dv PUSER + without touching anything that determines the user scheduling + priority. It is done during signalling while reenabling + processes. It ensures that it will run at least until the next + .Fn userret , + .Fn update_estcpu , + or + .Fn adjust_runqueues + is called. Note I'm getting a bit fuzzy here since I have to + trace out where and when this happens - + if the process isn't running, then how will changing only + .Fa p_priority + help things? Also, this isn't going to change things for the fixed + priority classes. This needs more examination, but should be + OK for normal processes. + .Pp + .Fn synch_proc_uninterruptible + returns true for a process waiting at a high kernel priority process, + that is, less than or equal to + .Dv PZERO . + This is used in vm_meter for keeping track of statistics of jobs in + "disk wait". Historically these were the uninterruptible sleeping + processes before + .Dv PCATCH + was added. I'm not sure if this has much meaning now. + .Pp + .Fn synch_proc_unswappable + returns true if a process can not be swapped. It will not permit + a real time priority or a process sleeping at less than + .Dv PSOCK + be swapped. It will now let idle priority processes be swapped, + but I have to track through the setting of + .Fa p_priority + at sleep time to make sure it behaves as expected. I believe it does. + .Pp + .Fn synch_yield + yields the CPU for the current process. + .Fa p + must be + .Fa curproc ; + it was added to the + .Fn yield + call so I have it here. The + .Fa flag + argument provides compatability with that + .Fn yield + system call in + .Pa sys/threads . + If + .Fa flag + is non-zero and the process is in the normal scheduling class you + sink to the bottom of the priorities, ensuring you go to the end + of the line. + .Pp + .Fn synch_zombie_charge + is another FreeBSD scheduling tweak, and like + .Fn synch_fork , + is a candidate for a sysctl. + For all processes except + .Nm init + it charges the estimated CPU time of a zombie child to the waiting + parent, delaying the startup of a parent with lots of busy children. + .Pp + .Fn update_estcpu + updates the CPU estimate as in the red book. Look here for the + alpha bug. Obviously I'm getting tired of typing. + .Sh RETURN VALUES + See above. + .Sh SEE ALSO + .Xr asleep 9 , + .Xr await 9 , + .Xr mi_switch 9 , + .Xr tsleep 9 , + .Xr wakeup 9 , + .Xr wakeup_one 9 , + .Sh HISTORY + Should be detailed above for each function. + .Sh BUGS + .Fn resched_wanted + shouldn't return true for real time processes. + .Pp + .Fn ksched_rr_get_interval + is broken now that you can change the round robin interval via a sysctl; + it grabs it once at attach time. + .Pp + There is an inconsistency in the ordering of + .Fn updatepri + and + .Fn setrunqueue + between + .Fn setrunnable + and the "optimized inline expansion" of + .Fn setrunnable + in + .Fn wakeup . + .Sh AUTHORS + .An Peter Dufault diff -c -N -r /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/alpha/alpha/trap.c /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/alpha/alpha/trap.c *** /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/alpha/alpha/trap.c Fri Aug 27 20:38:33 1999 --- /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/alpha/alpha/trap.c Thu Oct 28 18:06:29 1999 *************** *** 39,44 **** --- 39,45 ---- #include #include #include + #include #include #include #include *************** *** 71,78 **** struct proc *fpcurproc; /* current user of the FPU */ - void userret __P((struct proc *, u_int64_t, u_quad_t)); - unsigned long Sfloat_to_reg __P((unsigned int)); unsigned int reg_to_Sfloat __P((unsigned long)); unsigned long Tfloat_reg_cvt __P((unsigned long)); --- 72,77 ---- *************** *** 87,136 **** static void printtrap __P((const unsigned long, const unsigned long, const unsigned long, const unsigned long, struct trapframe *, int, int)); - /* - * Define the code needed before returning to user mode, for - * trap and syscall. - */ - void - userret(p, pc, oticks) - register struct proc *p; - u_int64_t pc; - u_quad_t oticks; - { - int sig, s; - - /* take pending signals */ - while ((sig = CURSIG(p)) != 0) - postsig(sig); - p->p_priority = p->p_usrpri; - if (want_resched) { - /* - * Since we are curproc, a clock interrupt could - * change our priority without changing run queues - * (the running process is not kept on a run queue). - * If this happened after we setrunqueue ourselves but - * before we switch()'ed, we might not be on the queue - * indicated by our priority. - */ - s = splstatclock(); - setrunqueue(p); - p->p_stats->p_ru.ru_nivcsw++; - mi_switch(); - splx(s); - while ((sig = CURSIG(p)) != 0) - postsig(sig); - } - - /* - * If profiling, charge recent system time to the trapped pc. - */ - if (p->p_flag & P_PROFIL) { - addupc_task(p, pc, (int)(p->p_sticks - oticks) * psratio); - } - - curpriority = p->p_priority; - } - static void printtrap(a0, a1, a2, entry, framep, isfatal, user) const unsigned long a0, a1, a2, entry; --- 86,91 ---- diff -c -N -r /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/alpha/include/cpu.h /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/alpha/include/cpu.h *** /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/alpha/include/cpu.h Fri Aug 27 20:38:42 1999 --- /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/alpha/include/cpu.h Thu Oct 28 18:06:29 1999 *************** *** 77,84 **** */ #define need_resched() { want_resched = 1; aston(); } - #define resched_wanted() want_resched - /* * Give a profiling tick to the current process when the user profiling * buffer pages are invalid. On the hp300, request an ast to send us --- 77,82 ---- diff -c -N -r /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/conf/options /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/conf/options *** /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/conf/options Mon Oct 25 18:07:30 1999 --- /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/conf/options Thu Oct 28 18:06:29 1999 *************** *** 69,78 **** UCONSOLE ICMP_BANDLIM ! # POSIX kernel options P1003_1B opt_posix.h _KPOSIX_PRIORITY_SCHEDULING opt_posix.h _KPOSIX_VERSION opt_posix.h # Do we want the config file compiled into the kernel? INCLUDE_CONFIG_FILE opt_config.h --- 69,89 ---- UCONSOLE ICMP_BANDLIM ! # POSIX kernel options. P1003_1B and priority scheduling are ! # now on by default. There are NO_ options to turn them off. ! # The positive options will go away after a grace period. ! ! NO_P1003_1B opt_posix.h P1003_1B opt_posix.h + NO_KPOSIX_PRIORITY_SCHEDULING opt_posix.h _KPOSIX_PRIORITY_SCHEDULING opt_posix.h _KPOSIX_VERSION opt_posix.h + + # Compile time disabling of RTPRIO + NO_RTPRIO opt_sched.h + + # Use RTPRIO and SMP even though it doesn't work + RTPRIO_AND_SMP_ANYWAY opt_sched.h # Do we want the config file compiled into the kernel? INCLUDE_CONFIG_FILE opt_config.h diff -c -N -r /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/dev/amr/amr.c /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/dev/amr/amr.c *** /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/dev/amr/amr.c Tue Oct 26 19:18:57 1999 --- /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/dev/amr/amr.c Thu Oct 28 18:06:29 1999 *************** *** 34,39 **** --- 34,40 ---- #include #include #include + #include #include #include diff -c -N -r /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/dev/ep/if_ep_isa.c /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/dev/ep/if_ep_isa.c *** /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/dev/ep/if_ep_isa.c Wed Oct 27 02:25:15 1999 --- /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/dev/ep/if_ep_isa.c Thu Oct 28 19:23:49 1999 *************** *** 131,136 **** --- 131,142 ---- } static void + bit_delay(void) + { + DELAY(DELAY_MULTIPLE * 10000); + } + + static void ep_isa_identify (driver_t *driver, device_t parent) { int tag = EP_LAST_TAG; *************** *** 147,153 **** outb(ELINK_ID_PORT, 0); outb(ELINK_ID_PORT, 0); ! elink_idseq(ELINK_509_POLY); elink_reset(); DELAY(DELAY_MULTIPLE * 10000); --- 153,159 ---- outb(ELINK_ID_PORT, 0); outb(ELINK_ID_PORT, 0); ! elink_idseq(ELINK_509_POLY, bit_delay); elink_reset(); DELAY(DELAY_MULTIPLE * 10000); *************** *** 156,162 **** outb(ELINK_ID_PORT, 0); outb(ELINK_ID_PORT, 0); ! elink_idseq(0xCF); /* For the first probe, clear all * board's tag registers. --- 162,168 ---- outb(ELINK_ID_PORT, 0); outb(ELINK_ID_PORT, 0); ! elink_idseq(0xCF, bit_delay); /* For the first probe, clear all * board's tag registers. diff -c -N -r /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/dev/mlx/mlx.c /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/dev/mlx/mlx.c *** /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/dev/mlx/mlx.c Tue Oct 26 19:20:42 1999 --- /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/dev/mlx/mlx.c Thu Oct 28 18:06:30 1999 *************** *** 34,39 **** --- 34,40 ---- #include #include #include + #include #include #include diff -c -N -r /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/i386/conf/LINT /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/i386/conf/LINT *** /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/i386/conf/LINT Wed Oct 27 02:30:10 1999 --- /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/i386/conf/LINT Thu Oct 28 18:06:30 1999 *************** *** 106,111 **** --- 106,112 ---- # Mandatory: options SMP # Symmetric MultiProcessor Kernel options APIC_IO # Symmetric (APIC) I/O + options RTPRIO_AND_SMP_ANYWAY # Even though they don't work together # Optional, these are the defaults plus 1: options NCPU=5 # number of CPUs diff -c -N -r /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/i386/i386/mp_machdep.c /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/i386/i386/mp_machdep.c *** /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/i386/i386/mp_machdep.c Fri Oct 15 17:38:15 1999 --- /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/i386/i386/mp_machdep.c Thu Oct 28 18:06:30 1999 *************** *** 29,34 **** --- 29,37 ---- #include "opt_cpu.h" #include "opt_user_ldt.h" + #warning Make non-SCHEDULER_FRIEND before commit + #define SCHEDULER_FRIEND + #ifdef SMP #include #else *************** *** 39,44 **** --- 42,48 ---- #include #include #include + #include #include #include #include *************** *** 2324,2336 **** } if (p != NULL) { p->p_cpticks++; ! if (++p->p_estcpu == 0) ! p->p_estcpu--; ! if ((p->p_estcpu & 3) == 0) { ! resetpriority(p); ! if (p->p_priority >= PUSER) ! p->p_priority = p->p_usrpri; ! } /* Update resource usage integrals and maximums. */ if ((pstats = p->p_stats) != NULL && --- 2328,2334 ---- } if (p != NULL) { p->p_cpticks++; ! update_estcpu(p); /* Update resource usage integrals and maximums. */ if ((pstats = p->p_stats) != NULL && diff -c -N -r /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/i386/i386/trap.c /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/i386/i386/trap.c *** /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/i386/i386/trap.c Fri Aug 27 20:43:51 1999 --- /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/i386/i386/trap.c Thu Oct 28 18:06:30 1999 *************** *** 51,56 **** --- 51,57 ---- #include #include #include + #include #include #include #include *************** *** 143,205 **** "machine check trap", /* 28 T_MCHK */ }; - static __inline void userret __P((struct proc *p, struct trapframe *frame, - u_quad_t oticks)); - #if defined(I586_CPU) && !defined(NO_F00F_HACK) extern int has_f00f_bug; #endif - - static __inline void - userret(p, frame, oticks) - struct proc *p; - struct trapframe *frame; - u_quad_t oticks; - { - int sig, s; - - while ((sig = CURSIG(p)) != 0) - postsig(sig); - - #if 0 - if (!want_resched && - (p->p_priority <= p->p_usrpri) && - (p->p_rtprio.type == RTP_PRIO_NORMAL)) { - int newpriority; - p->p_estcpu += 1; - newpriority = PUSER + p->p_estcpu / 4 + 2 * p->p_nice; - newpriority = min(newpriority, MAXPRI); - p->p_usrpri = newpriority; - } - #endif - - p->p_priority = p->p_usrpri; - if (want_resched) { - /* - * Since we are curproc, clock will normally just change - * our priority without moving us from one queue to another - * (since the running process is not on a queue.) - * If that happened after we setrunqueue ourselves but before we - * mi_switch()'ed, we might not be on the queue indicated by - * our priority. - */ - s = splhigh(); - setrunqueue(p); - p->p_stats->p_ru.ru_nivcsw++; - mi_switch(); - splx(s); - while ((sig = CURSIG(p)) != 0) - postsig(sig); - } - /* - * Charge system time if profiling. - */ - if (p->p_flag & P_PROFIL) - addupc_task(p, frame->tf_eip, - (u_int)(p->p_sticks - oticks) * psratio); - - curpriority = p->p_priority; - } /* * Exception, fault, and trap interface to the FreeBSD kernel. --- 144,152 ---- diff -c -N -r /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/i386/i386/vm_machdep.c /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/i386/i386/vm_machdep.c *** /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/i386/i386/vm_machdep.c Mon Oct 11 10:50:03 1999 --- /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/i386/i386/vm_machdep.c Thu Oct 28 18:06:31 1999 *************** *** 50,55 **** --- 50,56 ---- #include #include #include + #include #include #include #include diff -c -N -r /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/i386/ibcs2/ibcs2_misc.c /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/i386/ibcs2/ibcs2_misc.c *** /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/i386/ibcs2/ibcs2_misc.c Wed Sep 29 11:12:09 1999 --- /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/i386/ibcs2/ibcs2_misc.c Thu Oct 28 18:06:31 1999 *************** *** 65,70 **** --- 65,71 ---- #include #include #include + #include #include #include #include *************** *** 924,937 **** struct ibcs2_nice_args *uap; { int error; struct setpriority_args sa; SCARG(&sa, which) = PRIO_PROCESS; SCARG(&sa, who) = 0; ! SCARG(&sa, prio) = p->p_nice + SCARG(uap, incr); if ((error = setpriority(p, &sa)) != 0) return EPERM; ! p->p_retval[0] = p->p_nice; return 0; } --- 925,941 ---- struct ibcs2_nice_args *uap; { int error; + int nice; struct setpriority_args sa; + nice = synch_proc_priority(p, 0); + SCARG(&sa, which) = PRIO_PROCESS; SCARG(&sa, who) = 0; ! SCARG(&sa, prio) = nice + SCARG(uap, incr); if ((error = setpriority(p, &sa)) != 0) return EPERM; ! p->p_retval[0] = nice; return 0; } diff -c -N -r /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/i386/include/cpu.h /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/i386/include/cpu.h *** /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/i386/include/cpu.h Fri Aug 27 20:44:09 1999 --- /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/i386/include/cpu.h Thu Oct 28 18:06:31 1999 *************** *** 85,92 **** */ #define need_resched() { want_resched = 1; aston(); } - #define resched_wanted() want_resched - /* * Arrange to handle pending profiling ticks before returning to user mode. * --- 85,90 ---- diff -c -N -r /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/i386/isa/elink.c /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/i386/isa/elink.c *** /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/i386/isa/elink.c Fri Aug 27 20:44:41 1999 --- /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/i386/isa/elink.c Thu Oct 28 18:06:31 1999 *************** *** 58,72 **** /* * The `ID sequence' is really just snapshots of an 8-bit CRC register as 0 * bits are shifted in. Different board types use different polynomials. */ void ! elink_idseq(u_char p) { register int i; register u_char c; c = 0xff; for (i = 255; i; i--) { outb(ELINK_ID_PORT, c); if (c & 0x80) { c <<= 1; --- 58,75 ---- /* * The `ID sequence' is really just snapshots of an 8-bit CRC register as 0 * bits are shifted in. Different board types use different polynomials. + * + * Bit_delay is the appropriate bit delay for this architecture. */ void ! elink_idseq(u_char p, void (*bit_delay)(void)) { register int i; register u_char c; c = 0xff; for (i = 255; i; i--) { + (*bit_delay)(); outb(ELINK_ID_PORT, c); if (c & 0x80) { c <<= 1; diff -c -N -r /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/i386/isa/elink.h /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/i386/isa/elink.h *** /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/i386/isa/elink.h Fri Aug 27 20:44:41 1999 --- /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/i386/isa/elink.h Thu Oct 28 18:06:31 1999 *************** *** 40,43 **** #define ELINK_509_POLY 0xcf void elink_reset __P((void)); ! void elink_idseq __P((u_char p)); --- 40,43 ---- #define ELINK_509_POLY 0xcf void elink_reset __P((void)); ! void elink_idseq __P((u_char, void (*)(void))); diff -c -N -r /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/i386/isa/if_ie.c /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/i386/isa/if_ie.c *** /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/i386/isa/if_ie.c Mon Oct 11 14:53:59 1999 --- /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/i386/isa/if_ie.c Thu Oct 28 18:06:31 1999 *************** *** 401,406 **** --- 401,415 ---- } + /* + * This doesn't have a DELAY anywhere so one isn't put in + * as it was in if_ep. + */ + static void + bit_delay(void) + { + } + static int el_probe(struct isa_device *dvp) { *************** *** 422,429 **** /* Reset and put card in CONFIG state without changing address. */ elink_reset(); outb(ELINK_ID_PORT, 0x00); ! elink_idseq(ELINK_507_POLY); ! elink_idseq(ELINK_507_POLY); outb(ELINK_ID_PORT, 0xff); c = inb(PORT + IE507_MADDR); --- 431,438 ---- /* Reset and put card in CONFIG state without changing address. */ elink_reset(); outb(ELINK_ID_PORT, 0x00); ! elink_idseq(ELINK_507_POLY, bit_delay); ! elink_idseq(ELINK_507_POLY, bit_delay); outb(ELINK_ID_PORT, 0xff); c = inb(PORT + IE507_MADDR); *************** *** 435,441 **** } /* go to RUN state */ outb(ELINK_ID_PORT, 0x00); ! elink_idseq(ELINK_507_POLY); outb(ELINK_ID_PORT, 0x00); outb(PORT + IE507_CTRL, EL_CTRL_NRST); --- 444,450 ---- } /* go to RUN state */ outb(ELINK_ID_PORT, 0x00); ! elink_idseq(ELINK_507_POLY, bit_delay); outb(ELINK_ID_PORT, 0x00); outb(PORT + IE507_CTRL, EL_CTRL_NRST); diff -c -N -r /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/kern/init_main.c /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/kern/init_main.c *** /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/kern/init_main.c Mon Oct 11 11:19:08 1999 --- /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/kern/init_main.c Thu Oct 28 18:06:31 1999 *************** *** 51,56 **** --- 51,57 ---- #include #include #include + #include #include #include #include *************** *** 318,326 **** p->p_flag = P_INMEM | P_SYSTEM; p->p_stat = SRUN; ! p->p_nice = NZERO; ! p->p_rtprio.type = RTP_PRIO_NORMAL; ! p->p_rtprio.prio = 0; /* * Link for kernel based threads --- 319,325 ---- p->p_flag = P_INMEM | P_SYSTEM; p->p_stat = SRUN; ! synch_proc0_init(p); /* * Link for kernel based threads diff -c -N -r /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/kern/kern_clock.c /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/kern/kern_clock.c *** /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/kern/kern_clock.c Sun Oct 10 12:18:36 1999 --- /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/kern/kern_clock.c Thu Oct 28 18:06:31 1999 *************** *** 48,53 **** --- 48,54 ---- #include #include #include + #include #include #include #include *************** *** 392,398 **** * If this process is being profiled record the tick. */ p->p_uticks++; ! if (p->p_nice > NZERO) cp_time[CP_NICE]++; else cp_time[CP_USER]++; --- 393,400 ---- * If this process is being profiled record the tick. */ p->p_uticks++; ! ! if (synch_proc_isnice(p)) cp_time[CP_NICE]++; else cp_time[CP_USER]++; *************** *** 446,473 **** * programs: the amount of time in each cpu state. */ - /* - * We adjust the priority of the current process. The priority of - * a process gets worse as it accumulates CPU time. The cpu usage - * estimator (p_estcpu) is increased here. The formula for computing - * priorities (in kern_synch.c) will compute a different value each - * time p_estcpu increases by 4. The cpu usage estimator ramps up - * quite quickly when the process is running (linearly), and decays - * away exponentially, at a rate which is proportionally slower when - * the system is busy. The basic principal is that the system will - * 90% forget that the process used a lot of CPU time in 5 * loadav - * seconds. This causes the system to favor processes which haven't - * run much recently, and to round-robin among other processes. - */ if (p != NULL) { p->p_cpticks++; ! if (++p->p_estcpu == 0) ! p->p_estcpu--; ! if ((p->p_estcpu & 3) == 0) { ! resetpriority(p); ! if (p->p_priority >= PUSER) ! p->p_priority = p->p_usrpri; ! } /* Update resource usage integrals and maximums. */ if ((pstats = p->p_stats) != NULL && --- 448,456 ---- * programs: the amount of time in each cpu state. */ if (p != NULL) { p->p_cpticks++; ! update_estcpu(p); /* Update resource usage integrals and maximums. */ if ((pstats = p->p_stats) != NULL && diff -c -N -r /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/kern/kern_exit.c /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/kern/kern_exit.c *** /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/kern/kern_exit.c Mon Oct 11 16:33:12 1999 --- /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/kern/kern_exit.c Thu Oct 28 18:06:31 1999 *************** *** 48,53 **** --- 48,54 ---- #include #include #include + #include #include #include #include *************** *** 427,437 **** nfound++; if (p->p_stat == SZOMB) { ! /* charge childs scheduling cpu usage to parent */ ! if (curproc->p_pid != 1) { ! curproc->p_estcpu = min(curproc->p_estcpu + ! p->p_estcpu, UCHAR_MAX); ! } q->p_retval[0] = p->p_pid; #ifdef COMPAT_43 --- 428,434 ---- nfound++; if (p->p_stat == SZOMB) { ! synch_zombie_charge(p); q->p_retval[0] = p->p_pid; #ifdef COMPAT_43 diff -c -N -r /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/kern/kern_fork.c /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/kern/kern_fork.c *** /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/kern/kern_fork.c Mon Oct 11 11:19:08 1999 --- /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/kern/kern_fork.c Thu Oct 28 18:06:31 1999 *************** *** 49,54 **** --- 49,55 ---- #include #include #include + #include #include #include #include *************** *** 436,445 **** } #endif ! /* ! * set priority of child to be that of parent ! */ ! p2->p_estcpu = p1->p_estcpu; /* * This begins the section where we must prevent the parent --- 437,443 ---- } #endif ! synch_fork(p1, p2); /* * This begins the section where we must prevent the parent diff -c -N -r /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/kern/kern_resource.c /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/kern/kern_resource.c *** /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/kern/kern_resource.c Mon Oct 11 11:19:09 1999 --- /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/kern/kern_resource.c Thu Oct 28 18:06:31 1999 *************** *** 49,54 **** --- 49,55 ---- #include #include #include + #include #include #include *************** *** 57,63 **** #include #include - static int donice __P((struct proc *curp, struct proc *chgp, int n)); /* dosetrlimit non-static: Needed by SysVR4 emulator */ int dosetrlimit __P((struct proc *p, u_int which, struct rlimit *limp)); --- 58,63 ---- *************** *** 88,94 **** p = pfind(uap->who); if (p == 0) break; ! low = p->p_nice; break; case PRIO_PGRP: { --- 88,94 ---- p = pfind(uap->who); if (p == 0) break; ! low = synch_proc_priority(p, 0); break; case PRIO_PGRP: { *************** *** 100,107 **** break; for (p = pg->pg_members.lh_first; p != 0; p = p->p_pglist.le_next) { ! if (p->p_nice < low) ! low = p->p_nice; } break; } --- 100,108 ---- break; for (p = pg->pg_members.lh_first; p != 0; p = p->p_pglist.le_next) { ! int pri = synch_proc_priority(p, 0); ! if (pri < low) ! low = pri; } break; } *************** *** 109,118 **** case PRIO_USER: if (uap->who == 0) uap->who = curp->p_ucred->cr_uid; ! for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) if (p->p_ucred->cr_uid == uap->who && ! p->p_nice < low) ! low = p->p_nice; break; default: --- 110,121 ---- case PRIO_USER: if (uap->who == 0) uap->who = curp->p_ucred->cr_uid; ! for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) { ! int pri = synch_proc_priority(p, 0); if (p->p_ucred->cr_uid == uap->who && ! pri < low) ! low = pri; ! } break; default: *************** *** 186,213 **** return (error); } - static int - donice(curp, chgp, n) - register struct proc *curp, *chgp; - register int n; - { - register struct pcred *pcred = curp->p_cred; - - if (pcred->pc_ucred->cr_uid && pcred->p_ruid && - pcred->pc_ucred->cr_uid != chgp->p_ucred->cr_uid && - pcred->p_ruid != chgp->p_ucred->cr_uid) - return (EPERM); - if (n > PRIO_MAX) - n = PRIO_MAX; - if (n < PRIO_MIN) - n = PRIO_MIN; - if (n < chgp->p_nice && suser(curp)) - return (EACCES); - chgp->p_nice = n; - (void)resetpriority(chgp); - return (0); - } - /* rtprio system call */ #ifndef _SYS_SYSPROTO_H_ struct rtprio_args { --- 189,194 ---- *************** *** 228,234 **** register struct rtprio_args *uap; { register struct proc *p; - register struct pcred *pcred = curp->p_cred; struct rtprio rtp; int error; --- 209,214 ---- *************** *** 244,290 **** if (p == 0) return (ESRCH); ! switch (uap->function) { ! case RTP_LOOKUP: ! return (copyout(&p->p_rtprio, uap->rtp, sizeof(struct rtprio))); ! case RTP_SET: ! if (pcred->pc_ucred->cr_uid && pcred->p_ruid && ! pcred->pc_ucred->cr_uid != p->p_ucred->cr_uid && ! pcred->p_ruid != p->p_ucred->cr_uid) ! return (EPERM); ! /* disallow setting rtprio in most cases if not superuser */ ! if (suser(curp)) { ! /* can't set someone else's */ ! if (uap->pid) ! return (EPERM); ! /* can't set realtime priority */ ! /* ! * Realtime priority has to be restricted for reasons which should be ! * obvious. However, for idle priority, there is a potential for ! * system deadlock if an idleprio process gains a lock on a resource ! * that other processes need (and the idleprio process can't run ! * due to a CPU-bound normal process). Fix me! XXX ! */ ! #if 0 ! if (RTP_PRIO_IS_REALTIME(rtp.type)) ! #endif ! if (rtp.type != RTP_PRIO_NORMAL) ! return (EPERM); ! } ! switch (rtp.type) { ! #ifdef RTP_PRIO_FIFO ! case RTP_PRIO_FIFO: ! #endif ! case RTP_PRIO_REALTIME: ! case RTP_PRIO_NORMAL: ! case RTP_PRIO_IDLE: ! if (rtp.prio > RTP_PRIO_MAX) ! return (EINVAL); ! p->p_rtprio = rtp; ! return (0); ! default: ! return (EINVAL); ! } default: return (EINVAL); --- 224,237 ---- if (p == 0) return (ESRCH); ! switch (uap->function) { ! case RTP_LOOKUP: { ! (void)synch_proc_priority(p, &rtp); ! return (copyout(&rtp, uap->rtp, sizeof(struct rtprio))); ! } ! case RTP_SET: ! return dortprio(curp, p, &rtp); ! default: return (EINVAL); diff -c -N -r /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/kern/kern_sig.c /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/kern/kern_sig.c *** /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/kern/kern_sig.c Tue Oct 12 09:14:18 1999 --- /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/kern/kern_sig.c Thu Oct 28 18:06:32 1999 *************** *** 50,55 **** --- 50,56 ---- #include #include #include + #include #include #include #include *************** *** 1025,1033 **** action = SIG_DFL; } ! if (p->p_nice > NZERO && action == SIG_DFL && (prop & SA_KILL) && (p->p_flag & P_TRACED) == 0) ! p->p_nice = NZERO; if (prop & SA_CONT) SIG_STOPSIGMASK(p->p_siglist); --- 1026,1037 ---- action = SIG_DFL; } ! /* ! * Ensure that a process that is being killed can run. ! */ ! if (action == SIG_DFL && (prop & SA_KILL) && (p->p_flag & P_TRACED) == 0) ! synch_proc_killing(p); if (prop & SA_CONT) SIG_STOPSIGMASK(p->p_siglist); *************** *** 1176,1186 **** /*NOTREACHED*/ runfast: ! /* ! * Raise priority to at least PUSER. ! */ ! if (p->p_priority > PUSER) ! p->p_priority = PUSER; run: setrunnable(p); out: --- 1180,1187 ---- /*NOTREACHED*/ runfast: ! synch_proc_runfast(p); ! run: setrunnable(p); out: diff -c -N -r /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/kern/kern_subr.c /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/kern/kern_subr.c *** /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/kern/kern_subr.c Fri Aug 27 20:46:14 1999 --- /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/kern/kern_subr.c Thu Oct 28 18:06:32 1999 *************** *** 43,48 **** --- 43,49 ---- #include #include #include + #include #include #include #include *************** *** 53,60 **** #include #include - static void uio_yield __P((void)); - int uiomove(cp, n, uio) register caddr_t cp; --- 54,59 ---- *************** *** 91,98 **** case UIO_USERSPACE: case UIO_USERISPACE: ! if (ticks - switchticks >= hogticks) ! uio_yield(); if (uio->uio_rw == UIO_READ) error = copyout(cp, iov->iov_base, cnt); else --- 90,97 ---- case UIO_USERSPACE: case UIO_USERISPACE: ! if (resched_wanted()) ! synch_yield(curproc, 0); if (uio->uio_rw == UIO_READ) error = copyout(cp, iov->iov_base, cnt); else *************** *** 153,160 **** case UIO_USERSPACE: case UIO_USERISPACE: ! if (ticks - switchticks >= hogticks) ! uio_yield(); if (uio->uio_rw == UIO_READ) { #ifdef ENABLE_VFS_IOOPT if (vfs_ioopt && ((cnt & PAGE_MASK) == 0) && --- 152,159 ---- case UIO_USERSPACE: case UIO_USERISPACE: ! if (resched_wanted()) ! synch_yield(curproc, 0); if (uio->uio_rw == UIO_READ) { #ifdef ENABLE_VFS_IOOPT if (vfs_ioopt && ((cnt & PAGE_MASK) == 0) && *************** *** 235,242 **** cnt &= ~PAGE_MASK; ! if (ticks - switchticks >= hogticks) ! uio_yield(); error = vm_uiomove(&curproc->p_vmspace->vm_map, obj, uio->uio_offset, cnt, (vm_offset_t) iov->iov_base, &npagesmoved); --- 234,241 ---- cnt &= ~PAGE_MASK; ! if (resched_wanted()) ! synch_yield(curproc, 0); error = vm_uiomove(&curproc->p_vmspace->vm_map, obj, uio->uio_offset, cnt, (vm_offset_t) iov->iov_base, &npagesmoved); *************** *** 413,431 **** LIST_INIT(&hashtbl[i]); *nentries = hashsize; return (hashtbl); - } - - static void - uio_yield() - { - struct proc *p; - int s; - - p = curproc; - p->p_priority = p->p_usrpri; - s = splhigh(); - setrunqueue(p); - p->p_stats->p_ru.ru_nivcsw++; - mi_switch(); - splx(s); } --- 412,415 ---- diff -c -N -r /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/kern/kern_switch.c /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/kern/kern_switch.c *** /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/kern/kern_switch.c Thu Aug 19 12:06:08 1999 --- /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/kern/kern_switch.c Thu Oct 28 18:06:32 1999 *************** *** 26,35 **** --- 26,43 ---- * $FreeBSD: src/sys/kern/kern_switch.c,v 1.3 1999/08/19 16:06:08 peter Exp $ */ + /* + * Enable access to scheduler members. + */ + #define SCHEDULER_FRIEND + + #include "opt_sched.h" + #include #include #include #include + #include #include #include *************** *** 46,56 **** * queue. */ struct rq queues[NQS]; - struct rq rtqueues[NQS]; - struct rq idqueues[NQS]; u_int32_t queuebits; u_int32_t rtqueuebits; u_int32_t idqueuebits; /* * Initialize the run queues at boot time. --- 54,67 ---- * queue. */ struct rq queues[NQS]; u_int32_t queuebits; + + #ifndef NO_RTPRIO + struct rq rtqueues[NQS]; u_int32_t rtqueuebits; + struct rq idqueues[NQS]; u_int32_t idqueuebits; + #endif /* * Initialize the run queues at boot time. *************** *** 62,69 **** --- 73,82 ---- for (i = 0; i < NQS; i++) { TAILQ_INIT(&queues[i]); + #ifndef NO_RTPRIO TAILQ_INIT(&rtqueues[i]); TAILQ_INIT(&idqueues[i]); + #endif } } SYSINIT(runqueue, SI_SUB_RUN_QUEUE, SI_ORDER_FIRST, rqinit, NULL) *************** *** 82,87 **** --- 95,105 ---- u_int8_t pri; KASSERT(p->p_stat == SRUN, ("setrunqueue: proc not SRUN")); + #ifdef NO_RTPRIO + pri = p->p_priority >> 2; + q = &queues[pri]; + queuebits |= 1 << pri; + #else if (p->p_rtprio.type == RTP_PRIO_NORMAL) { pri = p->p_priority >> 2; q = &queues[pri]; *************** *** 98,103 **** --- 116,133 ---- } else { panic("setrunqueue: invalid rtprio type"); } + #endif + + /* XXX This is a little dangerous. We're looking up which + * queue to take the process off in remrunqueue from the scheduling + * class and saving this index in the proc. + * Instead here we ought to save everything + * (return a pointer to a {whichqueue,queuebits} structure) - + * then there isn't the possibility of someone changing + * p_rtprio.type and then calling remrunqueue. Also we don't need + * to look the queue up. + */ + p->p_rqindex = pri; /* remember the queue index */ TAILQ_INSERT_TAIL(q, p, p_procq); } *************** *** 115,120 **** --- 145,154 ---- u_int8_t pri; pri = p->p_rqindex; + #ifdef NO_RTPRIO + q = &queues[pri]; + which = &queuebits; + #else if (p->p_rtprio.type == RTP_PRIO_NORMAL) { q = &queues[pri]; which = &queuebits; *************** *** 128,133 **** --- 162,168 ---- } else { panic("remrunqueue: invalid rtprio type"); } + #endif TAILQ_REMOVE(q, p, p_procq); if (TAILQ_EMPTY(q)) { KASSERT((*which & (1 << pri)) != 0, *************** *** 144,150 **** --- 179,189 ---- u_int32_t procrunnable(void) { + #ifdef NO_RTPRIO + return (queuebits); + #else return (rtqueuebits || queuebits || idqueuebits); + #endif } /* *************** *** 159,164 **** --- 198,204 ---- * are mapped four priority levels per queue, this may allow the cpu to * choose a slightly lower priority process in order to preserve the cpu * caches. + * XXX This affinity doesn't play with a FIFO scheduler. */ struct proc * chooseproc(void) *************** *** 171,176 **** --- 211,226 ---- u_char id; #endif + #ifdef NO_RTPRIO + if (queuebits) { + pri = ffs(queuebits) - 1; + q = &queues[pri]; + which = &queuebits; + } else { + return NULL; + } + #else + if (rtqueuebits) { pri = ffs(rtqueuebits) - 1; q = &rtqueues[pri]; *************** *** 186,194 **** --- 236,248 ---- } else { return NULL; } + #endif p = TAILQ_FIRST(q); KASSERT(p, ("chooseproc: no proc on busy queue")); + #ifdef SMP + /* XXX Take this out for non-roundrobin scheduling classes */ + /* wander down the current run queue for this pri level for a match */ id = cpuid; while (p->p_lastcpu != id) { *************** *** 199,204 **** --- 253,259 ---- } } #endif + TAILQ_REMOVE(q, p, p_procq); if (TAILQ_EMPTY(q)) *which &= ~(1 << pri); diff -c -N -r /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/kern/kern_synch.c /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/kern/kern_synch.c *** /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/kern/kern_synch.c Wed Sep 29 11:03:42 1999 --- /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/kern/kern_synch.c Fri Oct 29 08:16:49 1999 *************** *** 39,49 **** --- 39,56 ---- * $FreeBSD: src/sys/kern/kern_synch.c,v 1.79 1999/09/29 15:03:42 marcel Exp $ */ + /* + * Enable access to scheduler members. + */ + #define SCHEDULER_FRIEND + #include "opt_ktrace.h" + #include "opt_sched.h" #include #include #include + #include #include #include #include *************** *** 62,72 **** #endif #include /* for UCHAR_MAX = typeof(p_priority)_MAX */ static void sched_setup __P((void *dummy)); SYSINIT(sched_setup, SI_SUB_KICK_SCHEDULER, SI_ORDER_FIRST, sched_setup, NULL) ! u_char curpriority; ! int hogticks; int lbolt; int sched_quantum; /* Roundrobin scheduling quantum in ticks. */ --- 69,95 ---- #endif #include /* for UCHAR_MAX = typeof(p_priority)_MAX */ + #define MAX_ESTCPU UCHAR_MAX + + /* RTPRIO doesn't work with SMP yet. + */ + #if defined(SMP) && !defined(NO_RTPRIO) && !defined RTPRIO_AND_SMP_ANYWAY + #error RTPRIO and SMP work incorrectly together (but sorta work). \ + Enable either NO_RTPRIO or RTPRIO_AND_SMP_ANYWAY + #endif + + #ifdef NO_RTPRIO + #define NORMAL_SCHEDULER(P) (1) + #define REALTIME_SCHEDULER(P) (0) + #else + #define NORMAL_SCHEDULER(P) ((P)->p_rtprio.type == RTP_PRIO_NORMAL) + #define REALTIME_SCHEDULER(P) (RTP_PRIO_IS_REALTIME((P)->p_rtprio.type)) + #endif + static void sched_setup __P((void *dummy)); SYSINIT(sched_setup, SI_SUB_KICK_SCHEDULER, SI_ORDER_FIRST, sched_setup, NULL) ! static int hogticks; int lbolt; int sched_quantum; /* Roundrobin scheduling quantum in ticks. */ *************** *** 74,79 **** --- 97,106 ---- static void roundrobin __P((void *arg)); static void schedcpu __P((void *arg)); static void updatepri __P((struct proc *p)); + static void resetpriority __P((struct proc *p)); + + + #define PPQ (128 / NQS) /* priorities per queue */ static int sysctl_kern_quantum SYSCTL_HANDLER_ARGS *************** *** 94,121 **** SYSCTL_PROC(_kern, OID_AUTO, quantum, CTLTYPE_INT|CTLFLAG_RW, 0, sizeof sched_quantum, sysctl_kern_quantum, "I", ""); ! /* maybe_resched: Decide if you need to reschedule or not ! * taking the priorities and schedulers into account. */ ! static void maybe_resched(struct proc *chk) { ! struct proc *p = curproc; /* XXX */ ! /* ! * Compare priorities if the new process is on the same scheduler, ! * otherwise the one on the more realtimeish scheduler wins. ! * ! * XXX idle scheduler still broken because proccess stays on idle ! * scheduler during waits (such as when getting FS locks). If a ! * standard process becomes runaway cpu-bound, the system can lockup ! * due to idle-scheduler processes in wakeup never getting any cpu. ! */ ! if (p == 0 || ! (chk->p_priority < curpriority && RTP_PRIO_BASE(p->p_rtprio.type) == RTP_PRIO_BASE(chk->p_rtprio.type)) || ! RTP_PRIO_BASE(chk->p_rtprio.type) < RTP_PRIO_BASE(p->p_rtprio.type) ! ) { need_resched(); } } int --- 121,214 ---- SYSCTL_PROC(_kern, OID_AUTO, quantum, CTLTYPE_INT|CTLFLAG_RW, 0, sizeof sched_quantum, sysctl_kern_quantum, "I", ""); ! static u_short curpriority; ! ! /* ! * prioritize: Compute the priority for a process. ! * ! * For normal processes this is basically the kernel priority divided ! * by the number of priorities per queue, that is, which priority ! * queue it is in. ! * ! * For fixed-scheduler priorities this is the priority ! * in the low byte together with the class in the high byte. ! */ ! ! #ifdef NO_RTPRIO ! #define prioritize(P) ((P)->p_priority / PPQ) ! #else ! ! /* ! * prioritize: Compute a priority based on the type of scheduler. */ ! static u_short ! prioritize(struct proc *p) { ! u_short priority; ! int class = RTP_PRIO_BASE(p->p_rtprio.type); ! if (class == RTP_PRIO_NORMAL) ! priority = (RTP_PRIO_NORMAL << 8) | (p->p_priority / PPQ); ! else ! priority = (class << 8) | p->p_rtprio.prio; ! ! return priority; ! } ! #endif ! ! /* ! * curpriority_cmp: Compare the priorities. Return: ! * <0: p < curpriority ! * 0: p == curpriority ! * >0: p > curpriority ! */ ! ! static int ! curpriority_cmp(struct proc *p) ! { ! return prioritize(p) - curpriority; ! } ! ! /* ! * maybe_resched: Decide if you need to reschedule or not, ! * taking the priorities and schedulers into account. ! * ! * This function needs to be call AFTER chk->p_priority has ! * been updated. ! */ ! static void ! maybe_resched(struct proc *chk) ! { ! if (curproc == 0) { need_resched(); } + else if (chk == curproc) { + /* + * If chk is curproc, we may need to preempt if + * we're making our priority less favorable. + * Yield the CPU. + */ + if (curpriority_cmp(chk) > 0) { + /* + * XXX Possibly increment nvcsw here, + * though we don't actually know. + */ + need_resched(); + } + } + /* + * If chk is not the curproc, we want to preempt if chk has + * a more favorable priority than curproc. + * + * We shouldn't preempt the current process because of the + * priority of a sleeping or stopped process. + * + */ + else if ((chk->p_flag & P_INMEM) && + chk->p_stat == SRUN && + curpriority_cmp(chk) < 0) { + need_resched(); + } } int *************** *** 132,147 **** roundrobin(arg) void *arg; { ! #ifndef SMP struct proc *p = curproc; /* XXX */ ! #endif ! ! #ifdef SMP need_resched(); forward_roundrobin(); ! #else ! if (p == 0 || RTP_PRIO_NEED_RR(p->p_rtprio.type)) ! need_resched(); #endif timeout(roundrobin, NULL, sched_quantum); --- 225,242 ---- roundrobin(arg) void *arg; { ! #if !defined(SMP) && !defined(NO_RTPRIO) struct proc *p = curproc; /* XXX */ ! ! if (p == 0 || RTP_PRIO_NEED_RR(p->p_rtprio.type)) { ! need_resched(); ! } ! #else need_resched(); + + #ifdef SMP forward_roundrobin(); ! #endif #endif timeout(roundrobin, NULL, sched_quantum); *************** *** 238,243 **** --- 333,364 ---- #define CCPU_SHIFT 11 /* + * Adjust the run queues in case the priority has changed enough + * to move a process into another run queue. + * + * Must be called splhigh(). + */ + + static void + adjust_runqueues(struct proc *p) + { + if (p->p_priority >= PUSER) { + if ((p != curproc) && + #ifdef SMP + (u_char)p->p_oncpu == 0xff && /* idle */ + #endif + p->p_stat == SRUN && + (p->p_flag & P_INMEM) && + (p->p_priority / PPQ) != (p->p_usrpri / PPQ)) { + remrunqueue(p); + p->p_priority = p->p_usrpri; + setrunqueue(p); + } else + p->p_priority = p->p_usrpri; + } + } + + /* * Recompute process priorities, every hz ticks. */ /* ARGSUSED */ *************** *** 281,303 **** (p->p_cpticks * FSCALE / realstathz)) >> FSHIFT; #endif p->p_cpticks = 0; ! newcpu = (u_int) decay_cpu(loadfac, p->p_estcpu) + p->p_nice; ! p->p_estcpu = min(newcpu, UCHAR_MAX); ! resetpriority(p); ! if (p->p_priority >= PUSER) { ! #define PPQ (128 / NQS) /* priorities per queue */ ! if ((p != curproc) && ! #ifdef SMP ! p->p_oncpu == 0xff && /* idle */ ! #endif ! p->p_stat == SRUN && ! (p->p_flag & P_INMEM) && ! (p->p_priority / PPQ) != (p->p_usrpri / PPQ)) { ! remrunqueue(p); ! p->p_priority = p->p_usrpri; ! setrunqueue(p); ! } else ! p->p_priority = p->p_usrpri; } splx(s); } --- 402,414 ---- (p->p_cpticks * FSCALE / realstathz)) >> FSHIFT; #endif p->p_cpticks = 0; ! if (NORMAL_SCHEDULER(p)) { ! newcpu = (u_int) decay_cpu(loadfac, p->p_estcpu) + ! p->p_nice; ! p->p_estcpu = min(newcpu, MAX_ESTCPU); ! resetpriority(p); ! adjust_runqueues(p); ! maybe_resched(p); } splx(s); } *************** *** 315,332 **** updatepri(p) register struct proc *p; { ! register unsigned int newcpu = p->p_estcpu; ! register fixpt_t loadfac = loadfactor(averunnable.ldavg[0]); ! ! if (p->p_slptime > 5 * loadfac) ! p->p_estcpu = 0; ! else { ! p->p_slptime--; /* the first time was done in schedcpu */ ! while (newcpu && --p->p_slptime) ! newcpu = (int) decay_cpu(loadfac, newcpu); ! p->p_estcpu = min(newcpu, UCHAR_MAX); } ! resetpriority(p); } /* --- 426,448 ---- updatepri(p) register struct proc *p; { ! if (NORMAL_SCHEDULER(p) && p->p_slptime > 1) { ! register unsigned int newcpu = p->p_estcpu; ! register fixpt_t loadfac = loadfactor(averunnable.ldavg[0]); ! ! if (p->p_slptime > 5 * loadfac) ! p->p_estcpu = 0; ! else { ! p->p_slptime--; /* first time was done in schedcpu */ ! while (newcpu && --p->p_slptime) ! newcpu = (int) decay_cpu(loadfac, newcpu); ! p->p_estcpu = min(newcpu, MAX_ESTCPU); ! } ! resetpriority(p); ! adjust_runqueues(p); ! maybe_resched(p); } ! p->p_slptime = 0; } /* *************** *** 440,446 **** p->p_stats->p_ru.ru_nvcsw++; mi_switch(); resume: ! curpriority = p->p_usrpri; splx(s); p->p_flag &= ~P_SINTR; if (p->p_flag & P_TIMEOUT) { --- 556,562 ---- p->p_stats->p_ru.ru_nvcsw++; mi_switch(); resume: ! curpriority = prioritize(p); splx(s); p->p_flag &= ~P_SINTR; if (p->p_flag & P_TIMEOUT) { *************** *** 579,585 **** p->p_stats->p_ru.ru_nvcsw++; mi_switch(); resume: ! curpriority = p->p_usrpri; splx(s); p->p_flag &= ~P_SINTR; --- 695,701 ---- p->p_stats->p_ru.ru_nvcsw++; mi_switch(); resume: ! curpriority = prioritize(p); splx(s); p->p_flag &= ~P_SINTR; *************** *** 676,686 **** } /* ! * Make all processes sleeping on the specified identifier runnable. */ ! void ! wakeup(ident) ! register void *ident; { register struct slpquehead *qp; register struct proc *p; --- 792,801 ---- } /* ! * Implement common wakeup code for wakeup_one and wakeup. */ ! static void ! wakeup_some(void *ident, int one_only) { register struct slpquehead *qp; register struct proc *p; *************** *** 695,703 **** p->p_wchan = 0; if (p->p_stat == SSLEEP) { /* OPTIMIZED EXPANSION OF setrunnable(p); */ ! if (p->p_slptime > 1) ! updatepri(p); ! p->p_slptime = 0; p->p_stat = SRUN; if (p->p_flag & P_INMEM) { setrunqueue(p); --- 810,816 ---- p->p_wchan = 0; if (p->p_stat == SSLEEP) { /* OPTIMIZED EXPANSION OF setrunnable(p); */ ! updatepri(p); p->p_stat = SRUN; if (p->p_flag & P_INMEM) { setrunqueue(p); *************** *** 707,713 **** wakeup((caddr_t)&proc0); } /* END INLINE EXPANSION */ ! goto restart; } } } --- 820,828 ---- wakeup((caddr_t)&proc0); } /* END INLINE EXPANSION */ ! if (!one_only) ! goto restart; ! break; } } } *************** *** 715,758 **** } /* * Make a process sleeping on the specified identifier runnable. ! * May wake more than one process if a target prcoess is currently * swapped out. */ void wakeup_one(ident) register void *ident; { ! register struct slpquehead *qp; ! register struct proc *p; ! int s; ! ! s = splhigh(); ! qp = &slpque[LOOKUP(ident)]; ! ! for (p = qp->tqh_first; p != NULL; p = p->p_procq.tqe_next) { ! if (p->p_wchan == ident) { ! TAILQ_REMOVE(qp, p, p_procq); ! p->p_wchan = 0; ! if (p->p_stat == SSLEEP) { ! /* OPTIMIZED EXPANSION OF setrunnable(p); */ ! if (p->p_slptime > 1) ! updatepri(p); ! p->p_slptime = 0; ! p->p_stat = SRUN; ! if (p->p_flag & P_INMEM) { ! setrunqueue(p); ! maybe_resched(p); ! break; ! } else { ! p->p_flag |= P_SWAPINREQ; ! wakeup((caddr_t)&proc0); ! } ! /* END INLINE EXPANSION */ ! } ! } ! } ! splx(s); } /* --- 830,854 ---- } /* + * Make all processes sleeping on the specified identifier runnable. + */ + void + wakeup(ident) + register void *ident; + { + wakeup_some(ident, 0); + } + + /* * Make a process sleeping on the specified identifier runnable. ! * May wake more than one process if a target process is currently * swapped out. */ void wakeup_one(ident) register void *ident; { ! wakeup_some(ident, 1); } /* *************** *** 856,867 **** break; } p->p_stat = SRUN; if (p->p_flag & P_INMEM) setrunqueue(p); splx(s); - if (p->p_slptime > 1) - updatepri(p); - p->p_slptime = 0; if ((p->p_flag & P_INMEM) == 0) { p->p_flag |= P_SWAPINREQ; wakeup((caddr_t)&proc0); --- 952,969 ---- break; } p->p_stat = SRUN; + /* + * XXX We were doing the setrunqueue here and then updatepri later. + * This is backwards from the "wakeup()" case, which seems + * correct and claims to be an optimized "setrunnable()". + * You'll wind up in the wrong run queue here. Same as in 4.4Lite + * This changes it. + */ + updatepri(p); + if (p->p_flag & P_INMEM) setrunqueue(p); splx(s); if ((p->p_flag & P_INMEM) == 0) { p->p_flag |= P_SWAPINREQ; wakeup((caddr_t)&proc0); *************** *** 872,893 **** /* * Compute the priority of a process when running in user mode. ! * Arrange to reschedule if the resulting priority is better * than that of the current process. */ ! void resetpriority(p) register struct proc *p; { register unsigned int newpriority; ! if (p->p_rtprio.type == RTP_PRIO_NORMAL) { ! newpriority = PUSER + p->p_estcpu / 4 + 2 * p->p_nice; ! newpriority = min(newpriority, MAXPRI); ! p->p_usrpri = newpriority; } ! maybe_resched(p); } /* ARGSUSED */ static void --- 974,1444 ---- /* * Compute the priority of a process when running in user mode. ! * ! * Unlike the original 4.4Lite resetpriority, this no longer ! * arranges to reschedule if the resulting priority is better * than that of the current process. */ ! static void resetpriority(p) register struct proc *p; { register unsigned int newpriority; ! newpriority = PUSER + p->p_estcpu / 4 + 2 * p->p_nice; ! newpriority = min(newpriority, MAXPRI); ! p->p_usrpri = newpriority; ! } ! ! /* ! * We adjust the priority of the current process. The priority of ! * a process gets worse as it accumulates CPU time. The cpu usage ! * estimator (p_estcpu) is increased here. The formula for computing ! * priorities (in kern_synch.c) will compute a different value each ! * time p_estcpu increases by 4. The cpu usage estimator ramps up ! * quite quickly when the process is running (linearly), and decays ! * away exponentially, at a rate which is proportionally slower when ! * the system is busy. The basic principal is that the system will ! * 90% forget that the process used a lot of CPU time in 5 * loadav ! * seconds. This causes the system to favor processes which haven't ! * run much recently, and to round-robin among other processes. ! */ ! void ! update_estcpu(p) ! register struct proc *p; ! { ! if (NORMAL_SCHEDULER(p) && p->p_estcpu < MAX_ESTCPU) { ! p->p_estcpu++; ! if ((p->p_estcpu & 3) == 0) { ! resetpriority(p); ! if (p->p_priority >= PUSER) ! p->p_priority = p->p_usrpri; ! } ! } ! } ! ! /* ! * synch_yield: Yield the CPU. ! * ! * Provide compatability with the "yield" system call from sys/thread. ! * I'm not sure if this behavior, which sinks you to the bottom of your ! * priorities, is needed. ! * ! * Without this flag you go to the end of your priority queue, and so if ! * you are still the highest priority process you will continue. This ! * is the POSIX defined behavior. ! * ! * The flag is ignored unless the current process is in the normal ! * scheduler class. ! */ ! ! int ! synch_yield(struct proc *p, const int is_thread) ! { ! int s = splhigh(); ! KASSERT(p == curproc, ("synch_yield")); ! ! if (NORMAL_SCHEDULER(p) && is_thread) ! p->p_priority = MAXPRI; ! ! setrunqueue(p); ! ! /* ! * XXX In the RTPRIO case ru_nvcsw can include unneeded ! * voluntary context switches to ourself. ! */ ! ! p->p_stats->p_ru.ru_nvcsw++; ! mi_switch(); ! splx(s); ! ! return 0; ! } ! ! /* ! * Initialize the scheduling info for proc0 ! */ ! void ! synch_proc0_init(struct proc *p0) ! { ! p0->p_nice = NZERO; ! ! #ifndef NO_RTPRIO ! p0->p_rtprio.type = RTP_PRIO_NORMAL; ! p0->p_rtprio.prio = 0; ! #endif ! } ! ! /* ! * Is a process running at a nice level? For now say idle priority ! * and nice processes are nice. ! */ ! int ! synch_proc_isnice(struct proc *p) ! { ! #ifdef NO_RTPRIO ! return p->p_nice > NZERO; ! #else ! return ( (p->p_rtprio.type == RTP_PRIO_IDLE) || ! (NORMAL_SCHEDULER(p) && p->p_nice > NZERO) ); ! #endif ! } ! ! /* ! * Return the current process priority. Since clients ! * expect this to return "p_nice" for now it does, and those ! * that know can get back the rtp. ! * ! * vm_glue uses this (p->p_nice) for selecting what to swap ! * back in. ! * ! * "ibcs2_nice" uses this to get back the nice value. ! */ ! int ! synch_proc_priority(struct proc *p, struct rtprio *rtp) ! { ! int nice; ! #ifdef NO_RTPRIO ! nice = p->p_nice; ! #else ! if (rtp) ! *rtp = p->p_rtprio; ! ! switch(p->p_rtprio.type) { ! case RTP_PRIO_REALTIME: ! nice = PRIO_MIN; ! break; ! ! case RTP_PRIO_IDLE: ! nice = PRIO_MAX; ! break; ! ! case RTP_PRIO_NORMAL: ! default: ! nice = p->p_nice; ! break; ! } ! #endif ! ! return nice; ! } ! ! /* ! * Ensure that a process that is being killed can run. ! * ! */ ! void ! synch_proc_killing(struct proc *p) ! { ! if (p->p_nice > NZERO) ! return donice(0, p, NZERO); ! } ! ! /* ! * Ensure we run fast. ! */ ! void ! synch_proc_runfast(struct proc *p) ! { ! /* ! * Raise kernel priority to at least PUSER. ! */ ! if (p->p_priority > PUSER) ! p->p_priority = PUSER; ! } ! ! /* ! * Force a process to run. This is called in vm_pageout_scan when ! * it selects a process to kill. Be careful if you change this ! * that it works properly for all flavors of processes - donice ! * is guaranteed to; the old version didn't. Since curproc better ! * be the pager this should work. ! * ! */ ! int ! synch_proc_force_runnable(struct proc *p) ! { ! return donice(0, p, PRIO_MIN); ! } ! ! /* ! * Don't swapout a realtime process or one waiting on a critical event ! * of some kind. This is used by swapout_procs in deciding what can ! * be swapped out. ! */ ! int ! synch_proc_unswappable(struct proc *p) ! { ! #ifdef NO_RTPRIO ! return ((p->p_priority & 0x7f) < PSOCK); ! #else ! return ( (p->p_rtprio.type == RTP_PRIO_REALTIME) || ! ((p->p_priority & 0x7f) < PSOCK) ); ! #endif ! } ! ! /* ! * Return true for a process waiting at a high kernel priority process. ! * This is used in vm_meter for keeping track of statitics of jobs in ! * "disk wait". Historically these were the uninterruptible sleeping ! * processes. I'm not sure if this has much meaning now. ! */ ! int ! synch_proc_uninterruptible(struct proc *p) ! { ! return p->p_priority <= PZERO; ! } ! ! /* ! * Charge a zombie process to the estimated CPU time for the parent. ! */ ! void ! synch_zombie_charge(struct proc *p) ! { ! /* charge child's scheduling cpu usage to parent */ ! if (curproc->p_pid != 1) { ! curproc->p_estcpu = min(curproc->p_estcpu + p->p_estcpu, UCHAR_MAX); ! } ! } ! ! /* ! * Set up for a fork. ! * XXX FreeBSD extension - sysctl'ize. ! */ ! void ! synch_fork(struct proc *parent, struct proc *child) ! { ! /* ! * set priority of child to be that of parent ! */ ! child->p_estcpu = parent->p_estcpu; ! } ! ! /* ! * synch_compare: Decide which of two runnable processes is to be ! * preferred. ! * ! * The runner with the highest cpu utilization is picked (p_estcpu). ! * Ties are broken by picking the highest pid. ! * ! * This is taken from and currently only used in tty.c. ! */ ! int ! synch_compare(struct proc *p1, struct proc *p2) ! { ! if (p2->p_estcpu > p1->p_estcpu) ! return (1); ! if (p1->p_estcpu > p2->p_estcpu) ! return (0); ! return (p2->p_pid > p1->p_pid); /* tie - return highest pid */ ! } ! ! /* ! * resched_wanted: Do we want to reschedule. ! * ! * XXX This was added to get around DOS attacks via huge uiomoves in ! * rawio. The only client is kern_subr. ! * We shouldn't do this if curproc is rtprio unless we need a reschedule. ! */ ! ! int ! resched_wanted(void) ! { ! return (ticks - switchticks >= hogticks); ! } ! ! int ! donice(curp, chgp, n) ! register struct proc *curp, *chgp; ! register int n; ! { ! int s; ! register struct pcred *pcred; ! ! if (n > PRIO_MAX) ! n = PRIO_MAX; ! if (n < PRIO_MIN) ! n = PRIO_MIN; ! ! if (curp) { ! pcred = curp->p_cred; ! ! if (pcred->pc_ucred->cr_uid && pcred->p_ruid && ! pcred->pc_ucred->cr_uid != chgp->p_ucred->cr_uid && ! pcred->p_ruid != chgp->p_ucred->cr_uid) ! return (EPERM); ! ! if (n < chgp->p_nice && suser(curp)) ! return (EACCES); ! } ! ! s = splhigh(); ! ! chgp->p_nice = n; ! ! /* Be sure that if you're switching schedulers you ! * get it off the correct run queue: ! */ ! ! #ifndef NO_RTPRIO ! if (!NORMAL_SCHEDULER(chgp) && ! (chgp != curproc) && ! #ifdef SMP ! (u_char)chgp->p_oncpu == 0xff && /* idle */ ! #endif ! chgp->p_stat == SRUN && ! (chgp->p_flag & P_INMEM)) { ! remrunqueue(chgp); ! chgp->p_rtprio.type = RTP_PRIO_NORMAL; ! setrunqueue(chgp); ! } else { ! chgp->p_rtprio.type = RTP_PRIO_NORMAL; ! resetpriority(chgp); ! adjust_runqueues(chgp); ! } ! #else ! resetpriority(chgp); ! adjust_runqueues(chgp); ! #endif ! splx(s); ! ! maybe_resched(chgp); ! ! return (0); } + + int + dortprio(struct proc *curp, struct proc *chgp, struct rtprio *rtp) + { + #ifdef NO_RTPRIO + return ENOSYS; + #else + register struct pcred *pcred = curp->p_cred; + + if (pcred->pc_ucred->cr_uid && pcred->p_ruid && + pcred->pc_ucred->cr_uid != chgp->p_ucred->cr_uid && + pcred->p_ruid != chgp->p_ucred->cr_uid) + return (EPERM); + + /* disallow setting rtprio in most cases if not superuser */ + if (suser(curp)) { + /* can't set someone else's */ + if (curp != chgp) + return (EPERM); + /* + * Realtime priority has to be restricted for reasons which should be + * obvious. However, for idle priority, there is a potential for + * system deadlock if an idleprio process gains a lock on a resource + * that other processes need (and the idleprio process can't run + * due to a CPU-bound normal process). Fix me! XXX + * + * Be careful when the above restriction is removed not to let a + * regular process lower its nice value. + * + */ + #if 0 + if (RTP_PRIO_IS_REALTIME(rtp->type)) + #endif + if (rtp->type != RTP_PRIO_NORMAL) + return (EPERM); + } + + switch (rtp->type) { + #ifdef RTP_PRIO_FIFO + case RTP_PRIO_FIFO: + #endif + case RTP_PRIO_REALTIME: + case RTP_PRIO_NORMAL: + case RTP_PRIO_IDLE: + if (rtp->prio > RTP_PRIO_MAX) + return (EINVAL); + if ((chgp != curproc) && + #ifdef SMP + (u_char)chgp->p_oncpu == 0xff && /* idle */ + #endif + chgp->p_stat == SRUN && + (chgp->p_flag & P_INMEM) && + (chgp->p_rtprio.type != rtp->type || + chgp->p_rtprio.prio != rtp->prio)) { + remrunqueue(chgp); + chgp->p_rtprio = *rtp; + setrunqueue(chgp); + } else + chgp->p_rtprio = *rtp; + maybe_resched(chgp); + return (0); + + default: + return (EINVAL); + } + #endif /* NO_RTPRIO */ + } + + /* + * Define the code needed before returning to user mode, for + * trap and syscall. + * + * XXX Moved to machine independent on FreeBSD. Notes: + * + * For i386: No longer inline. Second arg is now "frame->tf_eip". + * For alpha: mi_switch now "splhigh() instead of "splstatclock()". + * + * Perusing 4.4Lite showed that for multiple architectures this can be + * done MI, perhaps having to pass some methods and a cookie as well. + */ + + void + userret(p, pc, oticks) + struct proc *p; + const register_t pc; + const u_quad_t oticks; + { + int sig, s; + + /* take pending signals */ + while ((sig = CURSIG(p)) != 0) + postsig(sig); + #if 0 + if (!want_resched && + (p->p_priority <= p->p_usrpri) && + (p->p_rtprio.type == RTP_PRIO_NORMAL)) { + int newpriority; + p->p_estcpu += 1; + newpriority = PUSER + p->p_estcpu / 4 + 2 * p->p_nice; + newpriority = min(newpriority, MAXPRI); + p->p_usrpri = newpriority; + } + #endif + p->p_priority = p->p_usrpri; + if (want_resched) { + /* + * Since we are curproc, a clock interrupt could + * change our priority without changing run queues + * (the running process is not kept on a run queue). + * If this happened after we setrunqueue ourselves but + * before we switch()'ed, we might not be on the queue + * indicated by our priority. + */ + s = splhigh(); + setrunqueue(p); + p->p_stats->p_ru.ru_nivcsw++; + mi_switch(); + splx(s); + while ((sig = CURSIG(p)) != 0) + postsig(sig); + } + + /* + * If profiling, charge recent system time to the trapped pc. + */ + if (p->p_flag & P_PROFIL) { + addupc_task(p, pc, (int)(p->p_sticks - oticks) * psratio); + } + + curpriority = prioritize(p); + } + /* ARGSUSED */ static void diff -c -N -r /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/kern/kern_threads.c /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/kern/kern_threads.c *** /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/kern/kern_threads.c Fri Aug 27 20:46:15 1999 --- /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/kern/kern_threads.c Thu Oct 28 18:06:32 1999 *************** *** 53,58 **** --- 53,59 ---- #include #include #include + #include #include #include *************** *** 140,156 **** */ int yield(struct proc *p, struct yield_args *uap) { - int s; - p->p_retval[0] = 0; ! ! s = splhigh(); ! p->p_priority = MAXPRI; ! setrunqueue(p); ! p->p_stats->p_ru.ru_nvcsw++; ! mi_switch(); ! splx(s); ! ! return(0); } - --- 141,146 ---- */ int yield(struct proc *p, struct yield_args *uap) { p->p_retval[0] = 0; ! return synch_yield(p, 1); } diff -c -N -r /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/kern/subr_prof.c /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/kern/subr_prof.c *** /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/kern/subr_prof.c Mon Oct 11 22:54:23 1999 --- /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/kern/subr_prof.c Thu Oct 28 18:06:32 1999 *************** *** 382,387 **** --- 382,391 ---- * Scale is a fixed-point number with the binary point 16 bits * into the value, and is <= 1.0. pc is at most 32 bits, so the * intermediate result is at most 48 bits. + * + * XXX the above is not true. pc is u_long and is 64 bits on the alpha. + * Now that it is "register_t" and is obviously not true. + * */ #define PC_TO_INDEX(pc, prof) \ ((int)(((u_quad_t)((pc) - (prof)->pr_off) * \ *************** *** 403,409 **** void addupc_intr(p, pc, ticks) register struct proc *p; ! register u_long pc; u_int ticks; { register struct uprof *prof; --- 407,413 ---- void addupc_intr(p, pc, ticks) register struct proc *p; ! register register_t pc; u_int ticks; { register struct uprof *prof; *************** *** 433,439 **** void addupc_task(p, pc, ticks) register struct proc *p; ! register u_long pc; u_int ticks; { register struct uprof *prof; --- 437,443 ---- void addupc_task(p, pc, ticks) register struct proc *p; ! register register_t pc; u_int ticks; { register struct uprof *prof; diff -c -N -r /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/kern/sys_generic.c /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/kern/sys_generic.c *** /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/kern/sys_generic.c Thu Oct 14 06:50:06 1999 --- /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/kern/sys_generic.c Thu Oct 28 18:06:32 1999 *************** *** 49,54 **** --- 49,55 ---- #include #include #include + #include #include #include #include diff -c -N -r /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/kern/sys_process.c /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/kern/sys_process.c *** /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/kern/sys_process.c Mon Oct 11 11:19:11 1999 --- /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/kern/sys_process.c Thu Oct 28 18:06:32 1999 *************** *** 35,40 **** --- 35,41 ---- #include #include #include + #include #include #include diff -c -N -r /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/kern/tty.c /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/kern/tty.c *** /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/kern/tty.c Wed Sep 29 11:03:42 1999 --- /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/kern/tty.c Thu Oct 28 18:06:32 1999 *************** *** 78,83 **** --- 78,84 ---- #include #endif #include + #include #define TTYDEFCHARS #include #undef TTYDEFCHARS *************** *** 2269,2277 **** * The algorithm for picking the "interesting" process is thus: * * 1) Only foreground processes are eligible - implied. ! * 2) Runnable processes are favored over anything else. The runner ! * with the highest cpu utilization is picked (p_estcpu). Ties are ! * broken by picking the highest pid. * 3) The sleeper with the shortest sleep time is next. With ties, * we pick out just "short-term" sleepers (P_SINTR == 0). * 4) Further ties are broken by picking the highest pid. --- 2270,2277 ---- * The algorithm for picking the "interesting" process is thus: * * 1) Only foreground processes are eligible - implied. ! * 2) Runnable processes are favored over anything else. We defer to ! * "synch_compare" to decide how to choose between two runners. * 3) The sleeper with the shortest sleep time is next. With ties, * we pick out just "short-term" sleepers (P_SINTR == 0). * 4) Further ties are broken by picking the highest pid. *************** *** 2298,2311 **** case ONLYB: return (1); case BOTH: ! /* ! * tie - favor one with highest recent cpu utilization ! */ ! if (p2->p_estcpu > p1->p_estcpu) ! return (1); ! if (p1->p_estcpu > p2->p_estcpu) ! return (0); ! return (p2->p_pid > p1->p_pid); /* tie - return highest pid */ } /* * weed out zombies --- 2298,2304 ---- case ONLYB: return (1); case BOTH: ! return synch_compare(p1, p2); } /* * weed out zombies diff -c -N -r /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/kern/uipc_socket2.c /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/kern/uipc_socket2.c *** /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/kern/uipc_socket2.c Sat Oct 9 16:42:10 1999 --- /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/kern/uipc_socket2.c Thu Oct 28 18:06:33 1999 *************** *** 41,46 **** --- 41,47 ---- #include /* for maxfiles */ #include #include + #include #include #include #include diff -c -N -r /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/kern/uipc_syscalls.c /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/kern/uipc_syscalls.c *** /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/kern/uipc_syscalls.c Thu Oct 14 01:16:16 1999 --- /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/kern/uipc_syscalls.c Thu Oct 28 18:06:33 1999 *************** *** 47,52 **** --- 47,53 ---- #include #include #include + #include #include #include #include diff -c -N -r /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/kern/vfs_subr.c /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/kern/vfs_subr.c *** /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/kern/vfs_subr.c Mon Oct 11 11:19:12 1999 --- /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/kern/vfs_subr.c Thu Oct 28 18:06:33 1999 *************** *** 49,54 **** --- 49,55 ---- #include #include #include + #include #include #include #include diff -c -N -r /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/miscfs/procfs/procfs_ctl.c /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/miscfs/procfs/procfs_ctl.c *** /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/miscfs/procfs/procfs_ctl.c Wed Sep 29 11:03:46 1999 --- /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/miscfs/procfs/procfs_ctl.c Thu Oct 28 18:06:33 1999 *************** *** 43,48 **** --- 43,49 ---- #include #include #include + #include #include #include #include diff -c -N -r /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/posix4/ksched.c /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/posix4/ksched.c *** /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/posix4/ksched.c Tue May 19 17:11:52 1998 --- /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/posix4/ksched.c Thu Oct 28 18:06:33 1999 *************** *** 37,45 **** #include #include #include #include #include - #include /* For need_resched */ #include --- 37,45 ---- #include #include #include + #include #include #include #include *************** *** 50,103 **** struct timespec rr_interval; }; ! int ksched_attach(struct ksched **p) { struct ksched *ksched= p31b_malloc(sizeof(*ksched)); ksched->rr_interval.tv_sec = 0; ksched->rr_interval.tv_nsec = 1000000000L / roundrobin_interval(); ! *p = ksched; return 0; } ! int ksched_detach(struct ksched *p) { ! p31b_free(p); return 0; } /* ! * XXX About priorities * * POSIX 1003.1b requires that numerically higher priorities be of * higher priority. It also permits sched_setparam to be ! * implementation defined for SCHED_OTHER. I don't like ! * the notion of inverted priorites for normal processes when ! * you can use "setpriority" for that. ! * ! * I'm rejecting sched_setparam for SCHED_OTHER with EINVAL. */ ! /* Macros to convert between the unix (lower numerically is higher priority) * and POSIX 1003.1b (higher numerically is higher priority) */ ! #define p4prio_to_rtpprio(P) (RTP_PRIO_MAX - (P)) ! #define rtpprio_to_p4prio(P) (RTP_PRIO_MAX - (P)) ! /* These improve readability a bit for me: */ ! #define P1B_PRIO_MIN rtpprio_to_p4prio(RTP_PRIO_MAX) ! #define P1B_PRIO_MAX rtpprio_to_p4prio(RTP_PRIO_MIN) static __inline int ! getscheduler(int *ret, struct ksched *ksched, struct proc *p) { int e = 0; ! switch (p->p_rtprio.type) { case RTP_PRIO_FIFO: *ret = SCHED_FIFO; --- 50,110 ---- struct timespec rr_interval; }; ! int ksched_attach(struct ksched **kp) { struct ksched *ksched= p31b_malloc(sizeof(*ksched)); ksched->rr_interval.tv_sec = 0; ksched->rr_interval.tv_nsec = 1000000000L / roundrobin_interval(); ! *kp = ksched; return 0; } ! int ksched_detach(struct ksched *kp) { ! p31b_free(kp); return 0; } /* ! * About priorities: * * POSIX 1003.1b requires that numerically higher priorities be of * higher priority. It also permits sched_setparam to be ! * implementation defined for SCHED_OTHER. We'll use ! * the normal "setpriority()" priorities and treat a ! * call for setting the scheduler similar to setpriority(). ! * They still need to be reflected to make higher priorities higher. */ ! /* Macros to convert between the RTP_PRIO (lower numerically is higher priority) * and POSIX 1003.1b (higher numerically is higher priority) */ ! #define p4prio_to_rtprio(P) (RTP_PRIO_MAX - (P)) ! #define rtprio_to_p4prio(P) (RTP_PRIO_MAX - (P)) ! ! #define P1B_PRIO_MIN rtprio_to_p4prio(RTP_PRIO_MAX) ! #define P1B_PRIO_MAX rtprio_to_p4prio(RTP_PRIO_MIN) ! /* Similar macros for the BSD flavor p_nice priorities: */ ! #define p4prio_to_p_nice(P) (-(P + PRIO_MIN)) ! #define p_nice_to_p4prio(P) (-(P - PRIO_MAX)) ! ! #define P_NICE_PRIO_MIN p_nice_to_p4prio(PRIO_MAX) ! #define P_NICE_PRIO_MAX p_nice_to_p4prio(PRIO_MIN) static __inline int ! getscheduler(int *ret, struct ksched *ksched, struct proc *curp, struct proc *chgp) { + struct rtprio rtp; int e = 0; + (void)synch_proc_priority(chgp, &rtp); ! switch (rtp.type) { case RTP_PRIO_FIFO: *ret = SCHED_FIFO; *************** *** 107,143 **** *ret = SCHED_RR; break; ! default: *ret = SCHED_OTHER; break; } return e; } int ksched_setparam(int *ret, struct ksched *ksched, ! struct proc *p, const struct sched_param *param) { int e, policy; ! e = getscheduler(&policy, ksched, p); if (e == 0) ! { ! if (policy == SCHED_OTHER) ! e = EINVAL; ! else ! e = ksched_setscheduler(ret, ksched, p, policy, param); ! } return e; } int ksched_getparam(int *ret, struct ksched *ksched, ! struct proc *p, struct sched_param *param) { ! if (RTP_PRIO_IS_REALTIME(p->p_rtprio.type)) ! param->sched_priority = rtpprio_to_p4prio(p->p_rtprio.prio); return 0; } --- 114,172 ---- *ret = SCHED_RR; break; ! case RTP_PRIO_NORMAL: *ret = SCHED_OTHER; break; + + case RTP_PRIO_IDLE: + *ret = SCHED_IDLE; + break; + + default: + e = ESRCH; + break; } return e; } int ksched_setparam(int *ret, struct ksched *ksched, ! struct proc *curp, struct proc *chgp, const struct sched_param *param) { int e, policy; ! e = getscheduler(&policy, ksched, curp, chgp); if (e == 0) ! e = ksched_setscheduler(ret, ksched, ! curp, chgp, policy, param); return e; } int ksched_getparam(int *ret, struct ksched *ksched, ! struct proc *curp, struct proc *chgp, struct sched_param *param) { ! struct rtprio rtp; ! int e = 0; ! int nice = synch_proc_priority(chgp, &rtp); ! ! switch (rtp.type) ! { ! case RTP_PRIO_FIFO: ! case RTP_PRIO_REALTIME: ! case RTP_PRIO_IDLE: ! param->sched_priority = rtprio_to_p4prio(rtp.prio); ! break; ! ! case RTP_PRIO_NORMAL: ! param->sched_priority = p_nice_to_p4prio(nice); ! break; ! ! default: ! e = EFAULT; ! break; ! } return 0; } *************** *** 146,156 **** * XXX The priority and scheduler modifications should * be moved into published interfaces in kern/kern_sync. * ! * The permissions to modify process p were checked in "p31b_proc()". * */ int ksched_setscheduler(int *ret, struct ksched *ksched, ! struct proc *p, int policy, const struct sched_param *param) { int e = 0; struct rtprio rtp; --- 175,186 ---- * XXX The priority and scheduler modifications should * be moved into published interfaces in kern/kern_sync. * ! * The permissions to modify process chgp were checked in "p31b_proc()". * */ int ksched_setscheduler(int *ret, struct ksched *ksched, ! struct proc *curp, struct proc *chgp, ! int policy, const struct sched_param *param) { int e = 0; struct rtprio rtp; *************** *** 159,212 **** { case SCHED_RR: case SCHED_FIFO: if (param->sched_priority >= P1B_PRIO_MIN && param->sched_priority <= P1B_PRIO_MAX) { ! rtp.prio = p4prio_to_rtpprio(param->sched_priority); ! rtp.type = (policy == SCHED_FIFO) ! ? RTP_PRIO_FIFO : RTP_PRIO_REALTIME; - p->p_rtprio = rtp; - need_resched(); } else e = EPERM; - - break; case SCHED_OTHER: { ! rtp.type = RTP_PRIO_NORMAL; ! rtp.prio = p4prio_to_rtpprio(param->sched_priority); ! p->p_rtprio = rtp; ! ! /* XXX Simply revert to whatever we had for last ! * normal scheduler priorities. ! * This puts a requirement ! * on the scheduling code: You must leave the ! * scheduling info alone. ! */ ! need_resched(); } break; } return e; } ! int ksched_getscheduler(int *ret, struct ksched *ksched, struct proc *p) { ! return getscheduler(ret, ksched, p); } /* ksched_yield: Yield the CPU. */ int ksched_yield(int *ret, struct ksched *ksched) { ! need_resched(); ! return 0; } int ksched_get_priority_max(int *ret, struct ksched *ksched, int policy) --- 189,251 ---- { case SCHED_RR: case SCHED_FIFO: + case SCHED_IDLE: if (param->sched_priority >= P1B_PRIO_MIN && param->sched_priority <= P1B_PRIO_MAX) { ! rtp.prio = p4prio_to_rtprio(param->sched_priority); ! ! if (policy == SCHED_RR) ! rtp.type = RTP_PRIO_REALTIME; ! else if (policy == SCHED_FIFO) ! rtp.type = RTP_PRIO_FIFO; ! else ! rtp.type = RTP_PRIO_IDLE; ! ! return dortprio(curp, chgp, &rtp); } else e = EPERM; break; + /* XXX One thing I really don't like about this + * implementation is you'll have to provide a + * nice value to revert to. Either the process + * will have to do a "getparam" at the start and save it, + * (should always work), + * or we'll have to add some magic value (say PRIO_MAX + 1) + * that means "don't touch my nice value", and we'll + * have to include that as a valid priority in the + * "get_priority_min" call. + */ case SCHED_OTHER: + if (param->sched_priority >= P_NICE_PRIO_MIN && + param->sched_priority <= P_NICE_PRIO_MAX) { ! return donice(curp, chgp, ! p4prio_to_p_nice(param->sched_priority)); } + else + e = EPERM; break; } return e; } ! int ksched_getscheduler(int *ret, struct ksched *ksched, ! struct proc *curp, struct proc *chgp) { ! return getscheduler(ret, ksched, curp, chgp); } /* ksched_yield: Yield the CPU. */ int ksched_yield(int *ret, struct ksched *ksched) { ! return synch_yield(curproc, 0); } int ksched_get_priority_max(int *ret, struct ksched *ksched, int policy) *************** *** 217,227 **** { case SCHED_FIFO: case SCHED_RR: ! *ret = RTP_PRIO_MAX; break; case SCHED_OTHER: ! *ret = PRIO_MAX; break; default: --- 256,267 ---- { case SCHED_FIFO: case SCHED_RR: ! case SCHED_IDLE: ! *ret = P1B_PRIO_MAX; break; case SCHED_OTHER: ! *ret = P_NICE_PRIO_MAX; break; default: *************** *** 239,249 **** { case SCHED_FIFO: case SCHED_RR: *ret = P1B_PRIO_MIN; break; case SCHED_OTHER: ! *ret = PRIO_MIN; break; default: --- 279,290 ---- { case SCHED_FIFO: case SCHED_RR: + case SCHED_IDLE: *ret = P1B_PRIO_MIN; break; case SCHED_OTHER: ! *ret = P_NICE_PRIO_MIN; break; default: *************** *** 254,260 **** } int ksched_rr_get_interval(int *ret, struct ksched *ksched, ! struct proc *p, struct timespec *timespec) { *timespec = ksched->rr_interval; --- 295,301 ---- } int ksched_rr_get_interval(int *ret, struct ksched *ksched, ! struct proc *curp, struct proc *chgp, struct timespec *timespec) { *timespec = ksched->rr_interval; diff -c -N -r /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/posix4/p1003_1b.c /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/posix4/p1003_1b.c *** /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/posix4/p1003_1b.c Sat Apr 17 04:36:05 1999 --- /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/posix4/p1003_1b.c Thu Oct 28 18:06:33 1999 *************** *** 63,93 **** #if 0 /* ! * This is stolen from CANSIGNAL in kern_sig: * ! * Can process p, with pcred pc, do "write flavor" operations to process q? */ ! #define CAN_AFFECT(p, pc, q) \ ((pc)->pc_ucred->cr_uid == 0 || \ (pc)->p_ruid == (q)->p_cred->p_ruid || \ (pc)->pc_ucred->cr_uid == (q)->p_cred->p_ruid || \ (pc)->p_ruid == (q)->p_ucred->cr_uid || \ (pc)->pc_ucred->cr_uid == (q)->p_ucred->cr_uid) #else ! #define CAN_AFFECT(p, pc, q) ((pc)->pc_ucred->cr_uid == 0) #endif /* * p31b_proc: Look up a proc from a PID. If proc is 0 it is * my own proc. */ ! int p31b_proc(struct proc *p, pid_t pid, struct proc **pp) { int ret = 0; struct proc *other_proc = 0; if (pid == 0) ! other_proc = p; else other_proc = pfind(pid); --- 63,100 ---- #if 0 /* ! * This is from CANSIGNAL in kern_sig: * ! * Can process CURP, with pcred pc, do "write flavor" operations to process q? */ ! #define CAN_AFFECT(rw, CURP, pc, q) \ ((pc)->pc_ucred->cr_uid == 0 || \ (pc)->p_ruid == (q)->p_cred->p_ruid || \ (pc)->pc_ucred->cr_uid == (q)->p_cred->p_ruid || \ (pc)->p_ruid == (q)->p_ucred->cr_uid || \ (pc)->pc_ucred->cr_uid == (q)->p_ucred->cr_uid) #else ! #define CAN_AFFECT(rw, CURP, pc, q) ((rw == 0) || ((pc)->pc_ucred->cr_uid == 0)) #endif /* * p31b_proc: Look up a proc from a PID. If proc is 0 it is * my own proc. + * + * If perms[ind] is zero this is "read" flavor; + * if perms[ind] is one this is "write" flavor. + * + * The current policy is only root can write, anyone can read. + * */ ! int p31b_proc(const int *perms, int ind, ! struct proc *curp, pid_t pid, struct proc **pp) { int ret = 0; struct proc *other_proc = 0; if (pid == 0) ! other_proc = curp; else other_proc = pfind(pid); *************** *** 95,101 **** { /* Enforce permission policy. */ ! if (CAN_AFFECT(p, p->p_cred, other_proc)) *pp = other_proc; else ret = EPERM; --- 102,108 ---- { /* Enforce permission policy. */ ! if (CAN_AFFECT(perms[ind], curp, curp->p_cred, other_proc)) *pp = other_proc; else ret = EPERM; *************** *** 111,122 **** * start to use this when they shouldn't. That will be removed if annoying. */ int ! syscall_not_present(struct proc *p, const char *s, struct nosys_args *uap) { log(LOG_ERR, "cmd %s pid %d tried to use non-present %s\n", ! p->p_comm, p->p_pid, s); ! /* a " return nosys(p, uap); " here causes a core dump. */ return ENOSYS; --- 118,129 ---- * start to use this when they shouldn't. That will be removed if annoying. */ int ! syscall_not_present(struct proc *curp, const char *s, struct nosys_args *uap) { log(LOG_ERR, "cmd %s pid %d tried to use non-present %s\n", ! curp->p_comm, curp->p_pid, s); ! /* a " return nosys(curp, uap); " here causes a core dump. */ return ENOSYS; *************** *** 143,148 **** --- 150,159 ---- #else + /* Permissions + */ + static const int ksched_op_rw[] = KSCHED_OP_RW; + /* Configured in kernel version: */ static struct ksched *ksched; *************** *** 157,188 **** return ret; } ! int sched_setparam(struct proc *p, struct sched_setparam_args *uap) { int e; struct sched_param sched_param; copyin(uap->param, &sched_param, sizeof(sched_param)); (void) (0 ! || (e = p31b_proc(p, uap->pid, &p)) ! || (e = ksched_setparam(&p->p_retval[0], ksched, p, (const struct sched_param *)&sched_param)) ); return e; } ! int sched_getparam(struct proc *p, struct sched_getparam_args *uap) { int e; struct sched_param sched_param; (void) (0 ! || (e = p31b_proc(p, uap->pid, &p)) ! || (e = ksched_getparam(&p->p_retval[0], ksched, p, &sched_param)) ); if (!e) --- 168,204 ---- return ret; } ! int sched_setparam(struct proc *curp, struct sched_setparam_args *uap) { int e; + struct proc *other; struct sched_param sched_param; copyin(uap->param, &sched_param, sizeof(sched_param)); (void) (0 ! || (e = p31b_proc(ksched_op_rw, ! (int)SCHED_SETPARAM, curp, uap->pid, &other)) ! || (e = ksched_setparam(&curp->p_retval[0], ksched, curp, other, (const struct sched_param *)&sched_param)) ); return e; } ! int sched_getparam(struct proc *curp, struct sched_getparam_args *uap) { int e; + struct proc *other; struct sched_param sched_param; (void) (0 ! || (e = p31b_proc(ksched_op_rw, ! (int)SCHED_GETPARAM, curp, uap->pid, &other)) ! || (e = ksched_getparam(&curp->p_retval[0], ksched, ! curp, other, &sched_param)) ); if (!e) *************** *** 190,252 **** return e; } ! int sched_setscheduler(struct proc *p, struct sched_setscheduler_args *uap) { int e; struct sched_param sched_param; copyin(uap->param, &sched_param, sizeof(sched_param)); (void) (0 ! || (e = p31b_proc(p, uap->pid, &p)) ! || (e = ksched_setscheduler(&p->p_retval[0], ! ksched, p, uap->policy, (const struct sched_param *)&sched_param)) ); return e; } ! int sched_getscheduler(struct proc *p, struct sched_getscheduler_args *uap) { int e; (void) (0 ! || (e = p31b_proc(p, uap->pid, &p)) ! || (e = ksched_getscheduler(&p->p_retval[0], ksched, p)) ); return e; } ! int sched_yield(struct proc *p, struct sched_yield_args *uap) { ! return ksched_yield(&p->p_retval[0], ksched); } ! int sched_get_priority_max(struct proc *p, struct sched_get_priority_max_args *uap) { ! return ksched_get_priority_max(&p->p_retval[0], ksched, uap->policy); } ! int sched_get_priority_min(struct proc *p, struct sched_get_priority_min_args *uap) { ! return ksched_get_priority_min(&p->p_retval[0], ksched, uap->policy); - } - int sched_rr_get_interval(struct proc *p, - struct sched_rr_get_interval_args *uap) - { - int e; - - (void) (0 - || (e = p31b_proc(p, uap->pid, &p)) - || (e = ksched_rr_get_interval(&p->p_retval[0], ksched, - p, uap->interval)) - ); - - return e; } #endif --- 206,280 ---- return e; } ! int sched_setscheduler(struct proc *curp, struct sched_setscheduler_args *uap) { int e; + struct proc *other; struct sched_param sched_param; copyin(uap->param, &sched_param, sizeof(sched_param)); (void) (0 ! || (e = p31b_proc(ksched_op_rw, ! (int)SCHED_SETSCHEDULER, curp, uap->pid, &other)) ! || (e = ksched_setscheduler(&curp->p_retval[0], ! ksched, curp, other, uap->policy, (const struct sched_param *)&sched_param)) ); return e; } ! int sched_getscheduler(struct proc *curp, struct sched_getscheduler_args *uap) { int e; + struct proc *other; + (void) (0 + || (e = p31b_proc(ksched_op_rw, + (int)SCHED_GETSCHEDULER, curp, uap->pid, &other)) + || (e = ksched_getscheduler(&curp->p_retval[0], ksched, curp, other)) + ); + + return e; + } + + int sched_rr_get_interval(struct proc *curp, + struct sched_rr_get_interval_args *uap) + { + int e; + struct proc *other; + (void) (0 ! || (e = p31b_proc(ksched_op_rw, ! (int)SCHED_RR_GET_INTERVAL, curp, uap->pid, &other)) ! || (e = ksched_rr_get_interval(&curp->p_retval[0], ksched, ! curp, other, uap->interval)) ); return e; } ! ! /* XXX These should still check some permissions. ! */ ! int sched_yield(struct proc *curp, struct sched_yield_args *uap) { ! return ksched_yield(&curp->p_retval[0], ksched); } ! ! int sched_get_priority_max(struct proc *curp, struct sched_get_priority_max_args *uap) { ! return ksched_get_priority_max(&curp->p_retval[0], ksched, uap->policy); } ! ! int sched_get_priority_min(struct proc *curp, struct sched_get_priority_min_args *uap) { ! return ksched_get_priority_min(&curp->p_retval[0], ksched, uap->policy); } #endif diff -c -N -r /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/posix4/posix4.h /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/posix4/posix4.h *** /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/posix4/posix4.h Sat Apr 17 04:36:05 1999 --- /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/posix4/posix4.h Thu Oct 28 18:06:33 1999 *************** *** 60,66 **** #define p31b_malloc(SIZE) malloc((SIZE), M_P31B, M_WAITOK) #define p31b_free(P) free((P), M_P31B) ! int p31b_proc __P((struct proc *, pid_t, struct proc **)); void p31b_setcfg __P((int, int)); --- 60,66 ---- #define p31b_malloc(SIZE) malloc((SIZE), M_P31B, M_WAITOK) #define p31b_free(P) free((P), M_P31B) ! int p31b_proc __P((const int *, int, struct proc *, pid_t, struct proc **)); void p31b_setcfg __P((int, int)); *************** *** 94,113 **** int ksched_detach(struct ksched *); int ksched_setparam(int *, struct ksched *, ! struct proc *, const struct sched_param *); int ksched_getparam(int *, struct ksched *, ! struct proc *, struct sched_param *); int ksched_setscheduler(int *, struct ksched *, ! struct proc *, int, const struct sched_param *); ! int ksched_getscheduler(int *, struct ksched *, struct proc *); int ksched_yield(int *, struct ksched *); int ksched_get_priority_max(int *, struct ksched *, int); int ksched_get_priority_min(int *, struct ksched *, int); ! int ksched_rr_get_interval(int *, struct ksched *, struct proc *, struct timespec *); #endif /* _KPOSIX_PRIORITY_SCHEDULING */ --- 94,113 ---- int ksched_detach(struct ksched *); int ksched_setparam(int *, struct ksched *, ! struct proc *, struct proc *, const struct sched_param *); int ksched_getparam(int *, struct ksched *, ! struct proc *, struct proc *, struct sched_param *); int ksched_setscheduler(int *, struct ksched *, ! struct proc *, struct proc *, int, const struct sched_param *); ! int ksched_getscheduler(int *, struct ksched *, struct proc *, struct proc *); int ksched_yield(int *, struct ksched *); int ksched_get_priority_max(int *, struct ksched *, int); int ksched_get_priority_min(int *, struct ksched *, int); ! int ksched_rr_get_interval(int *, struct ksched *, struct proc *, struct proc *, struct timespec *); #endif /* _KPOSIX_PRIORITY_SCHEDULING */ diff -c -N -r /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/posix4/sched.h /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/posix4/sched.h *** /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/posix4/sched.h Tue May 12 01:11:51 1998 --- /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/posix4/sched.h Thu Oct 28 18:06:33 1999 *************** *** 49,54 **** --- 49,61 ---- #define SCHED_OTHER 2 #define SCHED_RR 3 + #if !defined(_POSIX_SOURCE) && !defined(_POSIX_C_SOURCE) + + /* BSD idprio */ + #define SCHED_IDLE 4 + + #endif + struct sched_param { int sched_priority; diff -c -N -r /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/sys/_posix.h /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/sys/_posix.h *** /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/sys/_posix.h Fri Aug 27 20:51:32 1999 --- /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/sys/_posix.h Thu Oct 28 18:06:33 1999 *************** *** 51,60 **** * XXX Complain if you think this dumb. */ ! /* Make P1003 structures visible for the kernel if ! * the P1003_1B option is in effect. */ ! #ifdef P1003_1B #define _P1003_1B_VISIBLE #ifndef _KPOSIX_VERSION #define _KPOSIX_VERSION 199309L --- 51,76 ---- * XXX Complain if you think this dumb. */ ! /* Make P1003 structures visible for the kernel unless ! * the NO_P1003_1B option is in effect. */ ! #ifndef NO_P1003_1B ! ! /* Turn on standard features that are always present if P1003_1B ! * is enabled here. The nested ifndef are for a grace period for old ! * kernel options. ! */ ! ! #ifndef P1003_1B ! #define P1003_1B ! #endif ! ! #ifndef NO_KPOSIX_PRIORITY_SCHEDULING ! #ifndef _KPOSIX_PRIORITY_SCHEDULING ! #define _KPOSIX_PRIORITY_SCHEDULING ! #endif ! #endif ! #define _P1003_1B_VISIBLE #ifndef _KPOSIX_VERSION #define _KPOSIX_VERSION 199309L diff -c -N -r /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/sys/proc.h /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/sys/proc.h *** /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/sys/proc.h Mon Oct 11 16:33:16 1999 --- /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/sys/proc.h Fri Oct 29 09:02:30 1999 *************** *** 42,47 **** --- 42,63 ---- #ifndef _SYS_PROC_H_ #define _SYS_PROC_H_ + /* + * XXX Temporary hack to be sure all scheduling members are accessed properly + * Remove "opt_sched.h" along with the "friend" stuff when taking out. + */ + #include "opt_sched.h" + #ifdef SCHEDULER_FRIEND + #define p_sched_estcpu p_estcpu + #define p_sched_priority p_priority + #define p_sched_usrpri p_usrpri + #define p_sched_nice p_nice + #ifndef NO_RTPRIO + #define p_sched_rtprio p_rtprio + #endif /* !NO_RTPRIO */ + #endif /* SCHEDULER_FRIEND */ + + #include /* Machine-dependent proc substruct. */ #include /* For struct callout_handle. */ #include *************** *** 153,159 **** struct vmspace *p_vmspace; /* Address space. */ /* scheduling */ ! u_int p_estcpu; /* Time averaged value of p_cpticks. */ int p_cpticks; /* Ticks of cpu time. */ fixpt_t p_pctcpu; /* %cpu for this process during p_swtime */ void *p_wchan; /* Sleep address. */ --- 169,175 ---- struct vmspace *p_vmspace; /* Address space. */ /* scheduling */ ! u_int p_sched_estcpu; /* Time averaged value of p_cpticks. */ int p_cpticks; /* Ticks of cpu time. */ fixpt_t p_pctcpu; /* %cpu for this process during p_swtime */ void *p_wchan; /* Sleep address. */ *************** *** 201,216 **** sigset_t p_sigmask; /* Current signal mask. */ stack_t p_sigstk; /* sp & on stack state variable */ ! u_char p_priority; /* Process priority. */ ! u_char p_usrpri; /* User-priority based on p_cpu and p_nice. */ ! char p_nice; /* Process "nice" value. */ char p_comm[MAXCOMLEN+1]; struct pgrp *p_pgrp; /* Pointer to process group. */ struct sysentvec *p_sysent; /* System call dispatch information. */ ! struct rtprio p_rtprio; /* Realtime priority. */ struct prison *p_prison; /* End area that is copied on creation. */ #define p_endcopy p_addr --- 217,232 ---- sigset_t p_sigmask; /* Current signal mask. */ stack_t p_sigstk; /* sp & on stack state variable */ ! u_char p_sched_priority; /* Process priority. */ ! u_char p_sched_usrpri; /* User-priority based on p_cpu and p_nice. */ ! char p_sched_nice; /* Process "nice" value. */ char p_comm[MAXCOMLEN+1]; struct pgrp *p_pgrp; /* Pointer to process group. */ struct sysentvec *p_sysent; /* System call dispatch information. */ ! struct rtprio p_sched_rtprio; /* Realtime priority. */ struct prison *p_prison; /* End area that is copied on creation. */ #define p_endcopy p_addr *************** *** 352,358 **** extern struct timeval switchtime; /* Uptime at last context switch */ #endif extern struct proc proc0; /* Process slot for swapper. */ - extern int hogticks; /* Limit on kernel cpu hogs. */ extern int nprocs, maxproc; /* Current and max number of procs. */ extern int maxprocperuid; /* Max procs per uid. */ extern int sched_quantum; /* Scheduling quantum in ticks */ --- 368,373 ---- *************** *** 362,376 **** extern struct proclist zombproc; /* List of zombie processes. */ extern struct proc *initproc, *pageproc, *updateproc; /* Process slots for init, pager. */ - #define NQS 32 /* 32 run queues. */ - TAILQ_HEAD(rq, proc); - extern struct rq queues[]; - extern struct rq rtqueues[]; - extern struct rq idqueues[]; - extern int whichqs; /* Bit mask summary of non-empty Q's. */ - extern int whichrtqs; /* Bit mask summary of non-empty Q's. */ - extern int whichidqs; /* Bit mask summary of non-empty Q's. */ - struct proc *pfind __P((pid_t)); /* Find process by id. */ struct pgrp *pgfind __P((pid_t)); /* Find process group by id. */ --- 377,382 ---- *************** *** 383,401 **** void fixjobc __P((struct proc *p, struct pgrp *pgrp, int entering)); int inferior __P((struct proc *p)); int leavepgrp __P((struct proc *p)); ! void mi_switch __P((void)); void procinit __P((void)); - void resetpriority __P((struct proc *)); - int roundrobin_interval __P((void)); - void setrunnable __P((struct proc *)); - void setrunqueue __P((struct proc *)); - void sleepinit __P((void)); int suser __P((struct proc *)); int suser_xxx __P((struct ucred *cred, struct proc *proc, int flag)); - void remrunqueue __P((struct proc *)); - void cpu_switch __P((struct proc *)); - void unsleep __P((struct proc *)); - void wakeup_one __P((void *chan)); void cpu_exit __P((struct proc *)) __dead2; void exit1 __P((struct proc *, int)) __dead2; --- 389,398 ---- void fixjobc __P((struct proc *p, struct pgrp *pgrp, int entering)); int inferior __P((struct proc *p)); int leavepgrp __P((struct proc *p)); ! void procinit __P((void)); int suser __P((struct proc *)); int suser_xxx __P((struct ucred *cred, struct proc *proc, int flag)); void cpu_exit __P((struct proc *)) __dead2; void exit1 __P((struct proc *, int)) __dead2; *************** *** 407,415 **** int cpu_coredump __P((struct proc *, struct vnode *, struct ucred *)); void setsugid __P((struct proc *p)); void faultin __P((struct proc *p)); - - struct proc * chooseproc __P((void)); - u_int32_t procrunnable __P((void)); #endif /* KERNEL */ --- 404,409 ---- diff -c -N -r /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/sys/resource.h /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/sys/resource.h *** /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/sys/resource.h Sat Oct 9 16:42:17 1999 --- /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/sys/resource.h Thu Oct 28 18:06:33 1999 *************** *** 131,136 **** --- 131,138 ---- #ifdef KERNEL extern struct loadavg averunnable; + struct rtprio; + struct proc; #else #include diff -c -N -r /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/sys/resourcevar.h /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/sys/resourcevar.h *** /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/sys/resourcevar.h Fri Aug 27 20:51:58 1999 --- /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/sys/resourcevar.h Thu Oct 28 18:06:33 1999 *************** *** 86,93 **** #ifdef KERNEL struct proc; ! void addupc_intr __P((struct proc *p, u_long pc, u_int ticks)); ! void addupc_task __P((struct proc *p, u_long pc, u_int ticks)); void calcru __P((struct proc *p, struct timeval *up, struct timeval *sp, struct timeval *ip)); int fuswintr __P((void *base)); --- 86,93 ---- #ifdef KERNEL struct proc; ! void addupc_intr __P((struct proc *p, register_t pc, u_int ticks)); ! void addupc_task __P((struct proc *p, register_t pc, u_int ticks)); void calcru __P((struct proc *p, struct timeval *up, struct timeval *sp, struct timeval *ip)); int fuswintr __P((void *base)); diff -c -N -r /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/sys/synch.h /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/sys/synch.h *** /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/sys/synch.h Fri Oct 29 02:07:24 1999 --- /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/sys/synch.h Fri Oct 29 09:03:36 1999 *************** *** 0 **** --- 1,84 ---- + /* + * Copyright (c) 1999 HD Associates, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/sys/kern/kern_switch.c,v 1.3 1999/08/19 16:06:08 peter Exp $ + */ + #ifndef _SYS_SYNCH_H_ + #define _SYS_SYNCH_H_ + #ifdef KERNEL + + #include + #include + #include + + struct proc; + struct rtprio; + + #define NQS 32 /* 32 run queues. */ + TAILQ_HEAD(rq, proc); + + /* kern_synch */ + + int donice __P((struct proc *, struct proc *, int)); + int dortprio __P((struct proc *, struct proc *, struct rtprio *)); + void mi_switch __P((void)); + int resched_wanted __P((void)); + int roundrobin_interval __P((void)); + void setrunnable __P((struct proc *)); + void sleepinit __P((void)); + int synch_compare __P((struct proc *, struct proc *)); + void synch_fork __P((struct proc *, struct proc *)); + void synch_proc0_init __P((struct proc *)); + int synch_proc_force_runnable __P((struct proc *)); + int synch_proc_isnice __P((struct proc *)); + void synch_proc_killing __P((struct proc *)); + int synch_proc_priority __P((struct proc *, struct rtprio *)); + void synch_proc_runfast __P((struct proc *)); + int synch_proc_uninterruptible __P((struct proc *)); + int synch_proc_unswappable __P((struct proc *)); + int synch_yield __P((struct proc *, const int)); + void synch_zombie_charge __P((struct proc *)); + void unsleep __P((struct proc *)); + void update_estcpu __P((struct proc *)); + void userret __P((struct proc *, const register_t, const u_quad_t)); + + /* kern_switch */ + + /* XXX can't these be static now */ + + extern struct rq queues[]; + extern struct rq rtqueues[]; + extern struct rq idqueues[]; + extern int whichqs; /* Bit mask summary of non-empty Q's. */ + extern int whichrtqs; /* Bit mask summary of non-empty Q's. */ + extern int whichidqs; /* Bit mask summary of non-empty Q's. */ + + u_int32_t procrunnable __P((void)); + void remrunqueue __P((struct proc *)); + void setrunqueue __P((struct proc *)); + struct proc * chooseproc __P((void)); + + #endif /* KERNEL */ + #endif /* !_SYS_SYNCH_H_ */ diff -c -N -r /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/sys/systm.h /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/sys/systm.h *** /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/sys/systm.h Sun Sep 26 14:19:49 1999 --- /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/sys/systm.h Thu Oct 28 18:06:33 1999 *************** *** 58,65 **** extern int selwait; /* select timeout address */ - extern u_char curpriority; /* priority of current process */ - extern int physmem; /* physical memory */ extern dev_t dumpdev; /* dump device */ --- 58,63 ---- diff -c -N -r /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/vm/vm_glue.c /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/vm/vm_glue.c *** /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/vm/vm_glue.c Fri Sep 17 00:56:39 1999 --- /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/vm/vm_glue.c Thu Oct 28 18:06:34 1999 *************** *** 68,73 **** --- 68,74 ---- #include #include #include + #include #include #include #include *************** *** 342,348 **** pri = p->p_swtime + p->p_slptime; if ((p->p_flag & P_SWAPINREQ) == 0) { ! pri -= p->p_nice * 8; } /* --- 343,349 ---- pri = p->p_swtime + p->p_slptime; if ((p->p_flag & P_SWAPINREQ) == 0) { ! pri -= synch_proc_priority(p, 0) * 8; } /* *************** *** 429,447 **** case SSLEEP: case SSTOP: /* ! * do not swapout a realtime process */ ! if (RTP_PRIO_IS_REALTIME(p->p_rtprio.type)) continue; /* ! * Do not swapout a process waiting on a critical ! * event of some kind. Also guarantee swap_idle_threshold1 ! * time in memory. */ ! if (((p->p_priority & 0x7f) < PSOCK) || ! (p->p_slptime < swap_idle_threshold1)) continue; /* --- 430,446 ---- case SSLEEP: case SSTOP: + /* ! * Do not swapout unswappable processes. */ ! if (synch_proc_unswappable(p)) continue; /* ! * Guarantee swap_idle_threshold1 time in memory. */ ! if (p->p_slptime < swap_idle_threshold1) continue; /* diff -c -N -r /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/vm/vm_meter.c /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/vm/vm_meter.c *** /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/vm/vm_meter.c Fri Sep 17 00:56:40 1999 --- /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/vm/vm_meter.c Thu Oct 28 18:06:34 1999 *************** *** 36,41 **** --- 36,42 ---- #include #include + #include #include #include #include *************** *** 82,88 **** for (nrun = 0, p = allproc.lh_first; p != 0; p = p->p_list.le_next) { switch (p->p_stat) { case SSLEEP: ! if (p->p_priority > PZERO || p->p_slptime != 0) continue; /* fall through */ case SRUN: --- 83,89 ---- for (nrun = 0, p = allproc.lh_first; p != 0; p = p->p_list.le_next) { switch (p->p_stat) { case SSLEEP: ! if (!synch_proc_uninterruptible(p) || p->p_slptime != 0) continue; /* fall through */ case SRUN: *************** *** 157,163 **** case SSLEEP: case SSTOP: if (p->p_flag & P_INMEM) { ! if (p->p_priority <= PZERO) totalp->t_dw++; else if (p->p_slptime < maxslp) totalp->t_sl++; --- 158,164 ---- case SSLEEP: case SSTOP: if (p->p_flag & P_INMEM) { ! if (synch_proc_uninterruptible(p)) totalp->t_dw++; else if (p->p_slptime < maxslp) totalp->t_sl++; diff -c -N -r /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/vm/vm_pageout.c /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/vm/vm_pageout.c *** /hosts/rt/B/old-sd1-A/dufault/posix4/current/usr/src/sys/vm/vm_pageout.c Fri Sep 17 00:56:40 1999 --- /hosts/rt/B/old-sd1-A/dufault/posix4/new/usr/src/sys/vm/vm_pageout.c Thu Oct 28 18:06:34 1999 *************** *** 77,82 **** --- 77,83 ---- #include #include #include + #include #include #include #include *************** *** 1129,1137 **** } if (bigproc != NULL) { killproc(bigproc, "out of swap space"); ! bigproc->p_estcpu = 0; ! bigproc->p_nice = PRIO_MIN; ! resetpriority(bigproc); wakeup(&cnt.v_free_count); } } --- 1130,1136 ---- } if (bigproc != NULL) { killproc(bigproc, "out of swap space"); ! (void)synch_proc_force_runnable(bigproc); wakeup(&cnt.v_free_count); } }