queuebuf.c

Go to the documentation of this file.
00001 /**
00002  * \addtogroup rimequeuebuf
00003  * @{
00004  */
00005 
00006 /*
00007  * Copyright (c) 2006, Swedish Institute of Computer Science.
00008  * All rights reserved.
00009  *
00010  * Redistribution and use in source and binary forms, with or without
00011  * modification, are permitted provided that the following conditions
00012  * are met:
00013  * 1. Redistributions of source code must retain the above copyright
00014  *    notice, this list of conditions and the following disclaimer.
00015  * 2. Redistributions in binary form must reproduce the above copyright
00016  *    notice, this list of conditions and the following disclaimer in the
00017  *    documentation and/or other materials provided with the distribution.
00018  * 3. Neither the name of the Institute nor the names of its contributors
00019  *    may be used to endorse or promote products derived from this software
00020  *    without specific prior written permission.
00021  *
00022  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
00023  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00024  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00025  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
00026  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00027  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00028  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00029  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00031  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00032  * SUCH DAMAGE.
00033  *
00034  * This file is part of the Contiki operating system.
00035  *
00036  * $Id: queuebuf.c,v 1.5 2010/11/25 08:43:59 adamdunkels Exp $
00037  */
00038 
00039 /**
00040  * \file
00041  *         Implementation of the Rime queue buffers
00042  * \author
00043  *         Adam Dunkels <adam@sics.se>
00044  */
00045 
00046 #include "contiki-net.h"
00047 
00048 #include <string.h> /* for memcpy() */
00049 
00050 #ifdef QUEUEBUF_CONF_REF_NUM
00051 #define QUEUEBUF_REF_NUM QUEUEBUF_CONF_REF_NUM
00052 #else
00053 #define QUEUEBUF_REF_NUM 2
00054 #endif
00055 
00056 struct queuebuf {
00057 #if QUEUEBUF_DEBUG
00058   struct queuebuf *next;
00059   const char *file;
00060   int line;
00061   clock_time_t time;
00062 #endif /* QUEUEBUF_DEBUG */
00063   uint16_t len;
00064   uint8_t data[PACKETBUF_SIZE];
00065   struct packetbuf_attr attrs[PACKETBUF_NUM_ATTRS];
00066   struct packetbuf_addr addrs[PACKETBUF_NUM_ADDRS];
00067 };
00068 
00069 struct queuebuf_ref {
00070   uint16_t len;
00071   uint8_t *ref;
00072   uint8_t hdr[PACKETBUF_HDR_SIZE];
00073   uint8_t hdrlen;
00074 };
00075 
00076 MEMB(bufmem, struct queuebuf, QUEUEBUF_NUM);
00077 MEMB(refbufmem, struct queuebuf_ref, QUEUEBUF_REF_NUM);
00078 
00079 #if QUEUEBUF_DEBUG
00080 #include "lib/list.h"
00081 LIST(queuebuf_list);
00082 #endif /* QUEUEBUF_DEBUG */
00083 
00084 #define DEBUG 0
00085 #if DEBUG
00086 #include <stdio.h>
00087 #define PRINTF(...) printf(__VA_ARGS__)
00088 #else
00089 #define PRINTF(...)
00090 #endif
00091 
00092 #ifdef QUEUEBUF_CONF_STATS
00093 #define QUEUEBUF_STATS QUEUEBUF_CONF_STATS
00094 #else
00095 #define QUEUEBUF_STATS 0
00096 #endif /* QUEUEBUF_CONF_STATS */
00097 
00098 #if QUEUEBUF_STATS
00099 uint8_t queuebuf_len, queuebuf_ref_len, queuebuf_max_len;
00100 #endif /* QUEUEBUF_STATS */
00101 
00102 /*---------------------------------------------------------------------------*/
00103 void
00104 queuebuf_init(void)
00105 {
00106   memb_init(&bufmem);
00107   memb_init(&refbufmem);
00108 #if QUEUEBUF_STATS
00109   queuebuf_max_len = QUEUEBUF_NUM;
00110 #endif /* QUEUEBUF_STATS */
00111 }
00112 /*---------------------------------------------------------------------------*/
00113 #if QUEUEBUF_DEBUG
00114 struct queuebuf *
00115 queuebuf_new_from_packetbuf_debug(const char *file, int line)
00116 #else /* QUEUEBUF_DEBUG */
00117 struct queuebuf *
00118 queuebuf_new_from_packetbuf(void)
00119 #endif /* QUEUEBUF_DEBUG */
00120 {
00121   struct queuebuf *buf;
00122   struct queuebuf_ref *rbuf;
00123 
00124   if(packetbuf_is_reference()) {
00125     rbuf = memb_alloc(&refbufmem);
00126     if(rbuf != NULL) {
00127 #if QUEUEBUF_STATS
00128       ++queuebuf_ref_len;
00129 #endif /* QUEUEBUF_STATS */
00130       rbuf->len = packetbuf_datalen();
00131       rbuf->ref = packetbuf_reference_ptr();
00132       rbuf->hdrlen = packetbuf_copyto_hdr(rbuf->hdr);
00133     } else {
00134       PRINTF("queuebuf_new_from_packetbuf: could not allocate a reference queuebuf\n");
00135     }
00136     return (struct queuebuf *)rbuf;
00137   } else {
00138     buf = memb_alloc(&bufmem);
00139     if(buf != NULL) {
00140 #if QUEUEBUF_DEBUG
00141       list_add(queuebuf_list, buf);
00142       buf->file = file;
00143       buf->line = line;
00144       buf->time = clock_time();
00145 #endif /* QUEUEBUF_DEBUG */
00146 #if QUEUEBUF_STATS
00147       ++queuebuf_len;
00148       PRINTF("queuebuf len %d\n", queuebuf_len);
00149       printf("#A q=%d\n", queuebuf_len);
00150       if(queuebuf_len == queuebuf_max_len + 1) {
00151         memb_free(&bufmem, buf);
00152         queuebuf_len--;
00153         return NULL;
00154       }
00155 #endif /* QUEUEBUF_STATS */
00156       buf->len = packetbuf_copyto(buf->data);
00157       packetbuf_attr_copyto(buf->attrs, buf->addrs);
00158     } else {
00159       PRINTF("queuebuf_new_from_packetbuf: could not allocate a queuebuf\n");
00160     }
00161     return buf;
00162   }
00163 }
00164 /*---------------------------------------------------------------------------*/
00165 void
00166 queuebuf_free(struct queuebuf *buf)
00167 {
00168   if(memb_inmemb(&bufmem, buf)) {
00169     memb_free(&bufmem, buf);
00170 #if QUEUEBUF_STATS
00171     --queuebuf_len;
00172     printf("#A q=%d\n", queuebuf_len);
00173 #endif /* QUEUEBUF_STATS */
00174 #if QUEUEBUF_DEBUG
00175     list_remove(queuebuf_list, buf);
00176 #endif /* QUEUEBUF_DEBUG */
00177   } else if(memb_inmemb(&refbufmem, buf)) {
00178     memb_free(&refbufmem, buf);
00179 #if QUEUEBUF_STATS
00180     --queuebuf_ref_len;
00181 #endif /* QUEUEBUF_STATS */
00182   }
00183 }
00184 /*---------------------------------------------------------------------------*/
00185 void
00186 queuebuf_to_packetbuf(struct queuebuf *b)
00187 {
00188   struct queuebuf_ref *r;
00189 
00190   if(memb_inmemb(&bufmem, b)) {
00191     packetbuf_copyfrom(b->data, b->len);
00192     packetbuf_attr_copyfrom(b->attrs, b->addrs);
00193   } else if(memb_inmemb(&refbufmem, b)) {
00194     r = (struct queuebuf_ref *)b;
00195     packetbuf_clear();
00196     packetbuf_copyfrom(r->ref, r->len);
00197     packetbuf_hdralloc(r->hdrlen);
00198     memcpy(packetbuf_hdrptr(), r->hdr, r->hdrlen);
00199   }
00200 }
00201 /*---------------------------------------------------------------------------*/
00202 void *
00203 queuebuf_dataptr(struct queuebuf *b)
00204 {
00205   struct queuebuf_ref *r;
00206   
00207   if(memb_inmemb(&bufmem, b)) {
00208     return b->data;
00209   } else if(memb_inmemb(&refbufmem, b)) {
00210     r = (struct queuebuf_ref *)b;
00211     return r->ref;
00212   }
00213   return NULL;
00214 }
00215 /*---------------------------------------------------------------------------*/
00216 int
00217 queuebuf_datalen(struct queuebuf *b)
00218 {
00219   return b->len;
00220 }
00221 /*---------------------------------------------------------------------------*/
00222 rimeaddr_t *
00223 queuebuf_addr(struct queuebuf *b, uint8_t type)
00224 {
00225   return &b->addrs[type - PACKETBUF_ADDR_FIRST].addr;
00226 }
00227 /*---------------------------------------------------------------------------*/
00228 packetbuf_attr_t
00229 queuebuf_attr(struct queuebuf *b, uint8_t type)
00230 {
00231   return b->attrs[type].val;
00232 }
00233 /*---------------------------------------------------------------------------*/
00234 void
00235 queuebuf_debug_print(void)
00236 {
00237 #if QUEUEBUF_DEBUG
00238   struct queuebuf *q;
00239   printf("queuebuf_list: ");
00240   for(q = list_head(queuebuf_list); q != NULL;
00241       q = list_item_next(q)) {
00242     printf("%s,%d,%lu ", q->file, q->line, q->time);
00243   }
00244   printf("\n");
00245 #endif /* QUEUEBUF_DEBUG */
00246 }
00247 /*---------------------------------------------------------------------------*/
00248 /** @} */

Generated on Mon Apr 11 14:23:30 2011 for Contiki 2.5 by  doxygen 1.6.1