changeset 176:3902ef905c9c

Merge from eCos master repository on 2001-08-03-06:43:13-BST
author jlarmour
date Fri, 03 Aug 2001 12:27:32 +0000
parents e7780801e1a7
children 4c750ce71ae3
files packages/ChangeLog packages/ecos.db packages/hal/i386/arch/current/ChangeLog packages/hal/i386/arch/current/src/hal_misc.c packages/hal/i386/pcmb/current/ChangeLog packages/hal/i386/pcmb/current/cdl/hal_i386_pcmb.cdl packages/hal/i386/pcmb/current/include/pcmb_io.h packages/hal/mips/arch/current/ChangeLog packages/hal/mips/arch/current/cdl/hal_mips.cdl packages/hal/mips/arch/current/include/hal_intr.h packages/hal/mips/arch/current/src/vectors.S packages/hal/synth/arch/current/ChangeLog packages/hal/synth/arch/current/include/hal_intr.h packages/hal/synth/i386linux/current/ChangeLog packages/hal/synth/i386linux/current/include/arch.inc packages/hal/synth/i386linux/current/include/var_arch.h packages/hal/synth/i386linux/current/src/context.S packages/net/tcpip/current/ChangeLog packages/net/tcpip/current/tests/linux_echo.c packages/net/tcpip/current/tests/nc_test_slave.c packages/net/tcpip/current/tests/server_test.c packages/net/tcpip/current/tests/tcp_echo.c packages/net/tcpip/current/tests/tcp_lo_test.c packages/net/tcpip/current/tests/tcp_sink.c packages/net/tcpip/current/tests/tcp_source.c packages/pkgconf/rules.mak packages/redboot/current/ChangeLog packages/redboot/current/src/fs/disk.c packages/redboot/current/src/fs/ide.c packages/services/memalloc/common/current/ChangeLog packages/services/memalloc/common/current/cdl/memalloc.cdl packages/services/memalloc/common/current/include/sepmeta.hxx packages/services/memalloc/common/current/include/sepmetaimpl.hxx packages/services/memalloc/common/current/include/sepmetaimpl.inl packages/services/memalloc/common/current/src/malloc.cxx packages/services/memalloc/common/current/src/sepmeta.cxx packages/services/memalloc/common/current/tests/sepmeta1.cxx packages/services/memalloc/common/current/tests/sepmeta2.cxx
diffstat 38 files changed, 1878 insertions(+), 113 deletions(-) [+]
line wrap: on
line diff
--- a/packages/ChangeLog
+++ b/packages/ChangeLog
@@ -1,3 +1,8 @@
+2001-07-31  Bart Veer  <bartv@redhat.com>
+
+	* pkgconf/rules.mak:
+	Fix header file dependencies for testcases.
+
 2001-07-30  Jesper Skov  <jskov@redhat.com>
 
 	* ecos.db: Added Dreamcast platform HAL, contributed by Takeshi
--- a/packages/ecos.db
+++ b/packages/ecos.db
@@ -410,7 +410,7 @@ package CYGPKG_IO_SERIAL_ARM_AT91 {
     hardware
     directory	      devs/serial/arm/at91
     script	      ser_arm_at91.cdl	
-    description       "Atmel AT91 evaulation board (EB40) serial drivers."
+    description       "Atmel AT91 evaluation board (EB40) serial drivers."
 }
 
 package CYGPKG_IO_SERIAL_POWERPC_COGENT {
@@ -1167,7 +1167,7 @@ package CYGPKG_HAL_ARM_SA11X0_ASSABET {
 	hardware
         description "
         The ASSABET HAL package provides the support needed to run
-        eCos on a Intel StrongARM SA1110 evaulation board (assabet)."
+        eCos on a Intel StrongARM SA1110 evaluation board (assabet)."
 }
 
 package CYGPKG_HAL_ARM_SA11X0_IPAQ {
@@ -1226,7 +1226,7 @@ package CYGPKG_HAL_ARM_SA11X0_BRUTUS {
 	hardware
         description "
         The BRUTUS HAL package provides the support needed to run
-        eCos on a Intel StrongARM SA1110 evaulation board (brutus)."
+        eCos on a Intel StrongARM SA1110 evaluation board (brutus)."
 }
 
 package CYGPKG_HAL_ARM_SA11X0_SA1100MM {
@@ -1858,7 +1858,7 @@ Evaluator7T board (aka AEB-2)."
 }
 
 target at91 {
-	alias { "Atmel evaulation board (EB40)" eb40 }
+	alias { "Atmel evaluation board (EB40)" eb40 }
 	packages { CYGPKG_HAL_ARM
                    CYGPKG_HAL_ARM_AT91
                    CYGPKG_DEVS_FLASH_AT91
--- a/packages/hal/i386/arch/current/ChangeLog
+++ b/packages/hal/i386/arch/current/ChangeLog
@@ -1,3 +1,7 @@
+2001-07-31  Jonathan Larmour  <jlarmour@redhat.com>
+
+	* src/hal_misc.c: Fix "implicit decl of diag_printf" warning.
+
 2001-07-13  Nick Garnett  <nickg@redhat.com>
 
 	* include/arch.inc:
--- a/packages/hal/i386/arch/current/src/hal_misc.c
+++ b/packages/hal/i386/arch/current/src/hal_misc.c
@@ -46,6 +46,7 @@
 
 #include <cyg/infra/cyg_type.h>
 #include <cyg/infra/cyg_ass.h>
+#include <cyg/infra/diag.h>      // diag_printf
 
 #include <cyg/hal/hal_arch.h>
 
--- a/packages/hal/i386/pcmb/current/ChangeLog
+++ b/packages/hal/i386/pcmb/current/ChangeLog
@@ -1,3 +1,8 @@
+2001-07-31  Mark Salter  <msalter@redhat.com>
+
+	* include/pcmb_io.h: Add IDE I/O macros.
+	* cdl/hal_i386_pcmb.cdl: Now implements CYGINT_HAL_PLF_IF_IDE.
+
 2001-07-18  Jonathan Larmour  <jlarmour@redhat.com>
 
 	* include/pcmb_intr.h: Fill in interrupt table descriptions.
--- a/packages/hal/i386/pcmb/current/cdl/hal_i386_pcmb.cdl
+++ b/packages/hal/i386/pcmb/current/cdl/hal_i386_pcmb.cdl
@@ -59,6 +59,7 @@ cdl_package CYGPKG_HAL_I386_PCMB {
     compile      pcmb_misc.c pcmb_serial.c 
 
     implements   CYGINT_HAL_I386_MEM_REAL_REGION_TOP
+    implements   CYGINT_HAL_PLF_IF_IDE
     
     # Real-time clock/counter specifics
     cdl_component CYGNUM_HAL_RTC_CONSTANTS {
--- a/packages/hal/i386/pcmb/current/include/pcmb_io.h
+++ b/packages/hal/i386/pcmb/current/include/pcmb_io.h
@@ -26,7 +26,7 @@
 //                                                                          
 // The Initial Developer of the Original Code is Red Hat.                   
 // Portions created by Red Hat are                                          
-// Copyright (C) 1998, 1999, 2000 Red Hat, Inc.                             
+// Copyright (C) 1998, 1999, 2000, 2001 Red Hat, Inc.                             
 // All Rights Reserved.                                                     
 // -------------------------------------------                              
 //                                                                          
@@ -193,5 +193,36 @@ CYG_MACRO_END
     PC_WRITE_SCREEN_16( (__pos)+4, __val );
 
 //-----------------------------------------------------------------------------
+// IDE interface macros
+//
+#define HAL_IDE_NUM_CONTROLLERS 2
+
+// Initialize the IDE controller(s).
+#define HAL_IDE_INIT()
+
+#define __PCMB_IDE_PRI_CMD   0x1f0
+#define __PCMB_IDE_PRI_CTL   0x3f4
+#define __PCMB_IDE_SEC_CMD   0x170
+#define __PCMB_IDE_SEC_CTL   0x374
+
+#define __CMD_ADDR(__n) ((__n) ? __PCMB_IDE_SEC_CMD : __PCMB_IDE_PRI_CMD)
+#define __CTL_ADDR(__n) ((__n) ? __PCMB_IDE_SEC_CTL : __PCMB_IDE_PRI_CTL)
+
+#define HAL_IDE_READ_UINT8( __ctlr, __regno, __val )  \
+    HAL_READ_UINT8(__CMD_ADDR(__ctlr) + (__regno), (__val))
+#define HAL_IDE_READ_UINT16( __ctlr, __regno, __val )  \
+    HAL_READ_UINT16(__CMD_ADDR(__ctlr) + (__regno), (__val))
+#define HAL_IDE_READ_ALTSTATUS( __ctlr, __val )  \
+    HAL_READ_UINT16(__CTL_ADDR(__ctlr), (__val))
+
+#define HAL_IDE_WRITE_UINT8( __ctlr, __regno, __val )  \
+    HAL_WRITE_UINT8(__CMD_ADDR(__ctlr) + (__regno), (__val))
+#define HAL_IDE_WRITE_UINT16( __ctlr, __regno, __val )  \
+    HAL_WRITE_UINT16(__CMD_ADDR(__ctlr) + (__regno), (__val))
+#define HAL_IDE_WRITE_CONTROL( __ctlr, __val )  \
+    HAL_WRITE_UINT16(__CTL_ADDR(__ctlr), (__val))
+
+
+//-----------------------------------------------------------------------------
 // end of pcmb_io.h
 #endif // CYGONCE_PCMB_IO_H
--- a/packages/hal/mips/arch/current/ChangeLog
+++ b/packages/hal/mips/arch/current/ChangeLog
@@ -1,3 +1,17 @@
+2001-08-01  Hugo Tyson  <hmt@redhat.com>
+
+	* src/vectors.S (restore_state): (see the change below 2001-07-03)
+	Make the code to keep SR IM bits from the ISR conditional on a CDL
+	interface so that it is selected on a per-platform or variant basis.
+
+	* cdl/hal_mips.cdl (CYGINT_HAL_MIPS_INTERRUPT_RETURN_KEEP_SR_IM):
+	New interface to control conditional code.
+
+	* include/hal_intr.h (HAL_ENABLE_INTERRUPTS): Make this (et al)
+	conditional on CYGHWR_HAL_INTERRUPT_ENABLE_DISABLE_RESTORE_DEFINED
+	so that the variant HAL can define these insead, in the usual
+	manner.
+
 2001-07-20  Jonathan Larmour  <jlarmour@redhat.com>
 
 	* src/redboot_linux_exec.c: Adjust below change by getting baud
--- a/packages/hal/mips/arch/current/cdl/hal_mips.cdl
+++ b/packages/hal/mips/arch/current/cdl/hal_mips.cdl
@@ -115,6 +115,20 @@ cdl_package CYGPKG_HAL_MIPS {
 	been compiled as 32-bit.  Do not use this for real 64-bit code."
     }
 
+    cdl_interface CYGINT_HAL_MIPS_INTERRUPT_RETURN_KEEP_SR_IM {
+	display  "Interrupt return keeps interrupt mask bits in SR"
+	description "
+	On some MIPS variants, the status register (SR) contains a number
+	of interrupt mask bits (IM\[0..7\]).  Default behavior is to restore
+	the whole SR over an interrupt.  This means that if the ISR
+	modifies those bits, the change is lost when the interrupt returns.
+	If this interface is implemented, changes made to the SR IM bits by
+	an ISR will instead be preserved.
+	Variants whose HAL_INTERRUPT_MASK() routines (et al) modify the IM
+	bits in the SR should implement this interface to get the necessary
+	preserving behavior."
+    }
+
     cdl_component CYGPKG_REDBOOT_MIPS_OPTIONS {
         display       "Redboot for MIPS options"
         flavor        none
--- a/packages/hal/mips/arch/current/include/hal_intr.h
+++ b/packages/hal/mips/arch/current/include/hal_intr.h
@@ -208,6 +208,7 @@ typedef cyg_uint32 CYG_INTERRUPT_STATE;
 // Beware of nops in this code. They fill delay slots and avoid CP0 hazards
 // that might otherwise cause following code to run in the wrong state or
 // cause a resource conflict.
+#ifndef CYGHWR_HAL_INTERRUPT_ENABLE_DISABLE_RESTORE_DEFINED
 
 #define HAL_DISABLE_INTERRUPTS(_old_)           \
 {                                               \
@@ -262,6 +263,8 @@ typedef cyg_uint32 CYG_INTERRUPT_STATE;
         );                                      \
 }
 
+#endif // CYGHWR_HAL_INTERRUPT_ENABLE_DISABLE_RESTORE_DEFINED
+
 //--------------------------------------------------------------------------
 // Routine to execute DSRs using separate interrupt stack
 
--- a/packages/hal/mips/arch/current/src/vectors.S
+++ b/packages/hal/mips/arch/current/src/vectors.S
@@ -722,7 +722,8 @@ restore_state:
 #endif
 
 	lw	k1,mipsreg_sr(sp)		# K1 = saved SR
-#ifndef CYG_HAL_MIPS_R3900	
+
+#if 0 < CYGINT_HAL_MIPS_INTERRUPT_RETURN_KEEP_SR_IM
 	# Keep the current settings of the IM[7:0] bits within the status
 	# register.  These may be used as interrupt masks, so if an ISR or
 	# DSR masks interrupts they must be preserved.
@@ -736,7 +737,7 @@ restore_state:
 	nop
 	andi	k0,k0,0xff00			# preserve interrupt set
 	or	k1,k1,k0			# insert into "saved SR"
-#endif
+#endif // 0 < CYGINT_HAL_MIPS_INTERRUPT_RETURN_KEEP_SR_IM
 	lva	k0,mipsreg_pc(sp)		# K0 = return PC
 	lsp	sp,sp				# load SP
 
--- a/packages/hal/synth/arch/current/ChangeLog
+++ b/packages/hal/synth/arch/current/ChangeLog
@@ -1,3 +1,10 @@
+2001-08-02  Bart Veer  <bartv@redhat.com>
+
+	* include/hal_intr.h:
+	Note a subtle interaction between the interrupt handling
+	and the context switch handling, which are in the
+	architectural and variant HAL packages respectively.
+
 2001-04-27  Bart Veer  <bartv@redhat.com>
 
 	* All files
--- a/packages/hal/synth/arch/current/include/hal_intr.h
+++ b/packages/hal/synth/arch/current/include/hal_intr.h
@@ -106,7 +106,10 @@
 // higher priority. There is one exception: the sequence
 // disable_interrupts() followed by restore_interrupts() occurs
 // frequently and is worth some inlining.
-// macro.
+//
+// Note: some of the details such as the existence of a global
+// variable hal_interrupts_enabled are known to the context switch
+// code in the variant HAL.
 typedef cyg_bool_t          CYG_INTERRUPT_STATE;
 externC volatile cyg_bool_t hal_interrupts_enabled;
 externC void                hal_enable_interrupts(void);
--- a/packages/hal/synth/i386linux/current/ChangeLog
+++ b/packages/hal/synth/i386linux/current/ChangeLog
@@ -1,3 +1,12 @@
+2001-08-02  Bart Veer  <bartv@redhat.com>
+
+	* src/context.S, include/arch.inc, include/var_arch.h:
+	Update thread context manipulation code to do the
+	right thing with respect to interrupt state.
+
+	* src/context.S (hal_setjmp):
+	 Fixed bug in hal_setjmp() that corrupted EBX.
+
 2001-04-27  Bart Veer  <bartv@redhat.com>
 
 	* All files
--- a/packages/hal/synth/i386linux/current/include/arch.inc
+++ b/packages/hal/synth/i386linux/current/include/arch.inc
@@ -61,7 +61,8 @@
 	.equ	i386reg_ebx,		12
 	.equ	i386reg_esi,		16
 	.equ	i386reg_edi,		20
-	.equ	i386reg_context_size, 	24
+	.equ	i386reg_interrupts,	24
+	.equ	i386reg_context_size, 	28
 
 #------------------------------------------------------------------------------
 # end of arch.inc
--- a/packages/hal/synth/i386linux/current/include/var_arch.h
+++ b/packages/hal/synth/i386linux/current/include/var_arch.h
@@ -60,6 +60,7 @@ typedef struct
     cyg_uint32  ebx;
     cyg_uint32  esi;
     cyg_uint32  edi;
+    cyg_bool    interrupts;             // Are interrupts enabled for this thread?
 } HAL_SavedRegisters;
 
 
@@ -117,6 +118,7 @@ CYG_MACRO_END
     _regs_->ebp    = (CYG_WORD)(_id_);                                    \
     _regs_->esi    = (CYG_WORD)(_id_);                                    \
     _regs_->edi    = (CYG_WORD)(_id_);                                    \
+    _regs_->interrupts = true;                                            \
     (_sparg_)      = (CYG_ADDRESS) _regs_;                                \
     CYG_MACRO_END
 
--- a/packages/hal/synth/i386linux/current/src/context.S
+++ b/packages/hal/synth/i386linux/current/src/context.S
@@ -78,7 +78,10 @@ name:
 # :     8(%esp) :     address of sp save location of current thread
 #
 # %eax, %ecx, and %edx are ours to abuse.
-        
+
+        .extern hal_interrupts_enabled
+        .extern hal_enable_interrupts
+                        
 FUNC_START(hal_thread_switch_context)
         movl    4(%esp),%eax            # next context ptr
         movl    8(%esp),%edx            # this context ptr
@@ -98,7 +101,11 @@ FUNC_START(hal_thread_switch_context)
         movl    %ebx,i386reg_ebx(%esp)
         movl    %esi,i386reg_esi(%esp)
         movl    %edi,i386reg_edi(%esp)
-        
+
+        # And interrupt state
+        movl    hal_interrupts_enabled,%eax
+        movl    %eax,i386reg_interrupts(%esp)
+                
         # Store the context ptr
         movl    %esp,(%edx)
 
@@ -126,6 +133,21 @@ FUNC_START(hal_thread_load_context)
         movl    i386reg_edi(%eax),%edi
         movl    i386reg_esp(%eax),%esp
 
+        # And see what needs to happen about interrupts
+        movl    i386reg_interrupts(%eax),%eax
+        cmpl    hal_interrupts_enabled,%eax
+        je      interrupts_ok
+
+        # The saved interrupt state differs from the current one.
+        # If interrupts are supposed to be enabled then invoke
+        # hal_enable_interrupts. That can be done as a tail call.
+        # If interrupts are supposed to be disabled then just
+        # update the global variable.
+        cmpl    $0,%eax
+        jne     hal_enable_interrupts
+        movl    %eax,hal_interrupts_enabled
+                
+interrupts_ok:          
         ret
 
 
@@ -157,8 +179,8 @@ FUNC_START(hal_setjmp)
 
         # Stack and PC
         movl    %esp,CYGARC_JMP_BUF_SP*4(%eax)
-        movl    0(%esp),%ebx
-        movl    %ebx,CYGARC_JMP_BUF_PC*4(%eax)
+        movl    0(%esp),%edx
+        movl    %edx,CYGARC_JMP_BUF_PC*4(%eax)
 
         # Return 0
         xor     %eax,%eax
--- a/packages/net/tcpip/current/ChangeLog
+++ b/packages/net/tcpip/current/ChangeLog
@@ -1,3 +1,13 @@
+2001-08-02  Jonathan Larmour  <jlarmour@redhat.com>
+
+	* tests/linux_echo.c (echo_test): Set socket options before bind.
+	* tests/nc_test_slave.c (do_tcp_test): Ditto.
+	* tests/server_test.c (server_test): Ditto.
+	* tests/tcp_echo.c (echo_test): Ditto.
+	* tests/tcp_lo_test.c (server): Ditto.
+	* tests/tcp_sink.c (sink_test): Ditto.
+	* tests/tcp_source.c (source_test): Ditto.
+
 2001-07-27  Jonathan Larmour  <jlarmour@redhat.com>
 
 	* include/sys/select.h: Renamed to....
--- a/packages/net/tcpip/current/tests/linux_echo.c
+++ b/packages/net/tcpip/current/tests/linux_echo.c
@@ -172,6 +172,9 @@ echo_test(void * p)
     if (s_source < 0) {
         pexit("stream socket");
     }
+    if (setsockopt(s_source, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one))) {
+        pexit("setsockopt /source/ SO_REUSEADDR");
+    }
     memset(&local, 0, sizeof(local));
     local.sin_family = AF_INET;
 //    local.sin_len = sizeof(local);
@@ -180,9 +183,6 @@ echo_test(void * p)
     if(bind(s_source, (struct sockaddr *) &local, sizeof(local)) < 0) {
         pexit("bind /source/ error");
     }
-    if (setsockopt(s_source, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one))) {
-        pexit("setsockopt /source/ SO_REUSEADDR");
-    }
     listen(s_source, SOMAXCONN);
 
     s_sink = socket(AF_INET, SOCK_STREAM, 0);
--- a/packages/net/tcpip/current/tests/nc_test_slave.c
+++ b/packages/net/tcpip/current/tests/nc_test_slave.c
@@ -324,15 +324,6 @@ do_tcp_test(int s1, struct nc_request *r
             pexit("datagram socket");
         }
 
-        memset((char *) &test_chan_slave, 0, sizeof(test_chan_slave));
-        test_chan_slave.sin_family = AF_INET;
-        test_chan_slave.sin_addr.s_addr = htonl(INADDR_ANY);
-        test_chan_slave.sin_port = htons(ntohl(req->slave_port));
-    
-        if (bind(s, (struct sockaddr *) &test_chan_slave, sizeof(test_chan_slave)) < 0) {
-            perror("bind");
-            close(s);
-        }
         if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one))) {
             perror("setsockopt SO_REUSEADDR");
             return;
@@ -343,6 +334,15 @@ do_tcp_test(int s1, struct nc_request *r
             return;
         }
 #endif
+        memset((char *) &test_chan_slave, 0, sizeof(test_chan_slave));
+        test_chan_slave.sin_family = AF_INET;
+        test_chan_slave.sin_addr.s_addr = htonl(INADDR_ANY);
+        test_chan_slave.sin_port = htons(ntohl(req->slave_port));
+    
+        if (bind(s, (struct sockaddr *) &test_chan_slave, sizeof(test_chan_slave)) < 0) {
+            perror("bind");
+            close(s);
+        }
         listen(s, SOMAXCONN);
         slave_tcp_port = s;
     }
--- a/packages/net/tcpip/current/tests/server_test.c
+++ b/packages/net/tcpip/current/tests/server_test.c
@@ -90,6 +90,12 @@ server_test(struct bootp *bp)
     if (s < 0) {
         pexit("stream socket");
     }
+    if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one))) {
+        pexit("setsockopt SO_REUSEADDR");
+    }
+    if (setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one))) {
+        pexit("setsockopt SO_REUSEPORT");
+    }
     memset(&local, 0, sizeof(local));
     local.sin_family = AF_INET;
     local.sin_len = sizeof(local);
@@ -98,12 +104,6 @@ server_test(struct bootp *bp)
     if(bind(s, (struct sockaddr *) &local, sizeof(local)) < 0) {
         pexit("bind error");
     }
-    if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one))) {
-        pexit("setsockopt SO_REUSEADDR");
-    }
-    if (setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one))) {
-        pexit("setsockopt SO_REUSEPORT");
-    }
     listen(s, SOMAXCONN);
     while (true) {
         client_len = sizeof(client_addr);
--- a/packages/net/tcpip/current/tests/tcp_echo.c
+++ b/packages/net/tcpip/current/tests/tcp_echo.c
@@ -388,6 +388,12 @@ echo_test(cyg_addrword_t p)
     if (s_source < 0) {
         pexit("stream socket");
     }
+    if (setsockopt(s_source, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one))) {
+        pexit("setsockopt /source/ SO_REUSEADDR");
+    }
+    if (setsockopt(s_source, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one))) {
+        pexit("setsockopt /source/ SO_REUSEPORT");
+    }
     memset(&local, 0, sizeof(local));
     local.sin_family = AF_INET;
     local.sin_len = sizeof(local);
@@ -396,12 +402,6 @@ echo_test(cyg_addrword_t p)
     if(bind(s_source, (struct sockaddr *) &local, sizeof(local)) < 0) {
         pexit("bind /source/ error");
     }
-    if (setsockopt(s_source, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one))) {
-        pexit("setsockopt /source/ SO_REUSEADDR");
-    }
-    if (setsockopt(s_source, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one))) {
-        pexit("setsockopt /source/ SO_REUSEPORT");
-    }
     listen(s_source, SOMAXCONN);
 
     s_sink = socket(AF_INET, SOCK_STREAM, 0);
--- a/packages/net/tcpip/current/tests/tcp_lo_test.c
+++ b/packages/net/tcpip/current/tests/tcp_lo_test.c
@@ -95,6 +95,12 @@ void server(void)
     if (s_source < 0) {
         pexit("stream socket");
     }   
+    if (setsockopt(s_source, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one))) {
+        pexit("setsockopt /source/ SO_REUSEADDR");
+    }
+    if (setsockopt(s_source, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one))) {
+        pexit("setsockopt /source/ SO_REUSEPORT");
+    }
     memset(&local, 0, sizeof(local));
     local.sin_family = AF_INET;
     local.sin_len = sizeof(local);
@@ -103,12 +109,6 @@ void server(void)
     if(bind(s_source, (struct sockaddr *) &local, sizeof(local)) < 0) {
         pexit("bind /source/ error");
     }
-    if (setsockopt(s_source, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one))) {
-        pexit("setsockopt /source/ SO_REUSEADDR");
-    }
-    if (setsockopt(s_source, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one))) {
-        pexit("setsockopt /source/ SO_REUSEPORT");
-    }
     listen(s_source, SOMAXCONN);
    
     e_source = 0; 
--- a/packages/net/tcpip/current/tests/tcp_sink.c
+++ b/packages/net/tcpip/current/tests/tcp_sink.c
@@ -194,6 +194,9 @@ sink_test(char *echo_node)
     if (s_sink < 0) {
         pexit("stream socket");
     }
+    if (setsockopt(s_sink, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one))) {
+        pexit("setsockopt /sink/ SO_REUSEADDR");
+    }
     memset(&local, 0, sizeof(local));
     local.sin_family = AF_INET;
     local.sin_port = INADDR_ANY;
@@ -201,9 +204,6 @@ sink_test(char *echo_node)
     if(bind(s_sink, (struct sockaddr *) &local, sizeof(local)) < 0) {
         pexit("bind /sink/ error");
     }
-    if (setsockopt(s_sink, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one))) {
-        pexit("setsockopt /sink/ SO_REUSEADDR");
-    }
 
     if (connect(s_sink, (struct sockaddr *)&slave, sizeof(slave)) < 0) { 
         pexit("Can't connect to target");
--- a/packages/net/tcpip/current/tests/tcp_source.c
+++ b/packages/net/tcpip/current/tests/tcp_source.c
@@ -196,6 +196,9 @@ source_test(char *echo_node, int load)
     if (s_source < 0) {
         pexit("stream socket");
     }
+    if (setsockopt(s_source, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one))) {
+        pexit("setsockopt /source/ SO_REUSEADDR");
+    }
     memset(&local, 0, sizeof(local));
     local.sin_family = AF_INET;
     local.sin_port = INADDR_ANY;
@@ -203,9 +206,6 @@ source_test(char *echo_node, int load)
     if(bind(s_source, (struct sockaddr *) &local, sizeof(local)) < 0) {
         pexit("bind /source/ error");
     }
-    if (setsockopt(s_source, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one))) {
-        pexit("setsockopt /source/ SO_REUSEADDR");
-    }
 
     if (connect(s_source, (struct sockaddr *)&slave, sizeof(slave)) < 0) { 
         pexit("Can't connect to target");
--- a/packages/pkgconf/rules.mak
+++ b/packages/pkgconf/rules.mak
@@ -23,7 +23,7 @@
 #                                                                          
 # The Initial Developer of the Original Code is Red Hat.                   
 # Portions created by Red Hat are                                          
-# Copyright (C) 1998, 1999, 2000 Red Hat, Inc.                             
+# Copyright (C) 1998, 1999, 2000, 2001 Red Hat, Inc.                             
 # All Rights Reserved.                                                     
 # -------------------------------------------                              
 #                                                                          
@@ -91,7 +91,7 @@ else
 	@mkdir -p $(dir $@)
 endif
 	$(CC) -c $(INCLUDE_PATH) -I$(dir $<) $(CFLAGS) -Wp,-MD,$(@:.d=.tmp) -o $(@:.d=.o) $<
-	@sed -e '/^ *\\/d' -e "s#.*: #$@: #" $(@:.o.d=.tmp) > $@
+	@sed -e '/^ *\\/d' -e "s#.*: #$@: #" $(@:.d=.tmp) > $@
 	@rm $(@:.d=.tmp)
 
 %.d : %.cxx
@@ -101,7 +101,7 @@ else
 	@mkdir -p $(dir $@)
 endif
 	$(CC) -c $(INCLUDE_PATH) -I$(dir $<) $(CFLAGS) -Wp,-MD,$(@:.d=.tmp) -o $(@:.d=.o) $<
-	@sed -e '/^ *\\/d' -e "s#.*: #$@: #" $(@:.o.d=.tmp) > $@
+	@sed -e '/^ *\\/d' -e "s#.*: #$@: #" $(@:.d=.tmp) > $@
 	@rm $(@:.d=.tmp)
 
 %.d : %.S
@@ -111,7 +111,7 @@ else
 	@mkdir -p $(dir $@)
 endif	
 	$(CC) -c $(INCLUDE_PATH) -I$(dir $<) $(CFLAGS) -Wp,-MD,$(@:.d=.tmp) -o $(@:.d=.o) $<
-	@sed -e '/^ *\\/d' -e "s#.*: #$@: #" $(@:.o.d=.tmp) > $@
+	@sed -e '/^ *\\/d' -e "s#.*: #$@: #" $(@:.d=.tmp) > $@
 	@rm $(@:.d=.tmp)
 
 # rule to generate a test executable from object code
--- a/packages/redboot/current/ChangeLog
+++ b/packages/redboot/current/ChangeLog
@@ -1,3 +1,14 @@
+2001-08-01  Mark Salter  <msalter@redhat.com>
+
+	* src/fs/ide.c (ide_reset): Check for bogus status and timeout. Add
+	return value to indicate success.
+	(ide_init): Check ide_reset() return value.
+
+2001-07-31  Mark Salter  <msalter@redhat.com>
+
+	* src/fs/disk.c (find_dos_partitions): Fix extended partitions.
+	* src/fs/ide.c (ide_init): Rework the test for device presence.
+
 2001-07-27  Gary Thomas  <gthomas@redhat.com>
 
 	* src/load.c (load_srec_image, do_load): 
--- a/packages/redboot/current/src/fs/disk.c
+++ b/packages/redboot/current/src/fs/disk.c
@@ -92,24 +92,30 @@ find_dos_partitions(disk_t *d, cyg_uint8
 
 #if CYGNUM_REDBOOT_MAX_PARTITIONS > 4
     {
-	cyg_uint32 buf[SECTOR_SIZE/sizeof(cyg_uint32)];
+	cyg_uint32 buf[SECTOR_SIZE/sizeof(cyg_uint32)], xoffset;
 	cyg_uint16 magic;
-	int j, nextp;
+	int nextp;
 
 	// Go back through and find extended partitions
 	for (i = 0, nextp = 4; i < 4 && nextp < CYGNUM_REDBOOT_MAX_PARTITIONS; i++) {
 	    if (d->partitions[i].systype == SYSTYPE_EXTENDED) {
-		// read partition boot record (same format as mbr)
-		if (DISK_READ(d, d->partitions[i].start_sector, buf, 1) <= 0)
-		    break;
+		// sector offsets in partition tables are relative to start
+		// of extended partition.
+		xoffset = d->partitions[i].start_sector;
+		for ( ; nextp < CYGNUM_REDBOOT_MAX_PARTITIONS; ++nextp) {
 
-		magic = *(cyg_uint16 *)((char *)buf + MBR_MAGIC_OFFSET);
-		if (SWAB_LE16(magic) != MBR_MAGIC)
-		    continue;
+		    // read partition boot record (same format as mbr except
+		    // there should only be 2 entries max: a normal partition
+		    // and another extended partition
+		    if (DISK_READ(d, xoffset, buf, 1) <= 0)
+			break;
 
-		p = (struct mbr_partition *)(buf + MBR_PTABLE_OFFSET);
+		    magic = *(cyg_uint16 *)((char *)buf + MBR_MAGIC_OFFSET);
+		    if (SWAB_LE16(magic) != MBR_MAGIC)
+			break;
 
-		for (j = 0; i < 4 && nextp < CYGNUM_REDBOOT_MAX_PARTITIONS; j++, nextp++) {
+		    p = (struct mbr_partition *)((char *)buf + MBR_PTABLE_OFFSET);
+
 		    // Have to use memcpy because of alignment
 		    memcpy(&tmp, p->start_sect, 4);
 		    s = SWAB_LE32(tmp);
@@ -119,18 +125,28 @@ find_dos_partitions(disk_t *d, cyg_uint8
 		    if (s && n) {
 			++found;
 			d->partitions[nextp].disk = d;
-			d->partitions[nextp].start_sector = s + d->partitions[i].start_sector;
+			d->partitions[nextp].start_sector = s + xoffset;
 			d->partitions[nextp].nr_sectors = n;
 			d->partitions[nextp].systype = p->sys_ind;
 			d->partitions[nextp].bootflag = p->boot_ind;
 		    }
 		    ++p;
+
+		    memcpy(&tmp, p->start_sect, 4);
+		    s = SWAB_LE32(tmp);
+		    memcpy(&tmp, p->nr_sects, 4);
+		    n = SWAB_LE32(tmp);
+
+		    // more extended partitions?
+		    if (p->sys_ind != SYSTYPE_EXTENDED || !s || !n)
+			break;
+
+		    xoffset += s;
 		}
 	    }
 	}
     }
 #endif
-
     return found;
 }
 
--- a/packages/redboot/current/src/fs/ide.c
+++ b/packages/redboot/current/src/fs/ide.c
@@ -81,14 +81,28 @@ static inline int
     return 0;
 }
 
-static void
+static int
 ide_reset(int ctlr)
 {
+    cyg_uint8 status;
+    int delay;
+
     HAL_IDE_WRITE_CONTROL(ctlr, 6);	// polled mode, reset asserted
     CYGACC_CALL_IF_DELAY_US(5000);
     HAL_IDE_WRITE_CONTROL(ctlr, 2);	// polled mode, reset cleared
     CYGACC_CALL_IF_DELAY_US((cyg_uint32)50000);
-    __wait_for_ready(ctlr);
+
+    // wait 30 seconds max for not busy
+    for (delay = 0; delay < 300; ++delay) {
+	CYGACC_CALL_IF_DELAY_US((cyg_uint32)100000);
+	HAL_IDE_READ_UINT8(ctlr, IDE_REG_STATUS, status);
+	// bail out early on bogus status
+	if ((status & (IDE_STAT_BSY|IDE_STAT_DRDY)) == (IDE_STAT_BSY|IDE_STAT_DRDY))
+	    break;
+	if (!(status & IDE_STAT_BSY))
+	    return 1;
+    }
+    return 0;
 }
 
 static int
@@ -98,16 +112,10 @@ ide_ident(int ctlr, int dev, int is_pack
 
     HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_DEVICE, dev << 4);
     HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_COMMAND, is_packet_dev ? 0xA1 : 0xEC);
-
-    if (!__wait_for_drq(ctlr)) {
-	cyg_uint8 status;
+    CYGACC_CALL_IF_DELAY_US((cyg_uint32)50000);
 
-	HAL_IDE_READ_UINT8(ctlr, IDE_REG_STATUS, status);
-
-	printf("%s: NO DRQ for ide%d, device %d. status[%02x]\n",
-	       __FUNCTION__, ctlr, dev, status);
+    if (!__wait_for_drq(ctlr))
 	return 0;
-    }
 
     for (i = 0; i < (SECTOR_SIZE / sizeof(cyg_uint16)); i++, buf++)
 	HAL_IDE_READ_UINT16(ctlr, IDE_REG_DATA, *buf);
@@ -157,14 +165,15 @@ ide_read(struct disk *d,
 static void
 ide_init(void)
 {
-    cyg_uint32 buf[SECTOR_SIZE/sizeof(cyg_uint32)];
-    cyg_uint32 u32;
+    cyg_uint32 buf[SECTOR_SIZE/sizeof(cyg_uint32)], u32;
     cyg_uint16 u16;
-    cyg_uint8  sig[2][4];
+    cyg_uint8 u8;
     int i, j;
     disk_t disk;
     struct ide_priv *priv;
 
+#define DEV_INIT_VAL ((j << 4) | 0xA0)
+
     HAL_IDE_INIT();
 
     CYGACC_CALL_IF_DELAY_US(5);
@@ -173,19 +182,8 @@ ide_init(void)
     for (i = 0; i < HAL_IDE_NUM_CONTROLLERS; i++) {
 
 	// soft reset the devices on this controller
-	ide_reset(i);
-
-	// save off signature values for later
-	HAL_IDE_WRITE_UINT8(i, IDE_REG_DEVICE, (0 << 4));
-	HAL_IDE_READ_UINT8(i, IDE_REG_COUNT,  sig[0][0]);
-	HAL_IDE_READ_UINT8(i, IDE_REG_LBALOW, sig[0][1]);
-	HAL_IDE_READ_UINT8(i, IDE_REG_LBAMID, sig[0][2]);
-	HAL_IDE_READ_UINT8(i, IDE_REG_LBAHI,  sig[0][3]);
-	HAL_IDE_WRITE_UINT8(i, IDE_REG_DEVICE, (1 << 4));
-	HAL_IDE_READ_UINT8(i, IDE_REG_COUNT,  sig[1][0]);
-	HAL_IDE_READ_UINT8(i, IDE_REG_LBALOW, sig[1][1]);
-	HAL_IDE_READ_UINT8(i, IDE_REG_LBAMID, sig[1][2]);
-	HAL_IDE_READ_UINT8(i, IDE_REG_LBAHI,  sig[1][3]);
+	if (!ide_reset(i))
+	    continue;
 
 	// 2 devices per controller
 	for (j = 0; j < 2; j++, priv++) {
@@ -193,23 +191,30 @@ ide_init(void)
 	    priv->controller = i;
 	    priv->drive = j;
 	    priv->flags = 0;
-
-	    if (sig[j][0] != 0x01 || sig[j][1] != 0x01)
-		continue;
-
-	    if (!(sig[j][2] == 0x00 && sig[j][3] == 0x00) &&
-		!(sig[j][2] == 0x14 && sig[j][3] == 0xeb))
+	    
+	    // This is reminiscent of a memory test. We write a value
+	    // to a certain location (device register), then write a
+	    // different value somewhere else so that the first value
+	    // is not hanging on the bus, then we read back the first
+	    // value to see if the write was succesful.
+	    //
+	    HAL_IDE_WRITE_UINT8(i, IDE_REG_DEVICE, DEV_INIT_VAL);
+	    HAL_IDE_WRITE_UINT8(i, IDE_REG_FEATURES, 0);
+	    CYGACC_CALL_IF_DELAY_US(50000);
+	    HAL_IDE_READ_UINT8(i, IDE_REG_DEVICE, u8);
+	    if (u8 != DEV_INIT_VAL)
 		continue;
 
 	    // device present
-
-	    priv->flags = IDE_DEV_PRESENT;
+	    priv->flags |= IDE_DEV_PRESENT;
 
-	    if (sig[j][2] == 0x14 && sig[j][3] == 0xeb)
-		priv->flags |= IDE_DEV_PACKET;
-
-	    if (ide_ident(i, j, priv->flags & IDE_DEV_PACKET, (cyg_uint16 *)buf) <= 0)
-		continue;
+	    if (ide_ident(i, j, 0, (cyg_uint16 *)buf) <= 0) {
+		if (ide_ident(i, j, 1, (cyg_uint16 *)buf) <= 0) {
+		    priv->flags = 0;
+		    continue;  // can't identify device
+		} else
+		    priv->flags |= IDE_DEV_PACKET;
+	    }
     
 	    memset(&disk, 0, sizeof(disk));
 	    disk.funs = &ide_funs;
--- a/packages/services/memalloc/common/current/ChangeLog
+++ b/packages/services/memalloc/common/current/ChangeLog
@@ -1,3 +1,20 @@
+2001-08-01  Jonathan Larmour  <jlarmour@redhat.com>
+
+	* include/sepmetaimpl.inl: Define check_free_memdq and
+	check_alloced_memdq as inlines.
+
+	* cdl/memalloc.cdl: Add new allocator supporting separate metadata,
+	and the associated config options, and build sepmeta.cxx and tests.
+	Build heapgeninc.tcl with macros that work with both gcc2 and gcc3.
+	Ditto for heaps.o.
+	Add CYGBLD_MEMALLOC_MALLOC_EXTERNAL_HEAP_H to allow external entities
+	to define the heap.
+	* src/malloc.cxx: Include CYGBLD_MEMALLOC_MALLOC_EXTERNAL_HEAP_H if
+	defined instead of default heap definition.
+	* include/sepmeta.hxx, include/sepmetaimpl.hxx, include/sepmetaimpl.inl,
+	src/sepmeta.cxx, tests/sepmeta1.cxx, tests/sepmeta2.cxx:
+	New files for seperated metadata allocator.
+
 2001-07-18  Jonathan Larmour  <jlarmour@redhat.com>
 
 	* src/heapgen.tcl: Use constructor priority of CYG_INIT_MEMALLOC
--- a/packages/services/memalloc/common/current/cdl/memalloc.cdl
+++ b/packages/services/memalloc/common/current/cdl/memalloc.cdl
@@ -46,7 +46,8 @@ cdl_package CYGPKG_MEMALLOC {
         dynamic memory allocators, including the ISO standard malloc
         interface. It also contains some sample implementations."
     include_dir   cyg/memalloc
-    compile       dlmalloc.cxx kapi.cxx malloc.cxx memfixed.cxx memvar.cxx
+    compile       dlmalloc.cxx kapi.cxx malloc.cxx memfixed.cxx memvar.cxx \
+                  sepmeta.cxx
 
 # ====================================================================
 
@@ -175,6 +176,26 @@ cdl_package CYGPKG_MEMALLOC {
                     are faster in some circumstances."
            }
         }
+
+        cdl_component CYGPKG_MEMALLOC_ALLOCATOR_SEPMETA {
+            display       "Variable block allocator with separate metadata"
+            flavor        none
+            no_define
+            description   "
+                This component contains configuration options related to the 
+                variable block memory allocator with separate metadata."
+
+            cdl_option CYGSEM_MEMALLOC_ALLOCATOR_SEPMETA_THREADAWARE {
+                display        "Make thread safe"
+                active_if      CYGPKG_KERNEL
+                default_value  1
+                description    "
+                    With this option enabled, this allocator will be
+                    made thread-safe. Additionally allocation functions
+                    are made available that allow a thread to wait
+                    until memory is available."
+            }
+        }
     }
 
     cdl_option CYGFUN_MEMALLOC_KAPI {
@@ -218,9 +239,7 @@ cdl_package CYGPKG_MEMALLOC {
         make -priority 50 {
             heapgeninc.tcl : <PACKAGE>/src/heapgen.cpp
             $(CC) $(CFLAGS) $(INCLUDE_PATH) -Wp,-MD,heapgen.tmp -E $< -o $@
-            @echo $@ ':' $< '\' > $(notdir $@).deps
-            @tail +2 heapgen.tmp >> $(notdir $@).deps
-            @echo >> $(notdir $@).deps
+            @sed -e '/^ *\\/d' -e "s#.*: #$@: #" heapgen.tmp > $(notdir $@).deps
             @rm heapgen.tmp
         }
     
@@ -239,12 +258,21 @@ cdl_package CYGPKG_MEMALLOC {
         make_object {
             heaps.o.d : heaps.cxx
             $(CC) $(CFLAGS) $(INCLUDE_PATH) -Wp,-MD,heaps.tmp -c -o $(OBJECT_PREFIX)_$(notdir $(@:.o.d=.o)) $<
-            @echo $@ ':' $< '\' > $@
-            @tail +2 heaps.tmp >> $@
-            @echo >> $@
+            @sed -e '/^ *\\/d' -e "s#.*: #$@: #" heaps.tmp > $@
             @rm heaps.tmp
         }
 
+        cdl_component CYGBLD_MEMALLOC_MALLOC_EXTERNAL_HEAP_H {
+            display       "Use external heap definition"
+            flavor        booldata
+            default_value 0
+            description   "This option allows other components in the
+                           system to override the default system
+                           provision of heap memory pools. This should
+                           be set to a header which provides the equivalent
+                           definitions to <pkgconf/heaps.hxx>."
+        }
+
         cdl_interface CYGINT_MEMALLOC_MALLOC_ALLOCATORS {
             display       "malloc() allocator implementations"
             requires      { CYGINT_MEMALLOC_MALLOC_ALLOCATORS == 1 }
@@ -343,7 +371,7 @@ cdl_package CYGPKG_MEMALLOC {
             display "Tests"
             flavor  data
             no_define
-            calculated { "tests/dlmalloc1 tests/dlmalloc2 tests/heaptest tests/kmemfix1 tests/kmemvar1 tests/malloc1 tests/malloc2 tests/malloc3 tests/malloc4 tests/memfix1 tests/memfix2 tests/memvar1 tests/memvar2 tests/realloc" }
+            calculated { "tests/dlmalloc1 tests/dlmalloc2 tests/heaptest tests/kmemfix1 tests/kmemvar1 tests/malloc1 tests/malloc2 tests/malloc3 tests/malloc4 tests/memfix1 tests/memfix2 tests/memvar1 tests/memvar2 tests/realloc tests/sepmeta1 tests/sepmeta2" }
             description   "
                 This option specifies the set of tests for this package."
         }
new file mode 100644
--- /dev/null
+++ b/packages/services/memalloc/common/current/include/sepmeta.hxx
@@ -0,0 +1,165 @@
+#ifndef CYGONCE_MEMALLOC_SEPMETA_HXX
+#define CYGONCE_MEMALLOC_SEPMETA_HXX
+
+//==========================================================================
+//
+//      sepmeta.hxx
+//
+//      Variable block memory pool with separate metadata
+//
+//==========================================================================
+//####COPYRIGHTBEGIN####
+//                                                                          
+// -------------------------------------------                              
+// The contents of this file are subject to the Red Hat eCos Public License 
+// Version 1.1 (the "License"); you may not use this file except in         
+// compliance with the License.  You may obtain a copy of the License at    
+// http://www.redhat.com/                                                   
+//                                                                          
+// Software distributed under the License is distributed on an "AS IS"      
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the 
+// License for the specific language governing rights and limitations under 
+// the License.                                                             
+//                                                                          
+// The Original Code is eCos - Embedded Configurable Operating System,      
+// released September 30, 1998.                                             
+//                                                                          
+// The Initial Developer of the Original Code is Red Hat.                   
+// Portions created by Red Hat are                                          
+// Copyright (C) 1998, 1999, 2000, 2001 Red Hat, Inc.
+// All Rights Reserved.                                                     
+// -------------------------------------------                              
+//                                                                          
+//####COPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):    jlarmour
+// Contributors: 
+// Date:         2001-06-28
+// Purpose:      Define Sepmeta class interface
+// Description:  Inline class for constructing a variable block allocator
+//               with separate metadata
+// Usage:        #include <cyg/memalloc/sepmeta.hxx>
+//              
+//
+//####DESCRIPTIONEND####
+//
+//==========================================================================
+
+// CONFIGURATION
+
+#include <pkgconf/memalloc.h>
+#ifdef CYGSEM_MEMALLOC_ALLOCATOR_SEPMETA_THREADAWARE
+# include <pkgconf/system.h>
+# ifdef CYGPKG_KERNEL
+#  include <pkgconf/kernel.h>
+# endif
+#endif
+
+#if 0
+// when used as an implementation for malloc, we need the following
+// to let the system know the name of the class
+#define CYGCLS_MEMALLOC_MALLOC_IMPL Cyg_Mempool_Sepmeta
+#endif
+
+// if the implementation is all that's required, don't output anything else
+#ifndef __MALLOC_IMPL_WANTED
+// INCLUDES
+
+#include <cyg/infra/cyg_type.h>        // types
+#include <cyg/infra/cyg_ass.h>         // assertion macros
+
+#ifdef CYGFUN_KERNEL_THREADS_TIMER
+# include <cyg/kernel/ktypes.h>        // cyg_tick_count
+#endif
+
+#ifdef CYGSEM_MEMALLOC_ALLOCATOR_SEPMETA_THREADAWARE
+# include <cyg/memalloc/mempolt2.hxx>  // kernel safe mempool template
+#endif
+
+#include <cyg/memalloc/sepmetaimpl.hxx>// implementation of this mem pool
+#include <cyg/memalloc/common.hxx>     // Common memory allocator infra
+
+
+// TYPE DEFINITIONS
+
+class Cyg_Mempool_Sepmeta
+{
+protected:
+    // This is a horrible workaround for the fact that C++ doesn't let
+    // you construct mypool explicitly if you have to initialize a struct
+    // to pass as an argument first.
+    struct Cyg_Mempool_Sepmeta_Implementation::constructorargs args;
+
+#ifdef CYGSEM_MEMALLOC_ALLOCATOR_SEPMETA_THREADAWARE
+    Cyg_Mempolt2<Cyg_Mempool_Sepmeta_Implementation> mypool;
+#else
+    Cyg_Mempool_Sepmeta_Implementation mypool;
+#endif
+public:
+    // This API makes concrete a class which implements a thread-safe
+    // kernel-savvy memory pool which manages variable size blocks with
+    // separate metadata.
+
+    // Constructor: gives the base and size of the arena in which memory is
+    // to be carved out, note that management structures are taken from the
+    // same arena.
+    Cyg_Mempool_Sepmeta( cyg_uint8 * /* base */, cyg_int32  /* size */,
+                         cyg_int32 /* alignment */,
+                         cyg_uint8 * /* metabase */,
+                         cyg_uint32 /* metasize */);
+
+    // Destructor
+    ~Cyg_Mempool_Sepmeta();
+
+    // get some memory; wait if none available
+    // if we aren't configured to be thread-aware this is irrelevant
+#ifdef CYGSEM_MEMALLOC_ALLOCATOR_SEPMETA_THREADAWARE
+    cyg_uint8 *
+    alloc( cyg_int32 /* size */ );
+    
+# ifdef CYGFUN_KERNEL_THREADS_TIMER
+    // get some memory with a timeout
+    cyg_uint8 *
+    alloc( cyg_int32 /* size */, cyg_tick_count /* delay_timeout */ );
+# endif
+#endif
+
+    // get some memory, return NULL if none available
+    cyg_uint8 *
+    try_alloc( cyg_int32 /* size */ );
+    
+    // resize existing allocation, if oldsize is non-NULL, previous
+    // allocation size is placed into it. If previous size not available,
+    // it is set to 0. NB previous allocation size may have been rounded up.
+    // Occasionally the allocation can be adjusted *backwards* as well as,
+    // or instead of forwards, therefore the address of the resized
+    // allocation is returned, or NULL if no resizing was possible.
+    // Note that this differs from ::realloc() in that no attempt is
+    // made to call malloc() if resizing is not possible - that is left
+    // to higher layers. The data is copied from old to new though.
+    // The effects of alloc_ptr==NULL or newsize==0 are undefined
+    cyg_uint8 *
+    resize_alloc( cyg_uint8 * /* alloc_ptr */, cyg_int32 /* newsize */,
+                  cyg_int32 * /* oldsize */ =NULL );
+
+    // free the memory back to the pool
+    // returns true on success
+    cyg_bool
+    free( cyg_uint8 * /* ptr */, cyg_int32 /* size */ =0 );
+
+    // Get memory pool status
+    // flags is a bitmask of requested fields to fill in. The flags are
+    // defined in common.hxx
+    void
+    get_status( cyg_mempool_status_flag_t /* flags */,
+                Cyg_Mempool_Status & /* status */ );
+
+    CYGDBG_DEFINE_CHECK_THIS
+};
+
+#endif // ifndef __MALLOC_IMPL_WANTED
+
+#endif // ifndef CYGONCE_MEMALLOC_SEPMETA_HXX
+// EOF sepmeta.hxx
new file mode 100644
--- /dev/null
+++ b/packages/services/memalloc/common/current/include/sepmetaimpl.hxx
@@ -0,0 +1,185 @@
+#ifndef CYGONCE_MEMALLOC_SEPMETAIMPL_HXX
+#define CYGONCE_MEMALLOC_SEPMETAIMPL_HXX
+
+//==========================================================================
+//
+//      sepmetaimpl.hxx
+//
+//      Variable block memory pool with separate metadata class declarations
+//
+//==========================================================================
+//####COPYRIGHTBEGIN####
+//                                                                          
+// -------------------------------------------                              
+// The contents of this file are subject to the Red Hat eCos Public License 
+// Version 1.1 (the "License"); you may not use this file except in         
+// compliance with the License.  You may obtain a copy of the License at    
+// http://www.redhat.com/                                                   
+//                                                                          
+// Software distributed under the License is distributed on an "AS IS"      
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the 
+// License for the specific language governing rights and limitations under 
+// the License.                                                             
+//                                                                          
+// The Original Code is eCos - Embedded Configurable Operating System,      
+// released September 30, 1998.                                             
+//                                                                          
+// The Initial Developer of the Original Code is Red Hat.                   
+// Portions created by Red Hat are                                          
+// Copyright (C) 1998, 1999, 2000, 2001 Red Hat, Inc.
+// All Rights Reserved.                                                     
+// -------------------------------------------                              
+//                                                                          
+//####COPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):    jlarmour
+// Contributors: 
+// Date:         2001-06-28
+// Purpose:      Define Sepmetaimpl class interface
+// Description:  Inline class for constructing a variable block allocator
+//               with separate metadata.
+// Usage:        #include <cyg/memalloc/sepmetaimpl.hxx>
+//              
+//
+//####DESCRIPTIONEND####
+//
+//==========================================================================
+
+
+#include <cyg/infra/cyg_type.h>
+#include <pkgconf/memalloc.h>
+#include <cyg/memalloc/common.hxx>     // Common memory allocator infra
+
+class Cyg_Mempool_Sepmeta_Implementation {
+protected:
+    // these constructors are explicitly disallowed
+    Cyg_Mempool_Sepmeta_Implementation() {};
+//    Cyg_Mempool_Sepmeta_Implementation( Cyg_Mempool_Sepmeta_Implementation &ref )
+//    {};
+    Cyg_Mempool_Sepmeta_Implementation &
+    operator=( Cyg_Mempool_Sepmeta_Implementation &ref )
+    { return ref; };
+
+    struct memdq {
+        struct memdq *prev, *next;       // prev/next alloced/free block
+        struct memdq *memprev, *memnext; // prev/next block in memory
+        cyg_uint8 *mem;           // memory address associated with this block
+    };
+
+    struct memdq allocedhead;   // list of alloced memory
+    struct memdq freehead;      // list of free memory
+    struct memdq memhead;       // initial block on free list
+    struct memdq memend;        // dummy memdq indicating the end
+                                // of memory, as if it were alloced
+    struct memdq *freemetahead; // unused memdq's
+    cyg_uint8  *obase;
+    cyg_int32  osize;
+    cyg_uint8  *metabase;
+    cyg_int32  metasize;
+    cyg_uint8  *bottom;
+    cyg_uint8  *top;
+    cyg_int32  alignment;
+    cyg_int32  freemem;
+
+    // round up addresses according to required alignment of pool
+    cyg_uint8 *
+    alignup( cyg_uint8 *addr );
+            
+    cyg_uint8 *
+    aligndown( cyg_uint8 *addr );
+
+    // round up addresses according to required alignment of metadata
+    cyg_uint8 *
+    alignmetaup( cyg_uint8 *addr );
+
+    cyg_uint8 *
+    alignmetadown( cyg_uint8 *addr );
+
+    // return the alloced dq at mem
+    struct memdq *
+    find_alloced_dq( cyg_uint8 *mem );
+
+    // returns a free dq of at least size, or NULL if none
+    struct memdq *
+    find_free_dq( cyg_int32 size );
+
+    // returns the free dq following mem
+    struct memdq *
+    find_free_dq_slot( cyg_uint8 *mem );
+
+    void
+    insert_free_block( struct memdq *freedq );
+
+    static void
+    copy_data( cyg_uint8 *dst, cyg_uint8 *src, cyg_int32 nbytes );
+
+    void
+    check_free_memdq( struct memdq *dq );
+
+    void
+    check_alloced_memdq( struct memdq *dq );
+
+public:
+    // THIS is the public API of memory pools generally that can have the
+    // kernel oriented thread-safe package layer atop.
+
+    struct constructorargs {
+        cyg_int32 alignment;
+        cyg_uint8 *metabase;
+        cyg_uint32 metasize;
+        constructorargs(cyg_int32 align, cyg_uint8 *mbase, cyg_uint32 msize)
+        {
+            alignment = align; metabase = mbase; metasize = msize;
+        }
+    };
+
+    // Constructor: gives the base and size of the arena in which memory is
+    // to be carved out.
+    Cyg_Mempool_Sepmeta_Implementation(
+        cyg_uint8 *  /* base */,
+        cyg_int32    /* size */,
+        CYG_ADDRWORD /* constructorargs */ );
+
+    // Destructor
+    ~Cyg_Mempool_Sepmeta_Implementation();
+
+    // get size bytes of memory
+    cyg_uint8 *
+    try_alloc( cyg_int32 /* size */ );
+    
+    // resize existing allocation, if oldsize is non-NULL, previous
+    // allocation size is placed into it. If previous size not available,
+    // it is set to 0. NB previous allocation size may have been rounded up.
+    // Occasionally the allocation can be adjusted *backwards* as well as,
+    // or instead of forwards, therefore the address of the resized
+    // allocation is returned, or NULL if no resizing was possible.
+    // Note that this differs from ::realloc() in that no attempt is
+    // made to call malloc() if resizing is not possible - that is left
+    // to higher layers. The data is copied from old to new though.
+    // The effects of alloc_ptr==NULL or newsize==0 are undefined
+    cyg_uint8 *
+    resize_alloc( cyg_uint8 * /* alloc_ptr */, cyg_int32 /* newsize */,
+                  cyg_int32 * /* oldsize */ );
+
+    // free size bytes of memory back to the pool
+    // returns true on success
+    cyg_bool
+    free( cyg_uint8 * /* ptr */,
+          cyg_int32   /* size */ );
+
+    // Get memory pool status
+    // flags is a bitmask of requested fields to fill in. The flags are
+    // defined in common.hxx
+    void
+    get_status( cyg_mempool_status_flag_t /* flags */,
+                Cyg_Mempool_Status & /* status */ );
+    
+};
+
+#include <cyg/memalloc/sepmetaimpl.inl>
+
+// -------------------------------------------------------------------------
+#endif // ifndef CYGONCE_MEMALLOC_SEPMETAIMPL_HXX
+// EOF sepmetaimpl.hxx
new file mode 100644
--- /dev/null
+++ b/packages/services/memalloc/common/current/include/sepmetaimpl.inl
@@ -0,0 +1,657 @@
+#ifndef CYGONCE_MEMALLOC_SEPMETAIMPL_INL
+#define CYGONCE_MEMALLOC_SEPMETAIMPL_INL
+
+//==========================================================================
+//
+//      sepmetaimpl.inl
+//
+//      Variable block memory pool with separate metadata class declarations
+//
+//==========================================================================
+//####COPYRIGHTBEGIN####
+//                                                                          
+// -------------------------------------------                              
+// The contents of this file are subject to the Red Hat eCos Public License 
+// Version 1.1 (the "License"); you may not use this file except in         
+// compliance with the License.  You may obtain a copy of the License at    
+// http://www.redhat.com/                                                   
+//                                                                          
+// Software distributed under the License is distributed on an "AS IS"      
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the 
+// License for the specific language governing rights and limitations under 
+// the License.                                                             
+//                                                                          
+// The Original Code is eCos - Embedded Configurable Operating System,      
+// released September 30, 1998.                                             
+//                                                                          
+// The Initial Developer of the Original Code is Red Hat.                   
+// Portions created by Red Hat are                                          
+// Copyright (C) 1998, 1999, 2000, 2001 Red Hat, Inc.
+// All Rights Reserved.                                                     
+// -------------------------------------------                              
+//                                                                          
+//####COPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):    jlarmour
+// Contributors: hmt
+// Date:         2001-06-28
+// Purpose:      Define Sepmetaimpl class interface
+// Description:  Inline class for constructing a variable block allocator
+//               with separate metadata.
+// Usage:        #include <cyg/memalloc/sepmetaimpl.hxx>
+//
+//
+//####DESCRIPTIONEND####
+//
+//==========================================================================
+
+#include <pkgconf/system.h>
+#ifdef CYGPKG_ISOINFRA
+# include <pkgconf/isoinfra.h>
+#endif
+#include <pkgconf/memalloc.h>
+#include <cyg/memalloc/sepmetaimpl.hxx>
+
+#include <cyg/infra/cyg_ass.h>           // assertion support
+#include <cyg/infra/cyg_trac.h>          // tracing support
+
+// Simple allocator
+
+// The memory block lists are doubly linked lists. One for all alloced
+// blocks, one for all free blocks. There's also a list of unused
+// metadata from the metadata pool.  The head of the
+// list has the same structure but its memnext/memprev fields are zero.
+// Always having at least one item on the list simplifies the alloc and
+// free code.
+#if CYGINT_ISO_STRING_MEMFUNCS
+# include <string.h>
+#endif
+
+inline void
+Cyg_Mempool_Sepmeta_Implementation::copy_data( cyg_uint8 *dst, 
+                                               cyg_uint8 *src, 
+                                               cyg_int32 nbytes )
+{
+#if CYGINT_ISO_STRING_MEMFUNCS
+    memmove( dst, src, nbytes );
+#else
+    if ((src < dst) && (dst < (src + nbytes))) {
+        // Have to copy backwards
+        src += nbytes;
+        dst += nbytes;
+        while (nbytes--) {
+            *--dst = *--src;
+        }
+    } else {
+        while (nbytes--) {
+            *dst++ = *src++;
+        }
+    }
+#endif
+}
+
+inline cyg_uint8 *
+Cyg_Mempool_Sepmeta_Implementation::alignup( cyg_uint8 *addr )
+{
+    return (cyg_uint8 *)((cyg_int32)(addr + alignment-1) & -alignment);
+}
+
+inline cyg_uint8 *
+Cyg_Mempool_Sepmeta_Implementation::aligndown( cyg_uint8 *addr )
+{
+    return (cyg_uint8 *)((cyg_int32)addr & -alignment);
+}
+
+inline cyg_uint8 *
+Cyg_Mempool_Sepmeta_Implementation::alignmetaup( cyg_uint8 *addr )
+{
+    const size_t memdqalign = __alignof__ (struct memdq);
+    return (cyg_uint8 *)((cyg_int32)(addr + memdqalign-1) & -memdqalign);
+}
+
+inline cyg_uint8 *
+Cyg_Mempool_Sepmeta_Implementation::alignmetadown( cyg_uint8 *addr )
+{
+    const size_t memdqalign = __alignof__ (struct memdq);
+    return (cyg_uint8 *)((cyg_int32)addr & -memdqalign);
+}
+
+// return the alloced dq at mem 
+inline struct Cyg_Mempool_Sepmeta_Implementation::memdq *
+Cyg_Mempool_Sepmeta_Implementation::find_alloced_dq( cyg_uint8 *mem )
+{
+    struct memdq *dq=allocedhead.next;
+
+    while (dq->mem != mem ) {
+        CYG_ASSERT( dq->next->prev==dq, "Bad link in dq");
+        CYG_ASSERT( dq->memnext->memprev==dq, "Bad link in mem dq");
+        if (dq->next == &memend) // address not found!
+            return NULL;
+        dq = dq->next;
+    }
+    return dq;
+}
+
+// returns a free dq of at least size, or NULL if none
+inline struct Cyg_Mempool_Sepmeta_Implementation::memdq *
+Cyg_Mempool_Sepmeta_Implementation::find_free_dq( cyg_int32 size )
+{
+    struct memdq *dq = freehead.next;
+
+    while ( (dq->memnext->mem - dq->mem) < size ) {
+        CYG_ASSERT( dq->next->prev==dq, "Bad link in dq");
+        CYG_ASSERT( dq->memnext->memprev==dq, "Bad link in mem dq");
+        if (dq->next == &freehead) { // reached end of list
+            return NULL;
+        }
+        dq = dq->next; // next on free list
+    }
+    return dq;
+}
+
+// returns the free dq following mem
+inline struct Cyg_Mempool_Sepmeta_Implementation::memdq *
+Cyg_Mempool_Sepmeta_Implementation::find_free_dq_slot( cyg_uint8 *mem )
+{
+    struct memdq *dq;
+    for (dq = freehead.next; dq->mem < mem; dq = dq->next) {
+        if ( dq == &freehead ) // wrapped round
+            break;
+    }
+    return dq;
+}
+
+inline void
+Cyg_Mempool_Sepmeta_Implementation::check_free_memdq( struct memdq *dq )
+{
+    if (dq == &freehead)
+        return;
+    CYG_ASSERT(dq->memnext->memprev == dq, "corrupted free dq #1");
+    CYG_ASSERT(dq->next->prev == dq, "corrupted free dq #2");
+    CYG_ASSERT(dq->memprev->memnext == dq, "corrupted free dq #3");
+    CYG_ASSERT(dq->prev->next == dq, "corrupted free dq #4");
+    CYG_ASSERT(dq->memnext->mem > dq->mem, "free dq mem not sorted #1");
+    if (dq->memprev != &memend)
+        CYG_ASSERT(dq->memprev->mem < dq->mem, "free dq mem not sorted #2");
+}
+
+inline void
+Cyg_Mempool_Sepmeta_Implementation::check_alloced_memdq( struct memdq *dq )
+{
+    CYG_ASSERT(dq->memnext->memprev == dq, "corrupted alloced dq #1");
+    CYG_ASSERT(dq->next->prev == dq, "corrupted alloced dq #2");
+    CYG_ASSERT(dq->memprev->memnext == dq, "corrupted alloced dq #3");
+    CYG_ASSERT(dq->prev->next == dq, "corrupted alloced dq #4");
+    if (dq != &memend)
+        CYG_ASSERT(dq->memnext->mem > dq->mem, "alloced dq mem not sorted #1");
+    if (dq->memprev != &memhead)
+        CYG_ASSERT(dq->memprev->mem < dq->mem, "alloced dq mem not sorted #2");
+}
+
+// -------------------------------------------------------------------------
+
+inline void
+Cyg_Mempool_Sepmeta_Implementation::insert_free_block( struct memdq *dq )
+{
+    // scan for correct slot in the sorted free list
+    struct memdq *fdq = find_free_dq_slot( dq->mem );
+
+    CYG_ASSERT(fdq != &freehead ? fdq->mem > dq->mem : 1,
+               "Block address is already in freelist");
+
+    check_free_memdq(fdq);
+
+    if (dq->memnext == fdq) {
+        // we can coalesce these two together
+        // adjust fdq's mem address backwards to include dq
+        fdq->mem = dq->mem;
+        // and remove dq
+        fdq->memprev = dq->memprev;
+        fdq->memprev->memnext = fdq;
+        // Don't need to adjust fdq's next/prev links as it stays in the
+        // same place in the free list
+
+        // dq is now redundant so return to metadata free list
+        dq->next = freemetahead;
+        freemetahead = dq;
+
+        // reset dq
+        dq = fdq;
+    } else {
+        // insert behind fdq
+        dq->next = fdq;
+        dq->prev = fdq->prev;
+        fdq->prev = dq;
+        dq->prev->next = dq;
+    }
+
+    check_free_memdq(dq);
+
+    // maybe also coalesce backwards
+    if (dq->memprev == dq->prev) {
+        // adjust dq's mem address backwards to include dq->prev
+        dq->mem = dq->prev->mem;
+
+        // return dq->prev to metadata free list
+        dq->prev->next = freemetahead;
+        freemetahead = dq->prev;
+
+        // and remove dq->prev from mem list
+        dq->memprev = dq->prev->memprev;
+        dq->memprev->memnext = dq;
+        // and free list
+        dq->prev = dq->prev->prev;
+        dq->prev->next = dq;
+
+        check_free_memdq(dq);
+    }
+}
+
+// -------------------------------------------------------------------------
+#include <cyg/infra/diag.h>
+inline
+Cyg_Mempool_Sepmeta_Implementation::Cyg_Mempool_Sepmeta_Implementation(
+        cyg_uint8 *base,
+        cyg_int32 size,
+        CYG_ADDRWORD consargs)
+{
+    CYG_REPORT_FUNCTION();
+    struct constructorargs *args = (struct constructorargs *)consargs;
+    CYG_CHECK_DATA_PTRC( args );
+
+    alignment = args->alignment;
+
+    CYG_ASSERT( alignment > 0, "Bad alignment" );
+    CYG_ASSERT( 0!=alignment, "alignment is zero" );
+    CYG_ASSERT( 0==(alignment & alignment-1), "alignment not a power of 2" );
+
+    obase=base;
+    osize=size;
+    metabase = args->metabase;
+    metasize = args->metasize;
+
+    // bottom is set to the lowest available address given the alignment. 
+    bottom = alignup( base );
+    cyg_uint8 *metabottom = alignmetaup( metabase );
+
+    // because we split free blocks by allocating memory from the end, not
+    // the beginning, then to preserve alignment, the *top* must also be
+    // aligned
+    top = aligndown( base+size );
+    cyg_uint8 *metatop = metabottom + 
+        sizeof(struct memdq)*(metasize/sizeof(struct memdq));
+    
+    CYG_ASSERT( top > bottom , "heap too small" );
+    CYG_ASSERT( top <= (base+size), "top too large" );
+    CYG_ASSERT( (((cyg_int32)(top)) & alignment-1)==0,
+                "top badly aligned" );
+    CYG_ASSERT( (((cyg_int32)(bottom)) & alignment-1)==0,
+                "bottom badly aligned" );
+
+    CYG_ASSERT( metatop > metabottom , "meta space too small" );
+    CYG_ASSERT( metatop <= (metabase+metasize), "metatop too large" );
+
+    // Initialize list of unused metadata blocks. Only need to do next
+    // pointers - can ignore prev and size
+    struct memdq *fq = freemetahead = (struct memdq *)metabottom;
+    
+    while ((cyg_uint8 *)fq < metatop) {
+        fq->next = fq+1;
+        fq++;
+    }
+
+    CYG_ASSERT((cyg_uint8 *)fq == metatop, "traversed metadata not aligned");
+
+    // set final pointer to NULL;
+    --fq; fq->next = NULL;
+
+    // initialize the free list. memhead is the initial free block occupying
+    // all of free memory.
+    memhead.next = memhead.prev = &freehead;
+    // The mem list is circular for consistency.
+    memhead.memprev = memhead.memnext = &memend;
+    memhead.mem = bottom;
+
+    // initialize block that indicates end of memory. This pretends to
+    // be an allocated block
+    memend.next = memend.prev = &allocedhead;
+    memend.memnext = memend.memprev = &memhead;
+    memend.mem = top;
+
+    // initialize alloced list memdq. memend pretends to be allocated memory
+    // at the end
+    allocedhead.next = allocedhead.prev = &memend;
+    freehead.next = freehead.prev = &memhead;
+    // Since allocedhead and freehead are placeholders, not real blocks,
+    // assign addresses which can't match list searches
+    allocedhead.memnext = allocedhead.memprev = NULL;
+    freehead.memnext = freehead.memprev = NULL;
+    freehead.mem = allocedhead.mem = NULL;
+
+    freemem = top - bottom;
+}
+
+// -------------------------------------------------------------------------
+
+inline
+Cyg_Mempool_Sepmeta_Implementation::~Cyg_Mempool_Sepmeta_Implementation()
+{
+}
+
+// -------------------------------------------------------------------------
+// allocation is mostly simple
+// First we look down the free list for a large enough block
+// If we find a block the right size, we unlink the block from
+//    the free list and return a pointer to it.
+// If we find a larger block, we chop a piece off the end
+//    and return that
+// Otherwise we reach the end of the list and return NULL
+
+inline cyg_uint8 *
+Cyg_Mempool_Sepmeta_Implementation::try_alloc( cyg_int32 size )
+{
+    struct memdq *alloced;
+
+    CYG_REPORT_FUNCTION();
+
+    //  Allow uninitialised (zero sized) heaps because they could exist as a
+    //  quirk of the MLT setup where a dynamically sized heap is at the top of
+    //  memory.
+    if (NULL == bottom || NULL==metabase)
+        return NULL;
+
+    size = (size + alignment - 1) & -alignment;
+
+    struct memdq *dq = find_free_dq( size );
+    if (NULL == dq)
+        return NULL;
+
+    cyg_int32 dqsize = dq->memnext->mem - dq->mem;
+
+    if( size == dqsize ) {
+        // exact fit -- unlink from free list
+        dq->prev->next = dq->next;
+        dq->next->prev = dq->prev;
+
+        // set up this block for insertion into alloced list
+        dq->next = dq->memnext; // since dq was free, dq->memnext must
+                                // be allocated otherwise it would have
+                                // been coalesced
+        dq->prev = dq->next->prev;
+
+        alloced = dq;
+    } else {
+
+        CYG_ASSERT( dqsize > size, "block found is too small");
+
+        // Split into two memdq's, returning the second one
+
+        // first get a memdq
+
+        if ( NULL == freemetahead ) // out of metadata. 
+            return NULL;
+
+        // FIXME: since we don't search all the way for an exact fit
+        // first we may be able to find an exact fit later and therefore
+        // not need more metadata. We don't do this yet though.
+
+        alloced = freemetahead;
+        freemetahead = alloced->next;
+
+        // now set its values
+        alloced->memnext = dq->memnext;
+        alloced->next = dq->memnext; // since dq was free, dq->memnext must
+                                     // be allocated otherwise it would have
+                                     // been coalesced
+        alloced->memprev = dq;
+        alloced->prev = alloced->next->prev;
+
+        alloced->mem = alloced->next->mem - size;
+
+        // now set up dq (the portion that remains a free block)
+        // dq->next and dq->prev are unchanged as we still end up pointing
+        // at the same adjacent free blocks
+        // dq->memprev obviously doesn't change
+        
+        dq->memnext = alloced;
+        
+        // finish inserting into memory block list
+        alloced->memnext->memprev = alloced;
+    alloced->next->prev = alloced->prev->next = alloced;
+
+        check_free_memdq(dq);
+    }
+
+    CYG_ASSERT( bottom <= alloced->mem && alloced->mem <= top,
+                "alloced outside pool" );
+
+    // Insert block into alloced list. 
+    alloced->next->prev = alloced->prev->next = alloced;
+
+    check_alloced_memdq(alloced);
+
+    freemem -=size;
+
+    CYG_ASSERT( ((CYG_ADDRESS)alloced->mem & (alignment-1)) == 0,
+                "returned memory not aligned" );
+    return alloced->mem;
+}
+
+// -------------------------------------------------------------------------
+// resize existing allocation, if oldsize is non-NULL, previous
+// allocation size is placed into it. If previous size not available,
+// it is set to 0. NB previous allocation size may have been rounded up.
+// Occasionally the allocation can be adjusted *backwards* as well as,
+// or instead of forwards, therefore the address of the resized
+// allocation is returned, or NULL if no resizing was possible.
+// Note that this differs from ::realloc() in that no attempt is
+// made to call malloc() if resizing is not possible - that is left
+// to higher layers. The data is copied from old to new though.
+// The effects of alloc_ptr==NULL or newsize==0 are undefined
+
+inline cyg_uint8 *
+Cyg_Mempool_Sepmeta_Implementation::resize_alloc( cyg_uint8 *alloc_ptr,
+                                                   cyg_int32 newsize,
+                                                   cyg_int32 *oldsize )
+{
+    cyg_int32 currsize, origsize;
+
+    CYG_REPORT_FUNCTION();
+    
+    CYG_CHECK_DATA_PTRC( alloc_ptr );
+    if ( NULL != oldsize )
+        CYG_CHECK_DATA_PTRC( oldsize );
+
+    CYG_ASSERT( (bottom <= alloc_ptr) && (alloc_ptr <= top),
+                "alloc_ptr outside pool" );
+    
+    struct memdq *dq=find_alloced_dq( alloc_ptr );
+    CYG_ASSERT( dq != NULL, "passed address not previously alloced");
+    
+    currsize = origsize = dq->memnext->mem - dq->mem;
+    if ( NULL != oldsize )
+        *oldsize = currsize;
+
+    if ( newsize > currsize ) {
+        cyg_int32 nextmemsize=0, prevmemsize=0;
+
+        // see if we can increase the allocation size. Don't change anything
+        // so we don't have to undo it later if it wouldn't fit
+        if ( dq->next != dq->memnext ) { // if not equal, memnext must
+                                         // be on free list
+            nextmemsize = dq->memnext->memnext->mem - dq->memnext->mem;
+        }
+        if ( dq->prev != dq->memprev) { // ditto
+            prevmemsize = dq->mem - dq->memprev->mem;
+        }
+        if (nextmemsize + prevmemsize + currsize < newsize)
+            return NULL; // can't fit it
+
+        // expand forwards
+        if ( nextmemsize != 0 ) {
+            if (nextmemsize <= (newsize - currsize)) { // taking all of it
+                struct memdq *fblk = dq->memnext;
+                
+                // fix up mem list ptrs
+                dq->memnext = fblk->memnext;
+                dq->memnext->memprev=dq;
+                // fix up free list ptrs
+                fblk->next->prev = fblk->prev;
+                fblk->prev->next = fblk->next;
+
+                // return to meta list
+                fblk->next = freemetahead;
+                freemetahead = fblk->next;
+                currsize += nextmemsize;
+            } else { // only needs some
+                dq->memnext->mem += (newsize - currsize);
+                currsize = newsize;
+            }
+        }
+
+        // expand backwards
+        if ( currsize < newsize && prevmemsize != 0 ) {
+            cyg_uint8 *oldmem = dq->mem;
+
+            CYG_ASSERT( prevmemsize >= newsize - currsize,
+                        "miscalculated expansion" );
+            if (prevmemsize == (newsize - currsize)) { // taking all of it
+                struct memdq *fblk = dq->memprev;
+                
+                // fix up mem list ptrs
+                dq->memprev = fblk->memprev;
+                dq->memprev->memnext=dq;
+                dq->mem = fblk->mem;
+                // fix up free list ptrs
+                fblk->next->prev = fblk->prev;
+                fblk->prev->next = fblk->next;
+
+                // return to meta list
+                fblk->next = freemetahead;
+                freemetahead = fblk->next;
+            } else { // only needs some
+                dq->mem -= (newsize - currsize);
+            }
+
+            // move data into place
+            copy_data( dq->mem, oldmem, origsize );
+        }
+    }
+
+    if (newsize < currsize) {
+        // shrink allocation
+
+        // easy if the next block is already a free block
+        if ( dq->memnext != dq->next ) {
+            dq->memnext->mem -= currsize - newsize;
+            CYG_ASSERT( dq->memnext->mem > dq->mem,
+                        "moving next block back corruption" );
+        } else {
+            // if its already allocated we need to create a new free list
+            // entry
+            if (NULL == freemetahead)
+                return NULL;  // can't do it
+
+            struct memdq *fdq = freemetahead;
+            freemetahead = fdq->next;
+
+            fdq->memprev = dq;
+            fdq->memnext = dq->memnext;
+            fdq->mem = dq->mem + newsize;
+            
+            insert_free_block( fdq );
+        }
+    }
+
+    freemem += origsize - newsize;
+
+    return dq->mem;
+} // resize_alloc()
+
+
+// -------------------------------------------------------------------------
+// When no coalescing is done, free is simply a matter of using the
+// freed memory as an element of the free list linking it in at the
+// start. When coalescing, the free list is sorted
+    
+inline cyg_bool
+Cyg_Mempool_Sepmeta_Implementation::free( cyg_uint8 *p, cyg_int32 size )
+{
+    CYG_REPORT_FUNCTION();
+
+    CYG_CHECK_DATA_PTRC( p );
+
+    if (!((bottom <= p) && (p <= top)))
+        return false;
+    
+    struct memdq *dq = find_alloced_dq( p );
+    if (NULL == dq)
+        return false;
+    
+    if (0 == size)
+        size = dq->memnext->mem - dq->mem;
+    else {
+        size = (size + alignment - 1) & -alignment;
+        if( (dq->memnext->mem - dq->mem) != size )
+            return false;
+    }
+    
+    check_alloced_memdq( dq );
+
+    // Remove dq from alloced list
+    dq->prev->next = dq->next;
+    dq->next->prev = dq->prev;
+
+    insert_free_block( dq );
+
+    freemem += size;
+
+    return true;
+}    
+
+// -------------------------------------------------------------------------
+
+inline void
+Cyg_Mempool_Sepmeta_Implementation::get_status(
+    cyg_mempool_status_flag_t flags,
+    Cyg_Mempool_Status &status )
+{
+    CYG_REPORT_FUNCTION();
+
+// as quick or quicker to just set it, rather than test flag first
+    status.arenabase = obase;
+    if ( 0 != (flags & CYG_MEMPOOL_STAT_ARENASIZE) )
+        status.arenasize = top - bottom;
+    if ( 0 != (flags & CYG_MEMPOOL_STAT_TOTALALLOCATED) )
+        status.totalallocated = (top-bottom) - freemem;
+// as quick or quicker to just set it, rather than test flag first
+    status.totalfree = freemem;
+    if ( 0 != (flags & CYG_MEMPOOL_STAT_MAXFREE) ) {
+        struct memdq *dq = &freehead;
+        cyg_int32 mf = 0;
+        
+        do {
+            CYG_ASSERT( dq->next->prev==dq, "Bad link in dq");
+            dq = dq->next;
+            if (dq == &freehead) // wrapped round
+                break;            
+            if(dq->memnext->mem - dq->mem > mf)
+                mf = dq->memnext->mem - dq->mem;
+        } while(1);
+        status.maxfree = mf;
+    }
+// as quick or quicker to just set it, rather than test flag first
+    status.origbase = obase;
+// as quick or quicker to just set it, rather than test flag first
+    status.origsize = osize;
+        
+    CYG_REPORT_RETURN();
+
+} // get_status()
+
+
+// -------------------------------------------------------------------------
+#endif // ifndef CYGONCE_MEMALLOC_SEPMETAIMPL_INL
+// EOF sepmetaimpl.inl
--- a/packages/services/memalloc/common/current/src/malloc.cxx
+++ b/packages/services/memalloc/common/current/src/malloc.cxx
@@ -58,7 +58,11 @@
 #include <cyg/infra/cyg_ass.h>     // Common assertion support
 #include <string.h>                // For memset() and memmove()
 #include <stdlib.h>                // header for this file
-#include <pkgconf/heaps.hxx>       // heap pools information
+#ifdef CYGBLD_MEMALLOC_MALLOC_EXTERNAL_HEAP_H
+# include CYGBLD_MEMALLOC_MALLOC_EXTERNAL_HEAP_H
+#else
+# include <pkgconf/heaps.hxx>       // heap pools information
+#endif
 #include CYGBLD_MEMALLOC_MALLOC_IMPLEMENTATION_HEADER
 
 // STATIC VARIABLES
new file mode 100644
--- /dev/null
+++ b/packages/services/memalloc/common/current/src/sepmeta.cxx
@@ -0,0 +1,175 @@
+//==========================================================================
+//
+//      sepmeta.cxx
+//
+//      Variable block memory pool with separated metadata class declarations
+//
+//==========================================================================
+//####COPYRIGHTBEGIN####
+//                                                                          
+// -------------------------------------------                              
+// The contents of this file are subject to the Red Hat eCos Public License 
+// Version 1.1 (the "License"); you may not use this file except in         
+// compliance with the License.  You may obtain a copy of the License at    
+// http://www.redhat.com/                                                   
+//                                                                          
+// Software distributed under the License is distributed on an "AS IS"      
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the 
+// License for the specific language governing rights and limitations under 
+// the License.                                                             
+//                                                                          
+// The Original Code is eCos - Embedded Configurable Operating System,      
+// released September 30, 1998.                                             
+//                                                                          
+// The Initial Developer of the Original Code is Red Hat.                   
+// Portions created by Red Hat are                                          
+// Copyright (C) 1998, 1999, 2000, 2001 Red Hat, Inc.  
+// All Rights Reserved.                                                     
+// -------------------------------------------                              
+//                                                                          
+//####COPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):    jlarmour
+// Contributors: 
+// Date:         2001-06-28
+// Description: 
+// Usage:        #include <cyg/memalloc/sepmeta.hxx>
+//              
+//
+//####DESCRIPTIONEND####
+//
+//==========================================================================
+
+// CONFIGURATION
+
+#include <pkgconf/memalloc.h>
+#include <pkgconf/system.h>
+#ifdef CYGPKG_KERNEL
+# include <pkgconf/kernel.h>
+#endif
+
+
+// INCLUDES
+
+#include <cyg/infra/cyg_type.h>        // types
+#include <cyg/infra/cyg_ass.h>         // assertion macros
+#include <cyg/infra/cyg_trac.h>        // tracing macros
+
+#ifdef CYGFUN_KERNEL_THREADS_TIMER
+# include <cyg/kernel/ktypes.h>        // cyg_tick_count
+#endif
+
+#ifdef CYGSEM_MEMALLOC_ALLOCATOR_SEPMETA_THREADAWARE
+# include <cyg/memalloc/mempolt2.hxx>   // kernel safe mempool template
+#endif
+
+#include <cyg/memalloc/sepmeta.hxx>
+#include <cyg/memalloc/sepmetaimpl.hxx>// implementation of this mem pool
+#include <cyg/memalloc/common.hxx>     // Common memory allocator infra
+
+// FUNCTIONS
+
+// -------------------------------------------------------------------------
+// debugging/assert function
+
+#ifdef CYGDBG_USE_ASSERTS
+cyg_bool
+Cyg_Mempool_Sepmeta::check_this(cyg_assert_class_zeal zeal) const
+{
+    CYG_REPORT_FUNCTION();
+    // check that we have a non-NULL pointer first
+    if( this == NULL ) return false;
+#ifdef CYGSEM_MEMALLOC_ALLOCATOR_SEPMETA_THREADAWARE
+    return mypool.check_this( zeal );
+#else
+    return true;
+#endif
+}
+#endif
+
+// -------------------------------------------------------------------------
+// Constructor: gives the base and size of the arena in which memory is
+// to be carved out
+Cyg_Mempool_Sepmeta::Cyg_Mempool_Sepmeta(
+    cyg_uint8 *base,
+    cyg_int32 size,
+    cyg_int32 alignment,
+    cyg_uint8 *metabase,
+    cyg_uint32 metasize)
+    : args(alignment, metabase, metasize),
+    mypool( base, size, (CYG_ADDRWORD)&args )
+{
+}
+
+// Destructor
+Cyg_Mempool_Sepmeta::~Cyg_Mempool_Sepmeta()
+{
+}
+
+// -------------------------------------------------------------------------
+// get some memory; wait if none available
+#ifdef CYGSEM_MEMALLOC_ALLOCATOR_SEPMETA_THREADAWARE
+cyg_uint8 *
+Cyg_Mempool_Sepmeta::alloc(cyg_int32 size)
+{
+    return mypool.alloc( size );
+}
+    
+# ifdef CYGFUN_KERNEL_THREADS_TIMER
+// get some memory with a timeout
+cyg_uint8 *
+Cyg_Mempool_Sepmeta::alloc(cyg_int32 size, cyg_tick_count delay_timeout)
+{
+    return mypool.alloc( size , delay_timeout );
+}
+# endif
+#endif
+
+// get some memory, return NULL if none available
+cyg_uint8 *
+Cyg_Mempool_Sepmeta::try_alloc(cyg_int32 size)
+{
+    return mypool.try_alloc( size );
+}
+
+// resize existing allocation, if oldsize is non-NULL, previous
+// allocation size is placed into it. If previous size not available,
+// it is set to 0. NB previous allocation size may have been rounded up.
+// Occasionally the allocation can be adjusted *backwards* as well as,
+// or instead of forwards, therefore the address of the resized
+// allocation is returned, or NULL if no resizing was possible.
+// Note that this differs from ::realloc() in that no attempt is
+// made to call malloc() if resizing is not possible - that is left
+// to higher layers. The data is copied from old to new though.
+// The effects of alloc_ptr==NULL or newsize==0 are undefined
+cyg_uint8 *
+Cyg_Mempool_Sepmeta::resize_alloc( cyg_uint8 *alloc_ptr, cyg_int32 newsize,
+                                    cyg_int32 *oldsize )
+{
+    return mypool.resize_alloc( alloc_ptr, newsize, oldsize );
+}
+
+// free the memory back to the pool
+cyg_bool 
+Cyg_Mempool_Sepmeta::free( cyg_uint8 *p, cyg_int32 size )
+{
+    return mypool.free( p, size );
+}
+
+// Get memory pool status
+void
+Cyg_Mempool_Sepmeta::get_status( cyg_mempool_status_flag_t flags,
+                                  Cyg_Mempool_Status &status )
+{
+    // set to 0 - if there's anything really waiting, it will be set to
+    // 1 later
+    status.waiting = 0;
+
+    return mypool.get_status( flags, status );
+}
+
+// -------------------------------------------------------------------------
+
+// End of sepmeta.cxx
new file mode 100644
--- /dev/null
+++ b/packages/services/memalloc/common/current/tests/sepmeta1.cxx
@@ -0,0 +1,216 @@
+//==========================================================================
+//
+//        sepmeta1.cxx
+//
+//        Variable memory pool with separate metadata test 1
+//
+//==========================================================================
+//####COPYRIGHTBEGIN####
+//                                                                          
+// -------------------------------------------                              
+// The contents of this file are subject to the Red Hat eCos Public License 
+// Version 1.1 (the "License"); you may not use this file except in         
+// compliance with the License.  You may obtain a copy of the License at    
+// http://www.redhat.com/                                                   
+//                                                                          
+// Software distributed under the License is distributed on an "AS IS"      
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the 
+// License for the specific language governing rights and limitations under 
+// the License.                                                             
+//                                                                          
+// The Original Code is eCos - Embedded Configurable Operating System,      
+// released September 30, 1998.                                             
+//                                                                          
+// The Initial Developer of the Original Code is Red Hat.                   
+// Portions created by Red Hat are                                          
+// Copyright (C) 1998, 1999, 2000, 2001 Red Hat, Inc.                    
+// All Rights Reserved.                                                     
+// -------------------------------------------                              
+//                                                                          
+//####COPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):     dsm, jlarmour
+// Contributors:  
+// Date:          2001-06-28
+// Description:   Tests basic variable memory pool functionality
+//####DESCRIPTIONEND####
+
+#include <pkgconf/memalloc.h>
+#include <pkgconf/system.h>
+
+#ifdef CYGPKG_KERNEL
+#include <pkgconf/kernel.h>
+
+#include <cyg/kernel/sched.hxx>        // Cyg_Scheduler::start()
+#include <cyg/kernel/thread.hxx>       // Cyg_Thread
+
+#include <cyg/kernel/sched.inl>
+#include <cyg/kernel/thread.inl>
+
+#include <cyg/kernel/timer.hxx>         // Cyg_Timer
+#include <cyg/kernel/clock.inl>         // Cyg_Clock
+
+#define NTHREADS 2
+#include "testaux.hxx"
+
+#endif
+
+#include <cyg/memalloc/sepmeta.hxx>
+
+#include <cyg/infra/testcase.h>
+
+static const cyg_int32 memsize = 10240;
+static const cyg_int32 metadatasize = 2048;
+
+static cyg_uint8 mem[2][memsize];
+static cyg_uint8 metadata[2][metadatasize];
+
+static Cyg_Mempool_Sepmeta mempool0(mem[0], memsize, 8,
+                                    metadata[0], metadatasize);
+
+static Cyg_Mempool_Sepmeta mempool1(mem[1], memsize, 8,
+                                    metadata[1], metadatasize);
+
+
+static void check_in_mp0(cyg_uint8 *p, cyg_int32 size)
+{
+    CYG_TEST_CHECK(NULL != p,
+                   "Allocation failed");
+    CYG_TEST_CHECK(mem[0] <= p && p+size <= mem[1],
+                   "Block outside memory pool");
+}
+
+
+static void entry0( CYG_ADDRWORD data )
+{
+    cyg_int32 f0,f1,f2,t0;
+    cyg_uint8 *p0, *p1;
+    cyg_int32 most_of_mem=memsize/4*3;
+    Cyg_Mempool_Status stat;
+    
+    mempool0.get_status( CYG_MEMPOOL_STAT_ORIGBASE|
+                         CYG_MEMPOOL_STAT_BLOCKSIZE|
+                         CYG_MEMPOOL_STAT_MAXFREE|
+                         CYG_MEMPOOL_STAT_ORIGSIZE, stat );
+    
+    CYG_TEST_CHECK(mem[0] == stat.origbase, "get_status: base wrong");
+    CYG_TEST_CHECK(memsize == stat.origsize, "get_status: size wrong");
+
+    CYG_TEST_CHECK(0 < stat.maxfree && stat.maxfree <= stat.origsize,
+                   "get_status: maxfree wildly wrong");
+    
+    CYG_TEST_CHECK(-1 == stat.blocksize, "blocksize wrong" );
+
+    mempool0.get_status( CYG_MEMPOOL_STAT_TOTALFREE|
+                         CYG_MEMPOOL_STAT_ARENASIZE, stat );
+    t0 = stat.arenasize;
+    CYG_TEST_CHECK(t0 > 0, "Negative total memory" );
+    f0 = stat.totalfree;
+    CYG_TEST_CHECK(f0 > 0, "Negative free memory" );
+    CYG_TEST_CHECK(t0 <= memsize, "get_totalsize: Too much memory");
+    CYG_TEST_CHECK(f0 <= t0 , "More memory free than possible" );
+
+    mempool0.get_status( CYG_MEMPOOL_STAT_WAITING, stat );
+    CYG_TEST_CHECK( !stat.waiting,
+                    "Thread waiting for memory; there shouldn't be");
+    
+    CYG_TEST_CHECK( NULL == mempool0.try_alloc(memsize+1),
+                    "Managed to allocate too much memory");
+    
+#ifdef CYGSEM_MEMALLOC_ALLOCATOR_SEPMETA_THREADAWARE
+    p0 = mempool0.alloc(most_of_mem);
+#else
+    p0 = mempool0.try_alloc(most_of_mem);
+#endif
+    check_in_mp0(p0, most_of_mem);
+
+    mempool0.get_status( CYG_MEMPOOL_STAT_TOTALFREE, stat );
+    f1 = stat.totalfree;
+    CYG_TEST_CHECK(f1 > 0, "Negative free memory" );
+    CYG_TEST_CHECK(f1 < f0, "Free memory didn't decrease after allocation" );
+
+    CYG_TEST_CHECK( NULL == mempool0.try_alloc(most_of_mem),
+                    "Managed to allocate too much memory");
+    
+    CYG_TEST_CHECK(mempool0.free(p0, most_of_mem), "Couldn't free");
+
+    mempool0.get_status( CYG_MEMPOOL_STAT_TOTALFREE, stat );
+    f2 = stat.totalfree;
+    CYG_TEST_CHECK(f2 > f1, "Free memory didn't increase after free" );
+    
+    // should be able to reallocate now memory is free
+    p0 = mempool0.try_alloc(most_of_mem);
+    check_in_mp0(p0, most_of_mem);
+
+    p1 = mempool0.try_alloc(10);
+    check_in_mp0(p1, 10);
+    
+    CYG_TEST_CHECK(p1+10 <= p0 || p1 >= p0+most_of_mem,
+                   "Ranges of allocated memory overlap");
+
+    CYG_TEST_CHECK(mempool0.free(p0, 0), "Couldn't free");
+    CYG_TEST_CHECK(mempool0.free(p1, 10), "Couldn't free");
+    
+#ifdef CYGSEM_MEMALLOC_ALLOCATOR_SEPMETA_THREADAWARE
+# ifdef CYGFUN_KERNEL_THREADS_TIMER
+    // This shouldn't have to wait
+    p0 = mempool0.alloc(most_of_mem,
+        Cyg_Clock::real_time_clock->current_value() + 100000);
+    check_in_mp0(p0, most_of_mem);
+    p1 = mempool0.alloc(most_of_mem,
+       Cyg_Clock::real_time_clock->current_value() + 2);
+    CYG_TEST_CHECK(NULL == p1, "Timed alloc unexpectedly worked");
+    p1 = mempool0.alloc(10,
+        Cyg_Clock::real_time_clock->current_value() + 2);
+    check_in_mp0(p1, 10);
+    
+    // Expect thread 1 to have run while processing previous timed
+    // allocation.  It should therefore tbe waiting.
+    mempool1.get_status( CYG_MEMPOOL_STAT_WAITING, stat );
+    CYG_TEST_CHECK(stat.waiting, "There should be a thread waiting");
+# endif
+#endif
+    
+    CYG_TEST_PASS_FINISH("Sepmeta memory pool 1 OK");
+}
+
+#ifdef CYGSEM_MEMALLOC_ALLOCATOR_SEPMETA_THREADAWARE
+static void entry1( CYG_ADDRWORD data )
+{
+    mempool1.alloc(memsize+1);
+    CYG_TEST_FAIL("Oversized alloc returned");
+}
+#endif
+
+void sepmeta1_main( void )
+{
+    CYG_TEST_INIT();
+    CYG_TEST_INFO("Starting Seperate metadata pool 1 test");
+
+#ifdef CYGSEM_MEMALLOC_ALLOCATOR_SEPMETA_THREADAWARE
+    new_thread(entry0, 0);
+    new_thread(entry1, 1);
+
+    Cyg_Scheduler::start();
+#elif defined(CYGPKG_KERNEL)
+    new_thread(entry0, 0);
+
+    Cyg_Scheduler::start();
+#else
+    entry0(0);
+#endif
+
+    CYG_TEST_FAIL_FINISH("Not reached");
+}
+
+externC void
+cyg_start( void )
+{ 
+#ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG
+    cyg_hal_invoke_constructors();
+#endif
+    sepmeta1_main();
+}
+// EOF sepmeta1.cxx
new file mode 100644
--- /dev/null
+++ b/packages/services/memalloc/common/current/tests/sepmeta2.cxx
@@ -0,0 +1,153 @@
+//==========================================================================
+//
+//        sepmeta2.cxx
+//
+//        Variable memory pool with separate metadata test 2
+//
+//==========================================================================
+//####COPYRIGHTBEGIN####
+//                                                                          
+// -------------------------------------------                              
+// The contents of this file are subject to the Red Hat eCos Public License 
+// Version 1.1 (the "License"); you may not use this file except in         
+// compliance with the License.  You may obtain a copy of the License at    
+// http://www.redhat.com/                                                   
+//                                                                          
+// Software distributed under the License is distributed on an "AS IS"      
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the 
+// License for the specific language governing rights and limitations under 
+// the License.                                                             
+//                                                                          
+// The Original Code is eCos - Embedded Configurable Operating System,      
+// released September 30, 1998.                                             
+//                                                                          
+// The Initial Developer of the Original Code is Red Hat.                   
+// Portions created by Red Hat are                                          
+// Copyright (C) 1998, 1999, 2000, 2001 Red Hat, Inc.                      
+// All Rights Reserved.                                                     
+// -------------------------------------------                              
+//                                                                          
+//####COPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):     dsm, jlarmour
+// Contributors:  
+// Date:          2001-06-28
+// Description:   test allocation and freeing in variable memory pools
+//####DESCRIPTIONEND####
+
+#include <pkgconf/memalloc.h>
+#include <pkgconf/system.h>
+
+#ifdef CYGPKG_KERNEL
+#include <pkgconf/kernel.h>
+
+#include <cyg/kernel/sched.hxx>         // Cyg_Scheduler::start()
+#include <cyg/kernel/thread.hxx>        // Cyg_Thread
+#include <cyg/kernel/thread.inl>
+#include <cyg/kernel/sema.hxx>
+
+#include <cyg/kernel/sched.inl>
+
+#define NTHREADS 1
+#include "testaux.hxx"
+
+#endif
+
+#include <cyg/memalloc/sepmeta.hxx>
+
+#include <cyg/infra/testcase.h>
+
+static const cyg_int32 memsize = 10240;
+static const cyg_int32 metadatasize = 2048;
+
+static cyg_uint8 mem[memsize];
+static cyg_uint8 metadata[metadatasize];
+
+static Cyg_Mempool_Sepmeta mempool(mem, memsize, 8,
+                                   metadata, metadatasize);
+
+#define NUM_PTRS 16                     // Should be even
+
+static cyg_uint8 *ptr[NUM_PTRS];
+static cyg_int32 size[NUM_PTRS];
+
+// We make a number of passes over a table of pointers which point to
+// blocks of allocated memory.  The block is freed and a new block
+// allocated.  The size and the order of the processing of blocks
+// is varied.
+static void entry( CYG_ADDRWORD data )
+{
+    cyg_uint32 s = 1;
+
+    // The number of passes that can be successfully performed
+    // depends on the fragmentation performance of the memory
+    // allocator.
+    for(cyg_ucount32 passes = 0; passes < 10; passes++) {
+
+
+        // The order which the table is processed varies according to
+        // stepsize.
+        cyg_ucount8 stepsize = (passes*2 + 1) % NUM_PTRS; // odd
+        
+
+        for(cyg_ucount8 c=0, i=0; c < NUM_PTRS; c++) {
+            i = (i+stepsize) % NUM_PTRS;
+            if(ptr[i]) {
+                for(cyg_ucount32 j=size[i];j--;) {
+                    CYG_TEST_CHECK(ptr[i][j]==i, "Memory corrupted");
+                }
+                CYG_TEST_CHECK(mempool.free(ptr[i], size[i]),
+                               "bad free");
+            }
+            s = (s*2 + 17) % 100;  // size always odds therefore non-0
+            ptr[i] = mempool.try_alloc(s);
+            size[i] = s;
+
+            CYG_TEST_CHECK(NULL != ptr[i], "Memory pool not big enough");
+            CYG_TEST_CHECK(mem<=ptr[i] && ptr[i]+s < mem+memsize,
+                           "Allocated region not within pool");
+            
+            // Scribble over memory to check whether region overlaps
+            // with other regions.  The contents of the memory are
+            // checked on freeing.  This also tests that the memory
+            // does not overlap with allocator memory structures.
+            for(cyg_ucount32 j=size[i];j--;) {
+                ptr[i][j]=i;
+            }
+        }
+    }
+    
+    CYG_TEST_PASS_FINISH("Sepmeta memory pool 2 OK");
+}
+
+
+void sepmeta2_main( void )
+{
+    CYG_TEST_INIT();
+    CYG_TEST_INFO("Starting Seperate metadata memory pool 2 test");
+
+    for(cyg_ucount32 i = 0; i<NUM_PTRS; i++) {
+        ptr[i]      = NULL;
+    }
+
+#ifdef CYGPKG_KERNEL
+    new_thread(entry, 0);
+    Cyg_Scheduler::start();
+#else
+    entry(0);
+#endif
+
+    CYG_TEST_FAIL_FINISH("Not reached");
+}
+
+externC void
+cyg_start( void )
+{ 
+#ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG
+    cyg_hal_invoke_constructors();
+#endif
+    sepmeta2_main();
+}
+// EOF sepmeta2.cxx