RE: [uClinux-dev] RE: [UCLINUX] Old kernel, old argument, new (maybe) point(s)

From: Joe deBlaquiere (joe@wirespeed.com)
Date: Thu Jul 20 2000 - 14:21:51 EDT


the pthreads library in glibc works great... and if you want to do your own
thread management, the clone() system call works (FYI : you might make sure
the kernel version you have actually uses the new stack area you pass
in...).

porting pthreads to uc-libc might be somewhat tedious, but still very
possible.

> -----Original Message-----
> From: owner-uclinux-dev@uClinux.org
> [mailto:owner-uclinux-dev@uClinux.org]On Behalf Of David Beckemeyer
> Sent: Thursday, July 20, 2000 12:06 PM
> To: uclinux-dev@uClinux.org
> Subject: Re: [uClinux-dev] RE: [UCLINUX] Old kernel, old argument, new
> (maybe) point(s)
>
>
>
> Nice list.  You list multihread as (2).  Does that mean you believe
> it's on the easier side?  That would be better than fork() IMHO for
> my purposes.
>
>
> On Thu, Jul 20, 2000 at 05:37:58PM +0200, Vadim Lebedev wrote:
> > 1) implement a trivial malloc/free/realloc in libc which
> does not make mmap
> > for each allocation, because mmap allocate stuff in PAGEs
> so you make
> > malloc(12) and you get 1K allocated, very vasteful
>
> I implemented the following hack the other afternoon to solve the
> mekory leak problem I mentioned in a separate message.  Perhaps
> this is something like what you describe, but either way I'd like
> peer review since I'm now using this in my libc (so far so good and
> it did resolve the memory leak for my case).
>
> ----------------------------------------------------------------
> #include <unistd.h>
> #include <sys/mman.h>
> #include <stdio.h>
> #include <stdlib.h>
>
>
> struct memblk
>   {
>     int mb_magic;
>     struct memblk *mb_next;
>     struct memblk *mb_prev;
>     size_t mb_len;
>     struct poolblk *mb_pool;
>   };
>
>
> struct poolblk
>   {
>     struct poolblk *pb_next;
>     struct memblk *pb_freelist;
>   };
>
> static struct poolblk *poollist;
>
> #define POOLSIZE 8*1024
>
> #define MEM_MAGIC_FREE 0x46524545
> #define MEM_MAGIC_USED 0x55534544
>
> static void *
>   real_malloc (size_t len)
> {
>   void *result = mmap ((void *) 0, len, PROT_READ | PROT_WRITE,
> 		       MAP_SHARED | MAP_ANONYMOUS, 0, 0);
>   if (result == (void *) -1)
>     return 0;
>
>   return result;
>
>
> }
>
> /* unlink from the freelist */
> static
>   mb_unlink (struct memblk *mb)
> {
>   if (mb->mb_prev)
>     mb->mb_prev->mb_next = mb->mb_next;
>   else
>     mb->mb_pool->pb_freelist = mb->mb_next;
>   if (mb->mb_next)
>     mb->mb_next->mb_prev = mb->mb_prev;
>   mb->mb_magic = MEM_MAGIC_USED;
> }
>
> /* relink onto the end of the freelist */
> static
>   mb_link (struct memblk *mb)
> {
>   struct memblk *lastmb;
>
>   lastmb = mb->mb_pool->pb_freelist;
>   if (lastmb)
>     {
>       while (lastmb->mb_next)
> 	lastmb = lastmb->mb_next;
>       lastmb->mb_next = mb;
>     }
>   else
>     {
>       mb->mb_pool->pb_freelist = mb;
>     }
>   mb->mb_prev = lastmb;
>   mb->mb_next = 0;
>   mb->mb_magic = MEM_MAGIC_FREE;
> }
>
>
> static char *
>   alloc_memblk (struct memblk *mb, size_t len)
> {
>   size_t newlen;
>   struct memblk *newmb;
>
>   newlen = mb->mb_len - len;
>   if (newlen > 1023)
>     {
>       newmb = (struct memblk *) ((char *) mb + len);
>
>       /* re-link the freelist */
>       *newmb = *mb;
>       if (mb->mb_prev)
> 	mb->mb_prev->mb_next = newmb;
>       else
> 	mb->mb_pool->pb_freelist = newmb;
>       if (mb->mb_next)
> 	mb->mb_next->mb_prev = newmb;
>       newmb->mb_len = newlen;
>       mb->mb_len = len;
>     }
>   else
>     {
>       mb_unlink (mb);
>     }
>   mb->mb_prev = mb->mb_next = 0;
>   return ((char *) ++mb);
> }
>
> #ifdef MEMORY_DEBUG
> show_pools ()
> {
>   struct poolblk *pb;
>   struct memblk *mb;
>
>   printf ("====\n");
>   for (pb = poollist; pb; pb = pb->pb_next)
>     {
>       printf ("Pool %x\n", pb);
>       for (mb = pb->pb_freelist; mb; mb = mb->mb_next)
> 	{
> 	  printf ("  Block: at %x %d bytes\n", mb, mb->mb_len);
> 	}
>     }
>   printf ("~~~~\n");
> }
> #endif
>
> static struct memblk *
>   m_search_pool (size_t len)
> {
>   struct poolblk *pb;
>   struct memblk *mb;
>
>   for (pb = poollist; pb; pb = pb->pb_next)
>     {
>       for (mb = pb->pb_freelist; mb; mb = mb->mb_next)
> 	if (mb->mb_len >= len)
> 	  {
> #ifdef MEMORY_DEBUG
> 	    printf ("found free segment at %x\n", mb);
> #endif
> 	    return (mb);
> 	  }
>     }
>   return ((struct memblk *) 0);
> }
>
> static
>   defrag_heap ()
> {
>   struct poolblk *pb;
>   struct memblk *mb, *mb2, *mbend;
>
> #ifdef MEMORY_DEBUG
>   printf ("Before defrag: ");
>   show_pools ();
> #endif
>
>   for (pb = poollist; pb; pb = pb->pb_next)
>     {
>     mb_again:
>       for (mb = pb->pb_freelist; mb; mb = mb->mb_next)
> 	{
> 	  mbend = (struct memblk *) ((char *) mb + mb->mb_len);
> 	  for (mb2 = pb->pb_freelist; mb2; mb2 = mb2->mb_next)
> 	    {
> 	      if (mb2 == mbend)
> 		{
> 		  /* unlink mb2 */
> 		  mb_unlink (mb2);
> 		  mb->mb_len += mb2->mb_len;
> 		  goto mb_again;
> 		}
> 	    }
> 	}
>     }
>
> #ifdef MEMORY_DEBUG
>   printf ("After defrag: ");
>   show_pools ();
> #endif
> }
>
>
> void *
>   malloc (size_t len)
> {
>   struct poolblk *pb, *newpb;
>   struct memblk *mb;
>   size_t lenadj, poolsz;
>   char *end;
>
>   lenadj = (len + sizeof (struct memblk) + 1023) & ~1023;
> #ifdef MEMORY_DEBUG
>   printf ("searching for segment of %d bytes\n", lenadj);
> #endif
>
>   if (poollist)
>     {
>       mb = m_search_pool (lenadj);
>       if (mb)
> 	return (alloc_memblk (mb, lenadj));
> #ifdef MEMORY_DEBUG
>       printf ("cleaning the heap\n");
> #endif
>       defrag_heap ();
>       mb = m_search_pool (lenadj);
>       if (mb)
> 	return (alloc_memblk (mb, lenadj));
>     }
> #ifdef MEMORY_DEBUG
>   printf ("allocating new pool\n");
> #endif
>   if (lenadj + sizeof (struct poolblk) > POOLSIZE)
>     poolsz = (lenadj + sizeof (struct poolblk) + 1023) & ~1023;
>   else
>     poolsz = POOLSIZE;
>   newpb = (struct poolblk *) real_malloc (poolsz);
>   if (!newpb)
>     return ((char *) 0);
>   if (poollist)
>     {
>       for (pb = poollist; pb->pb_next; pb = pb->pb_next)
> 	;
>       pb->pb_next = newpb;
>     }
>   else
>     {
>       poollist = newpb;
>     }
>   newpb->pb_next = 0;
>   end = (char *) newpb + poolsz;
>   mb = newpb->pb_freelist = (struct memblk *) (newpb + 1);
>   mb->mb_next = 0;
>   mb->mb_prev = 0;
>   mb->mb_pool = newpb;
>   mb->mb_len = end - (char *) mb;
>   mb->mb_magic = MEM_MAGIC_FREE;
> #ifdef MEMORY_DEBUG
>   printf ("newpb=%x\n", newpb);
>   printf ("newpb->pb_freelist=%x\n", newpb->pb_freelist);
>   printf ("newpb->pb_freelist->mb_len=%x\n",
> newpb->pb_freelist->mb_len);
>   show_pools ();
> #endif
>   mb = m_search_pool (lenadj);
>   if (mb)
>     return (alloc_memblk (mb, lenadj));
> #ifdef MEMORY_DEBUG
>   printf ("huh? m_search_pool failed?");
> #endif
>   return ((char *) 0);
> }
>
> void
>   free (void *p)
> {
>   struct memblk *mb;
>
>   mb = (struct memblk *) p;
>   --mb;
>   if (mb->mb_magic != MEM_MAGIC_USED) {
>     assert("attempted to free block with corrupt MAGIC");
>     kill(getpid(), 11);
>   }
>   mb_link (mb);
> }
> This message resent by the uclinux-dev@uclinux.org list
> server http://www.uClinux.org/
>

This message resent by the uclinux-dev@uclinux.org list server http://www.uClinux.org/


This archive was generated by hypermail 2.1.4 : Thu Sep 19 2002 - 13:19:15 EDT