]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/port/ucallocb.c
merge
[plan9front.git] / sys / src / 9 / port / ucallocb.c
1 /*
2  * allocate Blocks from uncached memory
3  */
4 #include        "u.h"
5 #include        "../port/lib.h"
6 #include        "mem.h"
7 #include        "dat.h"
8 #include        "fns.h"
9 #include        "error.h"
10
11 enum
12 {
13         Hdrspc          = 64,           /* leave room for high-level headers */
14         Bdead           = 0x51494F42,   /* "QIOB" */
15 };
16
17 struct
18 {
19         Lock;
20         ulong   bytes;
21 } ucialloc;
22
23 static Block*
24 _ucallocb(int size)
25 {
26         Block *b;
27         ulong addr;
28
29         if((b = ucalloc(sizeof(Block)+size+Hdrspc)) == nil)
30                 return nil;
31
32         b->next = nil;
33         b->list = nil;
34         b->free = 0;
35         b->flag = 0;
36         b->ref = 0;
37         _xinc(&b->ref);
38
39         /* align start of data portion by rounding up */
40         addr = (ulong)b;
41         addr = ROUND(addr + sizeof(Block), BLOCKALIGN);
42         b->base = (uchar*)addr;
43
44         /* align end of data portion by rounding down */
45         b->lim = ((uchar*)b) + msize(b);
46         addr = (ulong)(b->lim);
47         addr = addr & ~(BLOCKALIGN-1);
48         b->lim = (uchar*)addr;
49
50         /* leave sluff at beginning for added headers */
51         b->rp = b->lim - ROUND(size, BLOCKALIGN);
52         if(b->rp < b->base)
53                 panic("_ucallocb");
54         b->wp = b->rp;
55
56         return b;
57 }
58
59 Block*
60 ucallocb(int size)
61 {
62         Block *b;
63
64         /*
65          * Check in a process and wait until successful.
66          * Can still error out of here, though.
67          */
68         if(up == nil)
69                 panic("ucallocb without up: %#p", getcallerpc(&size));
70         if((b = _ucallocb(size)) == nil)
71                 panic("ucallocb: no memory for %d bytes", size);
72         setmalloctag(b, getcallerpc(&size));
73
74         return b;
75 }
76
77 Block*
78 uciallocb(int size)
79 {
80         Block *b;
81         static int m1, m2, mp;
82
83         if(0 && ucialloc.bytes > conf.ialloc){
84                 if((m1++%10000)==0){
85                         if(mp++ > 1000){
86                                 active.exiting = 1;
87                                 exit(0);
88                         }
89                         iprint("uciallocb: limited %lud/%lud\n",
90                                 ucialloc.bytes, conf.ialloc);
91                 }
92                 return nil;
93         }
94
95         if((b = _ucallocb(size)) == nil){
96                 if(0 && (m2++%10000)==0){
97                         if(mp++ > 1000){
98                                 active.exiting = 1;
99                                 exit(0);
100                         }
101                         iprint("uciallocb: no memory %lud/%lud\n",
102                                 ucialloc.bytes, conf.ialloc);
103                 }
104                 return nil;
105         }
106         setmalloctag(b, getcallerpc(&size));
107         b->flag = BINTR;
108
109         ilock(&ucialloc);
110         ucialloc.bytes += b->lim - b->base;
111         iunlock(&ucialloc);
112
113         return b;
114 }
115
116 void
117 ucfreeb(Block *b)
118 {
119         void *dead = (void*)Bdead;
120         long ref;
121
122         if(b == nil || (ref = _xdec(&b->ref)) > 0)
123                 return;
124
125         if(ref < 0){
126                 dumpstack();
127                 panic("ucfreeb: ref %ld; caller pc %#p", ref, getcallerpc(&b));
128         }
129
130         /*
131          * drivers which perform non cache coherent DMA manage their own buffer
132          * pool of uncached buffers and provide their own free routine.
133          */
134         if(b->free) {
135                 b->free(b);
136                 return;
137         }
138         if(b->flag & BINTR) {
139                 ilock(&ucialloc);
140                 ucialloc.bytes -= b->lim - b->base;
141                 iunlock(&ucialloc);
142         }
143
144         /* poison the block in case someone is still holding onto it */
145         b->next = dead;
146         b->rp = dead;
147         b->wp = dead;
148         b->lim = dead;
149         b->base = dead;
150
151         ucfree(b);
152 }