/[lwip]/lwip/src/core/pbuf.c
ViewVC logotype

Contents of /lwip/src/core/pbuf.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.64.2.2 - (show annotations) (download)
Thu Mar 18 01:36:03 2004 UTC (20 years, 1 month ago) by lukem
Branch: lukem-pbuf
Changes since 1.64.2.1: +10 -2 lines
File MIME type: text/plain
added pbuf_ref_chain unimplemented assertion, plus some #if 0'd code

1 #include "lwip/opt.h"
2 #include "lwip/pbuf.h"
3 #include "lwip/sys.h"
4 #include "arch/perf.h"
5
6 void
7 pbuf_init(void){
8 return;
9 }
10
11 /*
12 * abstracted pbuf interface functions
13 * these can be replaced with #defines, but for the time being
14 * we use functions so that we can check for stupidity
15 */
16 struct pbuf *
17 pbuf_alloc_new(u16_t offset, u16_t size, struct pbuf_manager *mgr, void *src){
18 LWIP_ASSERT("pbuf_alloc(): NULL pbuf manager", mgr!=NULL);
19 return mgr->pbuf_alloc_new(offset, size, mgr, src);
20 }
21
22 void
23 pbuf_realloc(struct pbuf *p, u16_t new_len){
24 LWIP_ASSERT("pbuf_realloc(): NULL pbuf", p!=NULL);
25 LWIP_ASSERT("pbuf_realloc(): NULL pbuf manager", p->manager!=NULL);
26 struct pbuf *q;
27 u16_t rem_len; /* remaining length */
28 s16_t grow;
29
30 /* desired length larger than current length? */
31 if (new_len >= p->tot_len) {
32 /* enlarging not yet supported */
33 return;
34 }
35
36 /* the pbuf chain grows by (new_len - p->tot_len) bytes
37 * (which may be negative in case of shrinking) */
38 grow = new_len - p->tot_len;
39
40 /* first, step over any pbufs that should remain in the chain */
41 rem_len = new_len;
42 q = p;
43 /* should this pbuf be kept? */
44 while (rem_len > q->len) {
45 /* decrease remaining length by pbuf length */
46 rem_len -= q->len;
47 /* decrease total length indicator */
48 q->tot_len += grow;
49 /* proceed to next pbuf in chain */
50 q = q->next;
51 }
52 /* we have now reached the new last pbuf (in q) */
53 /* rem_len == desired length for pbuf q */
54
55 /* shrink allocated memory */
56 /* (may only adjust their length fields) */
57
58 /* reallocate and adjust the length of the pbuf that will be split */
59 p->manager->pbuf_realloc(q, rem_len);
60
61 /* adjust length fields for new last pbuf */
62 q->len = rem_len;
63 q->tot_len = q->len;
64
65 /* any remaining pbufs in chain? */
66 if (q->next != NULL) {
67 /* free remaining pbufs in chain */
68 pbuf_free(q->next);
69 }
70 /* q is last packet in chain */
71 q->next = NULL;
72 }
73
74 u8_t
75 pbuf_header(struct pbuf *p, s16_t header_size){
76 LWIP_ASSERT("pbuf_header(): NULL pbuf", p!=NULL);
77 LWIP_ASSERT("pbuf_header(): NULL pbuf manager", p->manager!=NULL);
78 return p->manager->pbuf_header(p, header_size);
79 }
80
81 u8_t
82 pbuf_free(struct pbuf *p){
83 struct pbuf *q;
84 u8_t count;
85
86 if (p == NULL) {
87 LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 2,
88 ("pbuf_free(p == NULL) was called.\n"));
89 return 0;
90 }
91
92 LWIP_DEBUGF(PBUF_DEBUG, ("pbuf_free(%p)\n", (void *)p));
93
94 PERF_START;
95
96 count = 0;
97
98 /* Since decrementing ref cannot be guaranteed to be a single machine
99 * operation we must protect it. Also, the later test of ref must be
100 * protected.
101 */
102 SYS_ARCH_PROTECT(old_level);
103
104 /* de-allocate all consecutive pbufs from the head of the chain that
105 * obtain a zero reference count after decrementing
106 */
107 while (p != NULL) {
108 /* all pbufs in a chain are referenced at least once */
109 LWIP_ASSERT("pbuf_free: p->ref > 0", p->ref > 0);
110
111 /* decrease reference count (number of pointers to pbuf) */
112 p->ref--;
113
114 /* this pbuf is no longer referenced to? */
115 if (p->ref == 0) {
116 /* remember next pbuf in chain for next iteration */
117 q = p->next;
118 LWIP_DEBUGF(PBUF_DEBUG | 2, ("pbuf_free: deallocating %p\n", (void *)p));
119
120 /* call the pbuf-specific free function */
121 p->manager->pbuf_free(p);
122
123 count++;
124
125 /* proceed to next pbuf */
126 p = q;
127
128 } else {
129 /* p->ref > 0, this pbuf is still referenced to */
130 /* (and so the remaining pbufs in chain as well) */
131
132 LWIP_DEBUGF(PBUF_DEBUG | 2, ("pbuf_free: %p has ref %u, ending here.\n",
133 (void *)p, (unsigned int)p->ref));
134
135 /* stop walking through chain */
136 p = NULL;
137 }
138 }
139
140 SYS_ARCH_UNPROTECT(old_level);
141
142 PERF_STOP("pbuf_free");
143
144 /* return number of de-allocated pbufs */
145 return count;
146 }
147
148
149 /*
150 * generic pbuf interface functions
151 */
152
153 void
154 pbuf_ref_chain(struct pbuf *p){
155 LWIP_ASSERT("pbuf_ref_chain unimplemented!", 0);
156 }
157
158 void
159 pbuf_ref(struct pbuf *p){
160 SYS_ARCH_DECL_PROTECT(old_level);
161 /* pbuf given? */
162 if (p != NULL) {
163 SYS_ARCH_PROTECT(old_level);
164 ++(p->ref);
165 SYS_ARCH_UNPROTECT(old_level);
166 }
167 }
168
169 u8_t
170 pbuf_clen(struct pbuf *p){
171 u8_t len;
172
173 len = 0;
174 while (p != NULL) {
175 ++len;
176 #if 0
177 {
178 mem_ptr_t x = (mem_ptr_t)p;
179 if((x%sizeof(mem_ptr_t))!=0){
180 LWIP_ASSERT("pbuf not aligned!\n", 0);
181 }
182 }
183 #endif
184 p = p->next;
185 }
186
187 return len;
188 }
189
190 void
191 pbuf_cat(struct pbuf *h, struct pbuf *t){
192 struct pbuf *p;
193
194 LWIP_ASSERT("h != NULL", h != NULL);
195 LWIP_ASSERT("t != NULL", t != NULL);
196
197 if (t == NULL)
198 return;
199
200 /* proceed to last pbuf of chain */
201 for (p = h; p->next != NULL; p = p->next) {
202 /* add total length of second chain to all totals of first chain */
203 p->tot_len += t->tot_len;
204 }
205
206 /* p is last pbuf of first h chain */
207 LWIP_ASSERT("p->tot_len == p->len (of last pbuf in chain)",
208 p->tot_len == p->len);
209
210 /* add total length of second chain to last pbuf total of first chain */
211 p->tot_len += t->tot_len;
212
213 /* chain last pbuf of head (p) with first of tail (t) */
214 p->next = t;
215 }
216
217 void
218 pbuf_chain(struct pbuf *h, struct pbuf *t){
219 pbuf_cat(h, t);
220 /* t is now referenced to one more time */
221 pbuf_ref(t);
222 LWIP_DEBUGF(PBUF_DEBUG | DBG_FRESH | 2,
223 ("pbuf_chain: %p references %p\n", (void *)h, (void *)t));
224 }
225
226 struct pbuf *
227 pbuf_take(struct pbuf *f){
228 LWIP_ASSERT("pbuf_take() unimplemented", 0);
229 return NULL;
230 }
231
232 struct pbuf *
233 pbuf_dechain(struct pbuf *p){
234 struct pbuf *q;
235 u8_t tail_gone = 1;
236 /* tail */
237 q = p->next;
238 /* pbuf has successor in chain? */
239 if (q != NULL) {
240 /* assert tot_len invariant:
241 * (p->tot_len == p->len + (p->next? p->next->tot_len : 0)
242 */
243 LWIP_ASSERT("p->tot_len == p->len + q->tot_len",
244 q->tot_len == p->tot_len - p->len);
245
246 /* enforce invariant if assertion is disabled */
247 q->tot_len = p->tot_len - p->len;
248
249 /* decouple pbuf from remainder */
250 p->next = NULL;
251
252 /* total length of pbuf p is its own length only */
253 p->tot_len = p->len;
254
255 /* q is no longer referenced by p, free it */
256 LWIP_DEBUGF(PBUF_DEBUG | DBG_STATE,
257 ("pbuf_dechain: unreferencing %p\n", (void *)q));
258
259 tail_gone = pbuf_free(q);
260 if (tail_gone > 0)
261 LWIP_DEBUGF(PBUF_DEBUG | DBG_STATE,
262 ("pbuf_dechain: deallocated %p (no longer referenced)\n",
263 (void *)q));
264 }
265
266 /* assert tot_len invariant:
267 * (p->tot_len == p->len + (p->next? p->next->tot_len: 0)
268 */
269 LWIP_ASSERT("p->tot_len == p->len", p->tot_len == p->len);
270
271 return (tail_gone > 0? NULL: q);
272 }

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26