From 17d636bbfcc19d8c4b83207202969c471e5deaa6 Mon Sep 17 00:00:00 2001 From: Adrian Pop Date: Fri, 4 Mar 2011 14:40:26 +0000 Subject: [PATCH] - first MetaModelica GC draft, disabled for now - see more in c_runtime/meta_modelica_gc.h - added GC bindings to: Compiler/susan_codegen/SimCode/SimCodeC.tpl, commented out for now - made all structures non-constant to allow marking/unmarking. git-svn-id: https://openmodelica.org/svn/OpenModelica/trunk@8092 f25d12d1-65f4-0310-ae8a-bbce733d8d8e --- Compiler/susan_codegen/SimCode/SimCodeC.tpl | 48 +- c_runtime/Makefile.common | 8 + c_runtime/meta_modelica.c | 27 - c_runtime/meta_modelica.h | 27 +- c_runtime/meta_modelica_gc.c | 571 ++++++++++++++++++++ c_runtime/meta_modelica_gc.h | 121 +++++ c_runtime/meta_modelica_gc_list.c | 286 ++++++++++ c_runtime/meta_modelica_gc_list.h | 85 +++ c_runtime/meta_modelica_gc_pages.c | 84 +++ c_runtime/meta_modelica_gc_pages.h | 56 ++ c_runtime/meta_modelica_gc_roots.c | 84 +++ c_runtime/meta_modelica_gc_roots.h | 70 +++ c_runtime/meta_modelica_gc_stack.c | 87 +++ c_runtime/meta_modelica_gc_stack.h | 68 +++ c_runtime/meta_modelica_gc_stats.c | 49 ++ c_runtime/meta_modelica_gc_stats.h | 66 +++ 16 files changed, 1693 insertions(+), 44 deletions(-) create mode 100644 c_runtime/meta_modelica_gc.c create mode 100644 c_runtime/meta_modelica_gc.h create mode 100644 c_runtime/meta_modelica_gc_list.c create mode 100644 c_runtime/meta_modelica_gc_list.h create mode 100644 c_runtime/meta_modelica_gc_pages.c create mode 100644 c_runtime/meta_modelica_gc_pages.h create mode 100644 c_runtime/meta_modelica_gc_roots.c create mode 100644 c_runtime/meta_modelica_gc_roots.h create mode 100644 c_runtime/meta_modelica_gc_stack.c create mode 100644 c_runtime/meta_modelica_gc_stack.h create mode 100644 c_runtime/meta_modelica_gc_stats.c create mode 100644 c_runtime/meta_modelica_gc_stats.h diff --git a/Compiler/susan_codegen/SimCode/SimCodeC.tpl b/Compiler/susan_codegen/SimCode/SimCodeC.tpl index 5b4c44a6a6e..befd364f882 100644 --- a/Compiler/susan_codegen/SimCode/SimCodeC.tpl +++ b/Compiler/susan_codegen/SimCode/SimCodeC.tpl @@ -3227,6 +3227,16 @@ template functionBody(Function fn, Boolean inFunc) case fn as RECORD_CONSTRUCTOR(__) then functionBodyRecordConstructor(fn) end functionBody; +template addRoots(Variable var) +"template to add the roots, only the meta-types are added!" +::= + match var + case var as VARIABLE(__) then + match ty + case ET_METATYPE(__) + case ET_BOXED(__) then 'mmc_GC_add_root(<%contextCref(var.name,contextFunction)%>);' + end match +end addRoots; template functionBodyRegularFunction(Function fn, Boolean inFunc) "Generates the body for a Modelica/MetaModelica function." @@ -3243,6 +3253,8 @@ case FUNCTION(__) then let _ = (variableDeclarations |> var hasindex i1 from 1 => varInit(var, "", i1, &varDecls /*BUFD*/, &varInits /*BUFC*/) ) + let addRootsInputs = (functionArguments |> var => addRoots(var) ;separator="\n") + let addRootsOutputs = (outVars |> var => addRoots(var) ;separator="\n") let funArgs = (functionArguments |> var => functionArg(var, &varInits) ;separator="\n") let bodyPart = (body |> stmt => funStatement(stmt, &varDecls /*BUFD*/) ;separator="\n") let &outVarInits = buffer "" @@ -3256,6 +3268,11 @@ case FUNCTION(__) then << <%retType%> _<%fname%>(<%functionArguments |> var => funArgDefinition(var) ;separator=", "%>) { + /* disable GC for now + <%if acceptMetaModelicaGrammar() then '<%addRootsInputs%>'%> + <%if acceptMetaModelicaGrammar() then if addRootsInputs then 'mmc_GC_push_roots_mark();'%> + */ + <%funArgs%> <%varDecls%> <%outVarInits%> @@ -3269,6 +3286,21 @@ case FUNCTION(__) then <%outVarCopy%> <%if not acceptMetaModelicaGrammar() then 'restore_memory_state(<%stateVar%>);'%> <%outVarAssign%> + + /* disable GC for now + <%if acceptMetaModelicaGrammar() then '<%addRootsOutputs%>'%> + <%if acceptMetaModelicaGrammar() then if addRootsOutputs then 'mmc_GC_push_roots_mark();'%> + <% + if acceptMetaModelicaGrammar() + then if addRootsInputs + then 'mmc_GC_collect();' + else if addRootsOutputs + then 'mmc_GC_collect();' + %> + <%if acceptMetaModelicaGrammar() then if addRootsOutputs then 'mmc_GC_pop_roots_mark();'%> + <%if acceptMetaModelicaGrammar() then if addRootsInputs then 'mmc_GC_pop_roots_mark();'%> + */ + return<%if outVars then ' <%retVar%>' %>; } @@ -3992,7 +4024,7 @@ template algStatement(DAE.Statement stmt, Context context, Text &varDecls /*BUFP case s as STMT_THROW(__) then 'MMC_THROW();<%\n%>' case s as STMT_RETURN(__) then 'goto _return;<%\n%>' case s as STMT_NORETCALL(__) then algStmtNoretcall(s, context, &varDecls /*BUFD*/) - case s as STMT_REINIT(__) then algStmtReinit(s, context, &varDecls /*BUFD*/) + case s as STMT_REINIT(__) then algStmtReinit(s, context, &varDecls /*BUFD*/) else "#error NOT_IMPLEMENTED_ALG_STATEMENT" << /*#modelicaLine <%statementInfoString(stmt)%>*/ @@ -6390,7 +6422,7 @@ template literalExpConst(Exp lit, Integer index) "These should all be declared s ::= let name = '_OMC_LIT<%index%>' let tmp = '_OMC_LIT_STRUCT<%index%>' - let meta = 'static modelica_metatype const <%name%>' + let meta = 'static modelica_metatype /* const */ <%name%>' match lit case SCONST(__) then let escstr = Util.escapeModelicaStringToCString(string) @@ -6403,7 +6435,7 @@ template literalExpConst(Exp lit, Integer index) "These should all be declared s << #define <%name%>_data "<%escstr%>" static const size_t <%name%>_strlen = <%unescapedStringLength(escstr)%>; - static const MMC_DEFSTRINGLIT(<%tmp%>,<%name%>_strlen,<%name%>_data); + static /* const */ MMC_DEFSTRINGLIT(<%tmp%>,<%name%>_strlen,<%name%>_data); <%meta%> = MMC_REFSTRINGLIT(<%tmp%>); >> else @@ -6422,28 +6454,28 @@ template literalExpConst(Exp lit, Integer index) "These should all be declared s >> case BOX(exp=exp as RCONST(__)) then << - static const MMC_DEFREALLIT(<%tmp%>,<%exp.real%>); + static /* const */ MMC_DEFREALLIT(<%tmp%>,<%exp.real%>); <%meta%> = MMC_REFREALLIT(<%tmp%>); >> case CONS(__) then << - static const MMC_DEFSTRUCTLIT(<%tmp%>,2,1) {<%literalExpConstBoxedVal(car)%>,<%literalExpConstBoxedVal(cdr)%>}}; + static /* const */ MMC_DEFSTRUCTLIT(<%tmp%>,2,1) {<%literalExpConstBoxedVal(car)%>,<%literalExpConstBoxedVal(cdr)%>}}; <%meta%> = MMC_REFSTRUCTLIT(<%tmp%>); >> case META_TUPLE(__) then << - static const MMC_DEFSTRUCTLIT(<%tmp%>,<%listLength(listExp)%>,0) {<%listExp |> exp => literalExpConstBoxedVal(exp); separator=","%>}}; + static /* const */ MMC_DEFSTRUCTLIT(<%tmp%>,<%listLength(listExp)%>,0) {<%listExp |> exp => literalExpConstBoxedVal(exp); separator=","%>}}; <%meta%> = MMC_REFSTRUCTLIT(<%tmp%>); >> case META_OPTION(exp=SOME(exp)) then << - static const MMC_DEFSTRUCTLIT(<%tmp%>,1,1) {<%literalExpConstBoxedVal(exp)%>}}; + static /* const */ MMC_DEFSTRUCTLIT(<%tmp%>,1,1) {<%literalExpConstBoxedVal(exp)%>}}; <%meta%> = MMC_REFSTRUCTLIT(<%tmp%>); >> case METARECORDCALL(__) then let newIndex = getValueCtor(index) << - static const MMC_DEFSTRUCTLIT(<%tmp%>,<%intAdd(1,listLength(args))%>,<%newIndex%>) {&<%underscorePath(path)%>__desc,<%args |> exp => literalExpConstBoxedVal(exp); separator=","%>}}; + static /* const */ MMC_DEFSTRUCTLIT(<%tmp%>,<%intAdd(1,listLength(args))%>,<%newIndex%>) {&<%underscorePath(path)%>__desc,<%args |> exp => literalExpConstBoxedVal(exp); separator=","%>}}; <%meta%> = MMC_REFSTRUCTLIT(<%tmp%>); >> else '<%\n%>#error "literalExpConst failed: <%printExpStr(lit)%>"<%\n%>' diff --git a/c_runtime/Makefile.common b/c_runtime/Makefile.common index 2eca5836cff..4a23a2449d6 100644 --- a/c_runtime/Makefile.common +++ b/c_runtime/Makefile.common @@ -17,6 +17,8 @@ daux.o dlamch.o dpmpar.o hybrd.o lsame.o newuob.o r1mpyq.o update.o java_interface.o meta_modelica.o meta_modelica_builtin.o meta_modelica_real.o \ meta_modelica_string_lit.o meta_modelica_catch.o rtclock.o ModelicaUtilities.o \ simulation_varinfo.o read_matlab4.o \ +meta_modelica_gc.o meta_modelica_gc_list.o meta_modelica_gc_stack.o \ +meta_modelica_gc_roots.o meta_modelica_gc_pages.o meta_modelica_gc_stats.o \ $(EXTRA_OBJS) SIMOBJS = $(FOBJS) simulation_runtime.o simulation_init.o simulation_input.o \ @@ -45,6 +47,7 @@ matrix.h \ memory_pool.h \ meta_modelica_builtin.h \ meta_modelica_builtin_boxptr.h \ +meta_modelica_gc.h \ meta_modelica_real.h \ meta_modelica_string_lit.h \ meta_modelica.h \ @@ -74,6 +77,11 @@ simulation_varinfo.h \ solver_dasrt.h \ solver_main.h \ string_array.h \ +meta_modelica_gc_stack.h \ +meta_modelica_gc_list.h \ +meta_modelica_gc_roots.h \ +meta_modelica_gc_pages.h \ +meta_modelica_gc_stats.h \ utility.h \ linearize.h \ fmu_model_interface.h \ diff --git a/c_runtime/meta_modelica.c b/c_runtime/meta_modelica.c index f6391c41111..50927faa42a 100644 --- a/c_runtime/meta_modelica.c +++ b/c_runtime/meta_modelica.c @@ -29,37 +29,10 @@ * */ - #include "modelica.h" jmp_buf *mmc_jumper; -void *mmc_alloc_bytes(unsigned nbytes) -{ - static char *mmc_cur_malloc_buf = NULL; - static long mmc_cur_malloc_buf_ix=0; - /* Until we have GC, we simply allocate in 256MB chunks... */ - const long mmc_cur_malloc_buf_sz=256*1024*1024; /* 256MB chunks */ - void *p=0; - /* fprintf(stderr, "1 mmc_alloc_bytes(%ld): %ld,%ld\n", nbytes, mmc_cur_malloc_buf, mmc_cur_malloc_buf_ix); */ - if (mmc_cur_malloc_buf == NULL || nbytes>(mmc_cur_malloc_buf_sz-mmc_cur_malloc_buf_ix)) { - if ( (mmc_cur_malloc_buf = malloc(mmc_cur_malloc_buf_sz)) == 0 ) { - fflush(NULL); - fprintf(stderr, "malloc(%u) failed: %s\n", nbytes, strerror(errno)); - assert(p != 0); - } - mmc_cur_malloc_buf_ix = 0; - assert(nbytes <= mmc_cur_malloc_buf_sz); - } - p = mmc_cur_malloc_buf + mmc_cur_malloc_buf_ix; - - /* Force 16-byte alignment, like malloc... TODO: Check if this is needed :) */ - mmc_cur_malloc_buf_ix += nbytes; /* + ((nbytes%16) ? 16-(nbytes%16): 0); */ - - /* fprintf(stderr, "2 mmc_alloc_bytes(%ld): %ld,%ld => %ld\n", nbytes, mmc_cur_malloc_buf, mmc_cur_malloc_buf_ix, p); */ - return p; -} - void* mmc_mk_rcon(double d) { struct mmc_real *p = mmc_alloc_words(sizeof(struct mmc_real)/MMC_SIZE_INT); diff --git a/c_runtime/meta_modelica.h b/c_runtime/meta_modelica.h index 2bc8b6414f0..da5d50c71f3 100644 --- a/c_runtime/meta_modelica.h +++ b/c_runtime/meta_modelica.h @@ -39,6 +39,7 @@ #define META_MODELICA_H_ #include "modelica.h" +#include "meta_modelica_gc.h" #include "meta_modelica_string_lit.h" #if defined(__cplusplus) @@ -77,6 +78,7 @@ typedef int mmc_sint_t; #define MMC_CDR(X) MMC_FETCH(MMC_OFFSET(MMC_UNTAGPTR(X),2)) #define MMC_NILTEST(x) (MMC_GETHDR(x) == MMC_NILHDR) #define MMC_IMMEDIATE(i) ((void*)(i)) +#define MMC_IS_IMMEDIATE(x) (!((mmc_uint_t)(x) & 1)) #define MMC_TAGFIXNUM(i) ((i) << 1) #define MMC_UNTAGFIXNUM(X) (((mmc_sint_t) X) >> 1) #define MMC_REALHDR (((MMC_SIZE_DBL/MMC_SIZE_INT) << 10) + 9) @@ -93,6 +95,20 @@ typedef int mmc_sint_t; #define MMC_ARRAY_TAG 255 #define MMC_STRLEN(x) (MMC_HDRSTRLEN(MMC_GETHDR(x))) +/* + * adrpo: if a structure has pointers + * Bit 0 is zero if the node contains pointers, 1 otherwise. + */ +#define MMC_HDRHASPTRS(hdr) (!((hdr) & 1)) +/* + * adrpo: if this object was marked, used by GC! + * [xxxxxxxx1x] (used during garbage collection) a marked node; + */ +#define MMC_HDRISMARKED(hdr) ((hdr) & 2) +#define MMC_HDR_MARK(hdr) ((hdr) | 2) +#define MMC_HDR_UNMARK(hdr) ((hdr) & ~2) + + #define MMC_INT_MAX ((1<<30)-1) #define MMC_INT_MIN (-(1<<30)) @@ -138,13 +154,6 @@ struct mmc_string { char data[1]; /* `bytes' elements + terminating '\0' */ }; -void *mmc_alloc_bytes(unsigned nbytes); - -static void *mmc_alloc_words(unsigned nwords) -{ - return mmc_alloc_bytes(nwords * sizeof(void*)); -} - #define MMC_FALSE (mmc_mk_icon(0)) #define MMC_TRUE (mmc_mk_icon(1)) #define mmc_mk_bcon(X) ((X) != 0 ? MMC_TRUE : MMC_FALSE) @@ -305,8 +314,8 @@ static inline void *mmc_mk_box(int slots, unsigned ctor, ...) return MMC_TAGPTR(p); } -static const MMC_DEFSTRUCT0LIT(mmc_nil,0); -static const MMC_DEFSTRUCT0LIT(mmc_none,1); +static /* const */ MMC_DEFSTRUCT0LIT(mmc_nil,0); +static /* const */ MMC_DEFSTRUCT0LIT(mmc_none,1); #define mmc_mk_nil() MMC_REFSTRUCTLIT(mmc_nil) #define mmc_mk_none() MMC_REFSTRUCTLIT(mmc_none) diff --git a/c_runtime/meta_modelica_gc.c b/c_runtime/meta_modelica_gc.c new file mode 100644 index 00000000000..6808abd1277 --- /dev/null +++ b/c_runtime/meta_modelica_gc.c @@ -0,0 +1,571 @@ +/* + * This file is part of OpenModelica. + * + * Copyright (c) 1998-CurrentYear, Linköping University, + * Department of Computer and Information Science, + * SE-58183 Linköping, Sweden. + * + * All rights reserved. + * + * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF GPL VERSION 3 + * AND THIS OSMC PUBLIC LICENSE (OSMC-PL). + * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES RECIPIENT'S + * ACCEPTANCE OF THE OSMC PUBLIC LICENSE. + * + * The OpenModelica software and the Open Source Modelica + * Consortium (OSMC) Public License (OSMC-PL) are obtained + * from Linköping University, either from the above address, + * from the URLs: http://www.ida.liu.se/projects/OpenModelica or + * http://www.openmodelica.org, and in the OpenModelica distribution. + * GNU version 3 is obtained from: http://www.gnu.org/copyleft/gpl.html. + * + * This program is distributed WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH + * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS + * OF OSMC-PL. + * + * See the full OSMC Public License conditions for more details. + * + */ + + +/* + * Adrian Pop [Adrian.Pop@liu.se] + * This file implements the new MetaModelica Garbage Collector + * which is a mark-and-sweep collector. See more information + * in meta_modelica_gc.h file. + * + * RCS: $Id: meta_modelica_gc.c 8047 2011-03-01 10:19:49Z perost $ + * + */ + +#include "modelica.h" + +mmc_GC_state_type *mmc_GC_state = NULL; + +const char debug = 1; + +/* initialization of MetaModelica GC */ +int mmc_GC_init(int nr_mark_threads, int nr_sweep_threads, long default_page_size, int default_number_of_pages, long default_roots_size) +{ + /* + fprintf(stderr, "nilhdr: %ul\n", MMC_NILHDR); fflush(NULL); + fprintf(stderr, "conshdr: %ul\n", MMC_CONSHDR); fflush(NULL); + fprintf(stderr, "nonehdr: %ul\n", MMC_STRUCTHDR(0,1)); fflush(NULL); + */ + + /* do not init GC if already done */ + if (mmc_GC_state) return 0; + mmc_GC_state = (mmc_GC_state_type*) malloc (sizeof(mmc_GC_state_type)); + + if (!mmc_GC_state) + { + fprintf(stderr, "not enough memory to allocate the GC structure!\n"); + fflush(NULL); + assert(mmc_GC_state != 0); + } + + /* create the GC state structures */ + mmc_GC_state->default_number_of_mark_threads = nr_mark_threads; + mmc_GC_state->default_number_of_sweep_threads = nr_sweep_threads; + mmc_GC_state->default_number_of_pages = default_number_of_pages; + mmc_GC_state->default_page_size = default_page_size; + mmc_GC_state->default_roots_size = default_roots_size; + mmc_GC_state->pages = pages_create(default_page_size, default_number_of_pages); + mmc_GC_state->roots = roots_create(default_roots_size); + mmc_GC_state->free = list_clone(mmc_GC_state->pages); /* initially the free list is the list of pages! */ + mmc_GC_state->stats = stats_create(); + + return 0; +} + +/* add pointers to roots */ +int mmc_GC_add_root(modelica_metatype p) +{ + /* if GC was not setup, init it */ + if (!mmc_GC_state) + { + mmc_GC_init( + MMC_GC_NUMBER_OF_MARK_THREADS, + MMC_GC_NUMBER_OF_SWEEP_THREADS, + MMC_GC_PAGE_SIZE, + MMC_GC_NUMBER_OF_PAGES, + MMC_GC_ROOTS_SIZE_INITIAL); + } + + assert(mmc_GC_state != NULL); + + if (mmc_GC_state->roots.current == mmc_GC_state->roots.limit) + { + /* roots are filled, realloc! */ + mmc_GC_state->roots = roots_realloc(mmc_GC_state->roots, mmc_GC_state->default_roots_size); + } + + /* set the pointer to current */ + *mmc_GC_state->roots.current = p; + + /* increase the current */ + mmc_GC_state->roots.current++; + + return 0; +} + +/* save the current roots mark */ +int mmc_GC_push_roots_mark(void) +{ + /* if GC was not setup, init it */ + if (!mmc_GC_state) + { + mmc_GC_init( + MMC_GC_NUMBER_OF_MARK_THREADS, + MMC_GC_NUMBER_OF_SWEEP_THREADS, + MMC_GC_PAGE_SIZE, + MMC_GC_NUMBER_OF_PAGES, + MMC_GC_ROOTS_SIZE_INITIAL); + } + + assert(mmc_GC_state != NULL); + + { + mmc_uint_t mark = mmc_GC_state->roots.current - mmc_GC_state->roots.start; + + if (debug) fprintf(stderr, "pushing stack %ld\n", (long)mark); fflush(NULL); + + /* push the current index in the roots */ + stack_push(&mmc_GC_state->roots.marks, mark); + } + + return 0; +} + +/* remove the current roots mark */ +int mmc_GC_pop_roots_mark(void) +{ + long roots_index = 0; + + assert(mmc_GC_state != NULL); + + if (debug) fprintf(stderr, "poping stack: "); fflush(NULL); + + if (!stack_empty(mmc_GC_state->roots.marks)) + { + /* pop the marks stack */ + stack_pop(&mmc_GC_state->roots.marks); + /* get the previous mark */ + if (!stack_empty(mmc_GC_state->roots.marks)) + { + roots_index = stack_peek(mmc_GC_state->roots.marks); + } + } + + if (debug) fprintf(stderr, "index: %ld\n", roots_index); fflush(NULL); + + /* reset the roots current index */ + mmc_GC_state->roots.current = mmc_GC_state->roots.start + roots_index; + + return 0; +} + +void walk_object(modelica_metatype p, int markType) +{ +mmc_walk_top: + + /* if (debug) fprintf(stderr, "walking: %p\n", p); fflush(NULL); */ + + assert(p != NULL); + + if( MMC_IS_IMMEDIATE(p) ) + { + if (debug) fprintf(stderr, "immediate: %p\n", p); fflush(NULL); + return; + } + else + { + mmc_uint_t hdr = MMC_GETHDR(p); + struct mmc_header* sh = NULL; + + /* see if we should mark/unmark */ + if (markType == MMC_GC_MARK) + { + /* if we should mark it and is already marked, return */ + if ( MMC_HDRISMARKED(hdr) ) return; + /* else, mark it */ + if (debug) fprintf(stderr, "casting the header\n"); fflush(NULL); + sh = ((struct mmc_header*)MMC_UNTAGPTR(p)); + if (debug) fprintf(stderr, "marking: %p %ul\n", p, sh->header); fflush(NULL); + sh->header = MMC_HDR_MARK(hdr); + if (debug) fprintf(stderr, "marked: %p\n", p); fflush(NULL); + } + else /* we should unmark */ + { + /* if we should unmark it and is already unmarked, return */ + if ( !MMC_HDRISMARKED(hdr) ) return; + /* else, unmark it */ + if (debug) fprintf(stderr, "casting the header\n"); fflush(NULL); + sh = ((struct mmc_header*)MMC_UNTAGPTR(p)); + if (debug) fprintf(stderr, "unmarking: %p %p\n", p, (void*)sh); fflush(NULL); + sh->header = MMC_HDR_UNMARK(hdr); + if (debug) fprintf(stderr, "unmarked: %p\n", p); fflush(NULL); + } + + /* if is string or real, just return */ + if( MMC_HDRISSTRING(hdr) && (hdr == MMC_REALHDR) ) + { + if (debug) fprintf(stderr, "real or string: %p\n", p); fflush(NULL); + return; + } + + /* if is a structure, dive in! */ + if( MMC_HDRISSTRUCT(hdr) ) + { + mmc_uint_t slots = MMC_HDRSLOTS(hdr); + mmc_uint_t ctor = MMC_HDRCTOR(hdr); + mmc_uint_t slotsMin = 0; + void **pp = NULL; + + if (debug) fprintf(stderr, "structure: %p\n", p); fflush(NULL); + if (slots == 0) return; + + if (slots > 0 && ctor > 1) /* RECORD */ + { + slotsMin = 1; /* ignore the fields slot! */ + } + + + pp = MMC_STRUCTDATA(p); + + while( --slots > slotsMin ) + { + walk_object(*pp++, markType); + } + + p = *pp; + + /* go to the begining */ + goto mmc_walk_top; + } + else /* not a structure, move on! */ + { + return ; + } + } +} + +/* the mark phase */ +int mmc_GC_collect_mark(void) +{ + modelica_metatype* p = NULL; + + assert(mmc_GC_state != NULL); + + /* + * here we should start a number of mark threads: + * mmc_GC_state->default_number_of_mark_threads + * we can mark objects using multiple threads, + * each thread marking starting from a different + * root or a different root set. + * for now, we just do it in serial + */ + + for(p = mmc_GC_state->roots.start; p < mmc_GC_state->roots.current; p++) + { + walk_object(*p, MMC_GC_MARK); + } + + return 0; +} + +/* the unmark phase */ +int mmc_GC_collect_unmark(void) +{ + modelica_metatype* p = NULL; + + assert(mmc_GC_state != NULL); + + /* + * here we should start a number of mark threads: + * mmc_GC_state->default_number_of_mark_threads + * we can mark objects using multiple threads, + * each thread marking starting from a different + * root or a different root set. + * for now, we just do it in serial + */ + + for(p = mmc_GC_state->roots.start; p < mmc_GC_state->roots.current; p++) + { + walk_object(*p, MMC_GC_UNMARK); + } + + return 0; +} + +long get_filled_size(mmc_GC_free_slot page) +{ + mmc_List free = mmc_GC_state->free; + long filledSize = 0, filledCurrent = 0; + char found = 0; + while (free != NULL) + { + /* see if free is within page boundaries */ + if (free->el.start >= page.start && (char*)free->el.start < (char*)page.start + page.size) + { + filledCurrent = (char*)free->el.start - (char*)page.start; + filledSize = (filledSize > filledCurrent)?filledSize : filledCurrent; + found = 1; + } + free = free->next; + } + + filledSize = found?filledSize:page.size; + + return filledSize; +} + +/* + * walk page object by object and add all + * unmarked objects region to the free list! + */ +int sweep_page(mmc_GC_free_slot page) +{ + modelica_metatype scan = page.start; + mmc_uint_t hdr = 0, slots = 0; + mmc_GC_free_slot freeSlot = { 0 }; + + mmc_uint_t filledSize = get_filled_size(page); + + /* if this page was not filled at all, return */ + if (!filledSize) + return 0; + + if (debug) fprintf(stderr, "sweeping page: %p, size: %ul\n", (void*)scan, filledSize); fflush(NULL); + + /* scan the page */ + while ((char*)scan < ((char*)page.start + filledSize)) + { + if (debug) fprintf(stderr, "get obj header:\n"); fflush(NULL); + /* get the obj header */ + hdr = ((struct mmc_header*)scan)->header; + + /* if header is 0 it means this page is not filled, break */ + slots = MMC_HDRSLOTS(hdr); + + /* if the object is marked, skip it */ + if (MMC_HDRISMARKED(hdr)) + { + /* do nothing */ + if (debug) fprintf(stderr, "skipping marked obj: %p\n", scan); fflush(NULL); + } + else /* object is unmarked, add it to the free list */ + { + /* if (debug) fprintf(stderr, "adding obj to free list: %p\n", scan); fflush(NULL); */ + /* TODO! FIXME! collect larger free regions in a slot! */ + /* construct the free slot */ + freeSlot.start = scan; + freeSlot.size = slots * sizeof(void*); + /* add it to the free list */ + list_cons(&(mmc_GC_state->free), freeSlot); + } + /* move to next object which should be after slots + 1 (the header) */ + scan = (modelica_metatype)((mmc_uint_t)scan + (slots + 1)); + } + return 0; +} + +/* the sweep phase */ +int mmc_GC_collect_sweep(void) +{ + mmc_List pages = NULL; + mmc_GC_free_slot page = {0}; + + assert(mmc_GC_state != NULL); + + /* + * here we should start a number of sweep threads: + * mmc_GC_state->default_number_of_sweep_threads + * we can sweep using multiple threads, for example + * one for each page, or one for each half page. + * for now, we just do it in serial + */ + + /* + * walk all pages object by object and add all + * unmarked objects region to the free list! + */ + + pages = mmc_GC_state->pages; + while (pages != NULL) + { + page = pages->el; + sweep_page(page); + pages = pages->next; + } + + + return 0; +} + +/* do garbage collection */ +int mmc_GC_collect(void) +{ + assert(mmc_GC_state != NULL); + + /* only collect we have more than 3 pages */ + if (list_length(mmc_GC_state->pages) < 2) + return 0; + + /* collect only if mark stack top is non-zero */ + if (!mmc_GC_state->roots.marks) + return 0; + if (!stack_peek(mmc_GC_state->roots.marks)) + return 0; + + if (debug) fprintf(stderr, "mark\n"); fflush(NULL); + mmc_GC_collect_mark(); + if (debug) fprintf(stderr, "sweep\n"); fflush(NULL); + mmc_GC_collect_sweep(); + if (debug) fprintf(stderr, "unmark\n"); fflush(NULL); + mmc_GC_collect_unmark(); + if (debug) fprintf(stderr, "collect done\n"); fflush(NULL); + + return 0; +} + +/* get a region of memory of required size */ +modelica_metatype allocate_from_free(mmc_GC_state_type *gc_state, unsigned nbytes) +{ + modelica_metatype p = NULL; + mmc_List fl = NULL; + mmc_GC_free_slot slot; + + /* search in the free list for the big enough-slot */ + fl = gc_state->free; + + assert(fl != 0); + + /* try very fast allocation first */ + if (fl->el.size > nbytes) + { + /* found our free region, use it! */ + p = fl->el.start; + fl->el.start = ((char*)fl->el.start + nbytes); + fl->el.size = fl->el.size - nbytes; + + /* return out region */ + return p; + } + + /* go the long way by searching the entire list! */ + while (fl != NULL) + { + /* we found our slot! */ + if (fl->el.size >= nbytes) + break; + fl = fl->next; + } + + /* we didn't find a big enough slot, create one! */ + if (!fl) + { + mmc_GC_free_slot slot = {0, 0}; + /* if the required allocation size is bigger than the default page size make a new page! */ + if (nbytes > gc_state->default_page_size) + { + /* make a new page of big-enough size */ + slot = page_create(nbytes); + } + else + { + /* make a new page of default size */ + slot = page_create(gc_state->default_page_size); + } + + /* add it to pages */ + gc_state->pages = pages_add(gc_state->pages, slot); + /* add it to the free list */ + list_cons(&(gc_state->free), slot); + + /* point to it */ + fl = gc_state->free; + } + + assert(fl != 0); + + /* remember our free slot */ + slot = fl->el; + + /* delete the slot from the free list! */ + list_delete(&(gc_state->free), fl->el); + + /* found our free region, use it! */ + p = slot.start; + + /* if the slot was NOT fully filled, return the rest to the free list! */ + if (slot.size > nbytes) + { + slot.start = ((char*)slot.start + nbytes); + slot.size = slot.size - nbytes; + /* add the rest to the free list! */ + list_cons(&(gc_state->free), slot); + } + + return p; +} + +#if 0 + +/* primary allocation routine for MetaModelica */ +void *mmc_alloc_bytes(unsigned nbytes) +{ + modelica_metatype p = NULL; + + /* if GC was not setup, init it */ + if (!mmc_GC_state) + { + mmc_GC_init( + MMC_GC_NUMBER_OF_MARK_THREADS, + MMC_GC_NUMBER_OF_SWEEP_THREADS, + MMC_GC_PAGE_SIZE, + MMC_GC_NUMBER_OF_PAGES, + MMC_GC_ROOTS_SIZE_INITIAL); + } + + assert(mmc_GC_state != NULL); + + p = allocate_from_free(mmc_GC_state, nbytes); + + return p; +} + +#endif + +void *mmc_alloc_bytes(unsigned nbytes) +{ + static char *mmc_cur_malloc_buf = NULL; + static long mmc_cur_malloc_buf_ix=0; + /* Until we have GC, we simply allocate in 256MB chunks... */ + const long mmc_cur_malloc_buf_sz = MMC_GC_PAGE_SIZE; + void *p=0; + /* fprintf(stderr, "1 mmc_alloc_bytes(%ld): %ld,%ld\n", nbytes, mmc_cur_malloc_buf, mmc_cur_malloc_buf_ix); */ + if (mmc_cur_malloc_buf == NULL || nbytes>(mmc_cur_malloc_buf_sz-mmc_cur_malloc_buf_ix)) { + if ( (mmc_cur_malloc_buf = malloc(mmc_cur_malloc_buf_sz)) == 0 ) { + fflush(NULL); + fprintf(stderr, "malloc(%u) failed: %s\n", nbytes, strerror(errno)); + assert(p != 0); + } + mmc_cur_malloc_buf_ix = 0; + assert(nbytes <= mmc_cur_malloc_buf_sz); + } + p = mmc_cur_malloc_buf + mmc_cur_malloc_buf_ix; + + /* Force 16-byte alignment, like malloc... TODO: Check if this is needed :) */ + mmc_cur_malloc_buf_ix += nbytes; /* + ((nbytes%16) ? 16-(nbytes%16): 0); */ + + /* fprintf(stderr, "2 mmc_alloc_bytes(%ld): %ld,%ld => %ld\n", nbytes, mmc_cur_malloc_buf, mmc_cur_malloc_buf_ix, p); */ + return p; +} + + + + + diff --git a/c_runtime/meta_modelica_gc.h b/c_runtime/meta_modelica_gc.h new file mode 100644 index 00000000000..e55248ff004 --- /dev/null +++ b/c_runtime/meta_modelica_gc.h @@ -0,0 +1,121 @@ +/* + * This file is part of OpenModelica. + * + * Copyright (c) 1998-CurrentYear, Linköping University, + * Department of Computer and Information Science, + * SE-58183 Linköping, Sweden. + * + * All rights reserved. + * + * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF GPL VERSION 3 + * AND THIS OSMC PUBLIC LICENSE (OSMC-PL). + * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES RECIPIENT'S + * ACCEPTANCE OF THE OSMC PUBLIC LICENSE. + * + * The OpenModelica software and the Open Source Modelica + * Consortium (OSMC) Public License (OSMC-PL) are obtained + * from Linköping University, either from the above address, + * from the URLs: http://www.ida.liu.se/projects/OpenModelica or + * http://www.openmodelica.org, and in the OpenModelica distribution. + * GNU version 3 is obtained from: http://www.gnu.org/copyleft/gpl.html. + * + * This program is distributed WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH + * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS + * OF OSMC-PL. + * + * See the full OSMC Public License conditions for more details. + * + */ + +/* + * Adrian Pop [Adrian.Pop@liu.se] + * This file implements the new MetaModelica Garbage Collector (GC) + * which is a mark-and-sweep collector. + * + * RCS: $Id: meta_modelica_gc.h 8047 2011-03-01 10:19:49Z perost $ + * + * At first a configurable number of pages of configurable size + * are allocated and then made part of the free list. Allocation + * picks up a slot from the free list and updates it. + * All live data (made via mmc_mk_* functions) is added to the + * array of roots. The upper limit mark of the roots array is + * saved in a stack called marks which is pop-ed when a function + * exits of fails. + * + * Garbage collection happens in several phases: + * - mark phase when we start from roots (0 - currentMark) + * and marks all the objects that are live + * - sweep phase collects all the other parts of the pages + * which are not marked by the mark phase into the free + * list which can then be reused for allocation. + * - unmark phase when we start from roots (0 - currentMark) + * and un-marks all the objects that are live + * + * For more information see paper at Modelica Conference 2011: + * Martin Sjölund, Peter Fritzson, Adrian Pop + * "Bootstrapping a Modelica Compiler aiming at Modelica 4" + * or contact Adrian Pop. + * + */ + +#ifndef META_MODELICA_GC_H_ +#define META_MODELICA_GC_H_ + +#include "modelica.h" +#include "meta_modelica_gc_stack.h" +#include "meta_modelica_gc_list.h" +#include "meta_modelica_gc_roots.h" +#include "meta_modelica_gc_pages.h" +#include "meta_modelica_gc_stats.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +#define MMC_GC_NUMBER_OF_MARK_THREADS 5 +#define MMC_GC_NUMBER_OF_SWEEP_THREADS 5 + +#define MMC_GC_MARK 1 +#define MMC_GC_UNMARK 0 + +struct mmc_GC_state_type /* the structure of GC state */ +{ + int default_number_of_pages; /* the initial number of pages */ + long default_page_size; /* the default page size */ + long default_roots_size; /* the default size of the array of roots */ + int default_number_of_mark_threads; /* the initial number of mark threads */ + int default_number_of_sweep_threads; /* the initial number of sweep threads */ + struct mmc_ListElement* pages; /* the allocated pages is just a list with pointer and size */ + mmc_GC_roots_type roots; /* the current roots */ + struct mmc_ListElement* free; /* the free list is a list with pointer and size */ + mmc_GC_stats_type stats; /* the statistics */ +}; +typedef struct mmc_GC_state_type mmc_GC_state_type; + +extern mmc_GC_state_type* mmc_GC_state; + +/* primary allocation routine for MetaModelica */ +void *mmc_alloc_bytes(unsigned nbytes); +static void *mmc_alloc_words(unsigned nwords) +{ + return mmc_alloc_bytes(nwords * sizeof(void*)); +} + +/* initialization of MetaModelica GC */ +int mmc_GC_init(int nr_mark_threads, int nr_sweep_threads, long default_page_size, int default_number_of_pages, long default_roots_size); +/* add pointers to roots */ +int mmc_GC_add_root(modelica_metatype); +/* save the current roots mark */ +int mmc_GC_push_roots_mark(void); +/* remove the current roots mark */ +int mmc_GC_pop_roots_mark(void); +/* do garbage collection */ +int mmc_GC_collect(void); + +#if defined(__cplusplus) +} +#endif + +#endif /* #define META_MODELICA_GC_H_ */ diff --git a/c_runtime/meta_modelica_gc_list.c b/c_runtime/meta_modelica_gc_list.c new file mode 100644 index 00000000000..2c303b30d5a --- /dev/null +++ b/c_runtime/meta_modelica_gc_list.c @@ -0,0 +1,286 @@ +/* + * This file is part of OpenModelica. + * + * Copyright (c) 1998-CurrentYear, Linköping University, + * Department of Computer and Information Science, + * SE-58183 Linköping, Sweden. + * + * All rights reserved. + * + * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF GPL VERSION 3 + * AND THIS OSMC PUBLIC LICENSE (OSMC-PL). + * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES RECIPIENT'S + * ACCEPTANCE OF THE OSMC PUBLIC LICENSE. + * + * The OpenModelica software and the Open Source Modelica + * Consortium (OSMC) Public License (OSMC-PL) are obtained + * from Linköping University, either from the above address, + * from the URLs: http://www.ida.liu.se/projects/OpenModelica or + * http://www.openmodelica.org, and in the OpenModelica distribution. + * GNU version 3 is obtained from: http://www.gnu.org/copyleft/gpl.html. + * + * This program is distributed WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH + * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS + * OF OSMC-PL. + * + * See the full OSMC Public License conditions for more details. + * + */ + +#include "modelica.h" + + +/* make an empty list */ +mmc_List list_create(void) +{ + return NULL; +} + +/* return nonzero if the list is empty */ +int list_empty(mmc_List list) +{ + return list == NULL; +} + +/* number of elements */ +int list_length(mmc_List list) +{ + struct mmc_ListElement *curPtr; + int count = 0; + + curPtr = list; + + while(curPtr != NULL) + { + curPtr = curPtr->next; + count++; + } + return count; +} + +/* deleting a node from list depending upon the data in the node */ +int list_delete(mmc_List* list, mmc_GC_free_slot slot) +{ + struct mmc_ListElement *prevPtr = NULL, *curPtr = NULL; + + curPtr = *list; + + while(curPtr != NULL) + { + if(curPtr->el.start == slot.start) + { + if(curPtr == *list) + { + *list = curPtr->next; + free(curPtr); + return 0; + } + else + { + prevPtr->next = curPtr->next; + free(curPtr); + return 0; + } + } + else + { + prevPtr = curPtr; + curPtr = curPtr->next; + } + } + /* not found */ + return 1; +} + +/* deleting a node from list depending on the location */ +int list_delete_nth(mmc_List* list, int loc) +{ + struct mmc_ListElement *prevPtr = NULL, *curPtr = NULL; + int i; + + curPtr = *list; + + if(loc > (list_length(*list)) || loc <= 0) + { + printf("\nDeletion of mmc_ListElement at given location is not possible\n "); + } + else + { + /* if the location is starting of the list */ + if (loc == 1) + { + *list = curPtr->next; + free(curPtr); + return 0; + } + else + { + for(i = 1;i < loc; i++) + { + prevPtr = curPtr; + curPtr = curPtr->next; + } + + prevPtr->next = curPtr->next; + free(curPtr); + } + } + return 1; +} + +/* delete the entire list */ +int list_clear(mmc_List* list) +{ + struct mmc_ListElement *prevPtr, *curPtr; + + curPtr = *list; + + while(curPtr != NULL) + { + if(curPtr == *list) + { + *list = curPtr->next; + free(curPtr); + return 0; + } + else + { + prevPtr->next = curPtr->next; + free(curPtr); + return 0; + } + curPtr = curPtr->next; + } + + *list = NULL; + + return 1; +} + +/* adding a mmc_GC_free_slot at the end of the list */ +int list_add(mmc_List* list, mmc_GC_free_slot slot) +{ + struct mmc_ListElement *temp1, *temp2; + + temp1 = (struct mmc_ListElement *)malloc(sizeof(struct mmc_ListElement)); + + assert(temp1 != 0); + + temp1->el = slot; + + /* copying the *list location into another node */ + temp2 = *list; + + if(*list == NULL) + { + /* if list is empty we create first mmc_ListElement. */ + *list = temp1; + (*list)->next = NULL; + } + else + { + /* traverse down to end of the list */ + while(temp2->next != NULL) + temp2 = temp2->next; + + /* append at the end of the list */ + temp1->next = NULL; + temp2->next = temp1; + } + + return 0; +} + +/* adding a mmc_GC_free_slot at the end of the list */ +int list_cons(mmc_List* list, mmc_GC_free_slot slot) +{ + struct mmc_ListElement *temp; + + temp = (struct mmc_ListElement *)malloc(sizeof(struct mmc_ListElement)); + + assert(temp != 0); + + temp->el = slot; + + if (*list == NULL) + { + /* list is empty */ + *list = temp; + (*list)->next = NULL; + } + else + { + temp->next = *list; + *list = temp; + } + + return 0; +} + + +/* displaying list contents */ +void list_dump(mmc_List* list) +{ + struct mmc_ListElement *curPtr = NULL; + curPtr = *list; + + if(curPtr == NULL) + { + printf("\nList is Empty"); + } + else + { + fprintf(stderr, "\nElements in the List: "); + /* traverse the entire linked list */ + while(curPtr != NULL) + { + fprintf(stderr, "p[%p], size[%ld]\n", curPtr->el.start, curPtr->el.size); + curPtr = curPtr->next; + } + fprintf(stderr, "\n"); + fflush(NULL); + } +} + +/* reversing a list */ +int list_reverse(mmc_List* list) +{ + struct mmc_ListElement *prevPtr = NULL, *curPtr = NULL, *temp = NULL; + + curPtr = *list; + prevPtr = NULL; + + while(curPtr != NULL) + { + temp = prevPtr; + prevPtr = curPtr; + + curPtr = curPtr->next; + prevPtr->next = temp; + } + + *list = prevPtr; + + return 0; +} + +/* clone a list in reverse! */ +mmc_List list_clone(mmc_List list) +{ + mmc_List lst = NULL, curPtr = list; + + /* if empty return empty */ + if (!curPtr) + return lst; + + while(curPtr != NULL) + { + list_cons(&lst, curPtr->el); + curPtr = curPtr->next; + } + + return lst; +} + diff --git a/c_runtime/meta_modelica_gc_list.h b/c_runtime/meta_modelica_gc_list.h new file mode 100644 index 00000000000..5a296a14730 --- /dev/null +++ b/c_runtime/meta_modelica_gc_list.h @@ -0,0 +1,85 @@ +/* + * This file is part of OpenModelica. + * + * Copyright (c) 1998-CurrentYear, Linköping University, + * Department of Computer and Information Science, + * SE-58183 Linköping, Sweden. + * + * All rights reserved. + * + * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF GPL VERSION 3 + * AND THIS OSMC PUBLIC LICENSE (OSMC-PL). + * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES RECIPIENT'S + * ACCEPTANCE OF THE OSMC PUBLIC LICENSE. + * + * The OpenModelica software and the Open Source Modelica + * Consortium (OSMC) Public License (OSMC-PL) are obtained + * from Linköping University, either from the above address, + * from the URLs: http://www.ida.liu.se/projects/OpenModelica or + * http://www.openmodelica.org, and in the OpenModelica distribution. + * GNU version 3 is obtained from: http://www.gnu.org/copyleft/gpl.html. + * + * This program is distributed WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH + * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS + * OF OSMC-PL. + * + * See the full OSMC Public License conditions for more details. + * + */ + +#ifndef META_MODELICA_GC_LIST_H_ +#define META_MODELICA_GC_LIST_H_ + +#include "modelica.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +/* a free slot */ +struct mmc_GC_free_slot +{ + modelica_metatype start; /* the start of the free slot */ + long size; /* the free slot size */ +}; +typedef struct mmc_GC_free_slot mmc_GC_free_slot; + +/* a linked list */ +struct mmc_ListElement +{ + mmc_GC_free_slot el; + struct mmc_ListElement *next; +}; +typedef struct mmc_ListElement* mmc_List; + +/* make an empty list */ +mmc_List list_create(void); +/* return nonzero if the list is empty */ +int list_empty(mmc_List list); +/* number of elements */ +int list_length(mmc_List list); +/* deleting a node from list depending upon the data in the node */ +int list_delete(mmc_List* list, mmc_GC_free_slot slot); +/* deleting a node from list depending on the location */ +int list_delete_nth(mmc_List* list, int loc); +/* delete the entire list */ +int list_clear(mmc_List* list); +/* adding a mmc_GC_free_slot at the end of the list */ +int list_add(mmc_List* list, mmc_GC_free_slot slot); +/* adding a mmc_GC_free_slot at the end of the list */ +int list_cons(mmc_List* list, mmc_GC_free_slot slot); +/* displaying list contents */ +void list_dump(mmc_List* list); +/* reversing a list */ +int list_reverse(mmc_List* list); +/* clone a list in reverse! */ +mmc_List list_clone(mmc_List list); + +#if defined(__cplusplus) +} +#endif + +#endif /* #define META_MODELICA_GC_LIST_H_ */ + diff --git a/c_runtime/meta_modelica_gc_pages.c b/c_runtime/meta_modelica_gc_pages.c new file mode 100644 index 00000000000..33f89074388 --- /dev/null +++ b/c_runtime/meta_modelica_gc_pages.c @@ -0,0 +1,84 @@ +/* + * This file is part of OpenModelica. + * + * Copyright (c) 1998-CurrentYear, Linköping University, + * Department of Computer and Information Science, + * SE-58183 Linköping, Sweden. + * + * All rights reserved. + * + * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF GPL VERSION 3 + * AND THIS OSMC PUBLIC LICENSE (OSMC-PL). + * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES RECIPIENT'S + * ACCEPTANCE OF THE OSMC PUBLIC LICENSE. + * + * The OpenModelica software and the Open Source Modelica + * Consortium (OSMC) Public License (OSMC-PL) are obtained + * from Linköping University, either from the above address, + * from the URLs: http://www.ida.liu.se/projects/OpenModelica or + * http://www.openmodelica.org, and in the OpenModelica distribution. + * GNU version 3 is obtained from: http://www.gnu.org/copyleft/gpl.html. + * + * This program is distributed WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH + * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS + * OF OSMC-PL. + * + * See the full OSMC Public License conditions for more details. + * + */ + +#include "modelica.h" + +/* create and allocate a page */ +mmc_GC_free_slot page_create(long page_size) +{ + mmc_GC_free_slot slot = {0, 0}; + + slot.start = (modelica_metatype)malloc(page_size); + + if (!slot.start) + { + fprintf(stderr, "malloc(%ld) failed: %s\n", page_size, strerror(errno)); + fflush(NULL); + assert(slot.start != 0); + } + + slot.size = page_size; + + return slot; +} + +/* return the last allocated page */ +mmc_GC_free_slot pages_current(mmc_List list) +{ + if (list_empty(list)) + { + fprintf(stderr, "no current pages are allocated"); + fflush(NULL); + assert(list_empty(list) != 0); + } + return list->el; +} + +/* create the page list and add the first page */ +mmc_List pages_create(long default_page_size, int default_number_of_pages) +{ + mmc_List list = NULL; + int i = 0; + + for (i = 0; i < default_number_of_pages; i++) + { + list_cons(&list, page_create(default_page_size)); + } + + return list; +} + +/* add a page */ +mmc_List pages_add(mmc_List list, mmc_GC_free_slot page) +{ + list_cons(&list, page); + return list; +} diff --git a/c_runtime/meta_modelica_gc_pages.h b/c_runtime/meta_modelica_gc_pages.h new file mode 100644 index 00000000000..aafd961dac7 --- /dev/null +++ b/c_runtime/meta_modelica_gc_pages.h @@ -0,0 +1,56 @@ +/* + * This file is part of OpenModelica. + * + * Copyright (c) 1998-CurrentYear, Linköping University, + * Department of Computer and Information Science, + * SE-58183 Linköping, Sweden. + * + * All rights reserved. + * + * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF GPL VERSION 3 + * AND THIS OSMC PUBLIC LICENSE (OSMC-PL). + * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES RECIPIENT'S + * ACCEPTANCE OF THE OSMC PUBLIC LICENSE. + * + * The OpenModelica software and the Open Source Modelica + * Consortium (OSMC) Public License (OSMC-PL) are obtained + * from Linköping University, either from the above address, + * from the URLs: http://www.ida.liu.se/projects/OpenModelica or + * http://www.openmodelica.org, and in the OpenModelica distribution. + * GNU version 3 is obtained from: http://www.gnu.org/copyleft/gpl.html. + * + * This program is distributed WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH + * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS + * OF OSMC-PL. + * + * See the full OSMC Public License conditions for more details. + * + */ + +#ifndef META_MODELICA_GC_PAGES_H_ +#define META_MODELICA_GC_PAGES_H_ + +#include "modelica.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +#define MMC_GC_PAGE_SIZE 128*1024*1024 /* default page size 64MB chunks, can be changed */ +#define MMC_GC_NUMBER_OF_PAGES 2 /* default number of pages */ + +/* create the page list and add the first page */ +mmc_List pages_create(long default_page_size, int default_number_of_pages); +/* create and allocate a page */ +mmc_GC_free_slot page_create(long page_size); +/* add a page */ +mmc_List pages_add(mmc_List list, mmc_GC_free_slot page); + +#if defined(__cplusplus) +} +#endif + +#endif /* #define META_MODELICA_GC_PAGES_H_ */ + diff --git a/c_runtime/meta_modelica_gc_roots.c b/c_runtime/meta_modelica_gc_roots.c new file mode 100644 index 00000000000..5beaf7da52f --- /dev/null +++ b/c_runtime/meta_modelica_gc_roots.c @@ -0,0 +1,84 @@ +/* + * This file is part of OpenModelica. + * + * Copyright (c) 1998-CurrentYear, Linköping University, + * Department of Computer and Information Science, + * SE-58183 Linköping, Sweden. + * + * All rights reserved. + * + * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF GPL VERSION 3 + * AND THIS OSMC PUBLIC LICENSE (OSMC-PL). + * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES RECIPIENT'S + * ACCEPTANCE OF THE OSMC PUBLIC LICENSE. + * + * The OpenModelica software and the Open Source Modelica + * Consortium (OSMC) Public License (OSMC-PL) are obtained + * from Linköping University, either from the above address, + * from the URLs: http://www.ida.liu.se/projects/OpenModelica or + * http://www.openmodelica.org, and in the OpenModelica distribution. + * GNU version 3 is obtained from: http://www.gnu.org/copyleft/gpl.html. + * + * This program is distributed WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH + * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS + * OF OSMC-PL. + * + * See the full OSMC Public License conditions for more details. + * + */ + +/* + * Adrian Pop [Adrian.Pop@liu.se] + * This file implements GC roots + * + * RCS: $Id: meta_modelica_gc_roots.c 8047 2011-03-01 10:19:49Z perost $ + * + */ + +#include "modelica.h" + +/* create the roots structure */ +mmc_GC_roots_type roots_create(long default_roots_size) +{ + mmc_GC_roots_type roots = {0, 0, 0, 0}; + long sz = sizeof(modelica_metatype) * default_roots_size; + + roots.start = (modelica_metatype*)malloc(sz); + if (!roots.start) + { + fprintf(stderr, "not enough memory to allocate the roots array!\n"); + fflush(NULL); + assert(roots.start != 0); + } + /* the current index points to the start at the begining! */ + roots.current = roots.start; + /* the limit points to the end of the roots array */ + roots.limit = roots.start + sz; + + return roots; +} + +/* realloc the roots structure */ +mmc_GC_roots_type roots_realloc(mmc_GC_roots_type roots, long default_roots_size) +{ + long sz = (roots.limit - roots.start) + sizeof(modelica_metatype) * default_roots_size; + long current = (roots.current - roots.start); + + /* reallocate! */ + roots.start = (modelica_metatype*)realloc(roots.start, sz); + if (!roots.start) + { + fprintf(stderr, "not enough memory to re-allocate the roots array!\n"); + fflush(NULL); + assert(roots.start != 0); + } + + /* the current index now points to start + current size */ + roots.current = roots.start + current; + /* the limit points to the end of the roots array */ + roots.limit = roots.start + sz; + + return roots; +} diff --git a/c_runtime/meta_modelica_gc_roots.h b/c_runtime/meta_modelica_gc_roots.h new file mode 100644 index 00000000000..7a38266cef9 --- /dev/null +++ b/c_runtime/meta_modelica_gc_roots.h @@ -0,0 +1,70 @@ +/* + * This file is part of OpenModelica. + * + * Copyright (c) 1998-CurrentYear, Linköping University, + * Department of Computer and Information Science, + * SE-58183 Linköping, Sweden. + * + * All rights reserved. + * + * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF GPL VERSION 3 + * AND THIS OSMC PUBLIC LICENSE (OSMC-PL). + * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES RECIPIENT'S + * ACCEPTANCE OF THE OSMC PUBLIC LICENSE. + * + * The OpenModelica software and the Open Source Modelica + * Consortium (OSMC) Public License (OSMC-PL) are obtained + * from Linköping University, either from the above address, + * from the URLs: http://www.ida.liu.se/projects/OpenModelica or + * http://www.openmodelica.org, and in the OpenModelica distribution. + * GNU version 3 is obtained from: http://www.gnu.org/copyleft/gpl.html. + * + * This program is distributed WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH + * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS + * OF OSMC-PL. + * + * See the full OSMC Public License conditions for more details. + * + */ + +/* + * Adrian Pop [Adrian.Pop@liu.se] + * This file implements GC roots + * + * RCS: $Id: meta_modelica_gc_roots.h 8047 2011-03-01 10:19:49Z perost $ + * + */ + +#ifndef META_MODELICA_GC_ROOTS_H_ +#define META_MODELICA_GC_ROOTS_H_ + +#include "modelica.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +#define MMC_GC_ROOTS_SIZE_INITIAL 8*1024 /* initial size of roots, reallocate on full */ +/* the roots type is an array of void* with a current index and limits */ +struct mmc_GC_roots_type +{ + modelica_metatype* start; /* the start of tha array of roots */ + modelica_metatype* current; /* the current limit */ + modelica_metatype* limit; /* the limit of roots */ + struct mmc_StackElement* marks; /* the marks in the roots, saves current at certain points */ +}; +typedef struct mmc_GC_roots_type mmc_GC_roots_type; + +/* create the roots structure */ +mmc_GC_roots_type roots_create(long default_roots_size); +/* realloc the roots structure */ +mmc_GC_roots_type roots_realloc(mmc_GC_roots_type roots, long default_roots_size); + +#if defined(__cplusplus) +} +#endif + +#endif /* #define META_MODELICA_GC_ROOTS_H_ */ + diff --git a/c_runtime/meta_modelica_gc_stack.c b/c_runtime/meta_modelica_gc_stack.c new file mode 100644 index 00000000000..d37472b5eb6 --- /dev/null +++ b/c_runtime/meta_modelica_gc_stack.c @@ -0,0 +1,87 @@ +/* + * This file is part of OpenModelica. + * + * Copyright (c) 1998-CurrentYear, Linköping University, + * Department of Computer and Information Science, + * SE-58183 Linköping, Sweden. + * + * All rights reserved. + * + * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF GPL VERSION 3 + * AND THIS OSMC PUBLIC LICENSE (OSMC-PL). + * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES RECIPIENT'S + * ACCEPTANCE OF THE OSMC PUBLIC LICENSE. + * + * The OpenModelica software and the Open Source Modelica + * Consortium (OSMC) Public License (OSMC-PL) are obtained + * from Linköping University, either from the above address, + * from the URLs: http://www.ida.liu.se/projects/OpenModelica or + * http://www.openmodelica.org, and in the OpenModelica distribution. + * GNU version 3 is obtained from: http://www.gnu.org/copyleft/gpl.html. + * + * This program is distributed WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH + * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS + * OF OSMC-PL. + * + * See the full OSMC Public License conditions for more details. + * + */ + +#include "modelica.h" + +/* make an empty stack. */ +mmc_Stack stack_create(void) +{ + return NULL; +} + +/* Return nonzero if the stack is empty. */ +int stack_empty(mmc_Stack stack) +{ + return stack == NULL; +} + +/* peek stack */ +long stack_peek(mmc_Stack stack) +{ + assert (!stack_empty(stack)); + return (stack->el); +} + +/* pop the stack */ +long stack_pop(mmc_Stack* stack) +{ + long top; + mmc_Stack rest; + + assert (!stack_empty(*stack)); + top = (*stack)->el; + rest = (*stack)->next; + free (*stack); + *stack = rest; + return top; +} + +/* push stack */ +void stack_push(mmc_Stack* stack, long el) +{ + mmc_Stack newStack = (mmc_Stack) malloc (sizeof (struct mmc_StackElement)); + + assert(newStack != NULL); + + newStack->el = el; + newStack->next = *stack; + *stack = newStack; +} + +/* delete stack */ +void stack_clear(mmc_Stack* stack) +{ + while (!stack_empty (*stack)) { + stack_pop(stack); + } + stack = NULL; +} + diff --git a/c_runtime/meta_modelica_gc_stack.h b/c_runtime/meta_modelica_gc_stack.h new file mode 100644 index 00000000000..882f864cfff --- /dev/null +++ b/c_runtime/meta_modelica_gc_stack.h @@ -0,0 +1,68 @@ +/* + * This file is part of OpenModelica. + * + * Copyright (c) 1998-CurrentYear, Linköping University, + * Department of Computer and Information Science, + * SE-58183 Linköping, Sweden. + * + * All rights reserved. + * + * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF GPL VERSION 3 + * AND THIS OSMC PUBLIC LICENSE (OSMC-PL). + * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES RECIPIENT'S + * ACCEPTANCE OF THE OSMC PUBLIC LICENSE. + * + * The OpenModelica software and the Open Source Modelica + * Consortium (OSMC) Public License (OSMC-PL) are obtained + * from Linköping University, either from the above address, + * from the URLs: http://www.ida.liu.se/projects/OpenModelica or + * http://www.openmodelica.org, and in the OpenModelica distribution. + * GNU version 3 is obtained from: http://www.gnu.org/copyleft/gpl.html. + * + * This program is distributed WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH + * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS + * OF OSMC-PL. + * + * See the full OSMC Public License conditions for more details. + * + */ + +#ifndef META_MODELICA_GC_STACK_H_ +#define META_MODELICA_GC_STACK_H_ + +#include "modelica.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +/* A stack as a linked list. */ +struct mmc_StackElement +{ + long el; + struct mmc_StackElement* next; +}; + +typedef struct mmc_StackElement* mmc_Stack; + +/* make an empty stack */ +mmc_Stack stack_create(void); +/* check if stack is empty, nonzero */ +int stack_empty(mmc_Stack stack); +/* peek stack */ +long stack_peek(mmc_Stack stack); +/* pop the stack */ +long stack_pop(mmc_Stack* stack); +/* push stack */ +void stack_push(mmc_Stack* stack, long el); +/* delete stack */ +void stack_clear(mmc_Stack* stack); + +#if defined(__cplusplus) +} +#endif + +#endif /* #define META_MODELICA_STACK_H_ */ + diff --git a/c_runtime/meta_modelica_gc_stats.c b/c_runtime/meta_modelica_gc_stats.c new file mode 100644 index 00000000000..f760b367d01 --- /dev/null +++ b/c_runtime/meta_modelica_gc_stats.c @@ -0,0 +1,49 @@ +/* + * This file is part of OpenModelica. + * + * Copyright (c) 1998-CurrentYear, Linköping University, + * Department of Computer and Information Science, + * SE-58183 Linköping, Sweden. + * + * All rights reserved. + * + * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF GPL VERSION 3 + * AND THIS OSMC PUBLIC LICENSE (OSMC-PL). + * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES RECIPIENT'S + * ACCEPTANCE OF THE OSMC PUBLIC LICENSE. + * + * The OpenModelica software and the Open Source Modelica + * Consortium (OSMC) Public License (OSMC-PL) are obtained + * from Linköping University, either from the above address, + * from the URLs: http://www.ida.liu.se/projects/OpenModelica or + * http://www.openmodelica.org, and in the OpenModelica distribution. + * GNU version 3 is obtained from: http://www.gnu.org/copyleft/gpl.html. + * + * This program is distributed WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH + * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS + * OF OSMC-PL. + * + * See the full OSMC Public License conditions for more details. + * + */ + +/* + * Adrian Pop [Adrian.Pop@liu.se] + * This file implements GC statistics + * + * RCS: $Id: meta_modelica_gc_stats.c 8047 2011-03-01 10:19:49Z perost $ + * + */ + +#include "modelica.h" + +/* create the statistics structure */ +mmc_GC_stats_type stats_create(void) +{ + mmc_GC_stats_type stats = {0, 0, 0}; + return stats; +} + + diff --git a/c_runtime/meta_modelica_gc_stats.h b/c_runtime/meta_modelica_gc_stats.h new file mode 100644 index 00000000000..60bc87155d1 --- /dev/null +++ b/c_runtime/meta_modelica_gc_stats.h @@ -0,0 +1,66 @@ +/* + * This file is part of OpenModelica. + * + * Copyright (c) 1998-CurrentYear, Linköping University, + * Department of Computer and Information Science, + * SE-58183 Linköping, Sweden. + * + * All rights reserved. + * + * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF GPL VERSION 3 + * AND THIS OSMC PUBLIC LICENSE (OSMC-PL). + * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES RECIPIENT'S + * ACCEPTANCE OF THE OSMC PUBLIC LICENSE. + * + * The OpenModelica software and the Open Source Modelica + * Consortium (OSMC) Public License (OSMC-PL) are obtained + * from Linköping University, either from the above address, + * from the URLs: http://www.ida.liu.se/projects/OpenModelica or + * http://www.openmodelica.org, and in the OpenModelica distribution. + * GNU version 3 is obtained from: http://www.gnu.org/copyleft/gpl.html. + * + * This program is distributed WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH + * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS + * OF OSMC-PL. + * + * See the full OSMC Public License conditions for more details. + * + */ + +/* + * Adrian Pop [Adrian.Pop@liu.se] + * This file implements GC statistics + * + * RCS: $Id: meta_modelica_gc_stats.h 8047 2011-03-01 10:19:49Z perost $ + * + */ + +#ifndef META_MODELICA_GC_STATS_H_ +#define META_MODELICA_GC_STATS_H_ + +#include "modelica.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +/* GC statistics, add more here if needed */ +struct mmc_GC_stats_type +{ + long allocated; /* the total allocated memory */ + long collected; /* the total collected memory */ + long collections; /* the number of performed collections */ +}; +typedef struct mmc_GC_stats_type mmc_GC_stats_type; + +/* create the statistics structure */ +mmc_GC_stats_type stats_create(void); + +#if defined(__cplusplus) +} +#endif + +#endif /* #define META_MODELICA_GC_STATS_H_ */ +