hook for ps driver and untimeout stuff for lucas drivers
[unix-history] / usr / src / sys / kern / kern_physio.c
CommitLineData
bd841446 1/* kern_physio.c 4.30 82/05/22 */
663dbc72
BJ
2
3#include "../h/param.h"
4#include "../h/systm.h"
5#include "../h/dir.h"
6#include "../h/user.h"
7#include "../h/buf.h"
8#include "../h/conf.h"
9#include "../h/proc.h"
10#include "../h/seg.h"
11#include "../h/pte.h"
12#include "../h/vm.h"
973ecc4f 13#include "../h/trace.h"
663dbc72 14
663dbc72
BJ
15/*
16 * Swap IO headers -
17 * They contain the necessary information for the swap I/O.
18 * At any given time, a swap header can be in three
19 * different lists. When free it is in the free list,
20 * when allocated and the I/O queued, it is on the swap
21 * device list, and finally, if the operation was a dirty
22 * page push, when the I/O completes, it is inserted
23 * in a list of cleaned pages to be processed by the pageout daemon.
24 */
4c05b581
BJ
25struct buf *swbuf;
26short *swsize; /* CAN WE JUST USE B_BCOUNT? */
27int *swpf;
663dbc72 28
663dbc72
BJ
29/*
30 * swap I/O -
31 *
32 * If the flag indicates a dirty page push initiated
33 * by the pageout daemon, we map the page into the i th
34 * virtual page of process 2 (the daemon itself) where i is
35 * the index of the swap header that has been allocated.
36 * We simply initialize the header and queue the I/O but
37 * do not wait for completion. When the I/O completes,
38 * iodone() will link the header to a list of cleaned
39 * pages to be processed by the pageout daemon.
40 */
41swap(p, dblkno, addr, nbytes, rdflg, flag, dev, pfcent)
42 struct proc *p;
43 swblk_t dblkno;
44 caddr_t addr;
45 int flag, nbytes;
46 dev_t dev;
47 unsigned pfcent;
48{
49 register struct buf *bp;
50 register int c;
51 int p2dp;
52 register struct pte *dpte, *vpte;
530d0032 53 int s;
663dbc72 54
530d0032 55 s = spl6();
663dbc72
BJ
56 while (bswlist.av_forw == NULL) {
57 bswlist.b_flags |= B_WANTED;
58 sleep((caddr_t)&bswlist, PSWP+1);
59 }
60 bp = bswlist.av_forw;
61 bswlist.av_forw = bp->av_forw;
530d0032 62 splx(s);
663dbc72
BJ
63
64 bp->b_flags = B_BUSY | B_PHYS | rdflg | flag;
65 if ((bp->b_flags & (B_DIRTY|B_PGIN)) == 0)
66 if (rdflg == B_READ)
67 sum.v_pswpin += btoc(nbytes);
68 else
69 sum.v_pswpout += btoc(nbytes);
70 bp->b_proc = p;
71 if (flag & B_DIRTY) {
72 p2dp = ((bp - swbuf) * CLSIZE) * KLMAX;
73 dpte = dptopte(&proc[2], p2dp);
74 vpte = vtopte(p, btop(addr));
75 for (c = 0; c < nbytes; c += NBPG) {
76 if (vpte->pg_pfnum == 0 || vpte->pg_fod)
77 panic("swap bad pte");
78 *dpte++ = *vpte++;
79 }
80 bp->b_un.b_addr = (caddr_t)ctob(p2dp);
81 } else
82 bp->b_un.b_addr = addr;
83 while (nbytes > 0) {
84 c = imin(ctob(120), nbytes);
85 bp->b_bcount = c;
86 bp->b_blkno = dblkno;
87 bp->b_dev = dev;
d2f87136
BJ
88 if (flag & B_DIRTY) {
89 swpf[bp - swbuf] = pfcent;
90 swsize[bp - swbuf] = nbytes;
91 }
53f9ca20
BJ
92#ifdef TRACE
93 trace(TR_SWAPIO, dev, bp->b_blkno);
94#endif
663dbc72
BJ
95 (*bdevsw[major(dev)].d_strategy)(bp);
96 if (flag & B_DIRTY) {
97 if (c < nbytes)
98 panic("big push");
663dbc72
BJ
99 return;
100 }
530d0032 101 s = spl6();
663dbc72
BJ
102 while((bp->b_flags&B_DONE)==0)
103 sleep((caddr_t)bp, PSWP);
530d0032 104 splx(s);
663dbc72
BJ
105 bp->b_un.b_addr += c;
106 bp->b_flags &= ~B_DONE;
107 if (bp->b_flags & B_ERROR) {
108 if ((flag & (B_UAREA|B_PAGET)) || rdflg == B_WRITE)
109 panic("hard IO err in swap");
110 swkill(p, (char *)0);
111 }
112 nbytes -= c;
113 dblkno += btoc(c);
114 }
530d0032 115 s = spl6();
663dbc72
BJ
116 bp->b_flags &= ~(B_BUSY|B_WANTED|B_PHYS|B_PAGET|B_UAREA|B_DIRTY);
117 bp->av_forw = bswlist.av_forw;
118 bswlist.av_forw = bp;
119 if (bswlist.b_flags & B_WANTED) {
120 bswlist.b_flags &= ~B_WANTED;
121 wakeup((caddr_t)&bswlist);
122 wakeup((caddr_t)&proc[2]);
123 }
530d0032 124 splx(s);
663dbc72
BJ
125}
126
127/*
128 * If rout == 0 then killed on swap error, else
129 * rout is the name of the routine where we ran out of
130 * swap space.
131 */
132swkill(p, rout)
133 struct proc *p;
134 char *rout;
135{
444f631c 136 char *mesg;
663dbc72 137
444f631c 138 printf("pid %d: ", p->p_pid);
663dbc72 139 if (rout)
444f631c 140 printf(mesg = "killed due to no swap space\n");
663dbc72 141 else
444f631c
BJ
142 printf(mesg = "killed on swap error\n");
143 uprintf("sorry, pid %d was %s", p->p_pid, mesg);
663dbc72
BJ
144 /*
145 * To be sure no looping (e.g. in vmsched trying to
146 * swap out) mark process locked in core (as though
147 * done by user) after killing it so noone will try
148 * to swap it out.
149 */
a30d2e97 150 psignal(p, SIGKILL);
663dbc72
BJ
151 p->p_flag |= SULOCK;
152}
153
663dbc72
BJ
154/*
155 * Raw I/O. The arguments are
156 * The strategy routine for the device
157 * A buffer, which will always be a special buffer
158 * header owned exclusively by the device for this purpose
159 * The device number
160 * Read/write flag
161 * Essentially all the work is computing physical addresses and
162 * validating them.
163 * If the user has the proper access privilidges, the process is
164 * marked 'delayed unlock' and the pages involved in the I/O are
165 * faulted and locked. After the completion of the I/O, the above pages
166 * are unlocked.
167 */
168physio(strat, bp, dev, rw, mincnt)
169int (*strat)();
170register struct buf *bp;
171unsigned (*mincnt)();
172{
173 register int c;
174 char *a;
530d0032 175 int s;
663dbc72
BJ
176
177 if (useracc(u.u_base,u.u_count,rw==B_READ?B_WRITE:B_READ) == NULL) {
178 u.u_error = EFAULT;
179 return;
180 }
530d0032 181 s = spl6();
663dbc72
BJ
182 while (bp->b_flags&B_BUSY) {
183 bp->b_flags |= B_WANTED;
184 sleep((caddr_t)bp, PRIBIO+1);
185 }
ef3b3d5a 186 splx(s);
663dbc72
BJ
187 bp->b_error = 0;
188 bp->b_proc = u.u_procp;
189 bp->b_un.b_addr = u.u_base;
52a593fa 190 while (u.u_count != 0) {
663dbc72
BJ
191 bp->b_flags = B_BUSY | B_PHYS | rw;
192 bp->b_dev = dev;
193 bp->b_blkno = u.u_offset >> PGSHIFT;
194 bp->b_bcount = u.u_count;
195 (*mincnt)(bp);
196 c = bp->b_bcount;
197 u.u_procp->p_flag |= SPHYSIO;
198 vslock(a = bp->b_un.b_addr, c);
199 (*strat)(bp);
81263dba 200 (void) spl6();
663dbc72
BJ
201 while ((bp->b_flags&B_DONE) == 0)
202 sleep((caddr_t)bp, PRIBIO);
203 vsunlock(a, c, rw);
204 u.u_procp->p_flag &= ~SPHYSIO;
205 if (bp->b_flags&B_WANTED)
206 wakeup((caddr_t)bp);
530d0032 207 splx(s);
663dbc72
BJ
208 bp->b_un.b_addr += c;
209 u.u_count -= c;
210 u.u_offset += c;
52a593fa
BJ
211 if (bp->b_flags&B_ERROR)
212 break;
663dbc72
BJ
213 }
214 bp->b_flags &= ~(B_BUSY|B_WANTED|B_PHYS);
215 u.u_count = bp->b_resid;
216 geterror(bp);
217}
218
219/*ARGSUSED*/
220unsigned
221minphys(bp)
222struct buf *bp;
223{
224
2ec65c94
BJ
225 if (bp->b_bcount > 63 * 1024)
226 bp->b_bcount = 63 * 1024;
663dbc72
BJ
227}
228