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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.40.2.4 by likewise, Wed May 14 14:38:28 2003 UTC revision 1.40.2.5 by likewise, Wed Jun 4 10:05:35 2003 UTC
# Line 2  Line 2 
2   * @file   * @file
3   * Packet buffer management   * Packet buffer management
4   *   *
5   * Packets are represented by the pbuf data structure. It supports dynamic   * Packets are built from the pbuf data structure. It supports dynamic
6   * memory allocation for packet contents or can reference externally   * memory allocation for packet contents or can reference externally
7   * managed packet contents both in RAM and ROM. Quick allocation for   * managed packet contents both in RAM and ROM. Quick allocation for
8   * incoming packets is provided through pools with fixed sized pbufs.   * incoming packets is provided through pools with fixed sized pbufs.
9   *   *
10   * Pbufs can be chained as a singly linked list, called a pbuf chain, so   * A packet may span over multiple pbufs, chained as a singly linked
11   * that a packet may span over several pbufs.   * list. This is called a "pbuf chain".
12   *   *
13     * Multiple packets may be queued, also using this singly linked list.
14     * This is called a "packet queue". So, a packet queue consists of one
15     * or more pbuf chains, each of which consist of one or more pbufs.
16     *
17     * The last pbuf of a packet has a ->tot_len field that equals the
18     * ->len field. It can be found by traversing the list. If the last
19     * pbuf of a packet has a ->next field other than NULL, more packets
20     * are on the queue.
21   */   */
22    
23  /*  /*
# Line 65  static sys_sem_t pbuf_pool_free_sem; Line 73  static sys_sem_t pbuf_pool_free_sem;
73  #endif  #endif
74    
75  static struct pbuf *pbuf_pool = NULL;  static struct pbuf *pbuf_pool = NULL;
 static struct pbuf *pbuf_pool_alloc_cache = NULL;  
 static struct pbuf *pbuf_pool_free_cache = NULL;  
76    
77  /**  /**
78   * Initializes the pbuf module.   * Initializes the pbuf module.
# Line 125  pbuf_pool_alloc(void) Line 131  pbuf_pool_alloc(void)
131    
132    SYS_ARCH_DECL_PROTECT(old_level);    SYS_ARCH_DECL_PROTECT(old_level);
133    SYS_ARCH_PROTECT(old_level);    SYS_ARCH_PROTECT(old_level);
134    /* First, see if there are pbufs in the cache. */    
   if (pbuf_pool_alloc_cache) {  
     p = pbuf_pool_alloc_cache;  
     if (p) {  
       pbuf_pool_alloc_cache = p->next;  
     }  
   } else {  
135  #if !SYS_LIGHTWEIGHT_PROT        #if !SYS_LIGHTWEIGHT_PROT      
136      /* Next, check the actual pbuf pool, but if the pool is locked, we    /* Next, check the actual pbuf pool, but if the pool is locked, we
137         pretend to be out of buffers and return NULL. */       pretend to be out of buffers and return NULL. */
138      if (pbuf_pool_free_lock) {    if (pbuf_pool_free_lock) {
139  #ifdef PBUF_STATS  #ifdef PBUF_STATS
140        ++lwip_stats.pbuf.alloc_locked;      ++lwip_stats.pbuf.alloc_locked;
141  #endif /* PBUF_STATS */  #endif /* PBUF_STATS */
142        return NULL;      return NULL;
143      }    }
144      pbuf_pool_alloc_lock = 1;    pbuf_pool_alloc_lock = 1;
145      if (!pbuf_pool_free_lock) {    if (!pbuf_pool_free_lock) {
146  #endif /* SYS_LIGHTWEIGHT_PROT */          #endif /* SYS_LIGHTWEIGHT_PROT */        
147        p = pbuf_pool;      p = pbuf_pool;
148        if (p) {      if (p) {
149          pbuf_pool = p->next;        pbuf_pool = p->next;
150        }      }
151  #if !SYS_LIGHTWEIGHT_PROT        #if !SYS_LIGHTWEIGHT_PROT      
152  #ifdef PBUF_STATS  #ifdef PBUF_STATS
153      } else {    } else {
154        ++lwip_stats.pbuf.alloc_locked;      ++lwip_stats.pbuf.alloc_locked;
155  #endif /* PBUF_STATS */  #endif /* PBUF_STATS */
     }  
     pbuf_pool_alloc_lock = 0;  
 #endif /* SYS_LIGHTWEIGHT_PROT */      
156    }    }
157      pbuf_pool_alloc_lock = 0;
158    #endif /* SYS_LIGHTWEIGHT_PROT */    
159        
160  #ifdef PBUF_STATS  #ifdef PBUF_STATS
161    if (p != NULL) {        if (p != NULL) {    
# Line 171  pbuf_pool_alloc(void) Line 170  pbuf_pool_alloc(void)
170    return p;      return p;  
171  }  }
172    
 /**  
  * @internal only called from pbuf_alloc()  
  */  
 static void  
 pbuf_pool_free(struct pbuf *p)  
 {  
   struct pbuf *q;  
   SYS_ARCH_DECL_PROTECT(old_level);  
   SYS_ARCH_PROTECT(old_level);  
   
 #ifdef PBUF_STATS  
     for(q = p; q != NULL; q = q->next) {  
       --lwip_stats.pbuf.used;  
     }  
 #endif /* PBUF_STATS */  
   
   if (pbuf_pool_alloc_cache == NULL) {  
     pbuf_pool_alloc_cache = p;  
   } else {    
     for(q = pbuf_pool_alloc_cache; q->next != NULL; q = q->next);  
     q->next = p;      
   }  
   SYS_ARCH_UNPROTECT(old_level);  
 }  
173    
174  /**  /**
175   * Allocates a pbuf.   * Allocates a pbuf.
# Line 269  pbuf_alloc(pbuf_layer l, u16_t length, p Line 244  pbuf_alloc(pbuf_layer l, u16_t length, p
244      /* make the payload pointer point 'offset' bytes into pbuf data memory */      /* make the payload pointer point 'offset' bytes into pbuf data memory */
245      p->payload = MEM_ALIGN((void *)((u8_t *)p + (sizeof(struct pbuf) + offset)));      p->payload = MEM_ALIGN((void *)((u8_t *)p + (sizeof(struct pbuf) + offset)));
246      LWIP_ASSERT("pbuf_alloc: pbuf p->payload properly aligned",      LWIP_ASSERT("pbuf_alloc: pbuf p->payload properly aligned",
247              ((u32_t)p->payload % MEM_ALIGNMENT) == 0);              ((u32_t)p->payload % MEM_ALIGNMENT) == 0);
248      /* the total length of the pbuf chain is the requested size */      /* the total length of the pbuf chain is the requested size */
249      p->tot_len = length;      p->tot_len = length;
250      /* set the length of the first pbuf in the chain */      /* set the length of the first pbuf in the chain */
# Line 292  pbuf_alloc(pbuf_layer l, u16_t length, p Line 267  pbuf_alloc(pbuf_layer l, u16_t length, p
267          ++lwip_stats.pbuf.err;          ++lwip_stats.pbuf.err;
268  #endif /* PBUF_STATS */  #endif /* PBUF_STATS */
269          /* bail out unsuccesfully */          /* bail out unsuccesfully */
270          pbuf_pool_free(p);          pbuf_free(p);
271          return NULL;          return NULL;
272        }        }
273        //q->next = NULL;        /*q->next = NULL;*/
274        /* make previous pbuf point to this pbuf */        /* make previous pbuf point to this pbuf */
275        r->next = q;        r->next = q;
276        /* set length of this pbuf */        /* set total length of this pbuf and next in chain */
277          q->tot_len = rem_len;
278          /* this pbuf length is pool size, unless smaller sized tail */
279        q->len = rem_len > PBUF_POOL_BUFSIZE? PBUF_POOL_BUFSIZE: rem_len;        q->len = rem_len > PBUF_POOL_BUFSIZE? PBUF_POOL_BUFSIZE: rem_len;
280        q->flags = PBUF_FLAG_POOL;        q->flags = PBUF_FLAG_POOL;
281        q->payload = (void *)((u8_t *)q + sizeof(struct pbuf));        q->payload = (void *)((u8_t *)q + sizeof(struct pbuf));
282        LWIP_ASSERT("pbuf_alloc: pbuf q->payload properly aligned",        LWIP_ASSERT("pbuf_alloc: pbuf q->payload properly aligned",
283                ((u32_t)q->payload % MEM_ALIGNMENT) == 0);                ((u32_t)q->payload % MEM_ALIGNMENT) == 0);
284        q->ref = 1;        q->ref = 1;
285        /* calculate remaining length to be allocated */        /* calculate remaining length to be allocated */
286        rem_len -= q->len;        rem_len -= q->len;
# Line 327  pbuf_alloc(pbuf_layer l, u16_t length, p Line 304  pbuf_alloc(pbuf_layer l, u16_t length, p
304      p->flags = PBUF_FLAG_RAM;      p->flags = PBUF_FLAG_RAM;
305    
306      LWIP_ASSERT("pbuf_alloc: pbuf->payload properly aligned",      LWIP_ASSERT("pbuf_alloc: pbuf->payload properly aligned",
307             ((u32_t)p->payload % MEM_ALIGNMENT) == 0);             ((u32_t)p->payload % MEM_ALIGNMENT) == 0);
308      break;      break;
309    /* pbuf references existing (static constant) ROM payload? */    /* pbuf references existing (static constant) ROM payload? */
310    case PBUF_ROM:    case PBUF_ROM:
# Line 353  pbuf_alloc(pbuf_layer l, u16_t length, p Line 330  pbuf_alloc(pbuf_layer l, u16_t length, p
330    return p;    return p;
331  }  }
332    
 /**  
  *  
  * Moves free buffers from the pbuf_pool_free_cache to the pbuf_pool  
  * list (if possible).  
  *  
  */  
 void  
 pbuf_refresh(void)  
 {  
   struct pbuf *p;  
   SYS_ARCH_DECL_PROTECT(old_level);  
   SYS_ARCH_PROTECT(old_level);  
   
 #if !SYS_LIGHTWEIGHT_PROT  
   sys_sem_wait(pbuf_pool_free_sem);  
 #endif /* else SYS_LIGHTWEIGHT_PROT */  
     
   if (pbuf_pool_free_cache != NULL) {  
 #if !SYS_LIGHTWEIGHT_PROT        
     pbuf_pool_free_lock = 1;  
     if (!pbuf_pool_alloc_lock) {  
 #endif /* SYS_LIGHTWEIGHT_PROT */  
       if (pbuf_pool == NULL) {  
         pbuf_pool = pbuf_pool_free_cache;        
       } else {    
         for(p = pbuf_pool; p->next != NULL; p = p->next);  
         p->next = pbuf_pool_free_cache;    
       }  
       pbuf_pool_free_cache = NULL;  
 #if !SYS_LIGHTWEIGHT_PROT        
 #ifdef PBUF_STATS  
     } else {  
       ++lwip_stats.pbuf.refresh_locked;  
 #endif /* PBUF_STATS */  
     }  
       
     pbuf_pool_free_lock = 0;  
 #endif /* SYS_LIGHTWEIGHT_PROT */      
   }  
   SYS_ARCH_UNPROTECT(old_level);  
 #if !SYS_LIGHTWEIGHT_PROT        
   sys_sem_signal(pbuf_pool_free_sem);  
 #endif /* SYS_LIGHTWEIGHT_PROT */    
 }  
333    
334  #ifdef PBUF_STATS  #ifdef PBUF_STATS
335  #define DEC_PBUF_STATS do { --lwip_stats.pbuf.used; } while (0)  #define DEC_PBUF_STATS do { --lwip_stats.pbuf.used; } while (0)
# Line 405  pbuf_refresh(void) Line 338  pbuf_refresh(void)
338  #endif /* PBUF_STATS */  #endif /* PBUF_STATS */
339    
340  #define PBUF_POOL_FAST_FREE(p)  do {                                    \  #define PBUF_POOL_FAST_FREE(p)  do {                                    \
341                                    p->next = pbuf_pool_free_cache;       \                                    p->next = pbuf_pool;                  \
342                                    pbuf_pool_free_cache = p;             \                                    pbuf_pool = p;                        \
343                                    DEC_PBUF_STATS;                       \                                    DEC_PBUF_STATS;                       \
344                                  } while (0)                                  } while (0)
345    
# Line 436  pbuf_refresh(void) Line 369  pbuf_refresh(void)
369   * resized, and any remaining pbufs will be freed.   * resized, and any remaining pbufs will be freed.
370   *   *
371   * @note If the pbuf is ROM/REF, only the ->tot_len and ->len fields are adjusted.   * @note If the pbuf is ROM/REF, only the ->tot_len and ->len fields are adjusted.
372     * @note May not be called on a packet queue.
373   *   *
374   * @bug Cannot grow the size of a pbuf (chain) (yet).   * @bug Cannot grow the size of a pbuf (chain) (yet).
375   */   */
# Line 494  pbuf_realloc(struct pbuf *p, u16_t new_l Line 428  pbuf_realloc(struct pbuf *p, u16_t new_l
428    /* q is last packet in chain */    /* q is last packet in chain */
429    q->next = NULL;    q->next = NULL;
430    
   pbuf_refresh();  
431  }  }
432    
433  /**  /**
# Line 513  pbuf_realloc(struct pbuf *p, u16_t new_l Line 446  pbuf_realloc(struct pbuf *p, u16_t new_l
446   * the call will fail. A check is made that the increase in header size does   * the call will fail. A check is made that the increase in header size does
447   * not move the payload pointer in front of the start of the buffer.   * not move the payload pointer in front of the start of the buffer.
448   * @return 1 on failure, 0 on success.   * @return 1 on failure, 0 on success.
449     *
450     * @note May not be called on a packet queue.
451   */   */
452  u8_t  u8_t
453  pbuf_header(struct pbuf *p, s16_t header_size)  pbuf_header(struct pbuf *p, s16_t header_size)
# Line 571  pbuf_header(struct pbuf *p, s16_t header Line 506  pbuf_header(struct pbuf *p, s16_t header
506   * @return the number of unreferenced pbufs that were de-allocated   * @return the number of unreferenced pbufs that were de-allocated
507   * from the head of the chain.   * from the head of the chain.
508   *   *
509     * @note May not be called on a packet queue.
510   * @note the reference counter of a pbuf equals the number of pointers   * @note the reference counter of a pbuf equals the number of pointers
511   * that refer to the pbuf (or into the pbuf).   * that refer to the pbuf (or into the pbuf).
512   *   *
# Line 607  pbuf_free(struct pbuf *p) Line 543  pbuf_free(struct pbuf *p)
543     */     */
544    SYS_ARCH_PROTECT(old_level);    SYS_ARCH_PROTECT(old_level);
545    /* de-allocate all consecutive pbufs from the head of the chain that    /* de-allocate all consecutive pbufs from the head of the chain that
546     * obtain a zero reference count */     * obtain a zero reference count after decrementing*/
547    while (p != NULL) {    while (p != NULL) {
548      /* all pbufs in a chain are referenced at least once */      /* all pbufs in a chain are referenced at least once */
549      LWIP_ASSERT("pbuf_free: p->ref > 0", p->ref > 0);      LWIP_ASSERT("pbuf_free: p->ref > 0", p->ref > 0);
550        /* decrease reference count (number of pointers to pbuf) */
551      p->ref--;      p->ref--;
552      /* this pbuf is no longer referenced to? */      /* this pbuf is no longer referenced to? */
553      if (p->ref == 0) {      if (p->ref == 0) {
# Line 621  pbuf_free(struct pbuf *p) Line 558  pbuf_free(struct pbuf *p)
558          p->len = p->tot_len = PBUF_POOL_BUFSIZE;          p->len = p->tot_len = PBUF_POOL_BUFSIZE;
559          p->payload = (void *)((u8_t *)p + sizeof(struct pbuf));          p->payload = (void *)((u8_t *)p + sizeof(struct pbuf));
560          PBUF_POOL_FREE(p);          PBUF_POOL_FREE(p);
561        /* a RAM/ROM referencing pbuf */        /* a ROM or RAM referencing pbuf */
562        } else if (p->flags == PBUF_FLAG_ROM || p->flags == PBUF_FLAG_REF) {        } else if (p->flags == PBUF_FLAG_ROM || p->flags == PBUF_FLAG_REF) {
563          memp_freep(MEMP_PBUF, p);          memp_freep(MEMP_PBUF, p);
564        /* pbuf with data */        /* p->flags == PBUF_FLAG_RAM */
565        } else {        } else {
566          mem_free(p);          mem_free(p);
567        }        }
# Line 632  pbuf_free(struct pbuf *p) Line 569  pbuf_free(struct pbuf *p)
569        /* proceed to next pbuf */        /* proceed to next pbuf */
570        p = q;        p = q;
571      /* p->ref > 0, this pbuf is still referenced to */      /* p->ref > 0, this pbuf is still referenced to */
572      /* (so the remaining pbufs in chain as well)    */      /* (and so the remaining pbufs in chain as well) */
573      } else {      } else {
574        /* stop walking through chain */        /* stop walking through chain */
575        p = NULL;        p = NULL;
576      }      }
577    }    }
578    SYS_ARCH_UNPROTECT(old_level);    SYS_ARCH_UNPROTECT(old_level);
   pbuf_refresh();  
579    PERF_STOP("pbuf_free");    PERF_STOP("pbuf_free");
580    /* return number of de-allocated pbufs */    /* return number of de-allocated pbufs */
581    return count;    return count;
# Line 664  pbuf_clen(struct pbuf *p) Line 600  pbuf_clen(struct pbuf *p)
600    }    }
601    return len;    return len;
602  }  }
603    
604  /**  /**
605   *   *
606   * Increment the reference count of the pbuf.   * Increment the reference count of the pbuf.
# Line 685  pbuf_ref(struct pbuf *p) Line 622  pbuf_ref(struct pbuf *p)
622    
623  /**  /**
624   *   *
625   * Increment the reference count of all pbufs in a chain.   * Chain two pbufs (or pbuf chains) together. They must belong to the same packet.
  *  
  * @param p first pbuf of chain  
  *  
  */  
 void  
 pbuf_ref_chain(struct pbuf *p)  
 {  
   SYS_ARCH_DECL_PROTECT(old_level);  
   SYS_ARCH_PROTECT(old_level);  
       
   while (p != NULL) {  
     ++p->ref;  
     p = p->next;  
   }  
   SYS_ARCH_UNPROTECT(old_level);  
 }  
   
   
 /**  
  *  
  * Link two pbufs (or chains) together.  
626   *   *
627   * @param h head pbuf (chain)   * @param h head pbuf (chain)
628   * @param t tail pbuf (chain)   * @param t tail pbuf (chain)
629     * @note May not be called on a packet queue.
630     *
631     * The ->tot_len fields of all pbufs of the head chain are adjusted.
632     * The ->next field of the last pbuf of the head chain is adjusted.
633     * The ->ref field of the first pbuf of the tail chain is adjusted.
634   *   *
  * The ->tot_len field of the first pbuf (h) is adjusted.  
635   */   */
636  void  void
637  pbuf_chain(struct pbuf *h, struct pbuf *t)  pbuf_chain(struct pbuf *h, struct pbuf *t)
# Line 720  pbuf_chain(struct pbuf *h, struct pbuf * Line 640  pbuf_chain(struct pbuf *h, struct pbuf *
640    
641    LWIP_ASSERT("h != NULL", h != NULL);    LWIP_ASSERT("h != NULL", h != NULL);
642    LWIP_ASSERT("t != NULL", t != NULL);    LWIP_ASSERT("t != NULL", t != NULL);
643    
644      if (t == NULL)
645        return;
646        
647    /* proceed to last pbuf of chain */    /* proceed to last pbuf of chain */
648    for (p = h; p->next != NULL; p = p->next) {    for (p = h; p->next != NULL; p = p->next) {
# Line 727  pbuf_chain(struct pbuf *h, struct pbuf * Line 650  pbuf_chain(struct pbuf *h, struct pbuf *
650      p->tot_len += t->tot_len;      p->tot_len += t->tot_len;
651    }    }
652    /* p is last pbuf of first h chain */    /* p is last pbuf of first h chain */
653      LWIP_ASSERT("p->tot_len == p->len (of last pbuf in chain)", p->tot_len == p->len);
654    /* add total length of second chain to last pbuf total of first chain */    /* add total length of second chain to last pbuf total of first chain */
655    p->tot_len += t->tot_len;    p->tot_len += t->tot_len;
656    /* chain last pbuf of h chain (p) with first of tail (t) */    /* chain last pbuf of h chain (p) with first of tail (t) */
# Line 736  pbuf_chain(struct pbuf *h, struct pbuf * Line 660  pbuf_chain(struct pbuf *h, struct pbuf *
660    DEBUGF(PBUF_DEBUG | DBG_FRESH | 2, ("pbuf_chain: referencing tail %p\n", (void *) t));    DEBUGF(PBUF_DEBUG | DBG_FRESH | 2, ("pbuf_chain: referencing tail %p\n", (void *) t));
661  }  }
662    
663    /* For packet queueing. Note that queued packets must be dequeued first
664     * before calling any pbuf functions. */
665    #if ARP_QUEUEING
666  /**  /**
667   * Dechains the first pbuf from its succeeding pbufs in the chain.   * Add a packet to the end of a queue.
668   *   *
669   * Makes p->tot_len field equal to p->len.   * @param q pointer to first packet on the queue
670   * @param p pbuf to dechain   * @param n packet to be queued
671   * @return remainder of the pbuf chain, or NULL if it was de-allocated.   *
672     */
673    void
674    pbuf_queue(struct pbuf *p, struct pbuf *n)
675    {
676      LWIP_ASSERT("p != NULL", p != NULL);
677      LWIP_ASSERT("n != NULL", n != NULL);
678    
679      if ((p == NULL) || (n == NULL))
680        return;
681    
682      /* iterate through all packets on queue */
683      while (p->next != NULL) {
684    /* be very picky about pbuf chain correctness */
685    #if PBUF_DEBUG
686        /* iterate through all pbufs in packet */
687        while (p->tot_len != p->len) {
688          /* make sure each packet is complete */
689          LWIP_ASSERT("p->next != NULL", p->next != NULL);
690          p = p->next;
691        }
692    #endif
693        /* now p->tot_len == p->len */
694        /* proceed to next packet on queue */
695        p = p->next;
696      }  
697      /* chain last pbuf of h chain (p) with first of tail (t) */
698      p->next = n;
699      /* t is now referenced to one more time */
700      pbuf_ref(n);
701      DEBUGF(PBUF_DEBUG | DBG_FRESH | 2, ("pbuf_queue: referencing queued packet %p\n", (void *)n));
702    }
703    
704    /**
705     * Remove a packet from the head of a queue.
706     *
707     * @param p pointer to first packet on the queue which will be dequeued.
708     * @return first packet on the remaining queue (NULL if no further packets).
709     *
710   */   */
711  struct pbuf *  struct pbuf *
712  pbuf_dechain(struct pbuf *p)  pbuf_dequeue(struct pbuf *p)
713  {  {
714    struct pbuf *q;    struct pbuf *q;
715    u8_t tail_gone = 1;    LWIP_ASSERT("p != NULL", p != NULL);
716    /* tail */    
717    q = p->next;    /* iterate through all pbufs in packet */
718    /* pbuf has successor in chain? */    while (p->tot_len != p->len) {
719    if (q != NULL) {      /* make sure each packet is complete */
720      /* assert tot_len invariant: (p->tot_len == p->len + (p->next? p->next->tot_len: 0) */      LWIP_ASSERT("p->next != NULL", p->next != NULL);
721      LWIP_ASSERT("p->tot_len == p->len + q->tot_len", q->tot_len == p->tot_len - p->len);      p = p->next;
     /* enforce invariant if assertions are disabled -- this should not be necessary but is  
      * a robustness item */  
     q->tot_len = p->tot_len - p->len;  
     /* decouple pbuf from remainder */  
     p->next = NULL;  
     /* total length of pbuf p is its own length only */  
     p->tot_len = p->len;  
     /* q is no longer referenced by p, free it */  
     DEBUGF(PBUF_DEBUG | DBG_STATE, ("pbuf_dechain: unreferencing %p\n", (void *) q));  
     tail_gone = pbuf_free(q);  
722    }    }
723    /* assert tot_len invariant: (p->tot_len == p->len + (p->next? p->next->tot_len: 0) */    /* remember next packet on queue */
724    LWIP_ASSERT("p->tot_len == p->len", p->tot_len == p->len);    q = p->next;
725    /* return remaining tail or NULL if deallocated */    /* dequeue p from queue */
726    return (tail_gone > 0? NULL: q);    p->next = NULL;
727      /* q is now referenced to one less time */
728      pbuf_free(q);
729      DEBUGF(PBUF_DEBUG | DBG_FRESH | 2, ("pbuf_dequeue: dereferencing remaining queue %p\n", (void *)q));
730      return q;
731  }  }
732    #endif
733    
734  /**  /**
735   *   *
736   * Create PBUF_POOL (or PBUF_RAM) copies of PBUF_REF pbufs.   * Create PBUF_POOL (or PBUF_RAM) copies of PBUF_REF pbufs.
737   *   *
738     * Used to queue packets on behalf of the lwIP stack, such as
739     * ARP based queueing.
740     *
741   * Go through a pbuf chain and replace any PBUF_REF buffers   * Go through a pbuf chain and replace any PBUF_REF buffers
742   * with PBUF_POOL (or PBUF_RAM) pbufs, each taking a copy of   * with PBUF_POOL (or PBUF_RAM) pbufs, each taking a copy of
743   * the referenced data.   * the referenced data.
# Line 784  pbuf_dechain(struct pbuf *p) Line 747  pbuf_dechain(struct pbuf *p)
747   * by pbuf_take()!   * by pbuf_take()!
748   *   *
749   * @note Any replaced pbufs will be freed through pbuf_free().   * @note Any replaced pbufs will be freed through pbuf_free().
750   *   * This may allocate them if they become no longer referenced.
  * Used to queue packets on behalf of the lwIP stack, such as  
  * ARP based queueing.  
751   *   *
752   * @param p Head of pbuf chain to process   * @param p Head of pbuf chain to process
753   *   *
754   * @return Pointer to new head of pbuf chain   * @return Pointer to head of pbuf chain
755   */   */
756  struct pbuf *  struct pbuf *
757  pbuf_take(struct pbuf *p)  pbuf_take(struct pbuf *p)
# Line 813  pbuf_take(struct pbuf *p) Line 774  pbuf_take(struct pbuf *p)
774          q = pbuf_alloc(PBUF_RAW, p->len, PBUF_POOL);          q = pbuf_alloc(PBUF_RAW, p->len, PBUF_POOL);
775          if (q == NULL) DEBUGF(PBUF_DEBUG | DBG_TRACE | 2, ("pbuf_take: Could not allocate PBUF_POOL\n"));          if (q == NULL) DEBUGF(PBUF_DEBUG | DBG_TRACE | 2, ("pbuf_take: Could not allocate PBUF_POOL\n"));
776        } else {        } else {
777          /* no replacement pbuf yet */          /* no replacement pbuf yet */
778          q = NULL;          q = NULL;
779          DEBUGF(PBUF_DEBUG | DBG_TRACE | 2, ("pbuf_take: PBUF_POOL too small to replace PBUF_REF\n"));          DEBUGF(PBUF_DEBUG | DBG_TRACE | 2, ("pbuf_take: PBUF_POOL too small to replace PBUF_REF\n"));
780        }        }
# Line 875  pbuf_take(struct pbuf *p) Line 836  pbuf_take(struct pbuf *p)
836    return head;    return head;
837  }  }
838    
839    #if 0 /* TODO: See if we might need this for future features */
840    /**
841     * Dechains the first pbuf from its succeeding pbufs in the chain.
842     *
843     * Makes p->tot_len field equal to p->len.
844     * @param p pbuf to dechain
845     * @return remainder of the pbuf chain, or NULL if it was de-allocated.
846     * @note May not be called on a packet queue.
847     */
848    struct pbuf *
849    pbuf_dechain(struct pbuf *p)
850    {
851      struct pbuf *q;
852      u8_t tail_gone = 1;
853      /* tail */  
854      q = p->next;
855      /* pbuf has successor in chain? */
856      if (q != NULL) {
857        /* assert tot_len invariant: (p->tot_len == p->len + (p->next? p->next->tot_len: 0) */
858        LWIP_ASSERT("p->tot_len == p->len + q->tot_len", q->tot_len == p->tot_len - p->len);
859        /* enforce invariant if assertion is disabled */
860        q->tot_len = p->tot_len - p->len;
861        /* decouple pbuf from remainder */
862        p->next = NULL;
863        /* total length of pbuf p is its own length only */
864        p->tot_len = p->len;
865        /* q is no longer referenced by p, free it */
866        DEBUGF(PBUF_DEBUG | DBG_STATE, ("pbuf_dechain: unreferencing %p\n", (void *) q));
867        tail_gone = pbuf_free(q);
868        /* return remaining tail or NULL if deallocated */
869      }
870      /* assert tot_len invariant: (p->tot_len == p->len + (p->next? p->next->tot_len: 0) */
871      LWIP_ASSERT("p->tot_len == p->len", p->tot_len == p->len);
872      return (tail_gone > 0? NULL: q);
873    }
874    #endif /* pbuf_dechain() */
875    
876    /* TODO: This function is unused in the lwIP stack and will be deprecated. This is due
877     * to the new way chains are built. */
878    #if 0
879    /**
880     *
881     * Increment the reference count of all pbufs in a chain.
882     *
883     * @param p first pbuf of chain
884     *
885     */
886    void
887    pbuf_ref_chain(struct pbuf *p)
888    {
889      SYS_ARCH_DECL_PROTECT(old_level);
890      SYS_ARCH_PROTECT(old_level);
891        
892      while (p != NULL) {
893        ++p->ref;
894        p = p->next;
895      }
896      SYS_ARCH_UNPROTECT(old_level);
897    }
898    #endif

Legend:
Removed from v.1.40.2.4  
changed lines
  Added in v.1.40.2.5

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