From 585191310bb476deb7bdd4214adcc8b1076c9fd4 Mon Sep 17 00:00:00 2001 From: axel Date: Tue, 7 Feb 2006 00:25:02 +1000 Subject: [PATCH] First checkin of transition to using a new hierarchical memory allocator, some of the memory associated with a job is covered darcs-hash:20060206142502-ac50b-ba1c9a4f64ea0f44f65303a125f9ddae5bd31e2f.gz --- Makefile.in | 3 ++- exec.c | 4 +-- halloc.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++++ halloc.h | 18 +++++++++++++ io.c | 6 ++--- io.h | 4 +-- parser.c | 27 ++++++++++--------- proc.c | 21 ++------------- proc.h | 4 ++- 9 files changed, 125 insertions(+), 40 deletions(-) create mode 100644 halloc.c create mode 100644 halloc.h diff --git a/Makefile.in b/Makefile.in index 305519e5f..1c516b220 100644 --- a/Makefile.in +++ b/Makefile.in @@ -65,7 +65,8 @@ COMMON_OBJS := function.o builtin.o common.o complete.o env.o exec.o \ expand.o highlight.o history.o kill.o parser.o proc.o reader.o \ sanity.o tokenizer.o util.o wildcard.o wgetopt.o wutil.o input.o \ output.o intern.o env_universal.o env_universal_common.o \ - input_common.o event.o signal.o io.o translate.o parse_util.o + input_common.o event.o signal.o io.o translate.o parse_util.o \ + halloc.o # builtin_help.h exists, but builtin_help.c is autogenerated COMMON_OBJS_WITH_HEADER := builtin_help.o diff --git a/exec.c b/exec.c index d1abe5909..da3587a46 100644 --- a/exec.c +++ b/exec.c @@ -706,9 +706,9 @@ void exec( job_t *j ) if( block_io ) { if( j->io ) - j->io = io_add( io_duplicate(block_io), j->io ); + j->io = io_add( io_duplicate( j, block_io), j->io ); else - j->io=io_duplicate(block_io); + j->io=io_duplicate( j, block_io); } j->io = io_add( j->io, &pipe_write ); diff --git a/halloc.c b/halloc.c new file mode 100644 index 000000000..4d61601c3 --- /dev/null +++ b/halloc.c @@ -0,0 +1,78 @@ +/** \file halloc.c + A hierarchical memory allocation system +*/ + +#include "config.h" + +#include +#include + +#include "util.h" +#include "common.h" +#include "halloc.h" + +typedef struct halloc +{ + array_list_t children; + long long data[0]; +} + halloc_t; + +static halloc_t *halloc_from_data( void *data ) +{ + return (halloc_t *)(data - sizeof( halloc_t ) ); +} + + +void *halloc( void *context, size_t size ) +{ + halloc_t *res = (halloc_t *)calloc( 1, sizeof(halloc_t) + size ); + if( !res ) + return 0; + + al_init( &res->children ); + + if( context ) + { + halloc_t *parent = halloc_from_data( context ); + al_push( &parent->children, &res->data ); + } + return &res->data; +} + +void halloc_free( void *context ) +{ + halloc_t *me; + if( !context ) + return; + + me = halloc_from_data( context ); + al_foreach( &me->children, (void (*)(const void *))&halloc_free ); + al_destroy( &me->children ); + free(me); +} + +wchar_t *halloc_wcsdup( void *context, const wchar_t *in ) +{ + size_t len=wcslen(in); + wchar_t *out = halloc( context, sizeof( wchar_t)*(len+1)); + if( out == 0 ) + { + die_mem(); + } + + memcpy( out, in, sizeof( wchar_t)*(len+1)); + return out; +} + +wchar_t *halloc_wcsndup( void *context, const wchar_t *in, int c ) +{ + wchar_t *res = halloc( context, sizeof(wchar_t)*(c+1) ); + if( res == 0 ) + { + die_mem(); + } + wcsncpy( res, in, c ); + res[c] = L'\0'; + return res; +} diff --git a/halloc.h b/halloc.h new file mode 100644 index 000000000..a3bea49f0 --- /dev/null +++ b/halloc.h @@ -0,0 +1,18 @@ +/** \file halloc.h + A hierarchical memory allocation system +*/ + +/** + Allocate new memory using specified parent memory context. If \c + context is null, a new root context is created. +*/ +void *halloc( void *context, size_t size ); + +/** + Free memory context and all children. Only root contexts may be + freed explicitly. +*/ +void halloc_free( void *context ); + +wchar_t *halloc_wcsdup( void *context, const wchar_t *str ); +wchar_t *halloc_wcsndup( void *context, const wchar_t *in, int c ); diff --git a/io.c b/io.c index 661f424f6..8da4dad10 100644 --- a/io.c +++ b/io.c @@ -175,14 +175,14 @@ io_data_t *io_remove( io_data_t *list, io_data_t *element ) return list; } -io_data_t *io_duplicate( io_data_t *l ) +io_data_t *io_duplicate( void *context, io_data_t *l ) { io_data_t *res; if( l == 0 ) return 0; - res = malloc( sizeof( io_data_t) ); + res = halloc( context, sizeof( io_data_t) ); if( !res ) { @@ -191,7 +191,7 @@ io_data_t *io_duplicate( io_data_t *l ) } memcpy( res, l, sizeof(io_data_t )); - res->next=io_duplicate( l->next ); + res->next=io_duplicate( context, l->next ); return res; } diff --git a/io.h b/io.h index 7cf3eb659..d52211dfc 100644 --- a/io.h +++ b/io.h @@ -62,9 +62,9 @@ io_data_t *io_add( io_data_t *first_chain, io_data_t *decond_chain ); io_data_t *io_remove( io_data_t *list, io_data_t *element ); /** - Make a copy of the specified chain of redirections + Make a copy of the specified chain of redirections. Uses halloc. */ -io_data_t *io_duplicate( io_data_t *l ); +io_data_t *io_duplicate( void *context, io_data_t *l ); /** Return the last io redirection in ht e chain for the specified file descriptor. diff --git a/parser.c b/parser.c index 08d39281c..6808dc826 100644 --- a/parser.c +++ b/parser.c @@ -38,6 +38,7 @@ The fish parser. Contains functions for parsing code. #include "translate.h" #include "intern.h" #include "parse_util.h" +#include "halloc.h" /** Maximum number of block levels in code. This is not the same as @@ -1376,7 +1377,7 @@ static void parse_job_main_loop( process_t *p, } p->pipe_fd = wcstol( tok_last( tok ), 0, 10 ); p->argv = list_to_char_arr( args ); - p->next = calloc( 1, sizeof( process_t ) ); + p->next = halloc( j, sizeof( process_t ) ); if( p->next == 0 ) { die_mem(); @@ -1464,7 +1465,7 @@ static void parse_job_main_loop( process_t *p, unmatched_wildcard = 1; if( !unmatched ) { - unmatched = wcsdup(tok_last( tok )); + unmatched = halloc_wcsdup( j, tok_last( tok )); unmatched_pos = tok_get_pos( tok ); } @@ -1518,7 +1519,7 @@ static void parse_job_main_loop( process_t *p, break; } - new_io = calloc( 1, sizeof(io_data_t) ); + new_io = halloc( j, sizeof(io_data_t) ); if( !new_io ) die_mem(); @@ -1531,7 +1532,10 @@ static void parse_job_main_loop( process_t *p, { case TOK_STRING: { - target = expand_one( wcsdup( tok_last( tok ) ), 0); + wchar_t *tmp = expand_one( wcsdup( tok_last( tok ) ), 0); + target = halloc_wcsdup( j, tmp ); + free( tmp ); + if( target == 0 && error_code == 0 ) { error( SYNTAX_ERROR, @@ -1602,14 +1606,13 @@ static void parse_job_main_loop( process_t *p, tok_next(tok); } - free(target); } break; } } j->io = io_add( j->io, new_io ); - + } break; @@ -1660,7 +1663,6 @@ static void parse_job_main_loop( process_t *p, } } - free( unmatched ); return; } @@ -2221,8 +2223,7 @@ static void eval_job( tokenizer *tok ) } } - j->first_process = calloc( 1, sizeof( process_t ) ); - + j->first_process = halloc( j, sizeof( process_t ) ); if( parse_job( j->first_process, j, tok ) && j->first_process->argv ) @@ -2235,11 +2236,13 @@ static void eval_job( tokenizer *tok ) if( newline ) stop_pos = mini( stop_pos, newline - tok_string(tok) ); - j->command = wcsndup( tok_string(tok)+start_pos, - stop_pos-start_pos ); + j->command = halloc_wcsndup( j, + tok_string(tok)+start_pos, + stop_pos-start_pos ); } else - j->command = wcsdup( L"" ); + j->command = halloc_wcsdup( j, + L"" ); if( profile ) { diff --git a/proc.c b/proc.c index abfcbeb5e..5769ba142 100644 --- a/proc.c +++ b/proc.c @@ -119,8 +119,6 @@ static void free_process( process_t *p ) if( p==0 ) return; - - free_process( p->next ); free( p->actual_cmd ); if( p->argv != 0 ) @@ -131,7 +129,6 @@ static void free_process( process_t *p ) } free(p->argv ); } - free( p ); } /** @@ -176,21 +173,7 @@ void job_free( job_t * j ) /* Then free ourselves */ free_process( j->first_process); - if( j->command != 0 ) - free( j->command ); - - for( io=j->io; io; io=ionext ) - { - ionext = io->next; -// fwprintf( stderr, L"Kill redirect %d of type %d\n", ionext, io->io_mode ); - if( io->io_mode == IO_FILE ) - { - free( io->param1.filename ); - } - free( io ); - } - - free( j ); + halloc_free( j ); } void proc_destroy() @@ -223,7 +206,7 @@ job_t *job_create() while( job_get( free_id ) != 0 ) free_id++; - res = calloc( 1, sizeof(job_t) ); + res = halloc( 0, sizeof(job_t) ); res->next = first_job; res->job_id = free_id; first_job = res; diff --git a/proc.h b/proc.h index a68253310..4e46b2ae6 100644 --- a/proc.h +++ b/proc.h @@ -247,7 +247,9 @@ int proc_get_last_status(); void job_free( job_t* j ); /** - Create a new job + Create a new job. Job struct is allocated using halloc, so anything + that should be freed with the job can uset it as a halloc context + when allocating. */ job_t *job_create();