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