|
|
1.1 root 1: /* $Header: /v4a/coh/RCS/seg.c,v 1.2 92/01/06 12:00:15 hal Exp $ */
2: /* (lgl-
3: * The information contained herein is a trade secret of Mark Williams
4: * Company, and is confidential information. It is provided under a
5: * license agreement, and may be copied or disclosed only under the
6: * terms of that agreement. Any reproduction or disclosure of this
7: * material without the express written authorization of Mark Williams
8: * Company or persuant to the license agreement is unlawful.
9: *
10: * COHERENT Version 2.3.37
11: * Copyright (c) 1982, 1983, 1984.
12: * An unpublished work by Mark Williams Company, Chicago.
13: * All rights reserved.
14: -lgl) */
15: /*
16: * Coherent.
17: * Segment manipulation.
18: *
19: */
20: #include <sys/coherent.h>
21: #include <sys/buf.h>
22: #include <errno.h>
23: #include <sys/ino.h>
24: #include <sys/inode.h>
25: #include <sys/proc.h>
26: #include <sys/sched.h>
27: #include <sys/seg.h>
28: #include <a.out.h>
29:
30:
31: #define min(a, b) ((a) < (b) ? (a) : (b))
32:
33: /*
34: * Initialisation code.
35: */
36: seginit()
37: {
38: /*
39: * Create empty circular-list of memory segments.
40: */
41: segmq.s_forw = &segmq;
42: segmq.s_back = &segmq;
43:
44: /*
45: * Create empty circular-list of disk segments.
46: */
47: segdq.s_forw = &segdq;
48: segdq.s_back = &segdq;
49: }
50:
51: /*
52: * Given an inode, `ip', and flags, `ff', describing a segment associated
53: * with the inode, see if the segment already exists and if so, return a
54: * copy. If the segment does not exist, allocate the segment having size
55: * `ss', and read the segment using the inode at seek offset `dq' with a
56: * size of `ds'.
57: */
58: SEG *
59: ssalloc(ip, ff, ss)
60: register INODE *ip;
61: {
62: register SEG *sp;
63: register int f;
64:
65: lock(seglink);
66: f = ff & (SFSHRX|SFTEXT);
67:
68: /*
69: * Look for the segment in the memory queue.
70: */
71: for (sp=segmq.s_forw; sp!=&segmq; sp=sp->s_forw) {
72: if (sp->s_ip==ip && (sp->s_flags&(SFSHRX|SFTEXT))==f) {
73: unlock(seglink);
74: if ((sp = segdupl(sp)) != NULL)
75: segfinm(sp);
76: return (sp);
77: }
78: }
79:
80: /*
81: * Look for the segment on the disk queue.
82: */
83: for (sp=segdq.s_forw; sp!=&segdq; sp=sp->s_forw) {
84: if (sp->s_ip==ip && (sp->s_flags&(SFSHRX|SFTEXT))==f) {
85: unlock(seglink);
86: if ((sp = segdupl(sp)) != NULL)
87: segfinm(sp);
88: return (sp);
89: }
90: }
91: unlock(seglink);
92:
93: /*
94: * Allocate and create the segment.
95: */
96: return salloc(roundu(ss, NBPC), ff);
97: }
98:
99: /*
100: * Given a pointer to a newly created process, copy all of our segments
101: * into the given process.
102: */
103: segadup(cpp)
104: register PROC *cpp;
105: {
106: register SEG *sp;
107: register int n;
108: register PROC *pp;
109:
110: pp = SELF;
111: cpp->p_flags |= PFSWIO;
112: for (n=0; n<NUSEG; n++) {
113: if ((sp=pp->p_segp[n]) == NULL)
114: continue;
115: if ((sp=segdupl(sp)) == NULL)
116: break;
117: cpp->p_segp[n] = sp;
118: if ((sp->s_flags&SFCORE) == 0)
119: cpp->p_flags &= ~PFCORE;
120: }
121: if (n < NUSEG) {
122: while (n > 0) {
123: if ((sp=cpp->p_segp[--n]) != NULL) {
124: cpp->p_segp[n] = NULL;
125: sfree(sp);
126: }
127: }
128: }
129: cpp->p_flags &= ~PFSWIO;
130: return (n);
131: }
132:
133: /*
134: * Duplicate a segment.
135: */
136: SEG *
137: segdupl(sp)
138: register SEG *sp;
139: {
140: register SEG *sp1;
141:
142: if ((sp->s_flags&SFSHRX) != 0) {
143: sp->s_urefc++;
144: sp->s_lrefc++;
145: return (sp);
146: }
147: if ((sp->s_flags&SFCORE) == 0)
148: panic("Cannot duplicate non shared swapped segment");
149: if ((sp1=salloc(sp->s_size, sp->s_flags|SFNSWP|SFNCLR)) == NULL)
150: sp1 = segdupd(sp);
151: else {
152: sp1->s_flags = sp->s_flags;
153: dmacopy( btoc(sp->s_size), sp->s_vmem, sp1->s_vmem) ;
154: }
155: return sp1;
156: }
157:
158: /*
159: * Allocate a segment `bytes_wanted' bytes long.
160: * `flags' contains some pseudo flags.
161: */
162: SEG *
163: salloc(bytes_wanted, flags)
164: int bytes_wanted, flags;
165: {
166: register SEG *sp;
167: register int r;
168:
169: r = (flags & (SFSYST|SFTEXT|SFSHRX|SFDOWN)) | SFCORE;
170:
171: /*
172: #ifdef _I386
173: bytes_wanted += (sizeof(char *) - 1);
174: bytes_wanted &= ~(sizeof(char *) - 1);
175: #else
176: bytes_wanted += (BSIZE - 1);
177: bytes_wanted &= ~(BSIZE - 1);
178: #endif
179: */
180:
181: lock(seglink);
182: sp = smalloc(bytes_wanted);
183: unlock(seglink);
184:
185: if (sp) {
186: sp->s_flags = r;
187: } else {
188: #if 0
189: /* no room now - let the swapper try to grow it */
190: if (flags & SFNSWP)
191: return 0;
192: if ((sp=kalloc(sizeof(SEG))) == NULL)
193: return 0;
194: sp->s_forw = sp;
195: sp->s_back = sp;
196: sp->s_flags = r;
197: sp->s_urefc = 1;
198: sp->s_lrefc = 1;
199: if (segsext(sp, bytes_wanted) == NULL) {
200: kfree(sp);
201: return 0;
202: }
203: #else
204: return 0;
205: #endif
206: }
207: if ((flags&SFNCLR) == 0)
208: dmaclear(sp->s_size, MAPIO(sp->s_vmem, 0), 0L);
209: return sp;
210: }
211:
212: /*
213: * Free the given segment pointer.
214: */
215: sfree(sp)
216: register SEG *sp;
217: {
218: register INODE *ip;
219:
220: if ( sp->s_urefc != 1 ) {
221: sp->s_urefc--;
222: sp->s_lrefc--;
223: return;
224: }
225:
226: lock(seglink);
227: --sp->s_lrefc;
228: if (--sp->s_urefc != 0) {
229: unlock(seglink);
230: return;
231: }
232:
233: sp->s_back->s_forw = sp->s_forw;
234: sp->s_forw->s_back = sp->s_back;
235:
236: c_free(sp->s_vmem, btoc(sp->s_size));
237:
238: unlock(seglink);
239:
240: if (sp->s_lrefc != 0)
241: panic("Bad segment count");
242: if ((ip=sp->s_ip) != NULL)
243: ldetach(ip);
244: kfree(sp);
245: }
246:
247: /*
248: * Grow or shrink the segment `sp' so that it has size `new_bytes' bytes.
249: *
250: * downward growing segments not done yet!
251: */
252: seggrow(sp, new_bytes)
253: register SEG *sp;
254: unsigned int new_bytes;
255: {
256: register SEG *sp1;
257: register int dowflag;
258: unsigned int old_bytes, common_clicks;
259:
260: dowflag = sp->s_flags & SFDOWN;
261: old_bytes = sp->s_size;
262:
263: T_HAL(0x20, goto dont_c_grow);
264: /*
265: * If we want a larger segment AND c_grow() succeeds
266: * boost segment size to new_bytes
267: */
268: if (new_bytes >= old_bytes && c_grow(sp, new_bytes)==0) {
269: T_HAL(0x100, printf("c_grow(%d) ", new_bytes));
270: sp->s_size = new_bytes;
271: dmaclear(new_bytes - old_bytes,
272: MAPIO(sp->s_vmem, old_bytes), 0);
273: return 1;
274: }
275: dont_c_grow:
276:
277: if (sp1 = salloc(new_bytes, (sp->s_flags|SFNSWP|SFNCLR))) {
278: T_HAL(0x100, printf("salloc(%d) ", new_bytes));
279: if (dowflag == 0) {
280: common_clicks = btoc(min(new_bytes, old_bytes));
281: dmacopy(common_clicks, sp->s_vmem, sp1->s_vmem);
282: if (new_bytes > old_bytes) {
283: dmaclear(new_bytes - old_bytes,
284: MAPIO(sp1->s_vmem, old_bytes), 0);
285: }
286: } else
287: panic("downflag");
288: lock(seglink);
289: c_free(sp->s_vmem, btoc(old_bytes));
290: satcopy(sp, sp1);
291: unlock(seglink);
292:
293: return 1;
294: }
295:
296: #if 1
297: return 0;
298: #else
299: /*
300: * Last chance. Extend the segment by swapping it.
301: */
302: if (!segsext(sp, new_bytes))
303: return 0;
304:
305: if (dowflag == 0) {
306: if (new_bytes > old_bytes)
307: dmaclear(new_bytes - old_bytes, MAPIO(sp->s_vmem,old_bytes), 0);
308: } else
309: panic("downflag");
310:
311: return (1);
312: #endif
313: }
314:
315: /*
316: * Given a segment pointer, `sp' and a segment size, grow the given segment
317: * to the given size.
318: */
319: segsize(sp, s2)
320: register SEG *sp;
321: vaddr_t s2;
322: {
323: register vaddr_t s1;
324:
325: s1 = (vaddr_t) sp->s_size;
326: if (s2 == 0 || seggrow(sp, (off_t)s2) == 0) {
327: SET_U_ERROR( ENOMEM, "can not grow segment" );
328: return;
329: }
330: if (sproto(0) == 0) {
331: if (seggrow(sp, (off_t)s1)==0 || sproto(0)==0) {
332: T_PIGGY( 0x2000000, printf("auto SEGV\n"); );
333: sendsig(SIGSEGV, SELF);
334: }
335: }
336: segload();
337: }
338:
339: /*
340: * Grow the segment `sp1' to the size `s' in bytes by swapping it out
341: * and back in. The segment may not be locked.
342: */
343: SEG *
344: segsext(sp1, s)
345: register SEG *sp1;
346: register off_t s;
347: {
348: #if 0
349: register SEG *sp2;
350:
351: #if MONITOR
352: if (swmflag)
353: printf("Segsext(%p, %u)\n", SELF, SELF->p_pid);
354: #endif
355: if (sexflag == 0) {
356: SET_U_ERROR( ENOMEM, "can not extend, swapping is off" );
357: return (NULL);
358: }
359: lock(seglink);
360: if ((sp2=sdalloc(s)) == NULL) {
361: unlock(seglink);
362: return (NULL);
363: }
364: unlock(seglink);
365: sp1->s_lrefc++;
366: if (sp1->s_size != 0)
367: swapio(1, MAPIO(sp1->s_vmem, 0), sp2->s_daddr, sp1->s_size);
368: lock(seglink);
369: satcopy(sp1, sp2);
370: unlock(seglink);
371: sp1->s_flags &= ~SFCORE;
372: sp1->s_lrefc--;
373: segfinm(sp1);
374: return (sp1);
375: #else
376: return 0;
377: #endif
378: }
379:
380: /*
381: * Force the given segment to be in memory. One can only force
382: * one segment to be in memory at a time.
383: */
384: segfinm(sp)
385: register SEG *sp;
386: {
387: register PROC *pp;
388: register int s;
389:
390: if ((sp->s_flags&SFCORE) != 0)
391: return;
392: pp = SELF;
393: sp->s_urefc++;
394: sp->s_lrefc++;
395: pp->p_segp[SIAUXIL] = sp;
396: pp->p_flags &= ~PFCORE;
397: #ifndef QWAKEUP
398: s = sphi();
399: #endif
400: setrun(pp);
401: dispatch();
402: #ifndef QWAKEUP
403: spl(s);
404: #endif
405: pp->p_segp[SIAUXIL] = NULL;
406: sfree(sp);
407: }
408:
409: /*
410: * Make a copy of the segment `sp1' which is in memory by writing
411: * it out to disk.
412: */
413: SEG *
414: segdupd(sp1)
415: register SEG *sp1;
416: {
417: register SEG *sp2;
418:
419: if (sexflag == 0)
420: return (NULL);
421: lock(seglink);
422: if ((sp2=sdalloc(sp1->s_size)) == NULL) {
423: unlock(seglink);
424: return (NULL);
425: }
426: sp1->s_lrefc++;
427: unlock(seglink);
428: swapio(1, MAPIO(sp1->s_vmem, 0), sp2->s_daddr, sp1->s_size);
429: sp1->s_lrefc--;
430: sp2->s_flags = sp1->s_flags & ~SFCORE;
431: sp2->s_size = sp1->s_size;
432: return (sp2);
433: }
434:
435: /*
436: * Given a flag, a physical core address, a disk address and a count in
437: * bytes, perform an I/O operation between core and disk. If `flag' is
438: * set, the transfer is to the disk otherwise it is to memory. As you may
439: * have guessed, this is used by the swapper.
440: *
441: */
442: swapio(f, p, d, n)
443: paddr_t p;
444: daddr_t d;
445: off_t n;
446: {
447: register BUF * bp;
448: register SEG * sp;
449: register int s;
450: register int nb;
451:
452: #if MONITOR
453: if (swmflag > 1)
454: printf("swapio(%s,%x,%x,%x)\n",f?"out":"in",(int)p,(int)d,n);
455: #endif
456: if (d < swapbot || d+(n/BSIZE) > swaptop)
457: panic("Swapio bad parameter");
458:
459: bp = &swapbuf;
460: lock(bp->b_gate);
461: SELF->p_flags |= PFSWIO;
462: bp->b_paddr = p;
463:
464: while (n != 0) {
465: nb = (n > SCHUNK) ? SCHUNK : n;
466: /*
467: * Prevent I/O transfer from crossing 64 Kbyte boundary.
468: */
469: if ( (p & 0xFFFF0000L) != ((p+nb) & 0xFFFF0000L) )
470: nb = 0x10000L - (p & 0x0000FFFFL);
471: bp->b_flag = BFNTP;
472: bp->b_req = f ? BWRITE : BREAD;
473: bp->b_dev = swapdev;
474: bp->b_bno = d;
475: bp->b_paddr = p;
476: bp->b_count = nb;
477: s = sphi();
478: dblock(swapdev, bp);
479: while ((bp->b_flag&BFNTP) != 0) {
480: v_sleep((char *)bp, CVBLKIO, IVBLKIO, SVBLKIO, "swap");
481: /* Sleeping in the swapper. */
482: }
483: spl(s);
484: if ((bp->b_flag&BFERR) != 0)
485: panic("Swapio error");
486: bp->b_vaddr += nb;
487: p += nb;
488: d += nb / BSIZE;
489: n -= nb;
490: }
491: unlock(bp->b_gate);
492: SELF->p_flags &= ~PFSWIO;
493: }
494:
495: /*
496: * Make the segment descriptor pointed to by `sp1' have the attributes
497: * of `sp2' including it's position in the segment queue and release
498: * `sp2'. `seglink' must be locked when this routine is called.
499: */
500: satcopy(sp1, sp2)
501: register SEG *sp1;
502: register SEG *sp2;
503: {
504: sp1->s_back->s_forw = sp1->s_forw;
505: sp1->s_forw->s_back = sp1->s_back;
506: sp2->s_back->s_forw = sp1;
507: sp1->s_back = sp2->s_back;
508: sp2->s_forw->s_back = sp1;
509: sp1->s_forw = sp2->s_forw;
510: sp1->s_daddr = sp2->s_daddr;
511: sp1->s_size = sp2->s_size;
512: sp1->s_vmem = sp2->s_vmem;
513: kfree(sp2);
514: }
515:
516: /*
517: * Allocate a segment on disk that is `n' bytes long.
518: * The `seglink' gate should be locked before this routine is called.
519: */
520: SEG *
521: sdalloc( s )
522: off_t s;
523: {
524: register SEG *sp1;
525: register SEG *sp2;
526: register daddr_t d;
527: register daddr_t d1;
528: register daddr_t d2;
529:
530: d = s / BSIZE;
531: d1 = swapbot;
532: sp1 = &segdq;
533: do {
534: if (d1 >= swaptop)
535: return (NULL);
536: if ((sp1=sp1->s_forw) != &segdq)
537: d2 = sp1->s_daddr;
538: else
539: d2 = swaptop;
540: if (d2-d1 >= d) {
541: if ((sp2=kalloc(sizeof(SEG))) == NULL)
542: return (NULL);
543: sp1->s_back->s_forw = sp2;
544: sp2->s_back = sp1->s_back;
545: sp1->s_back = sp2;
546: sp2->s_forw = sp1;
547: sp2->s_urefc = 1;
548: sp2->s_lrefc = 1;
549: sp2->s_size = s;
550: sp2->s_daddr = d1;
551: return (sp2);
552: }
553: d1 = sp1->s_daddr + (sp1->s_size / BSIZE);
554: } while (sp1 != &segdq);
555: return (NULL);
556: }
557:
558: /*
559: * Allocate a segment in memory that is `bytes_wanted' bytes long.
560: * The `seglink' gate should be locked before this routine is called.
561: *
562: * if successful, return allocated SEG *
563: * else, return 0
564: */
565: SEG *
566: smalloc(bytes_wanted)
567: off_t bytes_wanted;
568: {
569: register SEG *sp1;
570: register SEG *new_seg;
571: unsigned clicks_wanted;
572:
573: clicks_wanted = btoc(bytes_wanted);
574:
575: /*
576: * Estimate space needed for new segment and its overhead.
577: * Fail if not enough free RAM available.
578: */
579: if (countsize(clicks_wanted) > allocno())
580: return 0;
581: /*
582: * Allocate a new SEG struct to keep track of the segment, if possible.
583: */
584: if ((new_seg = kalloc(sizeof (SEG))) == NULL)
585: return 0;
586:
587: if ((new_seg->s_vmem = c_alloc(clicks_wanted)) == 0) {
588: kfree(new_seg);
589: return 0;
590: }
591:
592: /* link new_seg in at start of segmq */
593: sp1 = segmq.s_forw;
594: sp1->s_back->s_forw = new_seg;
595: new_seg->s_back = sp1->s_back;
596: sp1->s_back = new_seg;
597: new_seg->s_forw = sp1;
598:
599: new_seg->s_urefc = 1;
600: new_seg->s_lrefc = 1;
601: new_seg->s_size = bytes_wanted;
602:
603: return new_seg;
604: }
605:
606: /*
607: * Set up `SR' structure in user area from segments descriptors in
608: * process structure. Also set up the user segmentation registers.
609: */
610: sproto(xhp)
611: struct xechdr *xhp;
612: {
613: register int n;
614: register SEG *sp;
615:
616: for (n=0; n<NUSEG; n++) {
617: u.u_segl[n].sr_flag = u.u_segl[n].sr_size = 0;
618: u.u_segl[n].sr_segp = 0;
619: if ((sp=SELF->p_segp[n]) == NULL)
620: continue;
621: if (n == SIUSERP)
622: u.u_segl[n].sr_base = &u;
623: else {
624: if (xhp)
625: u.u_segl[n].sr_base = xhp->segs[n].mbase;
626: u.u_segl[n].sr_flag |= SRFPMAP;
627: }
628: if (n!=SISTEXT)
629: u.u_segl[n].sr_flag |= SRFDUMP;
630: if (n!=SIUSERP && n!=SISTEXT)
631: u.u_segl[n].sr_flag |= SRFDATA;
632: u.u_segl[n].sr_size = sp->s_size;
633: u.u_segl[n].sr_segp = sp;
634: }
635: return (mproto());
636: }
637:
638: /*
639: * Search for a busy text inode.
640: */
641: sbusy(ip)
642: register INODE *ip;
643: {
644: register SEG *sp;
645:
646: lock(seglink);
647: /*
648: * Look for the segment in the memory queue.
649: */
650: for (sp=segmq.s_forw; sp!=&segmq; sp=sp->s_forw) {
651: if (sp->s_ip==ip
652: && (sp->s_flags&(SFSHRX|SFTEXT))==(SFSHRX|SFTEXT)) {
653: unlock(seglink);
654: return (1);
655: }
656: }
657:
658: /*
659: * Look for the segment on the disk queue.
660: */
661: for (sp=segdq.s_forw; sp!=&segdq; sp=sp->s_forw) {
662: if (sp->s_ip==ip
663: && (sp->s_flags&(SFSHRX|SFTEXT))==(SFSHRX|SFTEXT)) {
664: unlock(seglink);
665: return (1);
666: }
667: }
668: unlock(seglink);
669: return 0;
670: }
671:
672: /*
673: * Segment consistency checks for the paranoid.
674: segchk()
675: {
676: register SEG *sp;
677: register int nbad;
678: off_t s;
679: daddr_t d;
680:
681: nbad = 0;
682: sp = &segdq;
683: d = swapbot;
684: while ((sp=sp->s_forw) != &segdq) {
685: if (sp->s_daddr < d)
686: nbad += badseg("disk", (int)sp->s_daddr, 0);
687: d = sp->s_daddr + (sp->s_size / BSIZE);
688: }
689: if (swaptop < d)
690: nbad += badseg("disk", sp->s_back->s_daddr, sp->s_back->s_size);
691: }
692:
693: badseg(t, b, s)
694: char *t;
695: daddr_t b;
696: off_t s;
697: {
698: printf( "Bad %s segment at %X of len %X\n", t, b, s );
699: return (1);
700: }
701: */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.