Copyright © 2002 Southern Storm Software, Pty Ltd.
Permission to distribute unmodified copies of this work is hereby granted.
ilrun
, to embedded operating environments.For the purposes of this document, an embedded operating environment is any system with a limited amount of RAM, little or no secondary storage, and a restricted set of I/O devices or user purpose.
Note: this document describes how to reduce the size of the engine so
that it can operate in an embedded environment. It does not describe
how to reduce the size of the runtime C# class library, pnetlib
.
Reducing the class library is a separate problem.
Primarily, if the engine allocates a block of memory, it is assumed that the block is fixed in place until it is freed.
Operating environments that attempt to reclaim memory by shifting previously allocated blocks will not work, unless the environment has some kind of virtual memory capability for remapping memory pages while retaining the original virtual addresses.
The Portable.NET engine does not have any hooks that would allow it to "return back" to a co-operative multi-tasking system at regular intervals. Any other tasks or devices in the system will need to be serviced via a pre-emptive kernel.
It is recommended that the system have at least 1 Mb of RAM. It may be possible to use the engine with smaller configurations, but the list of features will need to be heavily trimmed.
We assume that the compilation environment is GNU-compatible, with at least gcc, GNU make, autoconf, and automake available. Using other compile environments will require a lot of work.
We also assume that the operating environment's C library provides ANSI-like features such as stdio, string, and stdlib. So, you will need an embedded version of libc. The following are some suggestions:
support
" directory contains the bulk of the platform
specific code (with the exception of some math routines in the engine).This directory is the first place to start when porting the engine to a new environment. You may need to replace memory management, locale handling, file operations, socket operations, threading, and floating-point routines, depending upon the operating environment.
Usually the "configure
" script is smart enough to detect
most platform-specific features, so you should only replace code in
"support
" if the environment is too strange for
"configure
" to detect automatically.
Some of the files in "support
" are generic ANSI C
(e.g. mempool.c
, hashtab.c
, utf8.c
),
and usually won't need to be replaced. However, your environment
may already have similar routines (especially for UTF-8 handling),
which you may want to use to reduce duplication.
Each profile is defined by a file in the "profiles
" directory.
At compile time, the profile is converted into the header file
"include/il_profile.h
". Definitions in this header file
are used to control which features are compiled into the final engine.
The profile is selected at build time using a "configure
"
option:
./configure --with-profile=kernel
The default profile is "full
", which enables all features.
You may need to define a new profile that describes the capabilities of
your embedded environment. Add a new file to the "profiles
"
directory and rebuild the system.
The following table summarises the available profile options:
IL_CONFIG_REDUCE_CODE
IL_CONFIG_REDUCE_DATA
IL_CONFIG_DIRECT
IL_CONFIG_UNROLL
IL_CONFIG_JAVA
IL_CONFIG_LATIN1
IL_CONFIG_CACHE_PAGE_SIZE
IL_CONFIG_STACK_SIZE
IL_CONFIG_FRAME_STACK_SIZE
IL_CONFIG_GROW_FRAMES
is set.IL_CONFIG_GC_HEAP_SIZE
IL_CONFIG_PINVOKE
IL_CONFIG_REFLECTION
System.Reflection
" classes
if set.IL_CONFIG_NETWORKING
System.Net
" classes if set.IL_CONFIG_FP_SUPPORTED
System.NotSupportedException
".IL_CONFIG_EXTENDED_NUMERICS
System.Math
",
"System.Single
", "System.Double
",
and "System.Decimal
" classes if set. This
option will be ignored if IL_CONFIG_FP_SUPPORTED
is not set.IL_CONFIG_NON_VECTOR_ARRAYS
IL_CONFIG_APPDOMAINS
IL_CONFIG_REMOTING
IL_CONFIG_VARARGS
IL_CONFIG_GROW_FRAMES
IL_CONFIG_FILTERED_EXCEPTIONS
IL_CONFIG_DEBUG_LINES
configure
options that can be supplied to alter the memory requirements
and feature lists:
--enable-threads=none
--without-libffi
--without-libgc
If you configure the system with the "--without-libgc
"
option, you will get a default garbage collector implementation
(support/def_gc.c
).
The default implementation allocates a fixed-sized block of memory and begins allocating from the lowest address. It keeps allocating until the block is full. At that time, out of memory is reported and the system stops. "Real" garbage collection is not performed.
This implementation may be suitable for use on low-memory devices where the application has been specially written to control its memory usage. It is unlikely to be suitable for executing arbitrary applications.
When porting the engine, you can replace "def_gc.c
"
with your own garbage collector, tuned to the particulars of
your embedded environment.
The replacement algorithm must be a conservative collector, able to locate all stack-based and register-based roots on its own. Other roots are specified by the engine when it allocates "persistent" GC memory blocks. Objects are identified by pointer, not handle.
The GC should not move objects when it performs garbage collection, and it must be capable of detecting "interior" pointers, which point to the interior of an object rather than its beginning.
The collector also must be able to suspend all threads cleanly to
perform mark and sweep collection. This may require some work in
the thread support code to synchronise GC suspension with normal
thread suspension (ILThreadSuspend
).
There is no support in the Portable.NET engine for handle-based or compacting garbage collectors. A complete rewrite of the engine would be required, and we have no plans to support such collectors.
ilrun
" program.
This may not be possible in an embedded operating environment.
The "engine/ilrun.c
" file demonstrates how to initialize
and launch applications within the engine. Similar code will be required
when embedding into other environments. The minimum steps required
are:
ILExecInit
".ILExecProcessCreate
".ILExecProcessLoadFile
" or something similar.ILExecProcessGetEntry
".ILExecProcessGetMain
".ILExecThreadCall
".ILExecProcessDestroy
" (may not be necessary
if the application is "infinite").