Contiki 2.5
queuebuf.c
Go to the documentation of this file.
1 /**
2  * \addtogroup rimequeuebuf
3  * @{
4  */
5 
6 /*
7  * Copyright (c) 2006, Swedish Institute of Computer Science.
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in the
17  * documentation and/or other materials provided with the distribution.
18  * 3. Neither the name of the Institute nor the names of its contributors
19  * may be used to endorse or promote products derived from this software
20  * without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  *
34  * This file is part of the Contiki operating system.
35  *
36  * $Id: queuebuf.c,v 1.5 2010/11/25 08:43:59 adamdunkels Exp $
37  */
38 
39 /**
40  * \file
41  * Implementation of the Rime queue buffers
42  * \author
43  * Adam Dunkels <adam@sics.se>
44  */
45 
46 #include "contiki-net.h"
47 
48 #include <string.h> /* for memcpy() */
49 
50 #ifdef QUEUEBUF_CONF_REF_NUM
51 #define QUEUEBUF_REF_NUM QUEUEBUF_CONF_REF_NUM
52 #else
53 #define QUEUEBUF_REF_NUM 2
54 #endif
55 
56 struct queuebuf {
57 #if QUEUEBUF_DEBUG
58  struct queuebuf *next;
59  const char *file;
60  int line;
61  clock_time_t time;
62 #endif /* QUEUEBUF_DEBUG */
63  uint16_t len;
64  uint8_t data[PACKETBUF_SIZE];
65  struct packetbuf_attr attrs[PACKETBUF_NUM_ATTRS];
66  struct packetbuf_addr addrs[PACKETBUF_NUM_ADDRS];
67 };
68 
69 struct queuebuf_ref {
70  uint16_t len;
71  uint8_t *ref;
72  uint8_t hdr[PACKETBUF_HDR_SIZE];
73  uint8_t hdrlen;
74 };
75 
76 MEMB(bufmem, struct queuebuf, QUEUEBUF_NUM);
77 MEMB(refbufmem, struct queuebuf_ref, QUEUEBUF_REF_NUM);
78 
79 #if QUEUEBUF_DEBUG
80 #include "lib/list.h"
81 LIST(queuebuf_list);
82 #endif /* QUEUEBUF_DEBUG */
83 
84 #define DEBUG 0
85 #if DEBUG
86 #include <stdio.h>
87 #define PRINTF(...) printf(__VA_ARGS__)
88 #else
89 #define PRINTF(...)
90 #endif
91 
92 #ifdef QUEUEBUF_CONF_STATS
93 #define QUEUEBUF_STATS QUEUEBUF_CONF_STATS
94 #else
95 #define QUEUEBUF_STATS 0
96 #endif /* QUEUEBUF_CONF_STATS */
97 
98 #if QUEUEBUF_STATS
99 uint8_t queuebuf_len, queuebuf_ref_len, queuebuf_max_len;
100 #endif /* QUEUEBUF_STATS */
101 
102 /*---------------------------------------------------------------------------*/
103 void
104 queuebuf_init(void)
105 {
106  memb_init(&bufmem);
107  memb_init(&refbufmem);
108 #if QUEUEBUF_STATS
109  queuebuf_max_len = QUEUEBUF_NUM;
110 #endif /* QUEUEBUF_STATS */
111 }
112 /*---------------------------------------------------------------------------*/
113 #if QUEUEBUF_DEBUG
114 struct queuebuf *
115 queuebuf_new_from_packetbuf_debug(const char *file, int line)
116 #else /* QUEUEBUF_DEBUG */
117 struct queuebuf *
118 queuebuf_new_from_packetbuf(void)
119 #endif /* QUEUEBUF_DEBUG */
120 {
121  struct queuebuf *buf;
122  struct queuebuf_ref *rbuf;
123 
124  if(packetbuf_is_reference()) {
125  rbuf = memb_alloc(&refbufmem);
126  if(rbuf != NULL) {
127 #if QUEUEBUF_STATS
128  ++queuebuf_ref_len;
129 #endif /* QUEUEBUF_STATS */
130  rbuf->len = packetbuf_datalen();
131  rbuf->ref = packetbuf_reference_ptr();
132  rbuf->hdrlen = packetbuf_copyto_hdr(rbuf->hdr);
133  } else {
134  PRINTF("queuebuf_new_from_packetbuf: could not allocate a reference queuebuf\n");
135  }
136  return (struct queuebuf *)rbuf;
137  } else {
138  buf = memb_alloc(&bufmem);
139  if(buf != NULL) {
140 #if QUEUEBUF_DEBUG
141  list_add(queuebuf_list, buf);
142  buf->file = file;
143  buf->line = line;
144  buf->time = clock_time();
145 #endif /* QUEUEBUF_DEBUG */
146 #if QUEUEBUF_STATS
147  ++queuebuf_len;
148  PRINTF("queuebuf len %d\n", queuebuf_len);
149  printf("#A q=%d\n", queuebuf_len);
150  if(queuebuf_len == queuebuf_max_len + 1) {
151  memb_free(&bufmem, buf);
152  queuebuf_len--;
153  return NULL;
154  }
155 #endif /* QUEUEBUF_STATS */
156  buf->len = packetbuf_copyto(buf->data);
157  packetbuf_attr_copyto(buf->attrs, buf->addrs);
158  } else {
159  PRINTF("queuebuf_new_from_packetbuf: could not allocate a queuebuf\n");
160  }
161  return buf;
162  }
163 }
164 /*---------------------------------------------------------------------------*/
165 void
166 queuebuf_update_attr_from_packetbuf(struct queuebuf *buf)
167 {
168  packetbuf_attr_copyto(buf->attrs, buf->addrs);
169 }
170 /*---------------------------------------------------------------------------*/
171 void
172 queuebuf_free(struct queuebuf *buf)
173 {
174  if(memb_inmemb(&bufmem, buf)) {
175  memb_free(&bufmem, buf);
176 #if QUEUEBUF_STATS
177  --queuebuf_len;
178  printf("#A q=%d\n", queuebuf_len);
179 #endif /* QUEUEBUF_STATS */
180 #if QUEUEBUF_DEBUG
181  list_remove(queuebuf_list, buf);
182 #endif /* QUEUEBUF_DEBUG */
183  } else if(memb_inmemb(&refbufmem, buf)) {
184  memb_free(&refbufmem, buf);
185 #if QUEUEBUF_STATS
186  --queuebuf_ref_len;
187 #endif /* QUEUEBUF_STATS */
188  }
189 }
190 /*---------------------------------------------------------------------------*/
191 void
192 queuebuf_to_packetbuf(struct queuebuf *b)
193 {
194  struct queuebuf_ref *r;
195 
196  if(memb_inmemb(&bufmem, b)) {
197  packetbuf_copyfrom(b->data, b->len);
198  packetbuf_attr_copyfrom(b->attrs, b->addrs);
199  } else if(memb_inmemb(&refbufmem, b)) {
200  r = (struct queuebuf_ref *)b;
201  packetbuf_clear();
202  packetbuf_copyfrom(r->ref, r->len);
203  packetbuf_hdralloc(r->hdrlen);
204  memcpy(packetbuf_hdrptr(), r->hdr, r->hdrlen);
205  }
206 }
207 /*---------------------------------------------------------------------------*/
208 void *
209 queuebuf_dataptr(struct queuebuf *b)
210 {
211  struct queuebuf_ref *r;
212 
213  if(memb_inmemb(&bufmem, b)) {
214  return b->data;
215  } else if(memb_inmemb(&refbufmem, b)) {
216  r = (struct queuebuf_ref *)b;
217  return r->ref;
218  }
219  return NULL;
220 }
221 /*---------------------------------------------------------------------------*/
222 int
223 queuebuf_datalen(struct queuebuf *b)
224 {
225  return b->len;
226 }
227 /*---------------------------------------------------------------------------*/
228 rimeaddr_t *
229 queuebuf_addr(struct queuebuf *b, uint8_t type)
230 {
231  return &b->addrs[type - PACKETBUF_ADDR_FIRST].addr;
232 }
233 /*---------------------------------------------------------------------------*/
234 packetbuf_attr_t
235 queuebuf_attr(struct queuebuf *b, uint8_t type)
236 {
237  return b->attrs[type].val;
238 }
239 /*---------------------------------------------------------------------------*/
240 void
241 queuebuf_debug_print(void)
242 {
243 #if QUEUEBUF_DEBUG
244  struct queuebuf *q;
245  printf("queuebuf_list: ");
246  for(q = list_head(queuebuf_list); q != NULL;
247  q = list_item_next(q)) {
248  printf("%s,%d,%lu ", q->file, q->line, q->time);
249  }
250  printf("\n");
251 #endif /* QUEUEBUF_DEBUG */
252 }
253 /*---------------------------------------------------------------------------*/
254 /** @} */