|
|
1.1 root 1: /*
2: * challoc.c
3: * Storage allocation routines for the Chaos N.C.P. for allocating
4: * packets, connections, and (possibly) tty structures for connections treated
5: * as UNIX tty's
6: */
7: #include "../chunix/chsys.h"
8: #include "../chunix/chconf.h"
9: #include "../chaos/chaos.h"
10: #include "../h/buf.h"
11:
12: #define BUFPRI PRIBIO /* Sleep priority for buffers */
13: #define b_bits b_blkno /* Bit map for chaos bufs in buffer (0=free) */
14: #define b_list b_resid /* Index in chsize that buffer belongs to */
15: #define b_nfree b_bcount /* Number of free chaos buffers in buffer */
16: #ifdef VMUNIX
17: #define CHMAXBUF 25
18: #define CHNMAXPKT 18
19: #define CHBSIZE BUFSIZE
20: #else
21: #define CHMAXBUF 12
22: #define CHNMAXPKT 9
23: #ifdef UCB_BUFOUT
24: #define CHBSIZE BUFSIZE
25: extern char abuffers[NABUF][CHBSIZE];
26: #else
27: #define CHBSIZE (BSIZE(0)+BSLOP)
28: extern char buffers[NBUF][CHBSIZE];
29: #endif UCB_BUFOUT
30: #endif VMUNIX
31:
32: /*
33: * Structure for keeping track of various sizes of chaos buffers.
34: * Initialized values should be parameterized.
35: */
36: struct chsize {
37: short ch_bufsize; /* Size of packets to allocate from buffer */
38: short ch_mxbufs; /* Maximum buffers to allocate to this size */
39: short ch_bufcount; /* The count of buffers already allocated */
40: short ch_buffree; /* Number of free buffers on this list now */
41: struct buf *ch_bufptr; /* Pointer to buffers of this size */
42: } Chsizes[] = {
43: #define CHMINPKT 32
44: { CHMINPKT, 1, },
45: { 128, 2, },
46: { 512, CHNMAXPKT, },
47: #endif
48: };
49:
50: #define NSIZES (sizeof(Chsizes)/sizeof(Chsizes[0]))
51:
52: int Chbufwait; /* Someone's waiting for buffers */
53: struct buf *Chbuflist; /* Unassigned buffers */
54: int Chnbufs;
55:
56: /*
57: * Allocate a chunk at least "size" large,
58: * set flag means called from interrupt level - don't hang waiting for buffers
59: * just return NULL
60: */
61: char *
62: ch_alloc(size, flag)
63: {
64: register struct chsize *sp;
65: register struct buf *bp;
66: register int j;
67: long bit;
68: int opl;
69:
70: opl = spl6();
71: again:
72: for (sp = Chsizes; sp < &Chsizes[NSIZES]; sp++) {
73: if (sp->ch_bufsize < size)
74: continue;
75: if (sp->ch_buffree == 0) {
76: if (sp->ch_bufcount == sp->ch_mxbufs ||
77: (bp = Chbuflist) == NULL)
78: continue;
79: Chbuflist = bp->av_forw;
80: bp->av_forw = sp->ch_bufptr;
81: sp->ch_bufptr = bp;
82: bp->b_nfree = j = BSIZE(0) / sp->ch_bufsize;
83: bp->b_bits = 0;
84: bp->b_list = sp - Chsizes;
85: sp->ch_buffree += j;
86: sp->ch_bufcount++;
87: } else
88: for (bp = sp->ch_bufptr;; bp = bp->av_forw)
89: if (bp == NULL)
90: panic("buffer lost somewhere");
91: else if (bp->b_nfree != 0)
92: break;
93: /* Here bp points to a buffer to allocate */
94: for (bit = 1L, j = 0; ; bit <<= 1, j++)
95: if (!(bit & bp->b_bits))
96: break;
97: bp->b_bits |= bit;
98: bp->b_nfree--;
99: sp->ch_buffree--;
100: debug(DALLOC,printf("Alloc: size=%d,adr = %x\n", size, bp->b_un.b_addr+(j * sp->ch_bufsize)));
101: splx(opl);
102: return (bp->b_un.b_addr+(j * sp->ch_bufsize));
103: }
104: if (!flag) {
105: Chbufwait++;
106: sleep((caddr_t)&Chbufwait, BUFPRI);
107: goto again;
108: }
109: debug(DALLOC|DABNOR,printf("Alloc: size=%d, failed\n", size));
110: splx(opl);
111: return((caddr_t)0);
112: }
113: /*
114: * Free the previously allocated storage at "p"
115: */
116: ch_free(p)
117: char *p;
118: {
119: register struct buf *bp;
120: register struct chsize *sp;
121: register int opl;
122: long bit;
123:
124: #ifdef UCB_BUFOUT
125: bp = &abuf[(p - abuffers) / CHBSIZE];
126: #else
127: bp = &buf[(p - buffers) / CHBSIZE];
128: #endif
129: sp = &Chsizes[bp->b_list];
130: debug(DALLOC,printf("Free: addr=%x\n", p));
131: bit = 1L << ((p - bp->b_un.b_addr) / sp->ch_bufsize);
132: if (!(bp->b_bits & bit)) {
133: printf("Free: buffer %x already freed\n", p);
134: panic("Chaos buffer already freed");
135: }
136: bp->b_nfree++;
137: bp->b_bits &= ~bit;
138: sp->ch_buffree++;
139: opl = spl6();
140: if (Chbufwait) {
141: wakeup((caddr_t)&Chbufwait);
142: Chbufwait = 0;
143: }
144: splx(opl);
145: }
146: #ifdef DEBUG
147: /*
148: * Check that address p is in the range of possible allocated packets
149: */
150: ch_badaddr(p)
151: char *p;
152: {
153: register struct buf *bp;
154: register struct chsize *sp;
155: register int opl = spl6();
156:
157: for (sp = Chsizes; sp < &Chsizes[NSIZES]; sp++)
158: for (bp = sp->ch_bufptr; bp; bp = bp->av_forw)
159: if (p >= bp->b_un.b_addr &&
160: p < bp->b_un.b_addr + BSIZE(0)) {
161: splx(opl);
162: return(0);
163: }
164: splx(opl);
165: return(1);
166: }
167: #endif
168: /*
169: * Return the size of the place pointed at by "p"
170: */
171: ch_size(p)
172: char *p;
173: {
174: register struct buf *bp;
175:
176: #ifdef UCB_BUFOUT
177: bp = &abuf[(p - abuffers) / CHBSIZE];
178: #else
179: bp = &buf[(p - buffers) / CHBSIZE];
180: #endif
181: return (Chsizes[bp->b_list].ch_bufsize);
182: }
183: /*
184: * Allocate some space when a new connection is created
185: */
186: ch_bufalloc()
187: {
188: register int cnt;
189: register struct buf *bp;
190: struct buf *geteblk();
191:
192: if (sizeof(bp->b_bits) != 4)
193: panic("challoc bits");
194: if (Chnbufs < 8)
195: cnt = 4;
196: else
197: cnt = 1;
198: if ((Chnbufs + cnt) > CHMAXBUF)
199: return;
200: Chnbufs += cnt;
201: for (; cnt > 0; cnt--) {
202: #ifndef VMUNIX
203: #ifdef UCB_BUFOUT
204: if (abfreelist.av_forw == &abfreelist)
205: #else
206: if (bfreelist.av_forw == &bfreelist)
207: #endif
208: break;
209: #endif VMUNIX
210: bp = geteblk();
211: LOCK;
212: bp->av_forw = Chbuflist;
213: Chbuflist = bp;
214: UNLOCK;
215: }
216: Chnbufs -= cnt;
217: }
218:
219: ch_buffree()
220: {
221: register int cnt;
222: register struct buf *bp;
223:
224: if (Chnbufs <= 8)
225: cnt = 4;
226: else
227: cnt = 1;
228: if (Chnbufs - cnt >= CHMAXBUF)
229: return;
230: LOCK;
231: for (; cnt > 0 && (bp = Chbuflist) != NULL; cnt--) {
232: Chbuflist = bp->av_forw;
233: #ifdef UCB_BUFOUT
234: abrelse(bp);
235: #else
236: brelse(bp);
237: #endif
238: Chnbufs--;
239: }
240: UNLOCK;
241: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.