/[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.22 by likewise, Mon Mar 24 15:15:18 2003 UTC revision 1.23 by likewise, Tue Mar 25 12:59:42 2003 UTC
# Line 1  Line 1 
1    /**
2     * @file
3     * Packet buffers/chains management module
4     */
5  /*  /*
6   * Copyright (c) 2001-2003 Swedish Institute of Computer Science.   * Copyright (c) 2001-2003 Swedish Institute of Computer Science.
7   * All rights reserved.   * All rights reserved.
# Line 88  pbuf_init(void) Line 92  pbuf_init(void)
92    lwip_stats.pbuf.avail = PBUF_POOL_SIZE;    lwip_stats.pbuf.avail = PBUF_POOL_SIZE;
93  #endif /* PBUF_STATS */  #endif /* PBUF_STATS */
94        
95    /* Set up ->next pointers to link the pbufs of the pool together. */    /* Set up ->next pointers to link the pbufs of the pool together */
96    p = pbuf_pool;    p = pbuf_pool;
97        
98    for(i = 0; i < PBUF_POOL_SIZE; ++i) {    for(i = 0; i < PBUF_POOL_SIZE; ++i) {
# Line 100  pbuf_init(void) Line 104  pbuf_init(void)
104    }    }
105        
106    /* The ->next pointer of last pbuf is NULL to indicate that there    /* The ->next pointer of last pbuf is NULL to indicate that there
107       are no more pbufs in the pool. */       are no more pbufs in the pool */
108    q->next = NULL;    q->next = NULL;
109    
110  #if !SYS_LIGHTWEIGHT_PROT    #if !SYS_LIGHTWEIGHT_PROT  
# Line 219  pbuf_alloc(pbuf_layer l, u16_t size, pbu Line 223  pbuf_alloc(pbuf_layer l, u16_t size, pbu
223    u16_t offset;    u16_t offset;
224    s32_t rsize;    s32_t rsize;
225    
226      /* determine header offset */
227    offset = 0;    offset = 0;
228    switch(l) {    switch(l) {
229    case PBUF_TRANSPORT:    case PBUF_TRANSPORT:
# Line 239  pbuf_alloc(pbuf_layer l, u16_t size, pbu Line 244  pbuf_alloc(pbuf_layer l, u16_t size, pbu
244    
245    switch(flag) {    switch(flag) {
246    case PBUF_POOL:    case PBUF_POOL:
247      /* Allocate head of pbuf chain into p. */      /* allocate head of pbuf chain into p */
248      p = pbuf_pool_alloc();      p = pbuf_pool_alloc();
249      if(p == NULL) {      if(p == NULL) {
250  #ifdef PBUF_STATS  #ifdef PBUF_STATS
# Line 249  pbuf_alloc(pbuf_layer l, u16_t size, pbu Line 254  pbuf_alloc(pbuf_layer l, u16_t size, pbu
254      }      }
255      p->next = NULL;      p->next = NULL;
256            
257      /* Set the payload pointer so that it points offset bytes into      /* make the payload pointer points offset bytes into pbuf data memory */
        pbuf data memory. */  
258      p->payload = MEM_ALIGN((void *)((u8_t *)p + (sizeof(struct pbuf) + offset)));      p->payload = MEM_ALIGN((void *)((u8_t *)p + (sizeof(struct pbuf) + offset)));
259    
260      /* The total length of the pbuf is the requested size. */      /* the total length of the pbuf is the requested size */
261      p->tot_len = size;      p->tot_len = size;
262    
263      /* Set the length of the first pbuf is the chain. */      /* set the length of the first pbuf is the chain */
264      p->len = size > PBUF_POOL_BUFSIZE - offset? PBUF_POOL_BUFSIZE - offset: size;      p->len = size > PBUF_POOL_BUFSIZE - offset? PBUF_POOL_BUFSIZE - offset: size;
265    
266      p->flags = PBUF_FLAG_POOL;      p->flags = PBUF_FLAG_POOL;
267            
268      /* Allocate the tail of the pbuf chain. */      /* allocate the tail of the pbuf chain. */
269      r = p;      r = p;
270      rsize = size - p->len;      rsize = size - p->len;
271      while(rsize > 0) {            while(rsize > 0) {      
# Line 304  pbuf_alloc(pbuf_layer l, u16_t size, pbu Line 308  pbuf_alloc(pbuf_layer l, u16_t size, pbu
308      LWIP_ASSERT("pbuf_alloc: pbuf->payload properly aligned",      LWIP_ASSERT("pbuf_alloc: pbuf->payload properly aligned",
309             ((u32_t)p->payload % MEM_ALIGNMENT) == 0);             ((u32_t)p->payload % MEM_ALIGNMENT) == 0);
310      break;      break;
311    /* pbuf references existing ROM payload? */    /* pbuf references existing (static constant) ROM payload? */
312    case PBUF_ROM:    case PBUF_ROM:
313    /* pbuf references existing (externally allocated) RAM payload? */    /* pbuf references existing (externally allocated) RAM payload? */
314    case PBUF_REF:    case PBUF_REF:
# Line 318  pbuf_alloc(pbuf_layer l, u16_t size, pbu Line 322  pbuf_alloc(pbuf_layer l, u16_t size, pbu
322      p->payload = NULL;      p->payload = NULL;
323      p->len = p->tot_len = size;      p->len = p->tot_len = size;
324      p->next = NULL;      p->next = NULL;
325      if (flag == PBUF_ROM)      p->flags = (flag == PBUF_ROM? PBUF_FLAG_ROM: PBUF_FLAG_REF);
       p->flags = PBUF_FLAG_ROM;  
     else  
       p->flags = PBUF_FLAG_REF;  
326      break;      break;
327    default:    default:
328      LWIP_ASSERT("pbuf_alloc: erroneous flag", 0);      LWIP_ASSERT("pbuf_alloc: erroneous flag", 0);
# Line 426  pbuf_realloc(struct pbuf *p, u16_t size) Line 427  pbuf_realloc(struct pbuf *p, u16_t size)
427                p->flags == PBUF_FLAG_RAM ||                p->flags == PBUF_FLAG_RAM ||
428                p->flags == PBUF_FLAG_REF);                p->flags == PBUF_FLAG_REF);
429    
     
430    if(p->tot_len <= size) {    if(p->tot_len <= size) {
431      return;      return;
432    }    }
# Line 487  pbuf_realloc(struct pbuf *p, u16_t size) Line 487  pbuf_realloc(struct pbuf *p, u16_t size)
487    
488    pbuf_refresh();    pbuf_refresh();
489  }  }
490  /*-----------------------------------------------------------------------------------*/  /**
491  /* pbuf_header():   * Decreases the header size by the given amount.
492   *   *
493   * Adjusts the ->payload pointer so that space for a header appears in   * Adjusts the ->payload pointer so that space for a header appears in
494   * the pbuf. Also, the ->tot_len and ->len fields are adjusted.   * the pbuf. Also, the ->tot_len and ->len fields are adjusted.
495   *   *
496   * Decreases the header size by the given amount.   * @param hdr_decrement Number of bytes to decrement header size.
497   * Using a negative value increases the header size.   * (Using a negative value increases the header size.)
498     *
499     * @return 1 on failure, 0 on succes.
500   */   */
501  /*-----------------------------------------------------------------------------------*/  /*-----------------------------------------------------------------------------------*/
502  u8_t  u8_t
503  pbuf_header(struct pbuf *p, s16_t header_size)  pbuf_header(struct pbuf *p, s16_t header_size)
504  {  {
505    void *payload;    void *payload;
506      /* referencing pbufs cannot be realloc()ed */
507    if(p->flags == PBUF_FLAG_ROM ||    if (p->flags == PBUF_FLAG_ROM ||
508       p->flags == PBUF_FLAG_REF) {        p->flags == PBUF_FLAG_REF) {
509      return 1;      return 1;
510    }    }
511        
# Line 512  pbuf_header(struct pbuf *p, s16_t header Line 514  pbuf_header(struct pbuf *p, s16_t header
514    
515    DEBUGF(PBUF_DEBUG, ("pbuf_header: old %p new %p (%d)\n", payload, p->payload, header_size));    DEBUGF(PBUF_DEBUG, ("pbuf_header: old %p new %p (%d)\n", payload, p->payload, header_size));
516        
517      /* */
518    if((u8_t *)p->payload < (u8_t *)p + sizeof(struct pbuf)) {    if((u8_t *)p->payload < (u8_t *)p + sizeof(struct pbuf)) {
519      DEBUGF(PBUF_DEBUG | 2, ("pbuf_header: failed %p %p\n",      DEBUGF(PBUF_DEBUG | 2, ("pbuf_header: failed as %p < %p\n",
520                          (u8_t *)p->payload,                          (u8_t *)p->payload,
521                          (u8_t *)p + sizeof(struct pbuf)));                          (u8_t *)p + sizeof(struct pbuf)));\
522        /* restore old payload pointer */
523      p->payload = payload;      p->payload = payload;
524      return 1;      return 1;
525    }    }
# Line 539  pbuf_free(struct pbuf *p) Line 543  pbuf_free(struct pbuf *p)
543    u8_t count = 0;    u8_t count = 0;
544    SYS_ARCH_DECL_PROTECT(old_level);    SYS_ARCH_DECL_PROTECT(old_level);
545    
546    if(p == NULL) {    if (p == NULL) {
547        DEBUGF(PBUF_DEBUG | DBG_TRACE | 2, ("pbuf_free(p==NULL) was called.\n"));
548      return 0;      return 0;
549    }    }
550    
# Line 551  pbuf_free(struct pbuf *p) Line 556  pbuf_free(struct pbuf *p)
556      p->flags == PBUF_FLAG_REF );      p->flags == PBUF_FLAG_REF );
557    
558    /* Since decrementing ref cannot be guarranteed to be a single machine operation    /* Since decrementing ref cannot be guarranteed to be a single machine operation
559    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.
560    */     */
561    SYS_ARCH_PROTECT(old_level);    SYS_ARCH_PROTECT(old_level);
562    /* Decrement reference count. */    /* decrement individual reference count for each pbufs in chain */
563    for (q = p; q != NULL; q = q->next) {    for (q = p; q != NULL; q = q->next) {
564      LWIP_ASSERT("pbuf_free: q->ref > 0", q->ref > 0);      LWIP_ASSERT("pbuf_free: q->ref > 0", q->ref > 0);
565      q->ref--;      q->ref--;
566      }    }
567    
568    /* If reference count == 0, actually deallocate pbuf. */    /* if reference count == 0, actually deallocate pbuf */
569    if(p->ref == 0) {    if (p->ref == 0) {
570        SYS_ARCH_UNPROTECT(old_level);      SYS_ARCH_UNPROTECT(old_level);
571    
572      while(p != NULL) {      while (p != NULL) {
573          /* remember next in chain */
574          q = p->next;
575        /* this is a pbuf from the pool? */        /* this is a pbuf from the pool? */
576        if(p->flags == PBUF_FLAG_POOL) {        if (p->flags == PBUF_FLAG_POOL) {
577          p->len = p->tot_len = PBUF_POOL_BUFSIZE;          p->len = p->tot_len = PBUF_POOL_BUFSIZE;
578          p->payload = (void *)((u8_t *)p + sizeof(struct pbuf));          p->payload = (void *)((u8_t *)p + sizeof(struct pbuf));
         q = p->next;  
579          PBUF_POOL_FREE(p);          PBUF_POOL_FREE(p);
580          /* not a pbuf from the pool */        /* RAM/ROM referencing pbuf */
581          } else if (p->flags == PBUF_FLAG_ROM || p->flags == PBUF_FLAG_REF) {
582            memp_freep(MEMP_PBUF, p);
583          /* pbuf with data */
584          } else {
585            mem_free(p);
586        }        }
587        else {        /* next in chain */
         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);  
         }  
       }  
   
588        p = q;        p = q;
589        /* Only free the next one in a chain if it's reference count is 0.        /* Only free the next one in a chain if it's reference count is 0.
590        This allows buffer chains to have multiple headers pointing to them. */        This allows buffer chains to have multiple headers pointing to them. */
591        if (p)        if (p != NULL)
592        {        {
593          p->ref--;          p->ref--;
594          if (p->ref > 0)          if (p->ref > 0)
# Line 597  pbuf_free(struct pbuf *p) Line 598  pbuf_free(struct pbuf *p)
598        ++count;        ++count;
599      }      }
600      pbuf_refresh();      pbuf_refresh();
601      }    } else
602    else      SYS_ARCH_UNPROTECT(old_level);
       SYS_ARCH_UNPROTECT(old_level);  
   
603    PERF_STOP("pbuf_free");    PERF_STOP("pbuf_free");
604    
605    return count;    return count;
# Line 682  pbuf_chain(struct pbuf *h, struct pbuf * Line 681  pbuf_chain(struct pbuf *h, struct pbuf *
681    p->next = t;    p->next = t;
682    h->tot_len += t->tot_len;      h->tot_len += t->tot_len;  
683  }  }
684  /*-----------------------------------------------------------------------------------*/  
685  /* pbuf_dechain():  /**
686     * Dechains a pbuf from any succeeding pbufs in the chain.
687   *   *
688   * Adjusts the ->tot_len field of the pbuf and returns the tail (if   * Makes p->tot_len field equal to p->len.
689   * any) of the pbuf chain.   * @param p pbuf to dechain
690     * @return remainder (if any) of the pbuf chain.
691   */   */
 /*-----------------------------------------------------------------------------------*/  
692  struct pbuf *  struct pbuf *
693  pbuf_dechain(struct pbuf *p)  pbuf_dechain(struct pbuf *p)
694  {  {
695    struct pbuf *q;    struct pbuf *q;
696        
697    q = p->next;    q = p->next;
698      /* pbuf has successor in chain? */
699    if (q != NULL) {    if (q != NULL) {
700        /* LW: shouldn't q->tot_len be already exactly this? (make this an assert?) */
701      q->tot_len = p->tot_len - p->len;      q->tot_len = p->tot_len - p->len;
702    }    }
703      /* decouple pbuf from remainder */
704    p->tot_len = p->len;    p->tot_len = p->len;
705    p->next = NULL;    p->next = NULL;
706    return q;    return q;

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

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