diff options
author | svn2git <svn2git@FreeBSD.org> | 1994-07-01 08:00:00 +0000 |
---|---|---|
committer | svn2git <svn2git@FreeBSD.org> | 1994-07-01 08:00:00 +0000 |
commit | 5e0e9b99dc3fc0ecd49d929db0d57c784b66f481 (patch) | |
tree | e779b5a6edddbb949b7990751b12d6f25304ba86 /sys/kern | |
parent | a16f65c7d117419bd266c28a1901ef129a337569 (diff) |
Diffstat (limited to 'sys/kern')
37 files changed, 1661 insertions, 568 deletions
diff --git a/sys/kern/imgact_aout.c b/sys/kern/imgact_aout.c index 8bfb19cfe28d..8837764c2735 100644 --- a/sys/kern/imgact_aout.c +++ b/sys/kern/imgact_aout.c @@ -28,7 +28,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: imgact_aout.c,v 1.3 1993/12/30 01:39:29 davidg Exp $ + * $Id: imgact_aout.c,v 1.4 1994/03/17 22:21:02 davidg Exp $ */ #include "param.h" @@ -151,9 +151,7 @@ exec_aout_imgact(iparams) &vmaddr, a_out->a_data, VM_PROT_READ | VM_PROT_WRITE | (a_out->a_text ? 0 : VM_PROT_EXECUTE), - VM_PROT_READ | VM_PROT_WRITE | (a_out->a_text ? 0 : VM_PROT_EXECUTE), - MAP_FILE | MAP_PRIVATE | MAP_FIXED, - iparams->vnodep, + VM_PROT_ALL, MAP_FILE | MAP_PRIVATE | MAP_FIXED, iparams->vnodep, file_offset + a_out->a_text); if (error) return (error); diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c index ce2f1bf8065f..9624bb3482b3 100644 --- a/sys/kern/init_main.c +++ b/sys/kern/init_main.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * from: @(#)init_main.c 7.41 (Berkeley) 5/15/91 - * $Id: init_main.c,v 1.14 1994/01/14 16:24:45 davidg Exp $ + * $Id: init_main.c,v 1.18 1994/06/16 02:55:28 davidg Exp $ */ #include "param.h" @@ -77,7 +77,7 @@ struct filedesc0 filedesc0; struct plimit limit0; struct vmspace vmspace0; struct proc *curproc = &proc0; -struct proc *initproc, *pageproc; +struct proc *initproc, *pageproc, *pagescanproc, *updateproc; int cmask = CMASK; extern struct user *proc0paddr; @@ -86,8 +86,6 @@ extern int (*mountroot)(); struct vnode *rootvp, *swapdev_vp; int boothowto; -struct proc *updateproc; - #if __GNUC__ >= 2 void __main() {} #endif @@ -96,6 +94,10 @@ void __main() {} * This table is filled in by the linker with functions that need to be * called to initialize various pseudo-devices and whatnot. */ + +static void dummyinit() {} +TEXT_SET(pseudo_set, dummyinit); + typedef void (*pseudo_func_t)(void); extern const struct linker_set pseudo_set; static const pseudo_func_t *pseudos = @@ -351,7 +353,7 @@ main() * Start up pageout daemon (process 2). */ if (fork(p, (void *) NULL, rval)) - panic("fork pager"); + panic("failed fork pageout daemon"); if (rval[1]) { /* * Now in process 2. @@ -364,11 +366,28 @@ main() /*NOTREACHED*/ } +#if 0 + /* + * Start page scanner daemon (process 3). + */ + if (fork(p, (void *) NULL, rval)) + panic("failed fork page scanner daemon"); + if (rval[1]) { + p = curproc; + pagescanproc = p; + p->p_flag |= SLOAD|SSYS; + bcopy("pagescan", p->p_comm, sizeof("pagescan")); + vm_pagescan(); + /*NOTREACHED*/ + } +#endif + /* - * Start update daemon (process 3). + * Start update daemon (process 4). */ +#ifndef LAPTOP if (fork(p, (void *) NULL, rval)) - panic("fork update"); + panic("failed fork update daemon"); if (rval[1]) { p = curproc; updateproc = p; @@ -377,6 +396,7 @@ main() vfs_update(); /*NOTREACHED*/ } +#endif /* * enter scheduling loop diff --git a/sys/kern/init_sysent.c b/sys/kern/init_sysent.c index 97056b0c3bbc..55a5b1e3263f 100644 --- a/sys/kern/init_sysent.c +++ b/sys/kern/init_sysent.c @@ -2,7 +2,7 @@ * System call switch table. * * DO NOT EDIT-- this file is automatically generated. - * created from $Id: syscalls.master,v 1.8 1994/01/31 10:27:25 davidg Exp $ + * created from $Id: syscalls.master,v 1.9 1994/03/15 01:58:33 wollman Exp $ */ #include "param.h" @@ -174,6 +174,8 @@ int msgsys(); int shmsys(); #else #endif +int ntp_gettime(); +int ntp_adjtime(); #ifdef MACHVMCOMPAT int svm_allocate(); int svm_deallocate(); @@ -453,8 +455,8 @@ struct sysent sysent[] = { 0, nosys, /* 172 = nosys */ 0, nosys, /* 173 = nosys */ 0, nosys, /* 174 = nosys */ - 0, nosys, /* 175 = nosys */ - 0, nosys, /* 176 = nosys */ + 1, ntp_gettime, /* 175 = ntp_gettime */ + 1, ntp_adjtime, /* 176 = ntp_adjtime */ #ifdef MACHVMCOMPAT 4, svm_allocate, /* 177 = vm_allocate */ 3, svm_deallocate, /* 178 = vm_deallocate */ diff --git a/sys/kern/kern_acct.c b/sys/kern/kern_acct.c index 6d2c0e6536c7..386886e9926a 100644 --- a/sys/kern/kern_acct.c +++ b/sys/kern/kern_acct.c @@ -38,7 +38,7 @@ * SUCH DAMAGE. * * from: @(#)kern_acct.c 7.18 (Berkeley) 5/11/91 - * $Id: kern_acct.c,v 1.9.2.1 1994/05/04 07:54:32 rgrimes Exp $ + * $Id: kern_acct.c,v 1.10 1994/05/04 08:26:46 rgrimes Exp $ */ #include "param.h" diff --git a/sys/kern/kern_clock.c b/sys/kern/kern_clock.c index 44a334e00ebc..8df606e4dc72 100644 --- a/sys/kern/kern_clock.c +++ b/sys/kern/kern_clock.c @@ -31,9 +31,27 @@ * SUCH DAMAGE. * * from: @(#)kern_clock.c 7.16 (Berkeley) 5/9/91 - * $Id: kern_clock.c,v 1.11 1993/12/19 00:51:20 wollman Exp $ + * $Id: kern_clock.c,v 1.16 1994/04/21 20:39:30 wollman Exp $ */ +/* Portions of this software are covered by the following: */ +/****************************************************************************** + * * + * Copyright (c) David L. Mills 1993, 1994 * + * * + * Permission to use, copy, modify, and distribute this software and its * + * documentation for any purpose and without fee is hereby granted, provided * + * that the above copyright notice appears in all copies and that both the * + * copyright notice and this permission notice appear in supporting * + * documentation, and that the name University of Delaware not be used in * + * advertising or publicity pertaining to distribution of the software * + * without specific, written prior permission. The University of Delaware * + * makes no representations about the suitability this software for any * + * purpose. It is provided "as is" without express or implied warranty. * + * * + *****************************************************************************/ + + #include "param.h" #include "systm.h" #include "dkstat.h" @@ -42,6 +60,7 @@ #include "proc.h" #include "signalvar.h" #include "resourcevar.h" +#include "timex.h" #include "machine/cpu.h" @@ -93,6 +112,238 @@ int ncallout; } /* + * Phase-lock loop (PLL) definitions + * + * The following variables are read and set by the ntp_adjtime() system + * call. + * + * time_state shows the state of the system clock, with values defined + * in the timex.h header file. + * + * time_status shows the status of the system clock, with bits defined + * in the timex.h header file. + * + * time_offset is used by the PLL to adjust the system time in small + * increments. + * + * time_constant determines the bandwidth or "stiffness" of the PLL. + * + * time_tolerance determines maximum frequency error or tolerance of the + * CPU clock oscillator and is a property of the architecture; however, + * in principle it could change as result of the presence of external + * discipline signals, for instance. + * + * time_precision is usually equal to the kernel tick variable; however, + * in cases where a precision clock counter or external clock is + * available, the resolution can be much less than this and depend on + * whether the external clock is working or not. + * + * time_maxerror is initialized by a ntp_adjtime() call and increased by + * the kernel once each second to reflect the maximum error + * bound growth. + * + * time_esterror is set and read by the ntp_adjtime() call, but + * otherwise not used by the kernel. + */ +int time_status = STA_UNSYNC; /* clock status bits */ +int time_state = TIME_OK; /* clock state */ +long time_offset = 0; /* time offset (us) */ +long time_constant = 0; /* pll time constant */ +long time_tolerance = MAXFREQ; /* frequency tolerance (scaled ppm) */ +long time_precision = 1; /* clock precision (us) */ +long time_maxerror = MAXPHASE; /* maximum error (us) */ +long time_esterror = MAXPHASE; /* estimated error (us) */ + +/* + * The following variables establish the state of the PLL and the + * residual time and frequency offset of the local clock. The scale + * factors are defined in the timex.h header file. + * + * time_phase and time_freq are the phase increment and the frequency + * increment, respectively, of the kernel time variable at each tick of + * the clock. + * + * time_freq is set via ntp_adjtime() from a value stored in a file when + * the synchronization daemon is first started. Its value is retrieved + * via ntp_adjtime() and written to the file about once per hour by the + * daemon. + * + * time_adj is the adjustment added to the value of tick at each timer + * interrupt and is recomputed at each timer interrupt. + * + * time_reftime is the second's portion of the system time on the last + * call to ntp_adjtime(). It is used to adjust the time_freq variable + * and to increase the time_maxerror as the time since last update + * increases. + */ +long time_phase = 0; /* phase offset (scaled us) */ +long time_freq = 0; /* frequency offset (scaled ppm) */ +long time_adj = 0; /* tick adjust (scaled 1 / hz) */ +long time_reftime = 0; /* time at last adjustment (s) */ + +#ifdef PPS_SYNC +/* + * The following variables are used only if the if the kernel PPS + * discipline code is configured (PPS_SYNC). The scale factors are + * defined in the timex.h header file. + * + * pps_time contains the time at each calibration interval, as read by + * microtime(). + * + * pps_offset is the time offset produced by the time median filter + * pps_tf[], while pps_jitter is the dispersion measured by this + * filter. + * + * pps_freq is the frequency offset produced by the frequency median + * filter pps_ff[], while pps_stabil is the dispersion measured by + * this filter. + * + * pps_usec is latched from a high resolution counter or external clock + * at pps_time. Here we want the hardware counter contents only, not the + * contents plus the time_tv.usec as usual. + * + * pps_valid counts the number of seconds since the last PPS update. It + * is used as a watchdog timer to disable the PPS discipline should the + * PPS signal be lost. + * + * pps_glitch counts the number of seconds since the beginning of an + * offset burst more than tick/2 from current nominal offset. It is used + * mainly to suppress error bursts due to priority conflicts between the + * PPS interrupt and timer interrupt. + * + * pps_count counts the seconds of the calibration interval, the + * duration of which is pps_shift in powers of two. + * + * pps_intcnt counts the calibration intervals for use in the interval- + * adaptation algorithm. It's just too complicated for words. + */ +struct timeval pps_time; /* kernel time at last interval */ +long pps_offset = 0; /* pps time offset (us) */ +long pps_jitter = MAXTIME; /* pps time dispersion (jitter) (us) */ +long pps_tf[] = {0, 0, 0}; /* pps time offset median filter (us) */ +long pps_freq = 0; /* frequency offset (scaled ppm) */ +long pps_stabil = MAXFREQ; /* frequency dispersion (scaled ppm) */ +long pps_ff[] = {0, 0, 0}; /* frequency offset median filter */ +long pps_usec = 0; /* microsec counter at last interval */ +long pps_valid = PPS_VALID; /* pps signal watchdog counter */ +int pps_glitch = 0; /* pps signal glitch counter */ +int pps_count = 0; /* calibration interval counter (s) */ +int pps_shift = PPS_SHIFT; /* interval duration (s) (shift) */ +int pps_intcnt = 0; /* intervals at current duration */ + +/* + * PPS signal quality monitors + * + * pps_jitcnt counts the seconds that have been discarded because the + * jitter measured by the time median filter exceeds the limit MAXTIME + * (100 us). + * + * pps_calcnt counts the frequency calibration intervals, which are + * variable from 4 s to 256 s. + * + * pps_errcnt counts the calibration intervals which have been discarded + * because the wander exceeds the limit MAXFREQ (100 ppm) or where the + * calibration interval jitter exceeds two ticks. + * + * pps_stbcnt counts the calibration intervals that have been discarded + * because the frequency wander exceeds the limit MAXFREQ / 4 (25 us). + */ +long pps_jitcnt = 0; /* jitter limit exceeded */ +long pps_calcnt = 0; /* calibration intervals */ +long pps_errcnt = 0; /* calibration errors */ +long pps_stbcnt = 0; /* stability limit exceeded */ +#endif /* PPS_SYNC */ + +/* XXX none of this stuff works under FreeBSD */ +#ifdef EXT_CLOCK +/* + * External clock definitions + * + * The following definitions and declarations are used only if an + * external clock (HIGHBALL or TPRO) is configured on the system. + */ +#define CLOCK_INTERVAL 30 /* CPU clock update interval (s) */ + +/* + * The clock_count variable is set to CLOCK_INTERVAL at each PPS + * interrupt and decremented once each second. + */ +int clock_count = 0; /* CPU clock counter */ + +#ifdef HIGHBALL +/* + * The clock_offset and clock_cpu variables are used by the HIGHBALL + * interface. The clock_offset variable defines the offset between + * system time and the HIGBALL counters. The clock_cpu variable contains + * the offset between the system clock and the HIGHBALL clock for use in + * disciplining the kernel time variable. + */ +extern struct timeval clock_offset; /* Highball clock offset */ +long clock_cpu = 0; /* CPU clock adjust */ +#endif /* HIGHBALL */ +#endif /* EXT_CLOCK */ + +/* + * hardupdate() - local clock update + * + * This routine is called by ntp_adjtime() to update the local clock + * phase and frequency. This is used to implement an adaptive-parameter, + * first-order, type-II phase-lock loop. The code computes new time and + * frequency offsets each time it is called. The hardclock() routine + * amortizes these offsets at each tick interrupt. If the kernel PPS + * discipline code is configured (PPS_SYNC), the PPS signal itself + * determines the new time offset, instead of the calling argument. + * Presumably, calls to ntp_adjtime() occur only when the caller + * believes the local clock is valid within some bound (+-128 ms with + * NTP). If the caller's time is far different than the PPS time, an + * argument will ensue, and it's not clear who will lose. + * + * For default SHIFT_UPDATE = 12, the offset is limited to +-512 ms, the + * maximum interval between updates is 4096 s and the maximum frequency + * offset is +-31.25 ms/s. + * + * Note: splclock() is in effect. + */ +void +hardupdate(offset) + long offset; +{ + long ltemp, mtemp; + + if (!(time_status & STA_PLL) && !(time_status & STA_PPSTIME)) + return; + ltemp = offset; +#ifdef PPS_SYNC + if (time_status & STA_PPSTIME && time_status & STA_PPSSIGNAL) + ltemp = pps_offset; +#endif /* PPS_SYNC */ + if (ltemp > MAXPHASE) + time_offset = MAXPHASE << SHIFT_UPDATE; + else if (ltemp < -MAXPHASE) + time_offset = -(MAXPHASE << SHIFT_UPDATE); + else + time_offset = ltemp << SHIFT_UPDATE; + mtemp = time.tv_sec - time_reftime; + time_reftime = time.tv_sec; + if (mtemp > MAXSEC) + mtemp = 0; + + /* ugly multiply should be replaced */ + if (ltemp < 0) + time_freq -= (-ltemp * mtemp) >> (time_constant + + time_constant + SHIFT_KF - SHIFT_USEC); + else + time_freq += (ltemp * mtemp) >> (time_constant + + time_constant + SHIFT_KF - SHIFT_USEC); + if (time_freq > time_tolerance) + time_freq = time_tolerance; + else if (time_freq < -time_tolerance) + time_freq = -time_tolerance; +} + + + +/* * The hz hardware interval timer. * We update the events relating to real time. * If this timer is also being used to gather statistics, @@ -111,6 +362,7 @@ hardclock(frame) int needsoft = 0; extern int tickdelta; extern long timedelta; + long ltemp, time_update = 0; /* * Update real-time timeout queue. @@ -234,49 +486,164 @@ hardclock(frame) * so we don't keep the relatively high clock interrupt * priority any longer than necessary. */ - if (timedelta == 0) - BUMPTIME(&time, tick) - else { - register delta; - - if (timedelta < 0) { - delta = tick - tickdelta; - timedelta += tickdelta; + { + int time_update; + if (timedelta == 0) { + time_update = tick; } else { - delta = tick + tickdelta; - timedelta -= tickdelta; + if (timedelta < 0) { + time_update = tick - tickdelta; + timedelta += tickdelta; + } else { + time_update = tick + tickdelta; + timedelta -= tickdelta; + } + } + /* + * Compute the phase adjustment. If the low-order bits + * (time_phase) of the update overflow, bump the high-order bits + * (time_update). + */ + time_phase += time_adj; + if (time_phase <= -FINEUSEC) { + ltemp = -time_phase >> SHIFT_SCALE; + time_phase += ltemp << SHIFT_SCALE; + time_update -= ltemp; + } + else if (time_phase >= FINEUSEC) { + ltemp = time_phase >> SHIFT_SCALE; + time_phase -= ltemp << SHIFT_SCALE; + time_update += ltemp; + } + + time.tv_usec += time_update; + /* + * On rollover of the second the phase adjustment to be used for + * the next second is calculated. Also, the maximum error is + * increased by the tolerance. If the PPS frequency discipline + * code is present, the phase is increased to compensate for the + * CPU clock oscillator frequency error. + * + * With SHIFT_SCALE = 23, the maximum frequency adjustment is + * +-256 us per tick, or 25.6 ms/s at a clock frequency of 100 + * Hz. The time contribution is shifted right a minimum of two + * bits, while the frequency contribution is a right shift. + * Thus, overflow is prevented if the frequency contribution is + * limited to half the maximum or 15.625 ms/s. + */ + if (time.tv_usec >= 1000000) { + time.tv_usec -= 1000000; + time.tv_sec++; + time_maxerror += time_tolerance >> SHIFT_USEC; + if (time_offset < 0) { + ltemp = -time_offset >> + (SHIFT_KG + time_constant); + time_offset += ltemp; + time_adj = -ltemp << + (SHIFT_SCALE - SHIFT_HZ - SHIFT_UPDATE); + } else { + ltemp = time_offset >> + (SHIFT_KG + time_constant); + time_offset -= ltemp; + time_adj = ltemp << + (SHIFT_SCALE - SHIFT_HZ - SHIFT_UPDATE); + } +#ifdef PPS_SYNC + /* + * Gnaw on the watchdog counter and update the frequency + * computed by the pll and the PPS signal. + */ + pps_valid++; + if (pps_valid == PPS_VALID) { + pps_jitter = MAXTIME; + pps_stabil = MAXFREQ; + time_status &= ~(STA_PPSSIGNAL | STA_PPSJITTER | + STA_PPSWANDER | STA_PPSERROR); + } + ltemp = time_freq + pps_freq; +#else + ltemp = time_freq; +#endif /* PPS_SYNC */ + if (ltemp < 0) + time_adj -= -ltemp >> + (SHIFT_USEC + SHIFT_HZ - SHIFT_SCALE); + else + time_adj += ltemp >> + (SHIFT_USEC + SHIFT_HZ - SHIFT_SCALE); + + /* + * When the CPU clock oscillator frequency is not a + * power of two in Hz, the SHIFT_HZ is only an + * approximate scale factor. In the SunOS kernel, this + * results in a PLL gain factor of 1/1.28 = 0.78 what it + * should be. In the following code the overall gain is + * increased by a factor of 1.25, which results in a + * residual error less than 3 percent. + */ + /* Same thing applies for FreeBSD --GAW */ + if (hz == 100) { + if (time_adj < 0) + time_adj -= -time_adj >> 2; + else + time_adj += time_adj >> 2; + } + + /* XXX - this is really bogus, but can't be fixed until + xntpd's idea of the system clock is fixed to know how + the user wants leap seconds handled; in the mean time, + we assume that users of NTP are running without proper + leap second support (this is now the default anyway) */ + /* + * Leap second processing. If in leap-insert state at + * the end of the day, the system clock is set back one + * second; if in leap-delete state, the system clock is + * set ahead one second. The microtime() routine or + * external clock driver will insure that reported time + * is always monotonic. The ugly divides should be + * replaced. + */ + switch (time_state) { + + case TIME_OK: + if (time_status & STA_INS) + time_state = TIME_INS; + else if (time_status & STA_DEL) + time_state = TIME_DEL; + break; + + case TIME_INS: + if (time.tv_sec % 86400 == 0) { + time.tv_sec--; + time_state = TIME_OOP; + } + break; + + case TIME_DEL: + if ((time.tv_sec + 1) % 86400 == 0) { + time.tv_sec++; + time_state = TIME_WAIT; + } + break; + + case TIME_OOP: + time_state = TIME_WAIT; + break; + + case TIME_WAIT: + if (!(time_status & (STA_INS | STA_DEL))) + time_state = TIME_OK; + } } - BUMPTIME(&time, delta); } -#ifdef DCFCLK - /* - * This is lousy, but until I can get the $&^%&^(!!! signal onto one - * of the interrupt's I'll have to poll it. No, it will not work if - * you attempt -DHZ=1000, things break. - * But keep the NDCFCLK low, to avoid waste of cycles... - * phk@data.fls.dk - */ - dcfclk_worker(); -#endif if (needsoft) { -#if 0 -/* - * XXX - hardclock runs at splhigh, so the splsoftclock is useless and - * softclock runs at splhigh as well if we do this. It is not much of - * an optimization, since the "software interrupt" is done with a call - * from doreti, and the overhead of checking there is sometimes less - * than checking here. Moreover, the whole %$$%$^ frame is passed by - * value here. - */ if (CLKF_BASEPRI(&frame)) { /* * Save the overhead of a software interrupt; * it will happen as soon as we return, so do it now. */ (void) splsoftclock(); - softclock(frame); + softclock(CLKF_USERMODE(&frame)); } else -#endif setsoftclock(); } } @@ -322,7 +689,7 @@ gatherstats(framep) cpstate = CP_SYS; if (curproc == NULL && CLKF_BASEPRI(framep)) cpstate = CP_IDLE; -#ifdef GPROF +#if defined(GPROF) && !defined(GUPROF) s = (u_long) CLKF_PC(framep) - (u_long) s_lowpc; if (profiling < 2 && s < s_textsize) kcount[s / (HISTFRACTION * sizeof (*kcount))]++; @@ -343,10 +710,9 @@ gatherstats(framep) * Software priority level clock interrupt. * Run periodic events from timeout queue. */ -/*ARGSUSED*/ void -softclock(frame) - clockframe frame; +softclock(usermode) + int usermode; { for (;;) { @@ -377,11 +743,11 @@ softclock(frame) * If trapped user-mode and profiling, give it * a profiling tick. */ - if (CLKF_USERMODE(&frame)) { + if (usermode) { register struct proc *p = curproc; if (p->p_stats->p_prof.pr_scale) - profile_tick(p, &frame); + profile_tick(p, unused was &frame); /* * Check to see if process has accumulated * more than 10 minutes of user time. If so @@ -515,3 +881,167 @@ hzto(tv) ticks = CLOCK_T_MAX; return (ticks); } + +#ifdef PPS_SYNC +/* + * hardpps() - discipline CPU clock oscillator to external pps signal + * + * This routine is called at each PPS interrupt in order to discipline + * the CPU clock oscillator to the PPS signal. It integrates successive + * phase differences between the two oscillators and calculates the + * frequency offset. This is used in hardclock() to discipline the CPU + * clock oscillator so that intrinsic frequency error is cancelled out. + * The code requires the caller to capture the time and hardware + * counter value at the designated PPS signal transition. + */ +void +hardpps(tvp, usec) + struct timeval *tvp; /* time at PPS */ + long usec; /* hardware counter at PPS */ +{ + long u_usec, v_usec, bigtick; + long cal_sec, cal_usec; + + /* + * During the calibration interval adjust the starting time when + * the tick overflows. At the end of the interval compute the + * duration of the interval and the difference of the hardware + * counters at the beginning and end of the interval. This code + * is deliciously complicated by the fact valid differences may + * exceed the value of tick when using long calibration + * intervals and small ticks. Note that the counter can be + * greater than tick if caught at just the wrong instant, but + * the values returned and used here are correct. + */ + bigtick = (long)tick << SHIFT_USEC; + pps_usec -= ntp_pll.ybar; + if (pps_usec >= bigtick) + pps_usec -= bigtick; + if (pps_usec < 0) + pps_usec += bigtick; + pps_time.tv_sec++; + pps_count++; + if (pps_count < (1 << pps_shift)) + return; + pps_count = 0; + ntp_pll.calcnt++; + u_usec = usec << SHIFT_USEC; + v_usec = pps_usec - u_usec; + if (v_usec >= bigtick >> 1) + v_usec -= bigtick; + if (v_usec < -(bigtick >> 1)) + v_usec += bigtick; + if (v_usec < 0) + v_usec = -(-v_usec >> ntp_pll.shift); + else + v_usec = v_usec >> ntp_pll.shift; + pps_usec = u_usec; + cal_sec = tvp->tv_sec; + cal_usec = tvp->tv_usec; + cal_sec -= pps_time.tv_sec; + cal_usec -= pps_time.tv_usec; + if (cal_usec < 0) { + cal_usec += 1000000; + cal_sec--; + } + pps_time = *tvp; + + /* + * Check for lost interrupts, noise, excessive jitter and + * excessive frequency error. The number of timer ticks during + * the interval may vary +-1 tick. Add to this a margin of one + * tick for the PPS signal jitter and maximum frequency + * deviation. If the limits are exceeded, the calibration + * interval is reset to the minimum and we start over. + */ + u_usec = (long)tick << 1; + if (!((cal_sec == -1 && cal_usec > (1000000 - u_usec)) + || (cal_sec == 0 && cal_usec < u_usec)) + || v_usec > ntp_pll.tolerance || v_usec < -ntp_pll.tolerance) { + ntp_pll.jitcnt++; + ntp_pll.shift = NTP_PLL.SHIFT; + pps_dispinc = PPS_DISPINC; + ntp_pll.intcnt = 0; + return; + } + + /* + * A three-stage median filter is used to help deglitch the pps + * signal. The median sample becomes the offset estimate; the + * difference between the other two samples becomes the + * dispersion estimate. + */ + pps_mf[2] = pps_mf[1]; + pps_mf[1] = pps_mf[0]; + pps_mf[0] = v_usec; + if (pps_mf[0] > pps_mf[1]) { + if (pps_mf[1] > pps_mf[2]) { + u_usec = pps_mf[1]; /* 0 1 2 */ + v_usec = pps_mf[0] - pps_mf[2]; + } else if (pps_mf[2] > pps_mf[0]) { + u_usec = pps_mf[0]; /* 2 0 1 */ + v_usec = pps_mf[2] - pps_mf[1]; + } else { + u_usec = pps_mf[2]; /* 0 2 1 */ + v_usec = pps_mf[0] - pps_mf[1]; + } + } else { + if (pps_mf[1] < pps_mf[2]) { + u_usec = pps_mf[1]; /* 2 1 0 */ + v_usec = pps_mf[2] - pps_mf[0]; + } else if (pps_mf[2] < pps_mf[0]) { + u_usec = pps_mf[0]; /* 1 0 2 */ + v_usec = pps_mf[1] - pps_mf[2]; + } else { + u_usec = pps_mf[2]; /* 1 2 0 */ + v_usec = pps_mf[1] - pps_mf[0]; + } + } + + /* + * Here the dispersion average is updated. If it is less than + * the threshold pps_dispmax, the frequency average is updated + * as well, but clamped to the tolerance. + */ + v_usec = (v_usec >> 1) - ntp_pll.disp; + if (v_usec < 0) + ntp_pll.disp -= -v_usec >> PPS_AVG; + else + ntp_pll.disp += v_usec >> PPS_AVG; + if (ntp_pll.disp > pps_dispmax) { + ntp_pll.discnt++; + return; + } + if (u_usec < 0) { + ntp_pll.ybar -= -u_usec >> PPS_AVG; + if (ntp_pll.ybar < -ntp_pll.tolerance) + ntp_pll.ybar = -ntp_pll.tolerance; + u_usec = -u_usec; + } else { + ntp_pll.ybar += u_usec >> PPS_AVG; + if (ntp_pll.ybar > ntp_pll.tolerance) + ntp_pll.ybar = ntp_pll.tolerance; + } + + /* + * Here the calibration interval is adjusted. If the maximum + * time difference is greater than tick/4, reduce the interval + * by half. If this is not the case for four consecutive + * intervals, double the interval. + */ + if (u_usec << ntp_pll.shift > bigtick >> 2) { + ntp_pll.intcnt = 0; + if (ntp_pll.shift > NTP_PLL.SHIFT) { + ntp_pll.shift--; + pps_dispinc <<= 1; + } + } else if (ntp_pll.intcnt >= 4) { + ntp_pll.intcnt = 0; + if (ntp_pll.shift < NTP_PLL.SHIFTMAX) { + ntp_pll.shift++; + pps_dispinc >>= 1; + } + } else + ntp_pll.intcnt++; +} +#endif /* PPS_SYNC */ diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c index d28faac16cbe..7ad2e2946f6a 100644 --- a/sys/kern/kern_descrip.c +++ b/sys/kern/kern_descrip.c @@ -38,7 +38,7 @@ * SUCH DAMAGE. * * from: @(#)kern_descrip.c 7.28 (Berkeley) 6/25/91 - * $Id: kern_descrip.c,v 1.6.2.1 1994/05/04 07:54:36 rgrimes Exp $ + * $Id: kern_descrip.c,v 1.8 1994/05/04 08:26:49 rgrimes Exp $ */ #include "param.h" @@ -100,10 +100,12 @@ dup(p, uap, retval) struct file *fp; int fd, error; +#if 0 /* * XXX Compatibility */ if (uap->i &~ 077) { uap->i &= 077; return (dup2(p, uap, retval)); } +#endif if ((unsigned)uap->i >= fdp->fd_nfiles || (fp = fdp->fd_ofiles[uap->i]) == NULL) diff --git a/sys/kern/kern_execve.c b/sys/kern/kern_execve.c index 5e0aa6565d3d..f72948400f1e 100644 --- a/sys/kern/kern_execve.c +++ b/sys/kern/kern_execve.c @@ -28,7 +28,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: kern_execve.c,v 1.15.2.2 1994/03/24 08:57:16 rgrimes Exp $ + * $Id: kern_execve.c,v 1.20 1994/03/26 12:24:27 davidg Exp $ */ #include "param.h" @@ -78,9 +78,6 @@ execve(p, uap, retval) char *stringbase, *stringp; int *stack_base; int error, resid, len, i; -#if 0 - char image_header[256]; -#endif struct image_params image_params, *iparams; struct vnode *vnodep; struct vattr attr; @@ -147,33 +144,13 @@ interpret: if (error) goto exec_fail_dealloc; -#if 0 - /* - * Read the image header from the file. - */ - error = vn_rdwr(UIO_READ, - vnodep, - image_header, - sizeof(image_header), - 0, - UIO_SYSSPACE, IO_NODELOCKED, - p->p_ucred, - &resid, - p); - if (error) - goto exec_fail_dealloc; - - /* Clear out junk in image_header if a partial read (small file) */ - if (resid) - bzero(image_header + (sizeof(image_header) - resid), resid); -#endif /* * Map the image header (first page) of the file into * kernel address space */ error = vm_mmap(kernel_map, /* map */ (vm_offset_t *)&image_header, /* address */ - NBPG, /* size */ + PAGE_SIZE, /* size */ VM_PROT_READ, /* protection */ VM_PROT_READ, /* max protection */ MAP_FILE, /* flags */ @@ -208,7 +185,7 @@ interpret: vput(ndp->ni_vp); FREE(ndp->ni_pnbuf, M_NAMEI); if (vm_deallocate(kernel_map, - (vm_offset_t)image_header, NBPG)) + (vm_offset_t)image_header, PAGE_SIZE)) panic("execve: header dealloc failed (1)"); /* set new name to that of the interpreter */ @@ -231,14 +208,15 @@ interpret: stack_base = exec_copyout_strings(iparams); p->p_vmspace->vm_minsaddr = (char *)stack_base; - /* * Stuff argument count as first item on stack */ *(--stack_base) = iparams->argc; - /* close files on exec, fixup signals */ + /* close files on exec */ fdcloseexec(p); + + /* reset caught signals */ execsigs(p); /* name this process - nameiexec(p, ndp) */ @@ -269,12 +247,12 @@ interpret: vrele(p->p_tracep); p->p_tracep = 0; } - if ((attr.va_mode&VSUID) && (p->p_flag & STRC) == 0) { + if ((attr.va_mode & VSUID) && (p->p_flag & STRC) == 0) { p->p_ucred = crcopy(p->p_ucred); p->p_ucred->cr_uid = attr.va_uid; p->p_flag |= SUGID; } - if ((attr.va_mode&VSGID) && (p->p_flag & STRC) == 0) { + if ((attr.va_mode & VSGID) && (p->p_flag & STRC) == 0) { p->p_ucred = crcopy(p->p_ucred); p->p_ucred->cr_groups[0] = attr.va_gid; p->p_flag |= SUGID; @@ -305,10 +283,9 @@ interpret: /* * free various allocated resources */ - if (vm_deallocate(kernel_map, (vm_offset_t)iparams->stringbase, - ARG_MAX)) + if (vm_deallocate(kernel_map, (vm_offset_t)iparams->stringbase, ARG_MAX)) panic("execve: string buffer dealloc failed (1)"); - if (vm_deallocate(kernel_map, (vm_offset_t)image_header, NBPG)) + if (vm_deallocate(kernel_map, (vm_offset_t)image_header, PAGE_SIZE)) panic("execve: header dealloc failed (2)"); vput(ndp->ni_vp); FREE(ndp->ni_pnbuf, M_NAMEI); @@ -322,7 +299,7 @@ exec_fail_dealloc: panic("execve: string buffer dealloc failed (2)"); if (iparams->image_header && iparams->image_header != (char *)-1) if (vm_deallocate(kernel_map, - (vm_offset_t)iparams->image_header, NBPG)) + (vm_offset_t)iparams->image_header, PAGE_SIZE)) panic("execve: header dealloc failed (3)"); vput(ndp->ni_vp); FREE(ndp->ni_pnbuf, M_NAMEI); diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c index e1deb4d855fe..a6cf4c732390 100644 --- a/sys/kern/kern_exit.c +++ b/sys/kern/kern_exit.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * from: @(#)kern_exit.c 7.35 (Berkeley) 6/27/91 - * $Id: kern_exit.c,v 1.14 1994/01/29 04:04:23 davidg Exp $ + * $Id: kern_exit.c,v 1.15 1994/03/14 21:54:13 davidg Exp $ */ #include "param.h" @@ -353,6 +353,9 @@ loop: continue; nfound++; if (p->p_stat == SZOMB) { + /* charge childs cpu usage to parent */ + if( curproc->p_pid != 1) + curproc->p_cpu += p->p_cpu; retval[0] = p->p_pid; #ifdef COMPAT_43 if (uap->compat) diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c index 5ca1d910f937..b9088766dd8b 100644 --- a/sys/kern/kern_fork.c +++ b/sys/kern/kern_fork.c @@ -38,7 +38,7 @@ * SUCH DAMAGE. * * from: @(#)kern_fork.c 7.29 (Berkeley) 5/15/91 - * $Id: kern_fork.c,v 1.6.2.1 1994/05/04 07:54:38 rgrimes Exp $ + * $Id: kern_fork.c,v 1.8 1994/05/04 08:26:54 rgrimes Exp $ */ #include "param.h" @@ -246,6 +246,11 @@ again: #endif /* + * set priority of child to be that of parent + */ + p2->p_cpu = p1->p_cpu; + + /* * This begins the section where we must prevent the parent * from being swapped. */ @@ -268,6 +273,9 @@ again: p2->p_stats->p_start = time; (void) spl0(); p2->p_acflag = AFORK; +/* + vm_map_init_pmap(&p2->p_vmspace->vm_map); +*/ return (0); } diff --git a/sys/kern/kern_malloc.c b/sys/kern/kern_malloc.c index 6841827446d0..ce3243a30367 100644 --- a/sys/kern/kern_malloc.c +++ b/sys/kern/kern_malloc.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * from: @(#)kern_malloc.c 7.25 (Berkeley) 5/8/91 - * $Id: kern_malloc.c,v 1.8 1994/02/10 08:04:07 davidg Exp $ + * $Id: kern_malloc.c,v 1.9 1994/04/13 00:54:59 ache Exp $ */ #include "param.h" @@ -259,3 +259,75 @@ kmeminit() kmemstats[M_MBUF].ks_limit = (vm_page_count * NBPG) / 16; #endif } + +void * +contigmalloc(size, type, flags, maxpa, alignmask, boundarymask) + unsigned long size; + int type; + int flags; + unsigned long maxpa; /* e.g. 16M - 1 for isa dma */ + unsigned long alignmask; /* e.g. 1M - 1 for M boundary */ + unsigned long boundarymask; /* e.g. 64K - 1 for 8-bit isa dma */ +{ + unsigned long skipsize; + void *skipva; + + size = round_page(size); + if (size == 0 || size > boundarymask + 1) + return (NULL); + + /* + * Attempt to push the physical address to a suitable boundary by + * skipping some memory. We could be cleverer here. E.g., mallocate + * lots of single pages and then free the ones that we hope to use. + * flags == M_WAIT is likely to hang the system. + */ + for (skipsize = 0, skipva = NULL; ; skipsize += NBPG) { + unsigned long off; + unsigned long pa; + unsigned long prevpa; + void *va; + + if (skipsize != 0) { + skipva = malloc(skipsize, type, flags); + if (skipva == NULL) { +#ifdef DEBUG + printf("contigmalloc: skipva NULL on try %d\n", + 1 + skipsize / NBPG); +#endif + return (NULL); + } + } + va = malloc(size, type, flags); + if (skipsize != 0) + free(skipva, type); + if (va == NULL) { +#ifdef DEBUG + printf("contigmalloc: va NULL on try %d\n", + 1 + skipsize / NBPG); +#endif + return (NULL); + } + for (off = 0, prevpa = 0; off < size; off += NBPG, prevpa = pa) + { + pa = pmap_extract(pmap_kernel(), (vm_offset_t)va + off); + if (pa + NBPG - 1 > maxpa + || off == 0 && pa & alignmask + || off != 0 + && (pa != prevpa + NBPG + || (pa & boundarymask) == 0)) + goto fail; + } +#ifdef DEBUG + printf("contigmalloc: success at va %lx pa %lx on try %d\n", + (unsigned long)va, + pmap_extract(pmap_kernel(), (unsigned long)va), + 1 + skipsize / NBPG); +#endif + return (va); +fail: + free(va, type); + } +} + + diff --git a/sys/kern/kern_ntptime.c b/sys/kern/kern_ntptime.c new file mode 100644 index 000000000000..9e50a42df282 --- /dev/null +++ b/sys/kern/kern_ntptime.c @@ -0,0 +1,267 @@ +/****************************************************************************** + * * + * Copyright (c) David L. Mills 1993, 1994 * + * * + * Permission to use, copy, modify, and distribute this software and its * + * documentation for any purpose and without fee is hereby granted, provided * + * that the above copyright notice appears in all copies and that both the * + * copyright notice and this permission notice appear in supporting * + * documentation, and that the name University of Delaware not be used in * + * advertising or publicity pertaining to distribution of the software * + * without specific, written prior permission. The University of Delaware * + * makes no representations about the suitability this software for any * + * purpose. It is provided "as is" without express or implied warranty. * + * * + ******************************************************************************/ + +/* + * Modification history kern_ntptime.c + * + * 24 Mar 94 David L. Mills + * Revised syscall interface to include new variables for PPS + * time discipline. + * + * 14 Feb 94 David L. Mills + * Added code for external clock + * + * 28 Nov 93 David L. Mills + * Revised frequency scaling to conform with adjusted parameters + * + * 17 Sep 93 David L. Mills + * Created file + */ +/* + * ntp_gettime(), ntp_adjtime() - precision time interface for SunOS + * 4.1.1 and 4.1.3 + * + * These routines consitute the Network Time Protocol (NTP) interfaces + * for user and daemon application programs. The ntp_gettime() routine + * provides the time, maximum error (synch distance) and estimated error + * (dispersion) to client user application programs. The ntp_adjtime() + * routine is used by the NTP daemon to adjust the system clock to an + * externally derived time. The time offset and related variables set by + * this routine are used by hardclock() to adjust the phase and + * frequency of the phase-lock loop which controls the system clock. + */ +#include "param.h" +#include "systm.h" +#include "kernel.h" +#include "proc.h" +#include "timex.h" + +/* + * The following variables are used by the hardclock() routine in the + * kern_clock.c module and are described in that module. + */ +extern struct timeval time; /* kernel time variable */ +extern int time_state; /* clock state */ +extern int time_status; /* clock status bits */ +extern long time_offset; /* time adjustment (us) */ +extern long time_freq; /* frequency offset (scaled ppm) */ +extern long time_maxerror; /* maximum error (us) */ +extern long time_esterror; /* estimated error (us) */ +extern long time_constant; /* pll time constant */ +extern long time_precision; /* clock precision (us) */ +extern long time_tolerance; /* frequency tolerance (scaled ppm) */ + +#ifdef PPS_SYNC +/* + * The following variables are used only if the PPS signal discipline + * is configured in the kernel. + */ +extern int pps_shift; /* interval duration (s) (shift) */ +extern long pps_freq; /* pps frequency offset (scaled ppm) */ +extern long pps_jitter; /* pps jitter (us) */ +extern long pps_stabil; /* pps stability (scaled ppm) */ +extern long pps_jitcnt; /* jitter limit exceeded */ +extern long pps_calcnt; /* calibration intervals */ +extern long pps_errcnt; /* calibration errors */ +extern long pps_stbcnt; /* stability limit exceeded */ +#endif /* PPS_SYNC */ + +/* + * ntp_gettime() - NTP user application interface + */ +struct ntp_gettime_args { + struct ntptimeval *tp; +}; + +int +ntp_gettime(struct proc *p, struct ntp_gettime_args *uap, int *retval) +{ + struct timeval atv; + struct ntptimeval ntv; + int s; + int error = 0; + + if (uap->tp) { + s = splclock(); +#ifdef EXT_CLOCK + /* + * The microtime() external clock routine returns a + * status code. If less than zero, we declare an error + * in the clock status word and return the kernel + * (software) time variable. While there are other + * places that call microtime(), this is the only place + * that matters from an application point of view. + */ + if (microtime(&atv) < 0) { + time_status |= STA_CLOCKERR; + ntv.time = time; + } else + time_status &= ~STA_CLOCKERR; +#else /* EXT_CLOCK */ + microtime(&atv); +#endif /* EXT_CLOCK */ + ntv.time = atv; + ntv.maxerror = time_maxerror; + ntv.esterror = time_esterror; + (void) splx(s); + + error = copyout((caddr_t)&ntv, (caddr_t)uap->tp, + sizeof (ntv)); + } + if (!error) { + *retval = time_state; + + /* + * Status word error decode. If any of these conditions + * occur, an error is returned, instead of the status + * word. Most applications will care only about the fact + * the system clock may not be trusted, not about the + * details. + * + * Hardware or software error + */ + if (time_status & (STA_UNSYNC | STA_CLOCKERR)) + *retval = TIME_ERROR; + + /* + * PPS signal lost when either time or frequency + * synchronization requested + */ + if (time_status & (STA_PPSFREQ | STA_PPSTIME) && + !(time_status & STA_PPSSIGNAL)) + *retval = TIME_ERROR; + + /* + * PPS jitter exceeded when time synchronization + * requested + */ + if (time_status & STA_PPSTIME && + time_status & STA_PPSJITTER) + *retval = TIME_ERROR; + + /* + * PPS wander exceeded or calibration error when + * frequency synchronization requested + */ + if (time_status & STA_PPSFREQ && + time_status & (STA_PPSWANDER | STA_PPSERROR)) + *retval = TIME_ERROR; + } + return error; +} + +/* + * ntp_adjtime() - NTP daemon application interface + */ +struct ntp_adjtime_args { + struct timex *tp; +}; + +int +ntp_adjtime(struct proc *p, struct ntp_adjtime_args *uap, int *retval) +{ + struct timex ntv; + int modes; + int s; + int error; + + error = copyin((caddr_t)uap->tp, (caddr_t)&ntv, sizeof(ntv)); + if (error) + return error; + + /* + * Update selected clock variables - only the superuser can + * change anything. Note that there is no error checking here on + * the assumption the superuser should know what it is doing. + */ + modes = ntv.modes; + if ((modes != 0) + && (error = suser(p->p_cred->pc_ucred, &p->p_acflag))) + return error; + + s = splclock(); + if (modes & MOD_FREQUENCY) +#ifdef PPS_SYNC + time_freq = ntv.freq - pps_freq; +#else /* PPS_SYNC */ + time_freq = ntv.freq; +#endif /* PPS_SYNC */ + if (modes & MOD_MAXERROR) + time_maxerror = ntv.maxerror; + if (modes & MOD_ESTERROR) + time_esterror = ntv.esterror; + if (modes & MOD_STATUS) { + time_status &= STA_RONLY; + time_status |= ntv.status & ~STA_RONLY; + } + if (modes & MOD_TIMECONST) + time_constant = ntv.constant; + if (modes & MOD_OFFSET) + hardupdate(ntv.offset); + + /* + * Retrieve all clock variables + */ + if (time_offset < 0) + ntv.offset = -(-time_offset >> SHIFT_UPDATE); + else + ntv.offset = time_offset >> SHIFT_UPDATE; +#ifdef PPS_SYNC + ntv.freq = time_freq + pps_freq; +#else /* PPS_SYNC */ + ntv.freq = time_freq; +#endif /* PPS_SYNC */ + ntv.maxerror = time_maxerror; + ntv.esterror = time_esterror; + ntv.status = time_status; + ntv.constant = time_constant; + ntv.precision = time_precision; + ntv.tolerance = time_tolerance; +#ifdef PPS_SYNC + ntv.shift = pps_shift; + ntv.ppsfreq = pps_freq; + ntv.jitter = pps_jitter >> PPS_AVG; + ntv.stabil = pps_stabil; + ntv.calcnt = pps_calcnt; + ntv.errcnt = pps_errcnt; + ntv.jitcnt = pps_jitcnt; + ntv.stbcnt = pps_stbcnt; +#endif /* PPS_SYNC */ + (void)splx(s); + + error = copyout((caddr_t)&ntv, (caddr_t)uap->tp, sizeof(ntv)); + if (!error) { + /* + * Status word error decode. See comments in + * ntp_gettime() routine. + */ + retval[0] = time_state; + if (time_status & (STA_UNSYNC | STA_CLOCKERR)) + retval[0] = TIME_ERROR; + if (time_status & (STA_PPSFREQ | STA_PPSTIME) && + !(time_status & STA_PPSSIGNAL)) + retval[0] = TIME_ERROR; + if (time_status & STA_PPSTIME && + time_status & STA_PPSJITTER) + retval[0] = TIME_ERROR; + if (time_status & STA_PPSFREQ && + time_status & (STA_PPSWANDER | STA_PPSERROR)) + retval[0] = TIME_ERROR; + } + return error; +} + + diff --git a/sys/kern/kern_physio.c b/sys/kern/kern_physio.c index cf76f80ae202..bc02348f73a9 100644 --- a/sys/kern/kern_physio.c +++ b/sys/kern/kern_physio.c @@ -45,7 +45,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: kern_physio.c,v 1.1.2.2 1994/05/01 18:59:48 rgrimes Exp $ + * $Id: kern_physio.c,v 1.7 1994/04/25 23:48:29 davidg Exp $ */ #include "param.h" @@ -56,8 +56,11 @@ #include "malloc.h" #include "vnode.h" #include "vm/vm.h" +#include "vm/vm_page.h" #include "specdev.h" +#define HOLD_WORKS_FOR_SHARING + /* * Driver interface to do "raw" I/O in the address space of a * user process directly for read and write operations.. @@ -79,6 +82,13 @@ rawwrite(dev, uio) (caddr_t) (u_long) dev, uio)); } +static void +physwakeup(bp) + struct buf *bp; +{ + wakeup((caddr_t) bp); + bp->b_flags &= ~B_CALL; +} int physio(strat, dev, bp, off, rw, base, len, p) d_strategy_t strat; @@ -92,7 +102,7 @@ int physio(strat, dev, bp, off, rw, base, len, p) int amttodo = *len; int error, amtdone; vm_prot_t ftype; - vm_offset_t v, lastv; + vm_offset_t v, lastv, pa; caddr_t adr; int oldflags; int s; @@ -122,7 +132,6 @@ int physio(strat, dev, bp, off, rw, base, len, p) splx(s); } - bp->b_flags = B_BUSY | B_PHYS | rw; bp->b_proc = p; bp->b_dev = dev; bp->b_error = 0; @@ -131,17 +140,25 @@ int physio(strat, dev, bp, off, rw, base, len, p) /* iteratively do I/O on as large a chunk as possible */ do { - bp->b_flags &= ~B_DONE; + bp->b_flags = B_BUSY | B_PHYS | B_CALL | rw; + bp->b_iodone = physwakeup; bp->b_un.b_addr = base; - /* XXX limit */ + /* + * Notice that b_bufsize is more owned by the buffer + * allocating entity, while b_bcount might be modified + * by the called I/O routines. So after I/O is complete + * the only thing guaranteed to be unchanged is + * b_bufsize. + */ bp->b_bcount = min (256*1024, amttodo); + bp->b_bufsize = bp->b_bcount; /* first, check if accessible */ - if (rw == B_READ && !useracc(base, bp->b_bcount, B_WRITE)) { + if (rw == B_READ && !useracc(base, bp->b_bufsize, B_WRITE)) { error = EFAULT; goto errrtn; } - if (rw == B_WRITE && !useracc(base, bp->b_bcount, B_READ)) { + if (rw == B_WRITE && !useracc(base, bp->b_bufsize, B_READ)) { error = EFAULT; goto errrtn; } @@ -153,16 +170,17 @@ int physio(strat, dev, bp, off, rw, base, len, p) ftype = VM_PROT_READ; lastv = 0; - for (adr = (caddr_t)trunc_page(base); adr < base + bp->b_bcount; + for (adr = (caddr_t)trunc_page(base); adr < base + bp->b_bufsize; adr += NBPG) { /* - * make sure that the pde is valid and wired + * make sure that the pde is valid and held */ v = trunc_page(((vm_offset_t)vtopte(adr))); if (v != lastv) { - vm_map_pageable(&p->p_vmspace->vm_map, v, - round_page(v+1), FALSE); + vm_fault_quick(v, VM_PROT_READ); + pa = pmap_extract(&p->p_vmspace->vm_pmap, v); + vm_page_hold(PHYS_TO_VM_PAGE(pa)); lastv = v; } @@ -170,65 +188,48 @@ int physio(strat, dev, bp, off, rw, base, len, p) * do the vm_fault if needed, do the copy-on-write thing when * reading stuff off device into memory. */ - if (ftype & VM_PROT_WRITE) { - /* - * properly handle copy-on-write - */ -#if 0 - *(volatile int *) adr += 0; -#endif - vm_fault(&curproc->p_vmspace->vm_map, - (vm_offset_t) adr, - VM_PROT_READ|VM_PROT_WRITE, FALSE); - } -#if 0 - else { - /* - * this clause is not really necessary because - * vslock does a vm_map_pageable FALSE. - * It is not optimally efficient to reference the - * page with the possiblity of it being paged out, but - * if this page is faulted here, it will be placed on the - * active queue, with the probability of it being paged - * out being very very low. This is here primarily for - * "symmetry". - */ - *(volatile int *) adr; - } -#endif - } + vm_fault_quick(adr, ftype); + pa = pmap_extract(&p->p_vmspace->vm_pmap, (vm_offset_t) adr); /* - * if the process has been blocked by the wiring of the page table pages - * above or faults of other pages, then the vm_map_pageable contained in the - * vslock will fault the pages back in if they have been paged out since - * being referenced in the loop above. (vm_map_pageable calls vm_fault_wire - * which calls vm_fault to get the pages if needed.) + * hold the data page */ + vm_page_hold(PHYS_TO_VM_PAGE(pa)); + } - /* lock in core (perform vm_map_pageable, FALSE) */ - vslock (base, bp->b_bcount); + vmapbuf(bp); /* perform transfer */ - physstrat(bp, strat, PRIBIO); + (*strat)(bp); - /* unlock (perform vm_map_pageable, TRUE) */ - vsunlock (base, bp->b_bcount, 0); + /* pageout daemon doesn't wait for pushed pages */ + s = splbio(); + while ((bp->b_flags & B_DONE) == 0) + tsleep((caddr_t)bp, PRIBIO, "physstr", 0); + splx(s); - lastv = 0; + vunmapbuf(bp); /* - * unwire the pde + * unhold the pde, and data pages */ - for (adr = (caddr_t)trunc_page(base); adr < base + bp->b_bcount; + lastv = 0; + for (adr = (caddr_t)trunc_page(base); adr < base + bp->b_bufsize; adr += NBPG) { v = trunc_page(((vm_offset_t)vtopte(adr))); if (v != lastv) { - vm_map_pageable(&p->p_vmspace->vm_map, v, round_page(v+1), TRUE); + pa = pmap_extract(&p->p_vmspace->vm_pmap, v); + vm_page_unhold(PHYS_TO_VM_PAGE(pa)); lastv = v; } + pa = pmap_extract(&p->p_vmspace->vm_pmap, (vm_offset_t) adr); + vm_page_unhold(PHYS_TO_VM_PAGE(pa)); } + /* + * in this case, we need to use b_bcount instead of + * b_bufsize. + */ amtdone = bp->b_bcount - bp->b_resid; amttodo -= amtdone; base += amtdone; diff --git a/sys/kern/kern_prot.c b/sys/kern/kern_prot.c index 2d1d7db1ce4e..48ea1cc33d06 100644 --- a/sys/kern/kern_prot.c +++ b/sys/kern/kern_prot.c @@ -38,7 +38,7 @@ * SUCH DAMAGE. * * from: @(#)kern_prot.c 7.21 (Berkeley) 5/3/91 - * $Id: kern_prot.c,v 1.5.2.2 1994/05/04 07:54:41 rgrimes Exp $ + * $Id: kern_prot.c,v 1.7 1994/05/04 08:26:59 rgrimes Exp $ */ /* diff --git a/sys/kern/kern_resource.c b/sys/kern/kern_resource.c index 941ead222a34..caaf6a5953a5 100644 --- a/sys/kern/kern_resource.c +++ b/sys/kern/kern_resource.c @@ -38,7 +38,7 @@ * SUCH DAMAGE. * * from: @(#)kern_resource.c 7.13 (Berkeley) 5/9/91 - * $Id: kern_resource.c,v 1.7.2.1 1994/05/04 07:54:43 rgrimes Exp $ + * $Id: kern_resource.c,v 1.8 1994/05/04 08:27:01 rgrimes Exp $ */ #include "param.h" diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c index 8450e1c2f588..f57966f8fbb6 100644 --- a/sys/kern/kern_sig.c +++ b/sys/kern/kern_sig.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * from: @(#)kern_sig.c 7.35 (Berkeley) 6/28/91 - * $Id: kern_sig.c,v 1.9 1993/12/19 00:51:30 wollman Exp $ + * $Id: kern_sig.c,v 1.12 1994/05/25 19:49:38 csgr Exp $ */ #define SIGPROP /* include signal properties table */ @@ -43,6 +43,7 @@ #include "mount.h" #include "filedesc.h" #include "proc.h" +#include "ucred.h" #include "systm.h" #include "timeb.h" #include "times.h" @@ -52,6 +53,7 @@ #include "kernel.h" #include "wait.h" #include "ktrace.h" +#include "syslog.h" #include "machine/cpu.h" @@ -1044,6 +1046,14 @@ sigexit(p, sig) p->p_acflag |= AXSIG; if (sigprop[sig] & SA_CORE) { p->p_sigacts->ps_sig = sig; + /* + * Log signals which would cause core dumps + * (Log as LOG_INFO to appease those who don't want + * these messages.) + * XXX : Todo, as well as euid, write out ruid too + */ + log(LOG_INFO, "pid %d: %s: uid %d: exited on signal %d\n", + p->p_pid, p->p_comm, p->p_ucred->cr_uid, sig); if (coredump(p) == 0) sig |= WCOREFLAG; } diff --git a/sys/kern/kern_subr.c b/sys/kern/kern_subr.c index bb860d2ca6bd..47af2d75b472 100644 --- a/sys/kern/kern_subr.c +++ b/sys/kern/kern_subr.c @@ -38,7 +38,7 @@ * SUCH DAMAGE. * * from: @(#)kern_subr.c 7.7 (Berkeley) 4/15/91 - * $Id: kern_subr.c,v 1.5.2.1 1994/05/04 07:54:46 rgrimes Exp $ + * $Id: kern_subr.c,v 1.6 1994/05/04 08:27:05 rgrimes Exp $ */ #include "param.h" diff --git a/sys/kern/kern_synch.c b/sys/kern/kern_synch.c index 554d38b004c4..67bd7e4786d8 100644 --- a/sys/kern/kern_synch.c +++ b/sys/kern/kern_synch.c @@ -32,7 +32,7 @@ * SUCH DAMAGE. * * from: @(#)kern_synch.c 7.18 (Berkeley) 6/27/91 - * $Id: kern_synch.c,v 1.4 1994/02/11 21:14:28 guido Exp $ + * $Id: kern_synch.c,v 1.5 1994/03/20 00:33:06 wollman Exp $ */ #include "param.h" @@ -381,7 +381,7 @@ endtsleep(arg1, dummy) splx(s); } -#if 1 /* XXX this should go away... */ +#if 0 /* This is obsolete, use tsleep(). */ /* * Short-term, non-interruptable sleep. */ diff --git a/sys/kern/kern_time.c b/sys/kern/kern_time.c index a0c4a117bb2f..3be34ee22d8e 100644 --- a/sys/kern/kern_time.c +++ b/sys/kern/kern_time.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * from: @(#)kern_time.c 7.15 (Berkeley) 3/17/91 - * $Id: kern_time.c,v 1.4 1993/11/25 01:33:14 wollman Exp $ + * $Id: kern_time.c,v 1.5 1994/06/22 05:52:47 jkh Exp $ */ #include "param.h" @@ -103,7 +103,9 @@ settimeofday(p, uap, retval) return (error); /* WHAT DO WE DO ABOUT PENDING REAL-TIME TIMEOUTS??? */ boottime.tv_sec += atv.tv_sec - time.tv_sec; - s = splhigh(); time = atv; splx(s); + s = splclock(); + time.tv_sec = atv.tv_sec; /* XXX avoid skew in tv_usec */ + splx(s); resettodr(); } if (uap->tzp && (error = copyin((caddr_t)uap->tzp, (caddr_t)&atz, diff --git a/sys/kern/makesyscalls.sh b/sys/kern/makesyscalls.sh index 77f61280c1bd..60826dfc4106 100644 --- a/sys/kern/makesyscalls.sh +++ b/sys/kern/makesyscalls.sh @@ -1,6 +1,6 @@ #! /bin/sh - # from: @(#)makesyscalls.sh 7.6 (Berkeley) 4/20/91 -# $Id: makesyscalls.sh,v 1.3 1993/11/07 21:22:30 wollman Exp $ +# $Id: makesyscalls.sh,v 1.4 1994/06/01 21:13:53 phk Exp $ set -e @@ -162,7 +162,7 @@ awk < $1 " printf("\n#else /* %s */\n", compat) > syscompat printf("#define compat(n, name) 0, nosys\n") > syscompat printf("#endif /* %s */\n\n", compat) > syscompat - printf("#endif /* _SYS_SYSCALL_H_ */") > syshdr + printf("#endif /* _SYS_SYSCALL_H_ */\n") > syshdr printf("};\n\n") > sysent printf("int\tnsysent = sizeof(sysent) / sizeof(sysent[0]);\n") > sysent diff --git a/sys/kern/spec_vnops.c b/sys/kern/spec_vnops.c index dd7a7c8be283..13ea715bef69 100644 --- a/sys/kern/spec_vnops.c +++ b/sys/kern/spec_vnops.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * from: @(#)spec_vnops.c 7.37 (Berkeley) 5/30/91 - * $Id: spec_vnops.c,v 1.3 1993/11/25 01:33:15 wollman Exp $ + * $Id: spec_vnops.c,v 1.4 1994/05/30 03:20:08 ache Exp $ */ #include "param.h" @@ -137,7 +137,9 @@ spec_open(vp, mode, cred, p) if ((u_int)maj >= nchrdev) return (ENXIO); VOP_UNLOCK(vp); + vp->v_opencount++; error = (*cdevsw[maj].d_open)(dev, mode, S_IFCHR, p); + --vp->v_opencount; VOP_LOCK(vp); return (error); diff --git a/sys/kern/subr_prf.c b/sys/kern/subr_prf.c index 6d4a61735965..afe2ddc99f36 100644 --- a/sys/kern/subr_prf.c +++ b/sys/kern/subr_prf.c @@ -38,7 +38,7 @@ * SUCH DAMAGE. * * from: @(#)subr_prf.c 7.30 (Berkeley) 6/29/91 - * $Id: subr_prf.c,v 1.6.2.1 1994/05/04 07:54:49 rgrimes Exp $ + * $Id: subr_prf.c,v 1.8 1994/05/04 08:27:06 rgrimes Exp $ */ #include "param.h" @@ -87,7 +87,6 @@ static void logpri __P((int level)); static void putchar __P((int ch, int flags, struct tty *tp)); static char *ksprintn __P((u_long num, int base, int *len)); void kprintf __P((const char *fmt, int flags, struct tty *tp, va_list)); -volatile void boot(int bootopt); /* * Variable panicstr contains argument to first call to panic; used @@ -106,14 +105,8 @@ int msgbufmapped; * and then reboots. If we are called twice, then we avoid trying to sync * the disks as this often leads to recursive panics. */ -#ifdef __STDC__ -volatile void -panic(const char *msg) -#else void -panic(msg) - char *msg; -#endif +panic(const char *msg) { int bootopt = RB_AUTOBOOT | RB_DUMP; diff --git a/sys/kern/subr_rand.c b/sys/kern/subr_rand.c new file mode 100644 index 000000000000..09f36a7d630a --- /dev/null +++ b/sys/kern/subr_rand.c @@ -0,0 +1,100 @@ +/* + * Copyright (c) 1993 Regents of the University of California. + * 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Computer Systems + * Engineering Group at Lawrence Berkeley Laboratory. + * 4. Neither the name of the University nor of the Laboratory may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + */ + +/* + * LBL BSD kernel random number generator (used by statclock). + * + * Written by Steve McCanne & Chris Torek (mccanne@ee.lbl.gov, + * torek@ee.lbl.gov), November, 1992. + * + * This implementation is based on ``Two Fast Implementations of + * the "Minimal Standard" Random Number Generator", David G. Carta, + * Communications of the ACM, Jan 1990, Vol 33 No 1. + */ + +#ifdef sparc +asm("\ + .global _kernrand ;\ +_kernrand: ;\ + sethi %hi(16807), %o1 ;\ + wr %o1, %lo(16807), %y ;\ + set 0xffff, %o4 ;\ + andcc %g0, 0, %o2 ;\ + mulscc %o2, %o0, %o2 ;\ + mulscc %o2, %o0, %o2 ;\ + mulscc %o2, %o0, %o2 ;\ + mulscc %o2, %o0, %o2 ;\ + mulscc %o2, %o0, %o2 ;\ + mulscc %o2, %o0, %o2 ;\ + mulscc %o2, %o0, %o2 ;\ + mulscc %o2, %o0, %o2 ;\ + mulscc %o2, %o0, %o2 ;\ + mulscc %o2, %o0, %o2 ;\ + mulscc %o2, %o0, %o2 ;\ + mulscc %o2, %o0, %o2 ;\ + mulscc %o2, %o0, %o2 ;\ + mulscc %o2, %o0, %o2 ;\ + mulscc %o2, %o0, %o2 ;\ + mulscc %o2, %g0, %o2 ;\ + rd %y, %o3 ;\ + srl %o2, 16, %o1 ;\ + and %o4, %o2, %o0 ;\ + sll %o0, 15, %o0 ;\ + srl %o3, 17, %o3 ;\ + or %o3, %o0, %o0 ;\ + addcc %o0, %o1, %o0 ;\ + bl 1f ;\ + sethi %hi(0x7fffffff), %o1 ;\ + retl ;\ + nop ;\ +1: ;\ + or %o1, %lo(0x7fffffff), %o1 ;\ + add %o0, 1, %o0 ;\ + retl ;\ + and %o1, %o0, %o0 "); +#else +long +kernrand(x) + register long x; +{ + register long hi, lo, t; + + hi = x / 127773; + lo = x % 127773; + t = 16807 * lo - 2836 * hi; + if (t > 0) + return (t); + else + return (t + 0x7fffffff); +} +#endif diff --git a/sys/kern/sys_process.c b/sys/kern/sys_process.c index b129f4f4d5bd..43f036c62568 100644 --- a/sys/kern/sys_process.c +++ b/sys/kern/sys_process.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * from: @(#)sys_process.c 7.22 (Berkeley) 5/11/91 - * $Id: sys_process.c,v 1.9.2.2 1994/05/03 20:44:01 rgrimes Exp $ + * $Id: sys_process.c,v 1.11 1994/04/02 23:03:01 jkh Exp $ */ #include "param.h" diff --git a/sys/kern/syscalls.c b/sys/kern/syscalls.c index 2f624acebcf7..1a65f4f70a44 100644 --- a/sys/kern/syscalls.c +++ b/sys/kern/syscalls.c @@ -2,7 +2,7 @@ * System call names. * * DO NOT EDIT-- this file is automatically generated. - * created from $Id: syscalls.master,v 1.8 1994/01/31 10:27:25 davidg Exp $ + * created from $Id: syscalls.master,v 1.9 1994/03/15 01:58:33 wollman Exp $ */ char *syscallnames[] = { @@ -218,8 +218,8 @@ char *syscallnames[] = { "#172", /* 172 = nosys */ "#173", /* 173 = nosys */ "#174", /* 174 = nosys */ - "#175", /* 175 = nosys */ - "#176", /* 176 = nosys */ + "ntp_gettime", /* 175 = ntp_gettime */ + "ntp_adjtime", /* 176 = ntp_adjtime */ #ifdef MACHVMCOMPAT "vm_allocate", /* 177 = vm_allocate */ "vm_deallocate", /* 178 = vm_deallocate */ diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master index a43845ebd1a4..db30a9330979 100644 --- a/sys/kern/syscalls.master +++ b/sys/kern/syscalls.master @@ -1,4 +1,4 @@ - $Id: syscalls.master,v 1.8 1994/01/31 10:27:25 davidg Exp $ + $Id: syscalls.master,v 1.9 1994/03/15 01:58:33 wollman Exp $ ; from: @(#)syscalls.master 7.26 (Berkeley) 3/25/91 ; System call name/number master file. ; Processed to created init_sysent.c, syscalls.c and syscall.h. @@ -243,8 +243,8 @@ 172 UNIMPL 0 nosys 173 UNIMPL 0 nosys 174 UNIMPL 0 nosys -175 UNIMPL 0 nosys -176 UNIMPL 0 nosys +175 STD 1 ntp_gettime +176 STD 1 ntp_adjtime #ifdef MACHVMCOMPAT 177 STD 4 svm_allocate vm_allocate 178 STD 3 svm_deallocate vm_deallocate diff --git a/sys/kern/sysv_msg.c b/sys/kern/sysv_msg.c index f861f53ece52..ff442d05b2cb 100644 --- a/sys/kern/sysv_msg.c +++ b/sys/kern/sysv_msg.c @@ -149,7 +149,7 @@ struct msgctl_args { struct msqid_ds *user_msqptr; }; -int +static int msgctl(p, uap, retval) struct proc *p; register struct msgctl_args *uap; @@ -309,7 +309,7 @@ struct msgget_args { int msgflg; }; -int +static int msgget(p, uap, retval) struct proc *p; register struct msgget_args *uap; @@ -766,7 +766,7 @@ struct msgrcv_args { int msgflg; }; -int +static int msgrcv(p, uap, retval) struct proc *p; register struct msgrcv_args *uap; diff --git a/sys/kern/sysv_sem.c b/sys/kern/sysv_sem.c index 6344018d9514..dbada0d09aad 100644 --- a/sys/kern/sysv_sem.c +++ b/sys/kern/sysv_sem.c @@ -62,7 +62,7 @@ semsys(p, uap, retval) { while ( semlock_holder != NULL && semlock_holder != p ) { /* printf("semaphore facility locked - sleeping ...\n"); */ - sleep( (caddr_t)&semlock_holder, (PZERO - 4) ); + tsleep( (caddr_t)&semlock_holder, (PZERO - 4), "semsys", 0 ); } if (uap->which >= sizeof(semcalls)/sizeof(semcalls[0])) @@ -89,7 +89,7 @@ struct semconfig_args { semconfig_ctl_t flag; }; -int +static int semconfig(p, uap, retval) struct proc *p; struct semconfig_args *uap; @@ -324,7 +324,7 @@ struct semctl_args { union semun *arg; }; -int +static int semctl(p, uap, retval) struct proc *p; register struct semctl_args *uap; @@ -556,7 +556,7 @@ struct semget_args { int semflg; }; -int +static int semget(p, uap, retval) struct proc *p; register struct semget_args *uap; @@ -676,7 +676,7 @@ struct semop_args { int nsops; }; -int +static int semop(p, uap, retval) struct proc *p; register struct semop_args *uap; @@ -1007,7 +1007,7 @@ semexit(p) #ifdef SEM_DEBUG printf("semaphore facility locked - sleeping ...\n"); #endif - sleep( (caddr_t)&semlock_holder, (PZERO - 4) ); + tsleep( (caddr_t)&semlock_holder, (PZERO - 4), "semexit", 0 ); } did_something = 0; diff --git a/sys/kern/sysv_shm.c b/sys/kern/sysv_shm.c index 00f123f529c5..3c7a45749583 100644 --- a/sys/kern/sysv_shm.c +++ b/sys/kern/sysv_shm.c @@ -37,7 +37,7 @@ * * from: Utah $Hdr: uipc_shm.c 1.9 89/08/14$ * from: @(#)sysv_shm.c 7.15 (Berkeley) 5/13/91 - * $Id: sysv_shm.c,v 1.9 1994/01/21 09:56:31 davidg Exp $ + * $Id: sysv_shm.c,v 1.12 1994/03/08 14:08:14 ats Exp $ */ /* @@ -69,7 +69,7 @@ struct shmid_ds *shmsegs; struct shminfo shminfo; -int shmat(), shmctl(), shmdt(), shmget(); /* XXX */ +static int shmat(), shmctl(), shmdt(), shmget(); /* XXX */ int (*shmcalls[])() = { shmat, shmctl, shmdt, shmget }; /* XXX */ int shmtot = 0; @@ -90,7 +90,7 @@ struct shmhandle { caddr_t shmh_id; }; -static int ipcaccess(struct ipc_perm *, int, struct ucred *); +extern int ipcaccess(struct ipc_perm *, int, struct ucred *); static void shmufree(struct proc *, struct shmdesc *); static void shmfree(struct shmid_ds *); static int shmvalid(int); @@ -146,7 +146,7 @@ struct shmget_args { int shmflg; }; -int +static int shmget(p, uap, retval) struct proc *p; register struct shmget_args *uap; @@ -244,7 +244,7 @@ struct shmctl_args { }; /* ARGSUSED */ -int +static int shmctl(p, uap, retval) struct proc *p; register struct shmctl_args *uap; @@ -316,7 +316,7 @@ struct shmat_args { int shmflg; }; -int +static int shmat(p, uap, retval) struct proc *p; register struct shmat_args *uap; @@ -402,7 +402,7 @@ struct shmdt_args { }; /* ARGSUSED */ -int +static int shmdt(p, uap, retval) struct proc *p; struct shmdt_args *uap; diff --git a/sys/kern/tty.c b/sys/kern/tty.c index 519b910ccfdb..146aa1545efe 100644 --- a/sys/kern/tty.c +++ b/sys/kern/tty.c @@ -32,7 +32,22 @@ * SUCH DAMAGE. * * from: @(#)tty.c 7.44 (Berkeley) 5/28/91 - * $Id: tty.c,v 1.19.2.1 1994/03/24 08:19:44 rgrimes Exp $ + * $Id: tty.c,v 1.32 1994/05/30 21:53:17 ache Exp $ + */ + +/*- + * TODO: + * o Fix races for sending the start char in ttyflush(). + * o Handle inter-byte timeout for "MIN > 0, TIME > 0" in ttselect(). + * With luck, there will be MIN chars before select() returns(). + * o Handle CLOCAL consistently for ptys. Perhaps disallow setting it. + * o Don't allow input in TS_ZOMBIE case. It would be visible through + * FIONREAD. + * o Do the new sio locking stuff here and use it to avoid special + * case for EXTPROC? + * o Lock PENDIN too? + * o Move EXTPROC and/or PENDIN to t_state? + * o Wrap most of ttioctl in spltty/splx. */ #include "param.h" @@ -47,6 +62,7 @@ #include "dkstat.h" #include "uio.h" #include "kernel.h" +#include "malloc.h" #include "vnode.h" #include "syslog.h" #include "signalvar.h" @@ -64,11 +80,12 @@ #define I_LOW_WATER ((TTYHOG - 2 * 256) * 7 / 8) /* XXX */ /* XXX RB_LEN() is too slow. */ -#define INPUT_LEN(tp) (RB_LEN(&(tp)->t_can) + RB_LEN(&(tp)->t_raw)) +#define INPUT_LEN(tp) (RB_LEN((tp)->t_can) + RB_LEN((tp)->t_raw)) #undef MAX_INPUT /* XXX wrong in <sys/syslimits.h> */ #define MAX_INPUT TTYHOG static int proc_compare __P((struct proc *p1, struct proc *p2)); +static int ttnread(struct tty *tp); static void ttyblock __P((struct tty *tp)); static void ttyecho __P((int c, struct tty *tp)); static int ttyoutput __P((int c, register struct tty *tp)); @@ -79,14 +96,6 @@ static void ttyrub __P((int c, struct tty *tp)); static void ttyrubo __P((struct tty *tp, int cnt)); static void ttyunblock __P((struct tty *tp)); -/* symbolic sleep message strings */ -const char ttyin[] = "ttyin"; -const char ttyout[] = "ttyout"; -const char ttopen[] = "ttyopn"; -const char ttclos[] = "ttycls"; -const char ttybg[] = "ttybg"; -const char ttybuf[] = "ttybuf"; - /* * Table giving parity for characters and indicating * character classes to tty driver. The 8th bit @@ -172,11 +181,19 @@ extern int nldisp; (c) == cc[VEOL] || (c) == cc[VEOL2]) && (c) != _POSIX_VDISABLE) void +termioschars(t) + struct termios *t; +{ + + bcopy(ttydefchars, t->c_cc, sizeof t->c_cc); +} + +void ttychars(tp) struct tty *tp; { - bcopy(ttydefchars, tp->t_cc, sizeof(ttydefchars)); + termioschars(&tp->t_termios); } /* @@ -202,36 +219,18 @@ ttywait(tp) { int error = 0, s = spltty(); - while ((RB_LEN(&tp->t_out) || tp->t_state&TS_BUSY) && - (tp->t_state&TS_CARR_ON || tp->t_cflag&CLOCAL) && - tp->t_oproc) { - /* - * XXX temporary fix for deadlock. - * - * If two processes wait for output to drain from the same - * tty, and the amount of output to drain is > 0 and - * <= tp->t_lowat, then the processes will take turns - * uselessly waking each other up until the output drains, - * with cpl higher than spltty() throughout. - * - * The sleep address and TS_ASLEEP flag ought to be different - * for the different events (output done) and (output almost - * done). - */ - tp->t_lowat = 0; - + while ((RB_LEN(tp->t_out) || tp->t_state&TS_BUSY) && + CAN_DO_IO(tp) && tp->t_oproc) { (*tp->t_oproc)(tp); - if ((RB_LEN(&tp->t_out) || tp->t_state&TS_BUSY) && - (tp->t_state&TS_CARR_ON || tp->t_cflag&CLOCAL)) { - tp->t_state |= TS_ASLEEP; - if (error = ttysleep(tp, (caddr_t)&tp->t_out, + if ((RB_LEN(tp->t_out) || tp->t_state&TS_BUSY) && + CAN_DO_IO(tp)) { + tp->t_state |= TS_SO_OCOMPLETE; + if (error = ttysleep(tp, TSA_OCOMPLETE(tp), TTOPRI | PCATCH, "ttywai", 0)) break; } else break; } - if (tp->t_lowat == 0) - ttsetwater(tp); splx(s); return (error); } @@ -257,21 +256,17 @@ ttyflush(tp, rw) tp->t_state &= ~TS_TTSTOP; (*cdevsw[major(tp->t_dev)].d_stop)(tp, rw); if (rw & FREAD) { - flushq(&tp->t_can); - flushq(&tp->t_raw); + flushq(tp->t_can); + flushq(tp->t_raw); + tp->t_lflag &= ~PENDIN; tp->t_rocount = 0; tp->t_rocol = 0; tp->t_state &= ~TS_LOCAL; ttwakeup(tp); } if (rw & FWRITE) { - flushq(&tp->t_out); - wakeup((caddr_t)&tp->t_out); - if (tp->t_wsel) { - selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); - tp->t_wsel = 0; - tp->t_state &= ~TS_WCOLL; - } + flushq(tp->t_out); + ttwwakeup(tp); } if (rw & FREAD) { if (tp->t_state & (TS_TBLOCK | TS_HW_IFLOW) @@ -286,16 +281,19 @@ ttyflush(tp, rw) * is still tricky because we don't want to add a * new obstruction to draining the output queue. */ - out_cc = RB_LEN(&tp->t_out); + out_cc = RB_LEN(tp->t_out); t_state = tp->t_state; ttyunblock(tp); tp->t_state &= ~TS_TBLOCK; - if (t_state & TS_TBLOCK && RB_LEN(&tp->t_out) != 0) - ttysleep(tp, (caddr_t)&tp->t_out, TTIPRI, + if (t_state & TS_TBLOCK && RB_LEN(tp->t_out) != 0) { + tp->t_state |= TS_SO_OCOMPLETE; + ttysleep(tp, TSA_OCOMPLETE(tp), TTIPRI, "ttyfls", hz / 10); - if (out_cc == 0 && RB_LEN(&tp->t_out) != 0) { + } + if (out_cc != 0 && RB_LEN(tp->t_out) != 0) { (*cdevsw[major(tp->t_dev)].d_stop)(tp, FWRITE); - flushq(&tp->t_out); + flushq(tp->t_out); + ttwwakeup(tp); } } } @@ -314,7 +312,7 @@ ttyblock(tp) if ((tp->t_state & TS_TBLOCK) == 0 && tp->t_cc[VSTOP] != _POSIX_VDISABLE - && putc(tp->t_cc[VSTOP], &tp->t_out) == 0) + && putc(tp->t_cc[VSTOP], tp->t_out) == 0) tp->t_state |= TS_TBLOCK; if (tp->t_cflag & CDTR_IFLOW) tp->t_state |= TS_DTR_IFLOW; @@ -334,7 +332,7 @@ ttyunblock(tp) if (tp->t_state & TS_TBLOCK && tp->t_cc[VSTART] != _POSIX_VDISABLE - && putc(tp->t_cc[VSTART], &tp->t_out) == 0) + && putc(tp->t_cc[VSTART], tp->t_out) == 0) tp->t_state &= ~TS_TBLOCK; tp->t_state &= ~TS_HW_IFLOW; ttstart(tp); @@ -413,7 +411,7 @@ ttioctl(tp, com, data, flag) (p->p_sigmask & sigmask(SIGTTOU)) == 0) { pgsignal(p->p_pgrp, SIGTTOU, 1); if (error = ttysleep(tp, (caddr_t)&lbolt, - TTOPRI | PCATCH, ttybg, 0)) + TTOPRI | PCATCH, "ttybg1", 0)) return (error); } break; @@ -490,11 +488,15 @@ ttioctl(tp, com, data, flag) /* return number of characters immediately available */ case FIONREAD: + s = spltty(); *(off_t *)data = ttnread(tp); + splx(s); break; case TIOCOUTQ: - *(int *)data = RB_LEN(&tp->t_out); + s = spltty(); + *(int *)data = RB_LEN(tp->t_out); + splx(s); break; case TIOCSTOP: @@ -555,47 +557,27 @@ ttioctl(tp, com, data, flag) if (tp->t_param && (error = (*tp->t_param)(tp, t))) { splx(s); return (error); - } else { - /* - * XXX doubtful. We mostly check both CLOCAL - * and TS_CARR_ON before doing anything, and - * changing TS_ISOPEN here just give another - * flag to worry about, and is probably - * inconsistent with not changing TS_ISOPEN - * when carrier drops or CLOCAL rises. OTOH - * we should maintain a flag to keep track - * of the combination of CLOCAL and TS_CARR_ON. - * This could be just TS_CARR_ON (if we don't - * need to - * - * XXX ttselect() doesn't worry about - * TS_ISOPEN, so it is inconsistent with - * ttread() after TS_ISOPEN gets cleared here. - */ - if ((tp->t_state&TS_CARR_ON) == 0 && - (tp->t_cflag&CLOCAL) && - (t->c_cflag&CLOCAL) == 0) { - tp->t_state &= ~TS_ISOPEN; - tp->t_state |= TS_WOPEN; - ttwakeup(tp); - } - tp->t_cflag = t->c_cflag; - tp->t_ispeed = t->c_ispeed; - tp->t_ospeed = t->c_ospeed; } + if (t->c_cflag & CLOCAL && !(tp->t_cflag & CLOCAL)) { + wakeup(TSA_CARR_ON(tp)); + ttwakeup(tp); + ttwwakeup(tp); + } + tp->t_cflag = t->c_cflag; + tp->t_ispeed = t->c_ispeed; + tp->t_ospeed = t->c_ospeed; ttsetwater(tp); } - if (com != TIOCSETAF) { - if ((t->c_lflag&ICANON) != (tp->t_lflag&ICANON)) - if (t->c_lflag&ICANON) { - tp->t_lflag |= PENDIN; - ttwakeup(tp); - } + if ((t->c_lflag&ICANON) != (tp->t_lflag&ICANON) && + com != TIOCSETAF) { + if (t->c_lflag&ICANON) + t->c_lflag |= PENDIN; else { - catb(&tp->t_raw, &tp->t_can); - catb(&tp->t_can, &tp->t_raw); + catb(tp->t_raw, tp->t_can); + catb(tp->t_can, tp->t_raw); } - } + ttwakeup(tp); + } tp->t_iflag = t->c_iflag; tp->t_oflag = t->c_oflag; /* @@ -606,6 +588,9 @@ ttioctl(tp, com, data, flag) else t->c_lflag &= ~EXTPROC; tp->t_lflag = t->c_lflag; + if (t->c_cc[VMIN] != tp->t_cc[VMIN] || + t->c_cc[VTIME] != tp->t_cc[VTIME]) + ttwakeup(tp); bcopy(t->c_cc, tp->t_cc, sizeof(t->c_cc)); splx(s); break; @@ -640,7 +625,13 @@ ttioctl(tp, com, data, flag) case TIOCSPGRP: { register struct pgrp *pgrp = pgfind(*(int *)data); +#ifdef broken_for_F_SETOWN + if (!suser(p->p_ucred, &p->p_acflag)) + ; + else if (!isctty(p, tp)) +#else if (!isctty(p, tp)) +#endif return (ENOTTY); else if (pgrp == NULL || pgrp->pg_session != p->p_session) return (EPERM); @@ -668,9 +659,7 @@ ttioctl(tp, com, data, flag) case TIOCCONS: if (*(int *)data) { - if (constty && constty != tp && - (constty->t_state & (TS_CARR_ON|TS_ISOPEN)) == - (TS_CARR_ON|TS_ISOPEN)) + if (constty && constty != tp && CAN_DO_IO(constty)) return (EBUSY); #ifndef UCONSOLE if (error = suser(p->p_ucred, &p->p_acflag)) @@ -696,19 +685,21 @@ ttioctl(tp, com, data, flag) return (0); } -int +/* + * Call at spltty(). + */ +static int ttnread(tp) struct tty *tp; { int nread = 0; - /* XXX races. */ if (tp->t_lflag & PENDIN) ttypend(tp); - nread = RB_LEN(&tp->t_can); + nread = RB_LEN(tp->t_can); if ((tp->t_lflag & ICANON) == 0) { - nread += RB_LEN(&tp->t_raw); - if (nread < tp->t_cc[VMIN]) + nread += RB_LEN(tp->t_raw); + if (nread < tp->t_cc[VMIN] && tp->t_cc[VTIME] == 0) nread = 0; } return (nread); @@ -720,17 +711,14 @@ ttselect(dev, rw, p) int rw; struct proc *p; { - register struct tty *tp = &cdevsw[major(dev)].d_ttys[minor(dev)]; - int nread; + register struct tty *tp = cdevsw[major(dev)].d_ttys[minor(dev)]; int s = spltty(); struct proc *selp; switch (rw) { case FREAD: - nread = ttnread(tp); - if (nread > 0 || - ((tp->t_cflag&CLOCAL) == 0 && (tp->t_state&TS_CARR_ON) == 0)) + if (ttnread(tp) > 0 || tp->t_state & TS_ZOMBIE) goto win; if (tp->t_rsel && (selp = pfind(tp->t_rsel)) && selp->p_wchan == (caddr_t)&selwait) tp->t_state |= TS_RCOLL; @@ -739,7 +727,8 @@ ttselect(dev, rw, p) break; case FWRITE: - if (RB_LEN(&tp->t_out) <= tp->t_lowat) + if (RB_LEN(tp->t_out) <= tp->t_lowat && CAN_DO_IO(tp) + || tp->t_state & TS_ZOMBIE) goto win; if (tp->t_wsel && (selp = pfind(tp->t_wsel)) && selp->p_wchan == (caddr_t)&selwait) tp->t_state |= TS_WCOLL; @@ -766,12 +755,11 @@ ttyopen(dev, tp, dummy) tp->t_dev = dev; - tp->t_state &= ~TS_WOPEN; if ((tp->t_state & TS_ISOPEN) == 0) { tp->t_state |= TS_ISOPEN; - initrb(&tp->t_raw); - initrb(&tp->t_can); - initrb(&tp->t_out); + initrb(tp->t_raw); + initrb(tp->t_can); + initrb(tp->t_out); bzero((caddr_t)&tp->t_winsize, sizeof(tp->t_winsize)); } return (0); @@ -793,7 +781,7 @@ ttylclose(tp, flag) } /* - * Handle close() on a tty line: flush and set to initial state, + * Handle close() on a tty line: set to initial state, * bumping generation number so that pending read/write calls * can detect recycling of the tty. */ @@ -803,7 +791,6 @@ ttyclose(tp) { if (constty == tp) constty = NULL; - ttyflush(tp, FREAD|FWRITE); tp->t_session = NULL; tp->t_pgrp = NULL; tp->t_state = 0; @@ -822,7 +809,7 @@ ttymodem(tp, flag) int flag; { - if ((tp->t_state&TS_WOPEN) == 0 && (tp->t_lflag&MDMBUF)) { + if (tp->t_state & TS_CARR_ON && tp->t_lflag & MDMBUF) { /* * MDMBUF: do flow control according to carrier flag */ @@ -839,6 +826,7 @@ ttymodem(tp, flag) */ tp->t_state &= ~TS_CARR_ON; if (tp->t_state&TS_ISOPEN && (tp->t_cflag&CLOCAL) == 0) { + tp->t_state |= TS_ZOMBIE; if (tp->t_session && tp->t_session->s_leader) psignal(tp->t_session->s_leader, SIGHUP); ttyflush(tp, FREAD|FWRITE); @@ -849,30 +837,9 @@ ttymodem(tp, flag) * Carrier now on. */ tp->t_state |= TS_CARR_ON; + wakeup(TSA_CARR_ON(tp)); ttwakeup(tp); - } - return (1); -} - -/* - * Default modem control routine (for other line disciplines). - * Return argument flag, to turn off device on carrier drop. - */ -int -nullmodem(tp, flag) - register struct tty *tp; - int flag; -{ - - if (flag) - tp->t_state |= TS_CARR_ON; - else { - tp->t_state &= ~TS_CARR_ON; - if ((tp->t_cflag&CLOCAL) == 0) { - if (tp->t_session && tp->t_session->s_leader) - psignal(tp->t_session->s_leader, SIGHUP); - return (0); - } + ttwwakeup(tp); } return (1); } @@ -889,12 +856,12 @@ ttypend(tp) tp->t_lflag &= ~PENDIN; tp->t_state |= TS_TYPEN; - hd = tp->t_raw.rb_hd; - tl = tp->t_raw.rb_tl; - flushq(&tp->t_raw); + hd = tp->t_raw->rb_hd; + tl = tp->t_raw->rb_tl; + flushq(tp->t_raw); while (hd != tl) { ttyinput(*hd, tp); - hd = RB_SUCC(&tp->t_raw, hd); + hd = RB_SUCC(tp->t_raw, hd); } tp->t_state &= ~TS_TYPEN; } @@ -937,7 +904,7 @@ ttyinput(c, tp) if ((iflag & IXOFF && (tp->t_state & TS_TBLOCK) == 0 || tp->t_cflag & TS_HW_IFLOW && (tp->t_state & TS_HW_IFLOW) == 0) && INPUT_LEN(tp) > I_HIGH_WATER - 3 - && ((lflag & ICANON) == 0 || RB_LEN(&tp->t_can) != 0)) + && ((lflag & ICANON) == 0 || RB_LEN(tp->t_can) != 0)) ttyblock(tp); /* * Handle exceptional conditions (break, parity, framing). @@ -959,9 +926,9 @@ ttyinput(c, tp) parmrk: if (INPUT_LEN(tp) > MAX_INPUT - 3) goto input_overflow; - putc(0377|TTY_QUOTE, &tp->t_raw); - putc(0|TTY_QUOTE, &tp->t_raw); - putc(c|TTY_QUOTE, &tp->t_raw); + putc(0377|TTY_QUOTE, tp->t_raw); + putc(0|TTY_QUOTE, tp->t_raw); + putc(c|TTY_QUOTE, tp->t_raw); goto endcase; } else c = 0; @@ -1074,23 +1041,23 @@ parmrk: * erase (^H / ^?) */ if (CCEQ(cc[VERASE], c)) { - if (RB_LEN(&tp->t_raw)) - ttyrub(unputc(&tp->t_raw), tp); + if (RB_LEN(tp->t_raw)) + ttyrub(unputc(tp->t_raw), tp); goto endcase; } /* * kill (^U) */ if (CCEQ(cc[VKILL], c)) { - if (lflag&ECHOKE && RB_LEN(&tp->t_raw) == tp->t_rocount && + if (lflag&ECHOKE && RB_LEN(tp->t_raw) == tp->t_rocount && (lflag&ECHOPRT) == 0) { - while (RB_LEN(&tp->t_raw)) - ttyrub(unputc(&tp->t_raw), tp); + while (RB_LEN(tp->t_raw)) + ttyrub(unputc(tp->t_raw), tp); } else { ttyecho(c, tp); if (lflag&ECHOK || lflag&ECHOKE) ttyecho('\n', tp); - while (getc(&tp->t_raw) > 0) + while (getc(tp->t_raw) > 0) ; tp->t_rocount = 0; } @@ -1106,7 +1073,7 @@ parmrk: /* * erase whitespace */ - while ((c = unputc(&tp->t_raw)) == ' ' || c == '\t') + while ((c = unputc(tp->t_raw)) == ' ' || c == '\t') ttyrub(c, tp); if (c == -1) goto endcase; @@ -1115,14 +1082,14 @@ parmrk: * next chars type (for ALTWERASE) */ ttyrub(c, tp); - c = unputc(&tp->t_raw); + c = unputc(tp->t_raw); if (c == -1) goto endcase; /* * Handle one-letter word cases. */ if (c == ' ' || c == '\t') { - putc(c, &tp->t_raw); + putc(c, tp->t_raw); goto endcase; } ctype = ISALPHA(c); @@ -1131,13 +1098,13 @@ parmrk: */ do { ttyrub(c, tp); - c = unputc(&tp->t_raw); + c = unputc(tp->t_raw); if (c == -1) goto endcase; } while (c != ' ' && c != '\t' && ((lflag & ALTWERASE) == 0 || ISALPHA(c) == ctype)); - (void) putc(c, &tp->t_raw); + (void) putc(c, tp->t_raw); goto endcase; } /* @@ -1163,7 +1130,7 @@ parmrk: if (INPUT_LEN(tp) >= MAX_INPUT) { input_overflow: if (iflag&IMAXBEL) { - if (RB_LEN(&tp->t_out) < tp->t_hiwat) + if (RB_LEN(tp->t_out) < tp->t_hiwat) (void) ttyoutput(CTRL('g'), tp); } else ttyflush(tp, FREAD); @@ -1173,7 +1140,7 @@ input_overflow: * Put data char in q for user and * wakeup on seeing a line delimiter. */ - if (putc(c, &tp->t_raw) >= 0) { + if (putc(c, tp->t_raw) >= 0) { if ((lflag&ICANON) == 0) { ttwakeup(tp); ttyecho(c, tp); @@ -1181,7 +1148,7 @@ input_overflow: } if (ttbreakc(c)) { tp->t_rocount = 0; - catb(&tp->t_raw, &tp->t_can); + catb(tp->t_raw, tp->t_can); ttwakeup(tp); } else if (tp->t_rocount++ == 0) tp->t_rocol = tp->t_col; @@ -1236,7 +1203,7 @@ ttyoutput(c, tp) if ((oflag&OPOST) == 0) { if (tp->t_lflag&FLUSHO) return (-1); - if (putc(c, &tp->t_out)) + if (putc(c, tp->t_out)) return (c); tk_nout++; tp->t_outcc++; @@ -1261,17 +1228,17 @@ ttyoutput(c, tp) #ifdef was c -= b_to_q(" ", c, &tp->t_outq); #else - i = imin(c, RB_CONTIGPUT(&tp->t_out)); - bcopy(" ", tp->t_out.rb_tl, i); - tp->t_out.rb_tl = - RB_ROLLOVER(&tp->t_out, tp->t_out.rb_tl+i); - i = imin(c - i, RB_CONTIGPUT(&tp->t_out)); + i = imin(c, RB_CONTIGPUT(tp->t_out)); + bcopy(" ", tp->t_out->rb_tl, i); + tp->t_out->rb_tl = + RB_ROLLOVER(tp->t_out, tp->t_out->rb_tl+i); + i = imin(c - i, RB_CONTIGPUT(tp->t_out)); /* off end and still have space? */ if (i) { - bcopy(" ", tp->t_out.rb_tl, i); - tp->t_out.rb_tl = - RB_ROLLOVER(&tp->t_out, tp->t_out.rb_tl+i); + bcopy(" ", tp->t_out->rb_tl, i); + tp->t_out->rb_tl = + RB_ROLLOVER(tp->t_out, tp->t_out->rb_tl+i); } #endif tk_nout += c; @@ -1291,7 +1258,7 @@ ttyoutput(c, tp) */ if (c == '\n' && (tp->t_oflag&ONLCR) && ttyoutput('\r', tp) >= 0) return (c); - if ((tp->t_lflag&FLUSHO) == 0 && putc(c, &tp->t_out)) + if ((tp->t_lflag&FLUSHO) == 0 && putc(c, tp->t_out)) return (c); col = tp->t_col; @@ -1342,8 +1309,8 @@ ttread(tp, uio, flag) long slp = 0; /* XXX this should be renamed `timo'. */ loop: - lflag = tp->t_lflag; s = spltty(); + lflag = tp->t_lflag; /* * take pending input first */ @@ -1351,6 +1318,7 @@ loop: ttypend(tp); splx(s); /* reduce latency */ s = spltty(); + lflag = tp->t_lflag; /* XXX ttypend() clobbers it */ } /* @@ -1364,18 +1332,32 @@ loop: return (EIO); pgsignal(p->p_pgrp, SIGTTIN, 1); if (error = ttysleep(tp, (caddr_t)&lbolt, TTIPRI | PCATCH, - ttybg, 0)) + "ttybg2", 0)) return (error); goto loop; } + if (tp->t_state & TS_ZOMBIE) { + splx(s); + return (0); /* EOF */ + } + /* * If canonical, use the canonical queue, * else use the raw queue. */ - qp = lflag&ICANON ? &tp->t_can : &tp->t_raw; + qp = lflag&ICANON ? tp->t_can : tp->t_raw; rblen = RB_LEN(qp); - + if (flag & IO_NDELAY) { + if (rblen > 0) + goto read; + if ((lflag & ICANON) == 0 && cc[VMIN] == 0) { + splx(s); + return (0); + } + splx(s); + return (EWOULDBLOCK); + } if ((lflag & ICANON) == 0) { int m = cc[VMIN]; long t = cc[VTIME]; @@ -1460,45 +1442,24 @@ loop: goto sleep; } if (rblen <= 0) { - int carrier; - sleep: /* - * If there is no input, sleep on rawq - * awaiting hardware receipt and notification. - * If we have data, we don't need to check for carrier. + * There is no input, or not enough input and we can block. */ - carrier = (tp->t_state&TS_CARR_ON) || (tp->t_cflag&CLOCAL); - if (!carrier && tp->t_state&TS_ISOPEN) { - splx(s); - return (0); /* EOF */ - } - if (flag & IO_NDELAY) { - splx(s); - return (EWOULDBLOCK); - } - if (slp) { - /* - * Use plain wakeup() not ttwakeup(). - * XXX why not use the timeout built into tsleep? - */ - timeout((timeout_func_t)wakeup, (caddr_t)qp, (int)slp); - } - error = ttysleep(tp, (caddr_t)&tp->t_raw, TTIPRI | PCATCH, - carrier ? ttyin : ttopen, 0); - if (slp) { - slp = 0; - untimeout((timeout_func_t)wakeup, (caddr_t)qp); - } + error = ttysleep(tp, TSA_HUP_OR_INPUT(tp), TTIPRI | PCATCH, + CAN_DO_IO(tp) ? "ttyin" : "ttyhup", (int)slp); splx(s); - if (error) + if (error == EWOULDBLOCK) + error = 0; + else if (error) return (error); /* - * XXX what happens if ICANON, MIN or TIME changes or - * another process eats some input while we are asleep - * (not just here)? It would be safest to detect changes - * and reset our state variables (has_stime and last_cc). + * XXX what happens if another process eats some input + * while we are asleep (not just here)? It would be + * safest to detect changes and reset our state variables + * (has_stime and last_cc). */ + slp = 0; goto loop; } @@ -1548,7 +1509,8 @@ slowcase: pgsignal(tp->t_pgrp, SIGTSTP, 1); if (first) { if (error = ttysleep(tp, (caddr_t)&lbolt, - TTIPRI | PCATCH, ttybg, 0)) + TTIPRI | PCATCH, "ttybg3", + 0)) break; goto loop; } @@ -1612,17 +1574,17 @@ ttycheckoutq(tp, wait) oldsig = curproc->p_sig; else oldsig = 0; - if (RB_LEN(&tp->t_out) > hiwat + 200) - while (RB_LEN(&tp->t_out) > hiwat) { + if (RB_LEN(tp->t_out) > hiwat + 200) + while (RB_LEN(tp->t_out) > hiwat) { ttstart(tp); + if (RB_LEN(tp->t_out) <= hiwat) + break; if (wait == 0 || (curproc && curproc->p_sig != oldsig)) { splx(s); return (0); } - timeout((timeout_func_t)wakeup, (caddr_t)&tp->t_out, - hz); /* XXX */ - tp->t_state |= TS_ASLEEP; - tsleep((caddr_t)&tp->t_out, PZERO - 1, "ttchout", 0); + tp->t_state |= TS_SO_OLOWAT; + tsleep(TSA_OLOWAT(tp), PZERO - 1, "ttchout", hz); } splx(s); return (1); @@ -1648,20 +1610,20 @@ ttwrite(tp, uio, flag) error = 0; loop: s = spltty(); - if ((tp->t_state&TS_CARR_ON) == 0 && (tp->t_cflag&CLOCAL) == 0) { - if (tp->t_state&TS_ISOPEN) { - splx(s); - return (EIO); - } else if (flag & IO_NDELAY) { + if (tp->t_state & TS_ZOMBIE) { + splx(s); + if (uio->uio_resid == cnt) + error = EIO; + goto out; + } + if (!CAN_DO_IO(tp)) { + if (flag & IO_NDELAY) { splx(s); error = EWOULDBLOCK; goto out; } else { - /* - * sleep awaiting carrier - */ - error = ttysleep(tp, (caddr_t)&tp->t_raw, - TTIPRI | PCATCH,ttopen, 0); + error = ttysleep(tp, TSA_CARR_ON(tp), TTIPRI | PCATCH, + "ttydcd", 0); splx(s); if (error) goto out; @@ -1679,7 +1641,7 @@ loop: p->p_pgrp->pg_jobc) { pgsignal(p->p_pgrp, SIGTTOU, 1); if (error = ttysleep(tp, (caddr_t)&lbolt, TTIPRI | PCATCH, - ttybg, 0)) + "ttybg4", 0)) goto out; goto loop; } @@ -1704,7 +1666,7 @@ loop: * to fix this is messy because of all the gotos. */ s = spltty(); - if (RB_LEN(&tp->t_out) > hiwat) { + if (RB_LEN(tp->t_out) > hiwat) { splx(s); goto ovhiwat; } @@ -1748,14 +1710,14 @@ loop: ttstart(tp); if (error = ttysleep(tp, (caddr_t)&lbolt, - TTOPRI | PCATCH, ttybuf, 0)) + TTOPRI | PCATCH, "ttybf1", 0)) break; goto loop; } cp++, cc--; s = spltty(); if ((tp->t_lflag&FLUSHO) || - RB_LEN(&tp->t_out) > hiwat) { + RB_LEN(tp->t_out) > hiwat) { splx(s); goto ovhiwat; } @@ -1778,18 +1740,18 @@ loop: #else i = ce; s = spltty(); - ce = imin(ce, RB_CONTIGPUT(&tp->t_out)); - bcopy(cp, tp->t_out.rb_tl, ce); - tp->t_out.rb_tl = RB_ROLLOVER(&tp->t_out, - tp->t_out.rb_tl + ce); + ce = imin(ce, RB_CONTIGPUT(tp->t_out)); + bcopy(cp, tp->t_out->rb_tl, ce); + tp->t_out->rb_tl = RB_ROLLOVER(tp->t_out, + tp->t_out->rb_tl + ce); i -= ce; if (i > 0) { int ii; - ii = imin(i, RB_CONTIGPUT(&tp->t_out)); - bcopy(cp + ce, tp->t_out.rb_tl, ii); - tp->t_out.rb_tl = RB_ROLLOVER(&tp->t_out, - tp->t_out.rb_tl + ii); + ii = imin(i, RB_CONTIGPUT(tp->t_out)); + bcopy(cp + ce, tp->t_out->rb_tl, ii); + tp->t_out->rb_tl = RB_ROLLOVER(tp->t_out, + tp->t_out->rb_tl + ii); i -= ii; ce += ii; } @@ -1801,14 +1763,15 @@ loop: if (i > 0) { ttstart(tp); s = spltty(); - if (RB_CONTIGPUT(&tp->t_out) > 0) { + if (RB_CONTIGPUT(tp->t_out) > 0) { splx(s); goto loop; /* synchronous/fast */ } /* out of space, wait a bit */ - tp->t_state |= TS_ASLEEP; - if (error = ttysleep(tp, (caddr_t)&tp->t_out, - TTOPRI | PCATCH, ttybuf, 0)) { + tp->t_state |= TS_SO_OLOWAT; + if (error = ttysleep(tp, TSA_OLOWAT(tp), + TTOPRI | PCATCH, "ttybf2", + 0)) { splx(s); break; } @@ -1816,7 +1779,7 @@ loop: goto loop; } s = spltty(); - if (tp->t_lflag&FLUSHO || RB_LEN(&tp->t_out) > hiwat) { + if (tp->t_lflag&FLUSHO || RB_LEN(tp->t_out) > hiwat) { splx(s); break; } @@ -1841,7 +1804,7 @@ ovhiwat: * This can only occur if FLUSHO is set in t_lflag, * or if ttstart/oproc is synchronous (or very fast). */ - if (RB_LEN(&tp->t_out) <= hiwat) { + if (RB_LEN(tp->t_out) <= hiwat) { splx(s); goto loop; } @@ -1852,8 +1815,8 @@ ovhiwat: return (EWOULDBLOCK); return (0); } - tp->t_state |= TS_ASLEEP; - error = ttysleep(tp, (caddr_t)&tp->t_out, TTOPRI | PCATCH, ttyout, 0); + tp->t_state |= TS_SO_OLOWAT; + error = ttysleep(tp, TSA_OLOWAT(tp), TTOPRI | PCATCH, "ttyout", 0); splx(s); if (error) goto out; @@ -1904,7 +1867,7 @@ ttyrub(c, tp) case TAB: { int c; - if (tp->t_rocount < RB_LEN(&tp->t_raw)) { + if (tp->t_rocount < RB_LEN(tp->t_raw)) { ttyretype(tp); return; } @@ -1913,9 +1876,9 @@ ttyrub(c, tp) tp->t_state |= TS_CNTTB; tp->t_lflag |= FLUSHO; tp->t_col = tp->t_rocol; - cp = tp->t_raw.rb_hd; - for (c = nextc(&cp, &tp->t_raw); c ; - c = nextc(&cp, &tp->t_raw)) + cp = tp->t_raw->rb_hd; + for (c = nextc(&cp, tp->t_raw); c ; + c = nextc(&cp, tp->t_raw)) ttyecho(c, tp); tp->t_lflag &= ~FLUSHO; tp->t_state &= ~TS_CNTTB; @@ -1979,16 +1942,16 @@ ttyretype(tp) (void) ttyoutput('\n', tp); s = spltty(); - cp = tp->t_can.rb_hd; - for (c = nextc(&cp, &tp->t_can); c ; c = nextc(&cp, &tp->t_can)) + cp = tp->t_can->rb_hd; + for (c = nextc(&cp, tp->t_can); c ; c = nextc(&cp, tp->t_can)) ttyecho(c, tp); - cp = tp->t_raw.rb_hd; - for (c = nextc(&cp, &tp->t_raw); c ; c = nextc(&cp, &tp->t_raw)) + cp = tp->t_raw->rb_hd; + for (c = nextc(&cp, tp->t_raw); c ; c = nextc(&cp, tp->t_raw)) ttyecho(c, tp); tp->t_state &= ~TS_ERASE; splx(s); - tp->t_rocount = RB_LEN(&tp->t_raw); + tp->t_rocount = RB_LEN(tp->t_raw); tp->t_rocol = 0; } @@ -2049,7 +2012,31 @@ ttwakeup(tp) } if (tp->t_state & TS_ASYNC) pgsignal(tp->t_pgrp, SIGIO, 1); - wakeup((caddr_t)&tp->t_raw); + wakeup(TSA_HUP_OR_INPUT(tp)); +} + +/* + * Wake up any writers on a tty. + */ +void +ttwwakeup(tp) + register struct tty *tp; +{ + if (RB_LEN(tp->t_out) <= tp->t_lowat) { + if (tp->t_state & TS_SO_OCOMPLETE && RB_LEN(tp->t_out) == 0) { + tp->t_state &= ~TS_SO_OCOMPLETE; + wakeup(TSA_OCOMPLETE(tp)); + } + if (tp->t_state & TS_SO_OLOWAT) { + tp->t_state &= ~TS_SO_OLOWAT; + wakeup(TSA_OLOWAT(tp)); + } + if (tp->t_wsel) { + selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); + tp->t_wsel = 0; + tp->t_state &= ~TS_WCOLL; + } + } } /* @@ -2099,7 +2086,7 @@ ttyinfo(tp) { register struct proc *p, *pick; struct timeval utime, stime; - int loadtmp; + int loadtmp, tmp; if (ttycheckoutq(tp,0) == 0) return; @@ -2152,8 +2139,13 @@ ttyinfo(tp) * Lock out clock if process is running; get user/system * cpu time. */ + tmp = 0; + if (curproc == pick) + tmp = splclock(); utime = pick->p_utime; stime = pick->p_stime; + if (curproc == pick) + splx(tmp); ttyprintf(tp, " cmd: %s %d [%s] ", comm, pid, wmesg); @@ -2258,7 +2250,7 @@ tputchar(c, tp) { register s = spltty(); - if ((tp->t_state & (TS_CARR_ON|TS_ISOPEN)) == (TS_CARR_ON|TS_ISOPEN)) { + if (CAN_DO_IO(tp)) { if (c == '\n') (void) ttyoutput('\r', tp); (void) ttyoutput(c, tp); @@ -2293,3 +2285,56 @@ ttysleep(tp, chan, pri, wmesg, timo) return (ERESTART); return (0); } + +/* + * Allocate a tty structure and its associated buffers. + */ +struct tty * +ttymalloc(itp) + struct tty *itp; +{ + struct tty *tp; + +#ifndef broken + /* + * Note that the itp input is not necessary when we can dealloc + * the struct tty. + */ + if(itp == NULL) { + MALLOC(tp, struct tty *, sizeof(struct tty), M_TTYS, M_WAITOK); + bzero(tp, sizeof *tp); + } else { + tp = itp; + } +#endif + if(tp->t_raw == NULL) { + MALLOC(tp->t_raw, struct ringb *, sizeof(struct ringb), M_TTYS, M_WAITOK); + bzero(tp->t_raw, sizeof *tp->t_raw); + } + if(tp->t_can == NULL) { + MALLOC(tp->t_can, struct ringb *, sizeof(struct ringb), M_TTYS, M_WAITOK); + bzero(tp->t_can, sizeof *tp->t_can); + } + if(tp->t_out == NULL) { + MALLOC(tp->t_out, struct ringb *, sizeof(struct ringb), M_TTYS, M_WAITOK); + bzero(tp->t_out, sizeof *tp->t_out); + } + return(tp); +} + +/* + * Free a tty structure and its buffers. + */ +void +ttyfree(tp) +struct tty *tp; +{ + FREE(tp->t_raw, M_TTYS); + FREE(tp->t_can, M_TTYS); + FREE(tp->t_out, M_TTYS); + tp->t_raw = tp->t_can = tp->t_out = NULL; +#ifdef broken /* session holds a ref to the tty; can't deallocate */ + /* also set tp to NULL when this isn't broken anymore */ + FREE(tp, M_TTYS); +#endif +} diff --git a/sys/kern/tty_conf.c b/sys/kern/tty_conf.c index 6b9ad4917460..ce7016415a5c 100644 --- a/sys/kern/tty_conf.c +++ b/sys/kern/tty_conf.c @@ -38,7 +38,7 @@ * SUCH DAMAGE. * * from: @(#)tty_conf.c 7.6 (Berkeley) 5/9/91 - * $Id: tty_conf.c,v 1.6.2.1 1994/05/04 07:54:52 rgrimes Exp $ + * $Id: tty_conf.c,v 1.9 1994/05/30 03:23:14 ache Exp $ */ #include "param.h" @@ -85,14 +85,14 @@ struct linesw linesw[] = #if NTB > 0 tbopen, tbclose, tbread, IE(enodev), tbioctl, - tbinput, enodev, nullop, ttstart, nullmodem, /* 3- TABLDISC */ + tbinput, enodev, nullop, ttstart, ttymodem, /* 3- TABLDISC */ #else IE(enodev), VE(enodev), IE(enodev), IE(enodev), IE(enodev), VE(enodev), IE(enodev), IE(enodev), VE(enodev), IE(enodev), #endif #if NSL > 0 slopen, VE(slclose), IE(enodev), IE(enodev), sltioctl, - VE(slinput), enodev, nullop, VE(slstart), nullmodem, /* 4- SLIPDISC */ + VE(slinput), enodev, nullop, VE(slstart), ttymodem, /* 4- SLIPDISC */ #else IE(enodev), VE(enodev), IE(enodev), IE(enodev), IE(enodev), VE(enodev), IE(enodev), IE(enodev), VE(enodev), IE(enodev), diff --git a/sys/kern/tty_pty.c b/sys/kern/tty_pty.c index 0e99e9329e0a..8039fa952b94 100644 --- a/sys/kern/tty_pty.c +++ b/sys/kern/tty_pty.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * from: @(#)tty_pty.c 7.21 (Berkeley) 5/30/91 - * $Id: tty_pty.c,v 1.9 1994/01/29 04:04:26 davidg Exp $ + * $Id: tty_pty.c,v 1.14 1994/05/30 03:22:34 ache Exp $ */ /* @@ -66,7 +66,7 @@ static void ptcwakeup(struct tty *, int); * pts == /dev/tty[pqrs]? * ptc == /dev/pty[pqrs]? */ -struct tty pt_tty[NPTY]; +struct tty *pt_tty[NPTY]; struct pt_ioctl { int pt_flags; pid_t pt_selr, pt_selw; @@ -75,13 +75,15 @@ struct pt_ioctl { } pt_ioctl[NPTY]; int npty = NPTY; /* for pstat -t */ -#define PF_RCOLL 0x01 -#define PF_WCOLL 0x02 -#define PF_PKT 0x08 /* packet mode */ -#define PF_STOPPED 0x10 /* user told stopped */ -#define PF_REMOTE 0x20 /* remote and flow controlled input */ -#define PF_NOSTOP 0x40 -#define PF_UCNTL 0x80 /* user control mode */ +#define PF_RCOLL 0x0001 +#define PF_WCOLL 0x0002 +#define PF_PKT 0x0008 /* packet mode */ +#define PF_STOPPED 0x0010 /* user told stopped */ +#define PF_REMOTE 0x0020 /* remote and flow controlled input */ +#define PF_NOSTOP 0x0040 +#define PF_UCNTL 0x0080 /* user control mode */ +#define PF_COPEN 0x0100 /* master open */ +#define PF_SOPEN 0x0200 /* slave open */ /*ARGSUSED*/ int @@ -99,9 +101,8 @@ ptsopen(dev, flag, devtype, p) #endif if (minor(dev) >= NPTY) return (ENXIO); - tp = &pt_tty[minor(dev)]; + tp = pt_tty[minor(dev)] = ttymalloc(pt_tty[minor(dev)]); if ((tp->t_state & TS_ISOPEN) == 0) { - tp->t_state |= TS_WOPEN; ttychars(tp); /* Set up default chars */ tp->t_iflag = TTYDEF_IFLAG; tp->t_oflag = TTYDEF_OFLAG; @@ -114,15 +115,17 @@ ptsopen(dev, flag, devtype, p) if (tp->t_oproc) /* Ctrlr still around. */ tp->t_state |= TS_CARR_ON; while ((tp->t_state & TS_CARR_ON) == 0) { - tp->t_state |= TS_WOPEN; if (flag&FNONBLOCK) break; - if (error = ttysleep(tp, (caddr_t)&tp->t_raw, TTIPRI | PCATCH, - ttopen, 0)) + if (error = ttysleep(tp, TSA_CARR_ON(tp), TTIPRI | PCATCH, + "ptsopn", 0)) return (error); } error = (*linesw[tp->t_line].l_open)(dev, tp, flag); - ptcwakeup(tp, FREAD|FWRITE); + if (error == 0) { + ptcwakeup(tp, FREAD|FWRITE); + pt_ioctl[minor(dev)].pt_flags |= PF_SOPEN; + } return (error); } @@ -134,10 +137,17 @@ ptsclose(dev, flag, mode, p) { register struct tty *tp; - tp = &pt_tty[minor(dev)]; + tp = pt_tty[minor(dev)]; + ptcwakeup(tp, FREAD|FWRITE); (*linesw[tp->t_line].l_close)(tp, flag); ttyclose(tp); - ptcwakeup(tp, FREAD|FWRITE); + pt_ioctl[minor(dev)].pt_flags &= ~PF_SOPEN; + if ((pt_ioctl[minor(dev)].pt_flags & PF_COPEN) == 0) { + ttyfree(tp); +#ifdef broken /* session holds a ref to the tty; can't deallocate */ + pt_tty[minor(dev)] = (struct tty *)NULL; +#endif + } return(0); } @@ -148,7 +158,7 @@ ptsread(dev, uio, flag) int flag; { struct proc *p = curproc; - register struct tty *tp = &pt_tty[minor(dev)]; + register struct tty *tp = pt_tty[minor(dev)]; register struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; int error = 0; @@ -162,25 +172,25 @@ again: return (EIO); pgsignal(p->p_pgrp, SIGTTIN, 1); if (error = ttysleep(tp, (caddr_t)&lbolt, - TTIPRI | PCATCH, ttybg, 0)) + TTIPRI | PCATCH, "ptsbg", 0)) return (error); } - if (RB_LEN(&tp->t_can) == 0) { + if (RB_LEN(tp->t_can) == 0) { if (flag & IO_NDELAY) return (EWOULDBLOCK); - if (error = ttysleep(tp, (caddr_t)&tp->t_can, - TTIPRI | PCATCH, ttyin, 0)) + if (error = ttysleep(tp, (caddr_t)tp->t_can, + TTIPRI | PCATCH, "ptsin", 0)) return (error); goto again; } - while (RB_LEN(&tp->t_can) > 1 && uio->uio_resid > 0) - if (ureadc(getc(&tp->t_can), uio) < 0) { + while (RB_LEN(tp->t_can) > 1 && uio->uio_resid > 0) + if (ureadc(getc(tp->t_can), uio) < 0) { error = EFAULT; break; } - if (RB_LEN(&tp->t_can) == 1) - (void) getc(&tp->t_can); - if (RB_LEN(&tp->t_can)) + if (RB_LEN(tp->t_can) == 1) + (void) getc(tp->t_can); + if (RB_LEN(tp->t_can)) return (error); } else if (tp->t_oproc) @@ -202,7 +212,7 @@ ptswrite(dev, uio, flag) { register struct tty *tp; - tp = &pt_tty[minor(dev)]; + tp = pt_tty[minor(dev)]; if (tp->t_oproc == 0) return (EIO); return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); @@ -240,7 +250,7 @@ ptcwakeup(tp, flag) pti->pt_selr = 0; pti->pt_flags &= ~PF_RCOLL; } - wakeup((caddr_t)&tp->t_out.rb_tl); + wakeup(TSA_PTC_READ(tp)); } if (flag & FWRITE) { if (pti->pt_selw) { @@ -248,7 +258,7 @@ ptcwakeup(tp, flag) pti->pt_selw = 0; pti->pt_flags &= ~PF_WCOLL; } - wakeup((caddr_t)&tp->t_raw.rb_hd); + wakeup(TSA_PTC_WRITE(tp)); } } @@ -268,14 +278,15 @@ ptcopen(dev, flag, devtype, p) if (minor(dev) >= NPTY) return (ENXIO); - tp = &pt_tty[minor(dev)]; + tp = pt_tty[minor(dev)] = ttymalloc(pt_tty[minor(dev)]); if (tp->t_oproc) return (EIO); tp->t_oproc = ptsstart; (void)(*linesw[tp->t_line].l_modem)(tp, 1); tp->t_lflag &= ~EXTPROC; pti = &pt_ioctl[minor(dev)]; - pti->pt_flags = 0; + pti->pt_flags &= PF_SOPEN; + pti->pt_flags |= PF_COPEN; pti->pt_send = 0; pti->pt_ucntl = 0; return (0); @@ -289,7 +300,7 @@ ptcclose(dev) { register struct tty *tp; - tp = &pt_tty[minor(dev)]; + tp = pt_tty[minor(dev)]; (void)(*linesw[tp->t_line].l_modem)(tp, 0); tp->t_state &= ~TS_CARR_ON; tp->t_oproc = 0; /* mark closed */ @@ -298,6 +309,13 @@ ptcclose(dev) if (constty==tp) constty = 0; + pt_ioctl[minor(dev)].pt_flags &= ~PF_COPEN; + if ((pt_ioctl[minor(dev)].pt_flags & PF_SOPEN) == 0) { + ttyfree(tp); +#ifdef broken /* session holds a ref to the tty; can't deallocate */ + pt_tty[minor(dev)] = (struct tty *)NULL; +#endif + } return (0); } @@ -307,7 +325,7 @@ ptcread(dev, uio, flag) struct uio *uio; int flag; { - register struct tty *tp = &pt_tty[minor(dev)]; + register struct tty *tp = pt_tty[minor(dev)]; struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; char buf[BUFSIZ]; int error = 0, cc; @@ -339,15 +357,15 @@ ptcread(dev, uio, flag) pti->pt_ucntl = 0; return (0); } - if (RB_LEN(&tp->t_out) && (tp->t_state&TS_TTSTOP) == 0) + if (RB_LEN(tp->t_out) && (tp->t_state&TS_TTSTOP) == 0) break; } if ((tp->t_state&TS_CARR_ON) == 0) return (0); /* EOF */ if (flag & IO_NDELAY) return (EWOULDBLOCK); - if (error = tsleep((caddr_t)&tp->t_out.rb_tl, TTIPRI | PCATCH, - ttyin, 0)) + if (error = tsleep(TSA_PTC_READ(tp), TTIPRI | PCATCH, + "ptcin", 0)) return (error); } if (pti->pt_flags & (PF_PKT|PF_UCNTL)) @@ -356,28 +374,19 @@ ptcread(dev, uio, flag) #ifdef was cc = q_to_b(&tp->t_outq, buf, MIN(uio->uio_resid, BUFSIZ)); #else - cc = min(MIN(uio->uio_resid, BUFSIZ), RB_CONTIGGET(&tp->t_out)); + cc = min(MIN(uio->uio_resid, BUFSIZ), RB_CONTIGGET(tp->t_out)); if (cc) { - bcopy(tp->t_out.rb_hd, buf, cc); - tp->t_out.rb_hd = - RB_ROLLOVER(&tp->t_out, tp->t_out.rb_hd+cc); + bcopy(tp->t_out->rb_hd, buf, cc); + tp->t_out->rb_hd = + RB_ROLLOVER(tp->t_out, tp->t_out->rb_hd+cc); } #endif if (cc <= 0) break; error = uiomove(buf, cc, uio); } - if (RB_LEN(&tp->t_out) <= tp->t_lowat) { - if (tp->t_state&TS_ASLEEP) { - tp->t_state &= ~TS_ASLEEP; - wakeup((caddr_t)&tp->t_out); - } - if (tp->t_wsel) { - selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); - tp->t_wsel = 0; - tp->t_state &= ~TS_WCOLL; - } - } + if (tp->t_state & (TS_SO_OCOMPLETE | TS_SO_OLOWAT) || tp->t_wsel) + ttwwakeup(tp); return (error); } @@ -411,7 +420,7 @@ ptcselect(dev, rw, p) int rw; struct proc *p; { - register struct tty *tp = &pt_tty[minor(dev)]; + register struct tty *tp = pt_tty[minor(dev)]; struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; struct proc *prev; int s; @@ -426,7 +435,7 @@ ptcselect(dev, rw, p) */ s = spltty(); if ((tp->t_state&TS_ISOPEN) && - RB_LEN(&tp->t_out) && (tp->t_state&TS_TTSTOP) == 0) { + RB_LEN(tp->t_out) && (tp->t_state&TS_TTSTOP) == 0) { splx(s); return (1); } @@ -448,12 +457,12 @@ ptcselect(dev, rw, p) case FWRITE: if (tp->t_state&TS_ISOPEN) { if (pti->pt_flags & PF_REMOTE) { - if (RB_LEN(&tp->t_can) == 0) + if (RB_LEN(tp->t_can) == 0) return (1); } else { - if (RB_LEN(&tp->t_raw) + RB_LEN(&tp->t_can) < TTYHOG-2) + if (RB_LEN(tp->t_raw) + RB_LEN(tp->t_can) < TTYHOG-2) return (1); - if (RB_LEN(&tp->t_can) == 0 && (tp->t_iflag&ICANON)) + if (RB_LEN(tp->t_can) == 0 && (tp->t_iflag&ICANON)) return (1); } } @@ -473,7 +482,7 @@ ptcwrite(dev, uio, flag) register struct uio *uio; int flag; { - register struct tty *tp = &pt_tty[minor(dev)]; + register struct tty *tp = pt_tty[minor(dev)]; register u_char *cp = 0; register int cc = 0; u_char locbuf[BUFSIZ]; @@ -485,12 +494,12 @@ again: if ((tp->t_state&TS_ISOPEN) == 0) goto block; if (pti->pt_flags & PF_REMOTE) { - if (RB_LEN(&tp->t_can)) + if (RB_LEN(tp->t_can)) goto block; - while (uio->uio_resid > 0 && RB_LEN(&tp->t_can) < TTYHOG - 1) { + while (uio->uio_resid > 0 && RB_LEN(tp->t_can) < TTYHOG - 1) { if (cc == 0) { cc = min(uio->uio_resid, BUFSIZ); - cc = min(cc, RB_CONTIGPUT(&tp->t_can)); + cc = min(cc, RB_CONTIGPUT(tp->t_can)); cp = locbuf; error = uiomove((caddr_t)cp, cc, uio); if (error) @@ -504,16 +513,16 @@ again: (void) b_to_q((char *)cp, cc, &tp->t_canq); #else if (cc) { - bcopy(cp, tp->t_can.rb_tl, cc); - tp->t_can.rb_tl = - RB_ROLLOVER(&tp->t_can, tp->t_can.rb_tl+cc); + bcopy(cp, tp->t_can->rb_tl, cc); + tp->t_can->rb_tl = + RB_ROLLOVER(tp->t_can, tp->t_can->rb_tl+cc); } #endif cc = 0; } - (void) putc(0, &tp->t_can); + (void) putc(0, tp->t_can); ttwakeup(tp); - wakeup((caddr_t)&tp->t_can); + wakeup((caddr_t)tp->t_can); return (0); } while (uio->uio_resid > 0) { @@ -528,9 +537,9 @@ again: return (EIO); } while (cc > 0) { - if ((RB_LEN(&tp->t_raw) + RB_LEN(&tp->t_can)) >= TTYHOG - 2 && - (RB_LEN(&tp->t_can) > 0 || !(tp->t_iflag&ICANON))) { - wakeup((caddr_t)&tp->t_raw); + if ((RB_LEN(tp->t_raw) + RB_LEN(tp->t_can)) >= TTYHOG - 2 && + (RB_LEN(tp->t_can) > 0 || !(tp->t_iflag&ICANON))) { + wakeup(TSA_HUP_OR_INPUT(tp)); goto block; } (*linesw[tp->t_line].l_rint)(*cp++, tp); @@ -554,8 +563,8 @@ block: return (EWOULDBLOCK); return (0); } - if (error = tsleep((caddr_t)&tp->t_raw.rb_hd, TTOPRI | PCATCH, - ttyout, 0)) { + if (error = tsleep(TSA_PTC_WRITE(tp), TTOPRI | PCATCH, + "ptcout", 0)) { /* adjust for data copied in but not written */ uio->uio_resid += cc; return (error); @@ -571,7 +580,7 @@ ptyioctl(dev, cmd, data, flag) dev_t dev; int flag; { - register struct tty *tp = &pt_tty[minor(dev)]; + register struct tty *tp = pt_tty[minor(dev)]; register struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; register u_char *cc = tp->t_cc; int stop, error; @@ -648,7 +657,7 @@ ptyioctl(dev, cmd, data, flag) case TIOCSETA: case TIOCSETAW: case TIOCSETAF: - while (getc(&tp->t_out) >= 0) + while (getc(tp->t_out) >= 0) ; break; diff --git a/sys/kern/uipc_mbuf.c b/sys/kern/uipc_mbuf.c index c0cf7a4c68cd..b735b0269666 100644 --- a/sys/kern/uipc_mbuf.c +++ b/sys/kern/uipc_mbuf.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * from: @(#)uipc_mbuf.c 7.19 (Berkeley) 4/20/91 - * $Id: uipc_mbuf.c,v 1.6 1993/12/19 00:51:44 wollman Exp $ + * $Id: uipc_mbuf.c,v 1.9 1994/06/11 23:06:35 paul Exp $ */ #include "param.h" @@ -312,7 +312,8 @@ m_copym(m, off0, len, wait) n->m_len = MIN(len, m->m_len - off); if (m->m_flags & M_EXT) { n->m_data = m->m_data + off; - mclrefcnt[mtocl(m->m_ext.ext_buf)]++; + if (m->m_ext.ext_free == (void (*)())0) + mclrefcnt[mtocl(m->m_ext.ext_buf)]++; n->m_ext = m->m_ext; n->m_flags |= M_EXT; } else @@ -441,8 +442,8 @@ m_adj(mp, req_len) } if (m->m_len >= len) { m->m_len -= len; - if ((mp = m)->m_flags & M_PKTHDR) - m->m_pkthdr.len -= len; + if (mp->m_flags & M_PKTHDR) + mp->m_pkthdr.len -= len; return; } count -= len; @@ -639,7 +640,8 @@ extpacket: if (m -> m_flags & M_EXT) { n -> m_flags |= M_EXT; n -> m_ext = m -> m_ext; - mclrefcnt[mtocl (m -> m_ext.ext_buf)]++; + if (m->m_ext.ext_free == (void (*)())0) + mclrefcnt[mtocl (m -> m_ext.ext_buf)]++; n -> m_data = m -> m_data + len; } else { bcopy (mtod (m, caddr_t) + len, mtod (n, caddr_t), remain); @@ -724,11 +726,6 @@ m_compress(in, out) (*out)->m_act = 0; while (in) { - if (in->m_flags & M_EXT) { -#ifdef DEBUG - ASSERT(in->m_len == 0); -#endif - } if ( in->m_len == 0) { in = in->m_next; continue; diff --git a/sys/kern/vfs__bio.c b/sys/kern/vfs__bio.c index 2ccf2e6126b7..6868618e9293 100644 --- a/sys/kern/vfs__bio.c +++ b/sys/kern/vfs__bio.c @@ -45,7 +45,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: vfs__bio.c,v 1.15 1994/01/31 05:57:45 davidg Exp $ + * $Id: vfs__bio.c,v 1.21 1994/05/29 18:06:31 ats Exp $ */ #include "param.h" @@ -73,7 +73,13 @@ struct buf bswlist; /* head of free swap header list */ struct buf *bclnlist; /* head of cleaned page list */ static struct buf *getnewbuf(int); -extern vm_map_t buffer_map; +extern vm_map_t buffer_map, io_map; + +/* + * Internel update daemon, process 3 + * The variable vfs_update_wakeup allows for internal syncs. + */ +int vfs_update_wakeup; /* * Initialize buffer headers and related structures. @@ -353,18 +359,8 @@ start: && bfreelist[BQ_EMPTY].av_forw != (struct buf *)bfreelist+BQ_EMPTY) { caddr_t addr; -/*#define notyet*/ -#ifndef notyet - if ((addr = malloc (sz, M_IOBUF, M_WAITOK)) == 0) goto tryfree; -#else /* notyet */ - /* get new memory buffer */ - if (round_page(sz) == sz) - addr = (caddr_t) kmem_alloc_wired_wait(buffer_map, sz); - else - addr = (caddr_t) malloc (sz, M_IOBUF, M_WAITOK); - /*if ((addr = malloc (sz, M_IOBUF, M_NOWAIT)) == 0) goto tryfree;*/ - bzero(addr, sz); -#endif /* notyet */ + if ((addr = malloc (sz, M_IOBUF, M_NOWAIT)) == 0) + goto tryfree; freebufspace -= sz; allocbufspace += sz; @@ -476,7 +472,14 @@ loop: /* if (bp->b_bufsize != size) allocbuf(bp, size); */ } else { - if ((bp = getnewbuf(size)) == 0) goto loop; + if ((bp = getnewbuf(size)) == 0) + goto loop; + if ( incore(vp, blkno)) { + bp->b_flags |= B_INVAL; + brelse(bp); + goto loop; + } + bp->b_blkno = bp->b_lblkno = blkno; bgetvp(vp, bp); bh = BUFHASH(vp, blkno); @@ -521,27 +524,13 @@ allocbuf(register struct buf *bp, int size) caddr_t newcontents; /* get new memory buffer */ -#ifndef notyet newcontents = (caddr_t) malloc (size, M_IOBUF, M_WAITOK); -#else /* notyet */ - if (round_page(size) == size) - newcontents = (caddr_t) kmem_alloc_wired_wait(buffer_map, size); - else - newcontents = (caddr_t) malloc (size, M_IOBUF, M_WAITOK); -#endif /* notyet */ /* copy the old into the new, up to the maximum that will fit */ bcopy (bp->b_un.b_addr, newcontents, min(bp->b_bufsize, size)); /* return old contents to free heap */ -#ifndef notyet free (bp->b_un.b_addr, M_IOBUF); -#else /* notyet */ - if (round_page(bp->b_bufsize) == bp->b_bufsize) - kmem_free_wakeup(buffer_map, bp->b_un.b_addr, bp->b_bufsize); - else - free (bp->b_un.b_addr, M_IOBUF); -#endif /* notyet */ /* adjust buffer cache's idea of memory allocated to buffer contents */ freebufspace -= size - bp->b_bufsize; @@ -593,6 +582,39 @@ biowait(register struct buf *bp) void biodone(register struct buf *bp) { + int s; + s = splbio(); + if (bp->b_flags & B_CLUSTER) { + struct buf *tbp; + bp->b_resid = bp->b_bcount; + while ( tbp = bp->b_clusterf) { + bp->b_clusterf = tbp->av_forw; + bp->b_resid -= tbp->b_bcount; + tbp->b_resid = 0; + if( bp->b_resid <= 0) { + tbp->b_error = bp->b_error; + tbp->b_flags |= (bp->b_flags & B_ERROR); + tbp->b_resid = -bp->b_resid; + bp->b_resid = 0; + } +/* + printf("rdc (%d,%d,%d) ", tbp->b_blkno, tbp->b_bcount, tbp->b_resid); +*/ + + biodone(tbp); + } +#ifndef NOBOUNCE + vm_bounce_kva_free( bp->b_un.b_addr, bp->b_bufsize, 0); +#endif + relpbuf(bp); + splx(s); + return; + } + +#ifndef NOBOUNCE + if (bp->b_flags & B_BOUNCE) + vm_bounce_free(bp); +#endif bp->b_flags |= B_DONE; if ((bp->b_flags & B_READ) == 0) { @@ -603,6 +625,7 @@ biodone(register struct buf *bp) if (bp->b_flags & B_CALL) { bp->b_flags &= ~B_CALL; (*bp->b_iodone)(bp); + splx(s); return; } @@ -618,19 +641,21 @@ biodone(register struct buf *bp) bp->b_flags &= ~B_WANTED; wakeup((caddr_t) bp); } + splx(s); } -/* - * Internel update daemon, process 3 - * The variable vfs_update_wakeup allows for internal syncs. - */ -int vfs_update_wakeup; +#ifndef UPDATE_INTERVAL +int vfs_update_interval = 30; +#else +int vfs_update_interval = UPDATE_INTERVAL; +#endif void vfs_update() { (void) spl0(); while(1) { - tsleep((caddr_t)&vfs_update_wakeup, PRIBIO, "update", hz*30); + tsleep((caddr_t)&vfs_update_wakeup, PRIBIO, "update", + hz * vfs_update_interval); vfs_update_wakeup = 0; sync(curproc, NULL, NULL); } diff --git a/sys/kern/vfs_lookup.c b/sys/kern/vfs_lookup.c index f35002a9460f..37a406d6651e 100644 --- a/sys/kern/vfs_lookup.c +++ b/sys/kern/vfs_lookup.c @@ -38,7 +38,7 @@ * SUCH DAMAGE. * * from: @(#)vfs_lookup.c 7.32 (Berkeley) 5/21/91 - * $Id: vfs_lookup.c,v 1.5.2.1 1994/05/04 07:54:56 rgrimes Exp $ + * $Id: vfs_lookup.c,v 1.9 1994/06/02 06:53:37 ache Exp $ */ #include "param.h" @@ -106,6 +106,13 @@ namei(ndp, p) else error = copyinstr(ndp->ni_dirp, ndp->ni_pnbuf, MAXPATHLEN, (u_int *)&ndp->ni_pathlen); +#if 0 + /* + * Don't allow empty pathname. + */ + if (!error && *ndp->ni_pnbuf == '\0') + error = ENOENT; +#endif if (error) { free(ndp->ni_pnbuf, M_NAMEI); ndp->ni_vp = NULL; @@ -284,10 +291,10 @@ dirloop: * responsibility for freeing the pathname buffer. */ ndp->ni_hash = 0; - for (cp = ndp->ni_ptr; *cp != 0 && *cp != '/'; cp++) + for (cp = ndp->ni_ptr; *cp != '\0' && *cp != '/'; cp++) ndp->ni_hash += (unsigned char)*cp; ndp->ni_namelen = cp - ndp->ni_ptr; - if (ndp->ni_namelen >= NAME_MAX) { + if (ndp->ni_namelen > NAME_MAX) { error = ENAMETOOLONG; goto bad; } @@ -367,7 +374,7 @@ dirloop: printf("not found\n"); #endif if (flag == LOOKUP || flag == DELETE || - error != ENOENT || *cp != 0) + error != ENOENT || *cp != '\0') goto bad; /* * If creating and at end of pathname, then can consider diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c index 024c5679000b..5525022e9811 100644 --- a/sys/kern/vfs_subr.c +++ b/sys/kern/vfs_subr.c @@ -38,7 +38,7 @@ * SUCH DAMAGE. * * from: @(#)vfs_subr.c 7.60 (Berkeley) 6/21/91 - * $Id: vfs_subr.c,v 1.7.2.2 1994/05/04 07:55:00 rgrimes Exp $ + * $Id: vfs_subr.c,v 1.13 1994/06/14 03:41:00 davidg Exp $ */ /* @@ -57,6 +57,9 @@ #include "buf.h" #include "errno.h" #include "malloc.h" +#include "vm/vm.h" +#include "vm/vm_object.h" +#include "vm/vm_pager.h" static void insmntque(struct vnode *, struct mount *); @@ -441,6 +444,8 @@ vinvalbuf(vp, save) register struct buf *bp; struct buf *nbp, *blist; int s, dirty = 0; + vm_pager_t pager; + vm_object_t object; for (;;) { if (blist = vp->v_dirtyblkhd) @@ -473,6 +478,20 @@ vinvalbuf(vp, save) brelse(bp); } } + + pager = (vm_pager_t)vp->v_vmdata; + if (pager != NULL) { + object = vm_object_lookup(pager); + if (object) { + vm_object_lock(object); + if (save) + vm_object_page_clean(object, 0, 0); + vm_object_page_remove(object, 0, object->size); + vm_object_unlock(object); + vm_object_deallocate(object); + } + } + if (vp->v_dirtyblkhd || vp->v_cleanblkhd) panic("vinvalbuf: flush failed"); return (dirty); @@ -645,6 +664,7 @@ loop: nvp->v_hashchain = vpp; nvp->v_specnext = *vpp; nvp->v_specflags = 0; + nvp->v_opencount = 0; *vpp = nvp; if (vp != NULL) { nvp->v_flag |= VALIASED; @@ -1068,6 +1088,7 @@ vfinddev(dev, type, vpp) /* * Calculate the total number of references to a special device. + * Not counting sleeping openers. */ int vcount(vp) @@ -1089,7 +1110,7 @@ loop: vgone(vq); goto loop; } - count += vq->v_usecount; + count += vq->v_usecount - vq->v_opencount; } return (count); } diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index 396bd6326f98..b218ab6dd380 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * from: @(#)vfs_syscalls.c 7.74 (Berkeley) 6/21/91 - * $Id: vfs_syscalls.c,v 1.10 1994/01/19 21:09:13 jtc Exp $ + * $Id: vfs_syscalls.c,v 1.17 1994/05/26 05:32:05 ache Exp $ */ #include "param.h" @@ -841,9 +841,10 @@ link(p, uap, retval) if (error = namei(ndp, p)) return (error); vp = ndp->ni_vp; - if (vp->v_type == VDIR && - (error = suser(p->p_ucred, &p->p_acflag))) + if (vp->v_type == VDIR) { + error = EPERM; goto out1; + } ndp->ni_nameiop = CREATE | LOCKPARENT; ndp->ni_dirp = (caddr_t)uap->linkname; if (error = namei(ndp, p)) diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c index b273dc8b3604..a9c03b99d6ad 100644 --- a/sys/kern/vfs_vnops.c +++ b/sys/kern/vfs_vnops.c @@ -38,7 +38,7 @@ * SUCH DAMAGE. * * from: @(#)vfs_vnops.c 7.33 (Berkeley) 6/27/91 - * $Id: vfs_vnops.c,v 1.4.2.2 1994/05/04 07:55:04 rgrimes Exp $ + * $Id: vfs_vnops.c,v 1.7 1994/05/04 08:27:20 rgrimes Exp $ */ #include "param.h" @@ -388,6 +388,7 @@ vn_ioctl(fp, com, data, p) default: return (ENOTTY); + case VPROC: case VFIFO: case VCHR: case VBLK: |