Skip to content

Commit

Permalink
inflate: refactor inflate malloc code
Browse files Browse the repository at this point in the history
Inflate requires some dynamic memory allocation very early in the boot
process and this is provided with a set of four functions:
malloc/free/gzip_mark/gzip_release.

The old inflate code used a mark/release strategy rather than implement
free.  This new version instead keeps a count on the number of outstanding
allocations and when it hits zero, it resets the malloc arena.

This allows removing all the mark and release implementations and unifying
all the malloc/free implementations.

The architecture-dependent code must define two addresses:
 - free_mem_ptr, the address of the beginning of the area in which
   allocations should be made
 - free_mem_end_ptr, the address of the end of the area in which
   allocations should be made. If set to 0, then no check is made on
   the number of allocations, it just grows as much as needed

The architecture-dependent code can also provide an arch_decomp_wdog()
function call.  This function will be called several times during the
decompression process, and allow to notify the watchdog that the system is
still running.  If an architecture provides such a call, then it must
define ARCH_HAS_DECOMP_WDOG so that the generic inflate code calls
arch_decomp_wdog().

Work initially done by Matt Mackall, updated to a recent version of the
kernel and improved by me.

[[email protected]: coding-style fixes]
Signed-off-by: Thomas Petazzoni <[email protected]>
Cc: Matt Mackall <[email protected]>
Cc: Richard Henderson <[email protected]>
Cc: Ivan Kokshaysky <[email protected]>
Cc: Mikael Starvik <[email protected]>
Cc: Jesper Nilsson <[email protected]>
Cc: Haavard Skinnemoen <[email protected]>
Cc: David Howells <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Thomas Gleixner <[email protected]>
Cc: Andi Kleen <[email protected]>
Cc: "H. Peter Anvin" <[email protected]>
Acked-by: Paul Mundt <[email protected]>
Acked-by: Yoshinori Sato <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
tpetazzoni authored and torvalds committed Jul 25, 2008
1 parent ba92a43 commit 2d6ffcc
Show file tree
Hide file tree
Showing 13 changed files with 62 additions and 439 deletions.
39 changes: 2 additions & 37 deletions arch/alpha/boot/misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,6 @@ static unsigned outcnt; /* bytes in output buffer */
static int fill_inbuf(void);
static void flush_window(void);
static void error(char *m);
static void gzip_mark(void **);
static void gzip_release(void **);

static char *input_data;
static int input_data_size;
Expand All @@ -88,51 +86,18 @@ static uch *output_data;
static ulg output_ptr;
static ulg bytes_out;

static void *malloc(int size);
static void free(void *where);
static void error(char *m);
static void gzip_mark(void **);
static void gzip_release(void **);

extern int end;
static ulg free_mem_ptr;
static ulg free_mem_ptr_end;
static ulg free_mem_end_ptr;

#define HEAP_SIZE 0x3000

#include "../../../lib/inflate.c"

static void *malloc(int size)
{
void *p;

if (size <0) error("Malloc error");
if (free_mem_ptr <= 0) error("Memory error");

free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */

p = (void *)free_mem_ptr;
free_mem_ptr += size;

if (free_mem_ptr >= free_mem_ptr_end)
error("Out of memory");
return p;
}

static void free(void *where)
{ /* gzip_mark & gzip_release do the free */
}

static void gzip_mark(void **ptr)
{
*ptr = (void *) free_mem_ptr;
}

static void gzip_release(void **ptr)
{
free_mem_ptr = (long) *ptr;
}

/* ===========================================================================
* Fill the input buffer. This is called only when the buffer is empty
* and at least one byte is really needed.
Expand Down Expand Up @@ -193,7 +158,7 @@ decompress_kernel(void *output_start,

/* FIXME FIXME FIXME */
free_mem_ptr = (ulg)output_start + ksize;
free_mem_ptr_end = (ulg)output_start + ksize + 0x200000;
free_mem_end_ptr = (ulg)output_start + ksize + 0x200000;
/* FIXME FIXME FIXME */

/* put in temp area to reduce initial footprint */
Expand Down
59 changes: 7 additions & 52 deletions arch/arm/boot/compressed/misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -217,8 +217,6 @@ static unsigned outcnt; /* bytes in output buffer */
static int fill_inbuf(void);
static void flush_window(void);
static void error(char *m);
static void gzip_mark(void **);
static void gzip_release(void **);

extern char input_data[];
extern char input_data_end[];
Expand All @@ -227,64 +225,21 @@ static uch *output_data;
static ulg output_ptr;
static ulg bytes_out;

static void *malloc(int size);
static void free(void *where);
static void error(char *m);
static void gzip_mark(void **);
static void gzip_release(void **);

static void putstr(const char *);

extern int end;
static ulg free_mem_ptr;
static ulg free_mem_ptr_end;
static ulg free_mem_end_ptr;

#define HEAP_SIZE 0x3000

#include "../../../../lib/inflate.c"

#ifndef STANDALONE_DEBUG
static void *malloc(int size)
{
void *p;

if (size <0) error("Malloc error");
if (free_mem_ptr <= 0) error("Memory error");

free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */

p = (void *)free_mem_ptr;
free_mem_ptr += size;

if (free_mem_ptr >= free_mem_ptr_end)
error("Out of memory");
return p;
}

static void free(void *where)
{ /* gzip_mark & gzip_release do the free */
}

static void gzip_mark(void **ptr)
{
arch_decomp_wdog();
*ptr = (void *) free_mem_ptr;
}
#ifdef STANDALONE_DEBUG
#define NO_INFLATE_MALLOC
#endif

static void gzip_release(void **ptr)
{
arch_decomp_wdog();
free_mem_ptr = (long) *ptr;
}
#else
static void gzip_mark(void **ptr)
{
}
#define ARCH_HAS_DECOMP_WDOG

static void gzip_release(void **ptr)
{
}
#endif
#include "../../../../lib/inflate.c"

/* ===========================================================================
* Fill the input buffer. This is called only when the buffer is empty
Expand Down Expand Up @@ -348,7 +303,7 @@ decompress_kernel(ulg output_start, ulg free_mem_ptr_p, ulg free_mem_ptr_end_p,
{
output_data = (uch *)output_start; /* Points to kernel start */
free_mem_ptr = free_mem_ptr_p;
free_mem_ptr_end = free_mem_ptr_end_p;
free_mem_end_ptr = free_mem_ptr_end_p;
__machine_arch_type = arch_id;

arch_decomp_setup();
Expand Down
36 changes: 1 addition & 35 deletions arch/cris/arch-v10/boot/compressed/misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -102,50 +102,16 @@ extern char *input_data; /* lives in head.S */
static long bytes_out = 0;
static uch *output_data;
static unsigned long output_ptr = 0;

static void *malloc(int size);
static void free(void *where);
static void gzip_mark(void **);
static void gzip_release(void **);

static void puts(const char *);

/* the "heap" is put directly after the BSS ends, at end */

extern int _end;
static long free_mem_ptr = (long)&_end;
static long free_mem_end_ptr;

#include "../../../../../lib/inflate.c"

static void *malloc(int size)
{
void *p;

if (size < 0)
error("Malloc error");

free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */

p = (void *)free_mem_ptr;
free_mem_ptr += size;

return p;
}

static void free(void *where)
{ /* Don't care */
}

static void gzip_mark(void **ptr)
{
*ptr = (void *) free_mem_ptr;
}

static void gzip_release(void **ptr)
{
free_mem_ptr = (long) *ptr;
}

/* decompressor info and error messages to serial console */

static void
Expand Down
39 changes: 3 additions & 36 deletions arch/cris/arch-v32/boot/compressed/misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,58 +89,25 @@ static unsigned outcnt = 0; /* bytes in output buffer */

static void flush_window(void);
static void error(char *m);
static void gzip_mark(void **);
static void gzip_release(void **);

extern char *input_data; /* lives in head.S */

static long bytes_out = 0;
static long bytes_out;
static uch *output_data;
static unsigned long output_ptr = 0;
static unsigned long output_ptr;

static void *malloc(int size);
static void free(void *where);
static void error(char *m);
static void gzip_mark(void **);
static void gzip_release(void **);

static void puts(const char *);

/* the "heap" is put directly after the BSS ends, at end */

extern int _end;
static long free_mem_ptr = (long)&_end;
static long free_mem_end_ptr;

#include "../../../../../lib/inflate.c"

static void *malloc(int size)
{
void *p;

if (size <0) error("Malloc error");

free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */

p = (void *)free_mem_ptr;
free_mem_ptr += size;

return p;
}

static void free(void *where)
{ /* Don't care */
}

static void gzip_mark(void **ptr)
{
*ptr = (void *) free_mem_ptr;
}

static void gzip_release(void **ptr)
{
free_mem_ptr = (long) *ptr;
}

/* decompressor info and error messages to serial console */

static inline void
Expand Down
38 changes: 0 additions & 38 deletions arch/h8300/boot/compressed/misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,6 @@ static unsigned outcnt = 0; /* bytes in output buffer */
static int fill_inbuf(void);
static void flush_window(void);
static void error(char *m);
static void gzip_mark(void **);
static void gzip_release(void **);

extern char input_data[];
extern int input_len;
Expand All @@ -77,11 +75,7 @@ static long bytes_out = 0;
static uch *output_data;
static unsigned long output_ptr = 0;

static void *malloc(int size);
static void free(void *where);
static void error(char *m);
static void gzip_mark(void **);
static void gzip_release(void **);

int puts(const char *);

Expand All @@ -98,38 +92,6 @@ static unsigned long free_mem_end_ptr;
#define TDR *((volatile unsigned char *)0xffff8b)
#define SSR *((volatile unsigned char *)0xffff8c)

static void *malloc(int size)
{
void *p;

if (size <0) error("Malloc error");
if (free_mem_ptr == 0) error("Memory error");

free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */

p = (void *)free_mem_ptr;
free_mem_ptr += size;

if (free_mem_ptr >= free_mem_end_ptr)
error("Out of memory");

return p;
}

static void free(void *where)
{ /* Don't care */
}

static void gzip_mark(void **ptr)
{
*ptr = (void *) free_mem_ptr;
}

static void gzip_release(void **ptr)
{
free_mem_ptr = (long) *ptr;
}

int puts(const char *s)
{
return 0;
Expand Down
37 changes: 0 additions & 37 deletions arch/m32r/boot/compressed/misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,6 @@ static unsigned outcnt = 0; /* bytes in output buffer */
static int fill_inbuf(void);
static void flush_window(void);
static void error(char *m);
static void gzip_mark(void **);
static void gzip_release(void **);

static unsigned char *input_data;
static int input_len;
Expand All @@ -82,48 +80,13 @@ static unsigned long output_ptr = 0;

#include "m32r_sio.c"

static void *malloc(int size);
static void free(void *where);

static unsigned long free_mem_ptr;
static unsigned long free_mem_end_ptr;

#define HEAP_SIZE 0x10000

#include "../../../../lib/inflate.c"

static void *malloc(int size)
{
void *p;

if (size <0) error("Malloc error");
if (free_mem_ptr == 0) error("Memory error");

free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */

p = (void *)free_mem_ptr;
free_mem_ptr += size;

if (free_mem_ptr >= free_mem_end_ptr)
error("Out of memory");

return p;
}

static void free(void *where)
{ /* Don't care */
}

static void gzip_mark(void **ptr)
{
*ptr = (void *) free_mem_ptr;
}

static void gzip_release(void **ptr)
{
free_mem_ptr = (long) *ptr;
}

void* memset(void* s, int c, size_t n)
{
int i;
Expand Down
Loading

0 comments on commit 2d6ffcc

Please sign in to comment.