]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/port/ucallocb.c
410aa62e85647d245ffc1ebe87d8c938d6955253
[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         uintptr 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 = nil;
35         b->flag = 0;
36
37         /* align start of data portion by rounding up */
38         addr = (uintptr)b;
39         addr = ROUND(addr + sizeof(Block), BLOCKALIGN);
40         b->base = (uchar*)addr;
41
42         /* align end of data portion by rounding down */
43         b->lim = (uchar*)b + msize(b);
44         addr = (uintptr)b->lim;
45         addr &= ~(BLOCKALIGN-1);
46         b->lim = (uchar*)addr;
47
48         /* leave sluff at beginning for added headers */
49         b->rp = b->lim - ROUND(size, BLOCKALIGN);
50         if(b->rp < b->base)
51                 panic("_ucallocb");
52         b->wp = b->rp;
53
54         return b;
55 }
56
57 Block*
58 ucallocb(int size)
59 {
60         Block *b;
61
62         /*
63          * Check in a process and wait until successful.
64          * Can still error out of here, though.
65          */
66         if(up == nil)
67                 panic("ucallocb without up: %#p", getcallerpc(&size));
68         if((b = _ucallocb(size)) == nil)
69                 panic("ucallocb: no memory for %d bytes", size);
70         setmalloctag(b, getcallerpc(&size));
71
72         return b;
73 }
74
75 Block*
76 uciallocb(int size)
77 {
78         Block *b;
79         static int m1, m2, mp;
80
81         if((b = _ucallocb(size)) == nil){
82                 if(0 && (m2++%10000)==0){
83                         if(mp++ > 1000)
84                                 panic("uciallocb: out of memory");
85                         iprint("uciallocb: no memory %lud/%lud\n",
86                                 ucialloc.bytes, conf.ialloc);
87                 }
88                 return nil;
89         }
90         setmalloctag(b, getcallerpc(&size));
91         b->flag = BINTR;
92
93         ilock(&ucialloc);
94         ucialloc.bytes += b->lim - b->base;
95         iunlock(&ucialloc);
96
97         return b;
98 }
99
100 void
101 ucfreeb(Block *b)
102 {
103         void *dead = (void*)Bdead;
104
105         if(b == nil)
106                 return;
107
108         /*
109          * drivers which perform non cache coherent DMA manage their own buffer
110          * pool of uncached buffers and provide their own free routine.
111          */
112         if(b->free != nil) {
113                 b->free(b);
114                 return;
115         }
116         if(b->flag & BINTR) {
117                 ilock(&ucialloc);
118                 ucialloc.bytes -= b->lim - b->base;
119                 iunlock(&ucialloc);
120         }
121
122         /* poison the block in case someone is still holding onto it */
123         b->next = dead;
124         b->rp = dead;
125         b->wp = dead;
126         b->lim = dead;
127         b->base = dead;
128
129         ucfree(b);
130 }