lwip-users
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[lwip-users] RE: [lwip] Porting problems


From: Björn Strandmark
Subject: [lwip-users] RE: [lwip] Porting problems
Date: Thu, 09 Jan 2003 00:35:06 -0000

This is a multi-part message in MIME format.

------=_NextPart_000_0004_01C16926.06A19110
Content-Type: text/plain;
        charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable

Hi Jason,

Been there, done that. We have discovered and corrected that bug in two =
different versions, while porting the lwIP stack to an ARM7 =
microcontroller. Our thesis worker Mikael Caleres has sent the corrected =
file to Adam, but I do not know if it is version controlled yet.

Anyway, the bug is local the mem.c module. I attach the corrected =
version in this mail. Good luck!

Best regards
Bj=F6rn Strandmark

-----Original Message-----
From: address@hidden [mailto:address@hidden Behalf Of Jason
Morgan
Sent: den 9 november 2001 11:51
To: LWIP Mailing List (E-mail)
Subject: [lwip] Porting problems


Hi,

We're still testing our port of lwIP to the C165, only to find what =
could be
a serious bug.

Its in mem.c and regards the assumption that variable storage in memory =
is
in ascending order compared
to the order that the variables are declared within the code.

The Keil compiler 'sorts' the non-automatic variables to conserve memory =
by
fitting storage sizes to fit the segmented
memory, the same is true of many C compilers targeted at micro =
controllers
where memory usage is important.

This means that the lines (circa line 83 in mem.c)

static char ram[MEM_SIZE];
static struct mem ram_end;

And the later comparisons similar to line 116 (approx) of the same code

if(mem !=3D nmem && nmem->used =3D=3D 0 && (char *)nmem !=3D (char =
*)&ram_end)
{
        if(lfree =3D=3D nmem)
        {
                lfree =3D mem;
        }


Are not necessarily going to work successfully.  This assumption is made
elsewhere in mem.c too.....

We can fix mem.c (I think) but we need to know if anybody is aware of =
the
same variable ordering assumption being
made elsewhere in the code so that we can remove it from there too.

We could fudge it be removing the variable ordering from the compiler, =
but
this would be inefficient and non-portable, it
would be better to fix the code properly.



Jason Morgan - Development Engineer
CITEL Technologies Ltd.
Wheatcroft Business Park
Landmere Lane, Edwalton
NOTTINGHAM, NG12 4DG, UK
Tel: +44 (0) 115 940 5444  Ext 204
Direct: +44 (0) 115 931 5104
Fax: +44 (0) 115 940 5664
mailto:address@hidden
WebSite http://www.citel.com

[This message was sent through the lwip discussion list.]

------=_NextPart_000_0004_01C16926.06A19110
Content-Type: application/octet-stream;
        name="mem.c"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
        filename="mem.c"

/*
 * Copyright (c) 2001, Swedish Institute of Computer Science.
 * All rights reserved.=20
 *
 * Redistribution and use in source and binary forms, with or without=20
 * modification, are permitted provided that the following conditions=20
 * are met:=20
 * 1. Redistributions of source code must retain the above copyright=20
 *    notice, this list of conditions and the following disclaimer.=20
 * 2. Redistributions in binary form must reproduce the above copyright=20
 *    notice, this list of conditions and the following disclaimer in =
the=20
 *    documentation and/or other materials provided with the =
distribution.=20
 * 3. Neither the name of the Institute nor the names of its =
contributors=20
 *    may be used to endorse or promote products derived from this =
software=20
 *    without specific prior written permission.=20
 *
 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' =
AND=20
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE =

 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR =
PURPOSE=20
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE =
LIABLE=20
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR =
CONSEQUENTIAL=20
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE =
GOODS=20
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) =

 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, =
STRICT=20
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY =
WAY=20
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY =
OF=20
 * SUCH DAMAGE.=20
 *
 * This file is part of the lwIP TCP/IP stack.
 *=20
 * Author: Adam Dunkels <address@hidden>
 *
 * $Id: mem.c,v 1.38 2001/10/07 01:59:46 adam Exp $
 */

/*-----------------------------------------------------------------------=
------------*/
/* mem.c
 *
 * Memory manager.
 *
 */
/*-----------------------------------------------------------------------=
------------*/
#ifdef MEM_PERF

#include <fcntl.h>
#include <unistd.h>

static unsigned long start_time;
static int memfile =3D 0;
static void mem_perf_output(void);
static int mem_perf_started =3D 0;

#endif /* MEM_PERF */

#include "lwip/debug.h"

#include "lwip/arch.h"
#include "lwip/opt.h"
#include "lwip/def.h"
#include "lwip/mem.h"

#include "lwip/sys.h"

#include "lwip/stats.h"

#if MEM_RECLAIM

struct mem_reclaim_ {
  struct mem_reclaim_ *next;
  mem_reclaim_func f;
  void *data; =20
};
#endif /* MEM_RECLAIM */

struct mem {
  mem_size_t next, prev;
  u8_t used;
#if MEM_ALIGNMENT =3D=3D 2
  u8_t dummy;
#endif /* MEM_ALIGNEMNT =3D=3D 2 */
};

// JN
//static char ram[MEM_SIZE];
//static struct mem ram_end;

static char ram[MEM_SIZE + sizeof(struct mem)];
static struct mem *ram_end =3D (struct mem *) ((char *)ram + MEM_SIZE);

#define MIN_SIZE 12
#define SIZEOF_STRUCT_MEM (sizeof(struct mem) + \
                          (((sizeof(struct mem) % MEM_ALIGNMENT) =3D=3D =
0)? 0 : \
                          (4 - (sizeof(struct mem) % MEM_ALIGNMENT))))


static struct mem *lfree;   /* pointer to the lowest free block */

#if MEM_RECLAIM
static struct mem_reclaim_ *mrlist;
#endif /* MEM_RECLAIM */

static sys_sem_t mem_sem;

/*-----------------------------------------------------------------------=
------------*/
static void
plug_holes(struct mem *mem)
{
  struct mem *nmem;
  struct mem *pmem;

  ASSERT("plug_holes: mem >=3D ram", (char *)mem >=3D ram);
  // JN
//  ASSERT("plug_holes: mem < ram_end", (char *)mem < (char *)&ram_end);
  ASSERT("plug_holes: mem < ram_end", (char *)mem < (char *)ram_end);
  ASSERT("plug_holes: mem->used =3D=3D 0", mem->used =3D=3D 0);
 =20
  /* plug hole forward */
  ASSERT("plug_holes: mem->next <=3D MEM_SIZE", mem->next <=3D =
MEM_SIZE);
 =20
  nmem =3D (struct mem *)&ram[mem->next];
// JN
  //  if(mem !=3D nmem && nmem->used =3D=3D 0 && (char *)nmem !=3D (char =
*)ram_end) {
  if(mem !=3D nmem && nmem->used =3D=3D 0 && (char *)nmem !=3D (char =
*)ram_end) {

          if(lfree =3D=3D nmem) {
      lfree =3D mem;
    }
    mem->next =3D nmem->next;
    ((struct mem *)&ram[nmem->next])->prev =3D (char *)mem - ram;
  }

  /* plug hole backward */
  pmem =3D (struct mem *)&ram[mem->prev];
  if(pmem !=3D mem && pmem->used =3D=3D 0) {
    if(lfree =3D=3D mem) {
      lfree =3D pmem;
    }
    pmem->next =3D mem->next;
    ((struct mem *)&ram[mem->next])->prev =3D (char *)pmem - ram;
  }

}
/*-----------------------------------------------------------------------=
------------*/
void
mem_init(void)
{
  struct mem *mem;

  bzero(ram, MEM_SIZE);
  mem =3D (struct mem *)ram;
  mem->next =3D MEM_SIZE;
  mem->prev =3D 0;
  mem->used =3D 0;
// JN
//   ram_end.used =3D 1;
//  ram_end.next =3D MEM_SIZE;
//  ram_end.prev =3D MEM_SIZE;
  ram_end->used =3D 1;
  ram_end->next =3D MEM_SIZE;
  ram_end->prev =3D MEM_SIZE;

  mem_sem =3D sys_sem_new(1);

  lfree =3D (struct mem *)ram;

#if MEM_RECLAIM
  mrlist =3D NULL;
#endif /* MEM_RECLAIM */
 =20
#ifdef MEM_STATS
  stats.mem.avail =3D MEM_SIZE;
#endif /* MEM_STATS */
}
/*-----------------------------------------------------------------------=
------------*/
#if MEM_RECLAIM
void
mem_reclaim(unsigned int size)
{
  struct mem_reclaim_ *mr;
  int rec;

  rec =3D 0;
     =20
  for(mr =3D mrlist; mr !=3D NULL; mr =3D mr->next) {
    DEBUGF(MEM_DEBUG, ("mem_malloc: calling reclaimer\n"));
    rec +=3D mr->f(mr->data, size);
  }
#ifdef MEM_STATS
  stats.mem.reclaimed +=3D rec;
#endif /* MEM_STATS */
}
#endif /* MEM_RECLAIM */
/*-----------------------------------------------------------------------=
------------*/
void *
mem_malloc2(mem_size_t size)
{
  void *mem;
  mem =3D mem_malloc(size);
#if MEM_RECLAIM     =20
  if(mem =3D=3D NULL) {
    mem_reclaim(size);   =20
    mem =3D mem_malloc(size);
  }
#endif /* MEM_RECLAIM */
  return mem;
}
/*-----------------------------------------------------------------------=
------------*/
void *
mem_malloc(mem_size_t size)
{
  mem_size_t ptr, ptr2;
  struct mem *mem, *mem2;

  if(size =3D=3D 0) {
    return NULL;
  }

  /* Expand the size of the allocated memory region so that we can
     adjust for alignment. */
  if((size % MEM_ALIGNMENT) !=3D 0) {
    size +=3D MEM_ALIGNMENT - ((size + SIZEOF_STRUCT_MEM) % =
MEM_ALIGNMENT);
  }
 =20
  ASSERT("mem_malloc: size < MEM_SIZE", size < MEM_SIZE);
 =20
  sys_sem_wait(mem_sem);

  for(ptr =3D (char *)lfree - ram; ptr < MEM_SIZE; ptr =3D ((struct mem =
*)&ram[ptr])->next) {
    mem =3D (struct mem *)&ram[ptr];
    if(!mem->used &&
       mem->next - (ptr + SIZEOF_STRUCT_MEM) >=3D size + =
SIZEOF_STRUCT_MEM) {
      ptr2 =3D ptr + SIZEOF_STRUCT_MEM + size;
      mem2 =3D (struct mem *)&ram[ptr2];

      mem2->prev =3D ptr;     =20
      mem2->next =3D mem->next;
      mem->next =3D ptr2;     =20
      if(mem2->next !=3D MEM_SIZE) {
        ((struct mem *)&ram[mem2->next])->prev =3D ptr2;
      }
     =20
      mem2->used =3D 0;     =20
      mem->used =3D 1;
#ifdef MEM_STATS
      stats.mem.used +=3D size;
      if(stats.mem.max < stats.mem.used) {
        stats.mem.max =3D stats.mem.used;
      }
#ifdef MEM_PERF
      mem_perf_output();
#endif /* MEM_PERF */ =20
#endif /* MEM_STATS */

      if(mem =3D=3D lfree) {
        /* Find next free block after mem */
// JN
                  //        while(lfree->used && lfree !=3D &ram_end) {

                  while(lfree->used && lfree !=3D ram_end) {
          lfree =3D (struct mem *)&ram[lfree->next];
        }
        ASSERT("mem_malloc: !lfree->used", !lfree->used);
      }
      sys_sem_signal(mem_sem);
      ASSERT("mem_malloc: allocated memory properly aligned.",
             (unsigned long)((char *)mem + SIZEOF_STRUCT_MEM) % MEM_ALIGNMENT =
=3D=3D 0);
      return (char *)mem + SIZEOF_STRUCT_MEM;
    }   =20
  }
  DEBUGF(MEM_DEBUG, ("mem_malloc: could not allocate %d bytes\n", =
(int)size));
#ifdef MEM_STATS
  stats.mem.err++;
#endif /* MEM_STATS */ =20
  sys_sem_signal(mem_sem);
  return NULL;
}
/*-----------------------------------------------------------------------=
------------*/
void
mem_free(void *rmem)
{
  struct mem *mem;

  if(rmem =3D=3D NULL) {
    return;
  }
 =20
  sys_sem_wait(mem_sem);

// JN
//  ASSERT("mem_free: legal memory", (char *)rmem >=3D (char *)ram &&
//       (char *)rmem < (char *)&ram_end);
 =20
  ASSERT("mem_free: legal memory", (char *)rmem >=3D (char *)ram &&
         (char *)rmem < (char *)ram_end);

// JN =20
//  if((char *)rmem < (char *)ram || (char *)rmem >=3D (char *)&ram_end) =
{
    if((char *)rmem < (char *)ram || (char *)rmem >=3D (char *)ram_end) =
{
    DEBUGF(MEM_DEBUG, ("mem_free: illegal memory\n"));
#ifdef MEM_STATS
    stats.mem.err++;
#endif /* MEM_STATS */
    return;
  }
  mem =3D (struct mem *)((char *)rmem - SIZEOF_STRUCT_MEM);

  ASSERT("mem_free: mem->used", mem->used);
 =20
  mem->used =3D 0;

  if(mem < lfree) {
    lfree =3D mem;
  }
 =20
#ifdef MEM_STATS
  stats.mem.used -=3D mem->next - ((char *)mem - ram) - =
SIZEOF_STRUCT_MEM;
#ifdef MEM_PERF
  mem_perf_output();
#endif /* MEM_PERF */
 =20
#endif /* MEM_STATS */
  plug_holes(mem);
  sys_sem_signal(mem_sem);
}
/*-----------------------------------------------------------------------=
------------*/
void *
mem_reallocm(void *rmem, mem_size_t newsize)
{
  void *nmem;
  nmem =3D mem_malloc(newsize);
  if(nmem =3D=3D NULL) {
    return mem_realloc(rmem, newsize);
  }
  bcopy(rmem, nmem, newsize);
  mem_free(rmem);
  return nmem;
}
/*-----------------------------------------------------------------------=
------------*/
void *
mem_realloc(void *rmem, mem_size_t newsize)
{
  mem_size_t size;
  mem_size_t ptr, ptr2;
  struct mem *mem, *mem2;
 =20
  sys_sem_wait(mem_sem);
 =20
  ASSERT("mem_realloc: legal memory", (char *)rmem >=3D (char *)ram &&
         (char *)rmem < (char *)&ram_end);
 =20
  if((char *)rmem < (char *)ram || (char *)rmem >=3D (char *)&ram_end) {
    DEBUGF(MEM_DEBUG, ("mem_free: illegal memory\n"));
    return rmem;
  }
  mem =3D (struct mem *)((char *)rmem - SIZEOF_STRUCT_MEM);

  ptr =3D (char *)mem - ram;

  size =3D mem->next - ptr - SIZEOF_STRUCT_MEM;
#ifdef MEM_STATS
  stats.mem.used -=3D (size - newsize);
#ifdef MEM_PERF
  mem_perf_output();
#endif /* MEM_PERF */=20
#endif /* MEM_STATS */
 =20
  if(newsize + SIZEOF_STRUCT_MEM + MIN_SIZE < size) {
    ptr2 =3D ptr + SIZEOF_STRUCT_MEM + newsize;
    mem2 =3D (struct mem *)&ram[ptr2];
    mem2->used =3D 0;
    mem2->next =3D mem->next;
    mem2->prev =3D ptr;
    mem->next =3D ptr2;
    if(mem2->next !=3D MEM_SIZE) {
      ((struct mem *)&ram[mem2->next])->prev =3D ptr2;
    }

    plug_holes(mem2);
  }
  sys_sem_signal(mem_sem); =20
  return rmem;
}
/*-----------------------------------------------------------------------=
------------*/
#if MEM_RECLAIM
void
mem_register_reclaim(mem_reclaim_func f, void *data)
{
  struct mem_reclaim_ *mr;

  mr =3D mem_malloc(sizeof(struct mem_reclaim_));
  if(mr =3D=3D NULL) {
    return;
  }
  mr->next =3D mrlist;
  mrlist =3D mr;
  mr->f =3D f;
  mr->data =3D data;
}    =20
#endif /* MEM_RECLAIM */
/*-----------------------------------------------------------------------=
------------*/
#ifdef MEM_PERF
static void
mem_timeout(void *data)
{
  mem_perf_output();
  sys_timeout(1000, mem_timeout, NULL);
}

void
mem_perf_init(char *fname)
{
  start_time =3D sys_now();
 =20
  memfile =3D open(fname, O_WRONLY | O_TRUNC | O_CREAT, 0644);
  if(memfile =3D=3D -1) {
    perror("mem_perf_init: open");
  }
  mem_perf_started =3D 1;
  sys_timeout(1000, mem_timeout, NULL);
}

void
mem_perf_start(void)
{
  if(!mem_perf_started) {
    mem_perf_started =3D 1;
  }
}

static void
mem_perf_output(void)
{
  char buf[1024];
  unsigned long now;
 =20
  if(mem_perf_started && memfile !=3D 0) {
   =20
    now =3D sys_now() - start_time;
    sprintf(buf, "%lu %u\n", now, stats.mem.used);
    write(memfile, buf, strlen(buf));
  } =20
}
#endif /* MEM_PERF */
/*-----------------------------------------------------------------------=
------------*/


------=_NextPart_000_0004_01C16926.06A19110--

[This message was sent through the lwip discussion list.]




reply via email to

[Prev in Thread] Current Thread [Next in Thread]