forked from Plan9-Archive/drawterm-metal-cocoa
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathallocb.c
131 lines (109 loc) · 2.55 KB
/
allocb.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#include "u.h"
#include "lib.h"
#include "dat.h"
#include "fns.h"
#include "error.h"
enum
{
Hdrspc = 64, /* leave room for high-level headers */
Tlrspc = 16, /* extra room at the end for pad/crc/mac */
Bdead = 0x51494F42, /* "QIOB" */
};
static Block*
_allocb(int size)
{
Block *b;
uintptr addr;
size += Tlrspc;
if((b = mallocz(sizeof(Block)+size+Hdrspc, 0)) == nil)
return nil;
b->next = nil;
b->list = nil;
b->free = nil;
b->flag = 0;
/* align start of data portion by rounding up */
addr = (uintptr)b;
addr = ROUND(addr + sizeof(Block), BLOCKALIGN);
b->base = (uchar*)addr;
/* align end of data portion by rounding down */
b->lim = (uchar*)b + sizeof(Block)+size+Hdrspc;
addr = (uintptr)b->lim;
addr &= ~(BLOCKALIGN-1);
b->lim = (uchar*)addr;
/* leave sluff at beginning for added headers */
b->rp = b->lim - ROUND(size, BLOCKALIGN);
if(b->rp < b->base)
panic("_allocb");
b->wp = b->rp;
return b;
}
Block*
allocb(int size)
{
Block *b;
/*
* Check in a process and wait until successful.
*/
if(up == nil)
panic("allocb without up: %#p", getcallerpc(&size));
if((b = _allocb(size)) == nil)
panic("allocb: no memory for %d bytes", size);
setmalloctag(b, getcallerpc(&size));
return b;
}
Block*
iallocb(int size)
{
Block *b;
if((b = _allocb(size)) == nil)
panic("iallocb: no memory for %d bytes", size);
setmalloctag(b, getcallerpc(&size));
b->flag = BINTR;
return b;
}
void
freeb(Block *b)
{
void *dead = (void*)Bdead;
if(b == nil)
return;
/*
* drivers which perform non cache coherent DMA manage their own buffer
* pool of uncached buffers and provide their own free routine.
*/
if(b->free != nil) {
b->free(b);
return;
}
/* poison the block in case someone is still holding onto it */
b->next = dead;
b->rp = dead;
b->wp = dead;
b->lim = dead;
b->base = dead;
free(b);
}
void
checkb(Block *b, char *msg)
{
void *dead = (void*)Bdead;
if(b == dead)
panic("checkb b %s %#p", msg, b);
if(b->base == dead || b->lim == dead || b->next == dead
|| b->rp == dead || b->wp == dead){
print("checkb: base %#p lim %#p next %#p\n",
b->base, b->lim, b->next);
print("checkb: rp %#p wp %#p\n", b->rp, b->wp);
panic("checkb dead: %s", msg);
}
if(b->base > b->lim)
panic("checkb 0 %s %#p %#p", msg, b->base, b->lim);
if(b->rp < b->base)
panic("checkb 1 %s %#p %#p", msg, b->base, b->rp);
if(b->wp < b->base)
panic("checkb 2 %s %#p %#p", msg, b->base, b->wp);
if(b->rp > b->lim)
panic("checkb 3 %s %#p %#p", msg, b->rp, b->lim);
if(b->wp > b->lim)
panic("checkb 4 %s %#p %#p", msg, b->wp, b->lim);
}