/[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.21 by likewise, Mon Mar 24 13:27:12 2003 UTC revision 1.22 by likewise, Mon Mar 24 15:15:18 2003 UTC
# Line 266  pbuf_alloc(pbuf_layer l, u16_t size, pbu Line 266  pbuf_alloc(pbuf_layer l, u16_t size, pbu
266      rsize = size - p->len;      rsize = size - p->len;
267      while(rsize > 0) {            while(rsize > 0) {      
268        q = pbuf_pool_alloc();        q = pbuf_pool_alloc();
269        if(q == NULL) {        if (q == NULL) {
270          DEBUGF(PBUF_DEBUG | 2, ("pbuf_alloc: Out of pbufs in pool.\n"));          DEBUGF(PBUF_DEBUG | 2, ("pbuf_alloc: Out of pbufs in pool.\n"));
271  #ifdef PBUF_STATS  #ifdef PBUF_STATS
272          ++lwip_stats.pbuf.err;          ++lwip_stats.pbuf.err;
# Line 281  pbuf_alloc(pbuf_layer l, u16_t size, pbu Line 281  pbuf_alloc(pbuf_layer l, u16_t size, pbu
281        q->payload = (void *)((u8_t *)q + sizeof(struct pbuf));        q->payload = (void *)((u8_t *)q + sizeof(struct pbuf));
282        r = q;        r = q;
283        q->ref = 1;        q->ref = 1;
       /*q = q->next;            DJH: Appears to be an unnecessary statement*/  
284        rsize -= PBUF_POOL_BUFSIZE;        rsize -= PBUF_POOL_BUFSIZE;
285      }      }
286        /* end of chain */
287      r->next = NULL;      r->next = NULL;
288    
289      LWIP_ASSERT("pbuf_alloc: pbuf->payload properly aligned",      LWIP_ASSERT("pbuf_alloc: pbuf->payload properly aligned",
# Line 304  pbuf_alloc(pbuf_layer l, u16_t size, pbu Line 304  pbuf_alloc(pbuf_layer l, u16_t size, pbu
304      LWIP_ASSERT("pbuf_alloc: pbuf->payload properly aligned",      LWIP_ASSERT("pbuf_alloc: pbuf->payload properly aligned",
305             ((u32_t)p->payload % MEM_ALIGNMENT) == 0);             ((u32_t)p->payload % MEM_ALIGNMENT) == 0);
306      break;      break;
307     case PBUF_ROM:    /* pbuf references existing ROM payload? */
308     case PBUF_REF:    case PBUF_ROM:
309      /* If the pbuf should point to ROM, we only need to allocate    /* pbuf references existing (externally allocated) RAM payload? */
310         memory for the pbuf structure. */    case PBUF_REF:
311        /* only allocate memory for the pbuf structure */
312      p = memp_mallocp(MEMP_PBUF);      p = memp_mallocp(MEMP_PBUF);
313      if(p == NULL) {      if(p == NULL) {
314          DEBUGF(PBUF_DEBUG | DBG_TRACE | 2, ("pbuf_alloc: Could not allocate MEMP_PBUF for PBUF_REF.\n"));
315        return NULL;        return NULL;
316      }      }
317              /* caller must set this field properly, afterwards */
318      p->payload = NULL;      p->payload = NULL;
319      p->len = p->tot_len = size;      p->len = p->tot_len = size;
320      p->next = NULL;      p->next = NULL;
# Line 535  pbuf_free(struct pbuf *p) Line 538  pbuf_free(struct pbuf *p)
538    struct pbuf *q;    struct pbuf *q;
539    u8_t count = 0;    u8_t count = 0;
540    SYS_ARCH_DECL_PROTECT(old_level);    SYS_ARCH_DECL_PROTECT(old_level);
541      
542    if(p == NULL) {    if(p == NULL) {
543      return 0;      return 0;
544    }    }
545    
546    PERF_START;    PERF_START;
547      
548    LWIP_ASSERT("pbuf_free: sane flags", p->flags == PBUF_FLAG_POOL ||    LWIP_ASSERT("pbuf_free: sane flags", p->flags == PBUF_FLAG_POOL ||
549           p->flags == PBUF_FLAG_ROM ||      p->flags == PBUF_FLAG_ROM ||
550           p->flags == PBUF_FLAG_RAM ||      p->flags == PBUF_FLAG_RAM ||
551           p->flags == PBUF_FLAG_REF );      p->flags == PBUF_FLAG_REF );
     
552    
553    /* Since decrementing ref cannot be guarranteed to be a single machine operation    /* Since decrementing ref cannot be guarranteed to be a single machine operation
554       we must protect it. Also, the later test of ref must be protected.    we must protect it. Also, the later test of ref must be protected.
555    */    */
556    SYS_ARCH_PROTECT(old_level);    SYS_ARCH_PROTECT(old_level);
557    /* Decrement reference count. */      /* Decrement reference count. */
558    for (q = p; q != NULL; q = q->next) {    for (q = p; q != NULL; q = q->next) {
559      LWIP_ASSERT("pbuf_free: q->ref == 0", q->ref > 0);      LWIP_ASSERT("pbuf_free: q->ref > 0", q->ref > 0);
560      q->ref--;      q->ref--;
561    }      }
562    
   /*q = NULL;           DJH: Unnecessary statement*/  
563    /* If reference count == 0, actually deallocate pbuf. */    /* If reference count == 0, actually deallocate pbuf. */
564    if(p->ref == 0) {    if(p->ref == 0) {
565        SYS_ARCH_UNPROTECT(old_level);        SYS_ARCH_UNPROTECT(old_level);
566          
567        while(p != NULL) {      while(p != NULL) {
568            /* Check if this is a pbuf from the pool. */        /* this is a pbuf from the pool? */
569            if(p->flags == PBUF_FLAG_POOL) {        if(p->flags == PBUF_FLAG_POOL) {
570                p->len = p->tot_len = PBUF_POOL_BUFSIZE;          p->len = p->tot_len = PBUF_POOL_BUFSIZE;
571                p->payload = (void *)((u8_t *)p + sizeof(struct pbuf));          p->payload = (void *)((u8_t *)p + sizeof(struct pbuf));
572                q = p->next;          q = p->next;
573                PBUF_POOL_FREE(p);          PBUF_POOL_FREE(p);
574            } else {          /* not a pbuf from the pool */
               if(p->flags == PBUF_FLAG_ROM || p->flags == PBUF_FLAG_REF) {  
                   q = p->next;  
                   memp_freep(MEMP_PBUF, p);  
               } else {  
                   q = p->next;  
                   mem_free(p);  
               }  
           }  
             
           p = q;  
           /* Only free the next one in a chain if it's reference count is 0.  
              This allows buffer chains to have multiple headers pointing to them. */  
           if (p)  
           {  
             p->ref--;  
             if (p->ref > 0)  
               break;  
           }  
             
           ++count;  
575        }        }
576        pbuf_refresh();        else {
577    }          if(p->flags == PBUF_FLAG_ROM || p->flags == PBUF_FLAG_REF) {
578              q = p->next;
579              memp_freep(MEMP_PBUF, p);
580            }
581            else {
582              q = p->next;
583              mem_free(p);
584            }
585          }
586    
587          p = q;
588          /* Only free the next one in a chain if it's reference count is 0.
589          This allows buffer chains to have multiple headers pointing to them. */
590          if (p)
591          {
592            p->ref--;
593            if (p->ref > 0)
594              break;
595          }
596    
597          ++count;
598        }
599        pbuf_refresh();
600        }
601    else    else
602        SYS_ARCH_UNPROTECT(old_level);        SYS_ARCH_UNPROTECT(old_level);
603    
604    PERF_STOP("pbuf_free");    PERF_STOP("pbuf_free");
605      
606    return count;    return count;
607  }  }
608  /*-----------------------------------------------------------------------------------*/  /*-----------------------------------------------------------------------------------*/
# Line 699  pbuf_dechain(struct pbuf *p) Line 703  pbuf_dechain(struct pbuf *p)
703    return q;    return q;
704  }  }
705    
706  /** Replace any pbufs of type PBUF_FLAG_REF with PBUF_POOL buffers.  /**
707     *
708      Go through pbuf chain and replace any PBUF_REF buffers with PBUF_POOL   * Replace any PBUF_REF pbufs of a chain into PBUF_POOL/RAM buffers.
709      buffers. This is generally done for buffer chains which need to be queued   *
710      in some way (either on an output queue or on the arp queue). All pbufs   * Go through pbuf chain and replace any PBUF_REF buffers with PBUF_POOL
711      replaced will be freed immediately.   * (or PBUF_RAM) buffers.
712     *
713      @param f Head of pbuf chain to process   * Used to queue packets on behalf of the lwIP stack, such as ARP based
714     * queueing.
715      @return Pointer to new head of pbuf chain.   *
716  */   * @param f Head of pbuf chain to process
717     *
718     * @return Pointer to new head of pbuf chain.
719     */
720  struct pbuf *  struct pbuf *
721  pbuf_unref(struct pbuf *f)  pbuf_unref(struct pbuf *f)
722  {  {
723    struct pbuf *p, *prev, *top;    struct pbuf *p, *prev, *top;
724    DEBUGF(PBUF_DEBUG | DBG_TRACE, ("pbuf_unref: %p\n", (void*)f));    LWIP_ASSERT("pbuf_unref: f != NULL", f != NULL);
725      DEBUGF(PBUF_DEBUG | DBG_TRACE | 3, ("pbuf_unref(%p)\n", (void*)f));
726    
727    prev = NULL;    prev = NULL;
728    p = f;    p = f;
729    top = f;    top = f;
730      /* iterate through pbuf chain */
731    do    do
732    {    {
733      /* pbuf is of type PBUF_REF? */      /* pbuf is of type PBUF_REF? */
734      if (p->flags == PBUF_FLAG_REF)      if (p->flags == PBUF_FLAG_REF)
735      {      {
736          /* the replacement pbuf */
737        struct pbuf *q;        struct pbuf *q;
738            q = NULL;            q = NULL;
739          DEBUGF(PBUF_DEBUG | DBG_TRACE, ("pbuf_unref: encountered PBUF_REF %p\n", (void *)p));
740        /* allocate a pbuf (w/ payload) fully in RAM */        /* allocate a pbuf (w/ payload) fully in RAM */
741        /* PBUF_POOL buffers are faster if we can use them */        /* PBUF_POOL buffers are faster if we can use them */
742        if (p->len <= PBUF_POOL_BUFSIZE) {        if (p->len <= PBUF_POOL_BUFSIZE) {
743          q = pbuf_alloc(PBUF_RAW, p->len, PBUF_POOL);          q = pbuf_alloc(PBUF_RAW, p->len, PBUF_POOL);
744          if (q == NULL) DEBUGF(PBUF_DEBUG | DBG_TRACE, ("pbuf_unref: Could not allocate PBUF_RAW\n"));          if (q == NULL) DEBUGF(PBUF_DEBUG | DBG_TRACE | 2, ("pbuf_unref: Could not allocate PBUF_RAW\n"));
745        }        }
746        /* no (large enough) PBUF_POOL was available? retry with PBUF_RAM */        /* no (large enough) PBUF_POOL was available? retry with PBUF_RAM */
747        if (q == NULL) {        if (q == NULL) {
748          q = pbuf_alloc(PBUF_RAW, p->len, PBUF_RAM);          q = pbuf_alloc(PBUF_RAW, p->len, PBUF_RAM);
749          if (q == NULL) DEBUGF(PBUF_DEBUG | DBG_TRACE, ("pbuf_unref: Could not allocate PBUF_POOL\n"));          if (q == NULL) DEBUGF(PBUF_DEBUG | DBG_TRACE | 2, ("pbuf_unref: Could not allocate PBUF_POOL\n"));
750        }        }
751        if (q != NULL)        if (q != NULL)
752        {          {  
753          /* copy pbuf struct */          /* copy successor */
754          q->next = p->next;          q->next = p->next;
755          if (prev != NULL)          if (prev != NULL)
756            /* Break chain and insert new pbuf instead */            /* Break chain and insert new pbuf instead */
# Line 751  pbuf_unref(struct pbuf *f) Line 762  pbuf_unref(struct pbuf *f)
762          memcpy(q->payload, p->payload, p->len);          memcpy(q->payload, p->payload, p->len);
763          q->tot_len = p->tot_len;          q->tot_len = p->tot_len;
764          q->len = p->len;          q->len = p->len;
765                    /* do not copy ref, since someone else might be using the old buffer */
766          /* Don't copy ref, since someone else might be using the old buffer */          /* pbuf is not freed, as this is the responsibility of the application */
767                    DEBUGF(PBUF_DEBUG, ("pbuf_unref: replaced PBUF_REF %p with %q\n", (void *)p, (void *)q));
         /* de-allocate PBUF_REF */  
         /* pbuf is not freed because it is assumed that some upper level  
            program has a direct pointer to this pbuf and will free it. */  
768          p = q;          p = q;
         DEBUGF(PBUF_DEBUG, ("pbuf_unref: succesful %p \n", (void *)p));  
769        }        }
770        else        else
771        {        {
772          /* deallocate chain */          /* deallocate chain */
773          pbuf_free(top);          pbuf_free(top);
774          DEBUGF(PBUF_DEBUG | 2, ("pbuf_unref: failed\n"));          DEBUGF(PBUF_DEBUG | 2, ("pbuf_unref: failed to allocate replacement pbuf for %p\n", (void *)p));
775          return NULL;          return NULL;
776        }        }
777      }      }
778            else {
779              DEBUGF(PBUF_DEBUG | DBG_TRACE | 1, ("pbuf_unref: not PBUF_REF"));
780            }
781    
782      prev = p;      prev = p;
783      p = p->next;      p = p->next;
784    } while (p);    } while (p);
785      DEBUGF(PBUF_DEBUG | DBG_TRACE | 1, ("pbuf_unref: end of chain reached."));
786        
787    return top;    return top;
788  }  }

Legend:
Removed from v.1.21  
changed lines
  Added in v.1.22

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