/[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.16 by jani, Mon Feb 24 10:49:05 2003 UTC revision 1.17 by davidhaas, Wed Mar 19 22:14:49 2003 UTC
# Line 200  pbuf_pool_free(struct pbuf *p) Line 200  pbuf_pool_free(struct pbuf *p)
200   * * PBUF_ROM: no buffer memory is allocated for the pbuf, even for   * * PBUF_ROM: no buffer memory is allocated for the pbuf, even for
201   *             protocol headers. Additional headers must be prepended   *             protocol headers. Additional headers must be prepended
202   *             by allocating another pbuf and chain in to the front of   *             by allocating another pbuf and chain in to the front of
203   *             the ROM pbuf.             *             the ROM pbuf. It is assumed that the memory used is really
204     *             similar to ROM in that it is immutable and will not be
205     *             changed. Memory which is dynamic should generally not
206     *             be attached to PBUF_ROM pbufs. Use PBUF_REF instead.
207     * * PBUF_REF: no buffer memory is allocated for the pbuf, even for
208     *             protocol headers. It is assumed that the pbuf is only
209     *             being used in a single thread. If the pbuf gets queued,
210     *             then pbuf_unref should be called to copy the buffer.
211   * * PBUF_POOL: the pbuf is allocated as a pbuf chain, with pbufs from   * * PBUF_POOL: the pbuf is allocated as a pbuf chain, with pbufs from
212   *              the pbuf pool that is allocated during pbuf_init().   *              the pbuf pool that is allocated during pbuf_init().
213   */   */
# Line 297  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:     case PBUF_ROM:
308       case PBUF_REF:
309      /* If the pbuf should point to ROM, we only need to allocate      /* If the pbuf should point to ROM, we only need to allocate
310         memory for the pbuf structure. */         memory for the pbuf structure. */
311      p = memp_mallocp(MEMP_PBUF);      p = memp_mallocp(MEMP_PBUF);
# Line 307  pbuf_alloc(pbuf_layer l, u16_t size, pbu Line 315  pbuf_alloc(pbuf_layer l, u16_t size, pbu
315      p->payload = NULL;      p->payload = NULL;
316      p->len = p->tot_len = size;      p->len = p->tot_len = size;
317      p->next = NULL;      p->next = NULL;
318      p->flags = PBUF_FLAG_ROM;      if (flag == PBUF_ROM)
319          p->flags = PBUF_FLAG_ROM;
320        else
321          p->flags = PBUF_FLAG_REF;
322      break;      break;
323    default:    default:
324      LWIP_ASSERT("pbuf_alloc: erroneous flag", 0);      LWIP_ASSERT("pbuf_alloc: erroneous flag", 0);
# Line 408  pbuf_realloc(struct pbuf *p, u16_t size) Line 419  pbuf_realloc(struct pbuf *p, u16_t size)
419    u16_t rsize;    u16_t rsize;
420    
421    LWIP_ASSERT("pbuf_realloc: sane p->flags", p->flags == PBUF_FLAG_POOL ||    LWIP_ASSERT("pbuf_realloc: sane p->flags", p->flags == PBUF_FLAG_POOL ||
422           p->flags == PBUF_FLAG_ROM ||                p->flags == PBUF_FLAG_ROM ||
423           p->flags == PBUF_FLAG_RAM);                p->flags == PBUF_FLAG_RAM ||
424                  p->flags == PBUF_FLAG_REF);
425    
426        
427    if(p->tot_len <= size) {    if(p->tot_len <= size) {
# Line 438  pbuf_realloc(struct pbuf *p, u16_t size) Line 450  pbuf_realloc(struct pbuf *p, u16_t size)
450        q = r;        q = r;
451      }      }
452      break;      break;
453    case PBUF_FLAG_ROM:        case PBUF_FLAG_ROM:
454      case PBUF_FLAG_REF:
455      p->len = size;      p->len = size;
456      break;      break;
457    case PBUF_FLAG_RAM:    case PBUF_FLAG_RAM:
# Line 486  pbuf_header(struct pbuf *p, s16_t header Line 499  pbuf_header(struct pbuf *p, s16_t header
499  {  {
500    void *payload;    void *payload;
501    
502    if(p->flags & PBUF_FLAG_ROM) {    if(p->flags == PBUF_FLAG_ROM ||
503         p->flags == PBUF_FLAG_REF) {
504      return 1;      return 1;
505    }    }
506        
# Line 530  pbuf_free(struct pbuf *p) Line 544  pbuf_free(struct pbuf *p)
544        
545    LWIP_ASSERT("pbuf_free: sane flags", p->flags == PBUF_FLAG_POOL ||    LWIP_ASSERT("pbuf_free: sane flags", p->flags == PBUF_FLAG_POOL ||
546           p->flags == PBUF_FLAG_ROM ||           p->flags == PBUF_FLAG_ROM ||
547           p->flags == PBUF_FLAG_RAM);           p->flags == PBUF_FLAG_RAM ||
548             p->flags == PBUF_FLAG_REF );
549        
550    LWIP_ASSERT("pbuf_free: p->ref > 0", p->ref > 0);    LWIP_ASSERT("pbuf_free: p->ref > 0", p->ref > 0);
551    
# Line 554  pbuf_free(struct pbuf *p) Line 569  pbuf_free(struct pbuf *p)
569                q = p->next;                q = p->next;
570                PBUF_POOL_FREE(p);                PBUF_POOL_FREE(p);
571            } else {            } else {
572                if(p->flags == PBUF_FLAG_ROM) {                if(p->flags == PBUF_FLAG_ROM || p->flags == PBUF_FLAG_REF) {
573                    q = p->next;                    q = p->next;
574                    memp_freep(MEMP_PBUF, p);                    memp_freep(MEMP_PBUF, p);
575                } else {                } else {
# Line 564  pbuf_free(struct pbuf *p) Line 579  pbuf_free(struct pbuf *p)
579            }            }
580                        
581            p = q;            p = q;
582              /* Only free the next one in a chain if it's reference count is 0.
583                 This allows buffer chains to have multiple headers pointing to them. */
584              if (p)
585              {
586                p->ref--;
587                if (p->ref > 0)
588                  break;
589              }
590              
591            ++count;            ++count;
592        }        }
593        pbuf_refresh();        pbuf_refresh();
# Line 673  pbuf_dechain(struct pbuf *p) Line 697  pbuf_dechain(struct pbuf *p)
697    return q;    return q;
698  }  }
699  /*-----------------------------------------------------------------------------------*/  /*-----------------------------------------------------------------------------------*/
700    /** Replace any pbufs of type PBUF_FLAG_REF with PBUF_POOL buffers.
701    
702        Go through pbuf chain and replace any PBUF_REF buffers with PBUF_POOL
703        buffers. This is generally done for buffer chains which need to be queued
704        in some way (either on an output queue or on the arp queue). All pbufs
705        replaced will be freed immediately.
706    
707        @param f Head of pbuf chain to process
708    
709        @return Pointer to new head of pbuf chain.
710    */
711  struct pbuf *  struct pbuf *
712  pbuf_unref(struct pbuf *f)  pbuf_unref(struct pbuf *f)
713  {  {
714    struct pbuf *p, *q;    struct pbuf *p, *prev, *q, *top;
715    DEBUGF(PBUF_DEBUG, ("pbuf_unref: %p \n", (void*)f));    DEBUGF(PBUF_DEBUG, ("pbuf_unref: %p \n", (void*)f));
716    /* first pbuf is of type PBUF_REF? */  
717    if (f->flags == PBUF_FLAG_REF)    prev = 0;
718      p = f;
719      top = f;
720      do
721    {    {
722      /* allocate a pbuf (w/ payload) fully in RAM */      /* pbuf is of type PBUF_REF? */
723      p = pbuf_alloc(PBUF_RAW, f->len, PBUF_RAM);      if (p->flags == PBUF_FLAG_REF)
724      if (p != 0)      {
725      {          /* allocate a pbuf (w/ payload) fully in RAM */
726        int i;        /* PBUF_POOL buffers are faster if we can use them */
727        unsigned char *src, *dst;        if (p->len <= PBUF_POOL_BUFSIZE)
728        /* copy pbuf struct */          q = pbuf_alloc(PBUF_RAW, p->len, PBUF_POOL);
729        p->next = f->next;        else
730        src = f->payload;          q = pbuf_alloc(PBUF_RAW, p->len, PBUF_RAM);
731        dst = p->payload;        if (q != 0)
732        i = 0;        {  
733        /* copy payload to RAM pbuf */          /* copy pbuf struct */
734        while(i < p->len)          q->next = p->next;
735            if (prev)
736              /* Break chain and insert new pbuf instead */
737              prev->next = q;
738            else
739              top = q;
740            p->next = NULL;
741            
742            memcpy(q->payload, p->payload, p->len);
743            q->tot_len = p->tot_len;
744            q->len = p->len;
745            
746            /* Don't copy ref, since someone else might be using the old buffer */
747            
748            /* de-allocate PBUF_REF */
749            /* pbuf is not freed because it is assumed that some upper level
750               program has a direct pointer to this pbuf and will free it. */
751            p = q;
752            DEBUGF(PBUF_DEBUG, ("pbuf_unref: succesful %p \n", (void *)p));
753          }
754          else
755        {        {
756          *dst = *src;          /* deallocate chain */
757          dst++;          pbuf_free(top);
758          src++;          DEBUGF(PBUF_DEBUG, ("pbuf_unref: failed\n"));
759            return NULL;
760        }        }
       f->next = NULL;  
       /* de-allocate PBUF_REF */  
       pbuf_free(f);  
       f = p;  
       DEBUGF(PBUF_DEBUG, ("pbuf_unref: succesful %p \n", (void *)f));  
761      }      }
762      else      prev = p;
763      {      p = p->next;
764        /* deallocate chain */    } while (p);
765        pbuf_free(f);    
766        f = NULL;    return top;
       DEBUGF(PBUF_DEBUG, ("pbuf_unref: failed\n"));  
       return NULL;  
     }  
   }  
   /* p = previous pbuf == first pbuf  */  
   p = f;  
   /* q = current pbuf */  
   q = f->next;  
   while (q != NULL)  
   {  
     q = q->next;  
   }  
   return f;  
767  }  }

Legend:
Removed from v.1.16  
changed lines
  Added in v.1.17

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