Cosm Programmers Guide
Version: 2000-Nov-23
Overview
The purpose of this document is to establish common programming
methods for those developing code compatable with the Cosm libraries.
Development Cycle
Since we use CVS the development cycle is continuous. Coders should
make sure they are familiar with CVS and
cvs.html.
Coordination
_Any_ questions at all, ask. Before implementing any additional low level
functions inform me, so we can make sure there isn't any overlap. I intend
to be familiar with every line of code, so if you need any "major"
functionality let me know, someone else may already be working on it. Also,
if you're going to do anything "neat" be sure and inform me first, just so
more than one person knows what you're doing.
Use of Other Code and Libraries
All code must be original and your own writing, you can't cut-n-paste from
_any_ other projects or code libraries due to license problems (and other code
won't follow the Cosm standards anyway). I've made sure there are no license
problems with the couple of libraries that are eventually needed, and even
then they will be completely separated from the main code.
Simplicity
Simplicity and clarity in the code are more important than weird optimization
tricks. Especially since all the real work is done in the cores. All code
interfaces are designed to be as simple as possible.
Thread Safe Code
All Cosm routines must be fully thread safe. This is not optional. If you
don't know how to use locks correctly please go read up, there are many
sources on the net on using locks. Keep in mind also that 64 and 128bit
data types may not be atomic.
Portability
Straight ANSI C + GNU Assembly. Period.
For numerous reasons of portability and readability Cosm will be written in
straight ANSI C. The ASM optimizations should be done in GNU-ASM for
portability to all OS variants of a given chip. C++ Is nice, but has caused
a great deal of strange porting problems in the past requiring the addition
of many #define and #ifdef statements. Pointers are of unknown length so
care must be taken not to do pointer math. The non-portable types int/long
etc. should only be used as return values for pass/fail/error functions.
Testing
The v3_TestModule() functions must test all the functions in a file, causing
all cases to be taken within the functions and all outcomes and errors to be
generated. Cosm will also use the "well tested, infrequent release"
philosophy, not "rapid release, let the user debug it" one. All code should
always be kept in a state where it can be compiled without errors/warnings.
Never submit code that you can't compile. The v3_TestModule() code will also
serve as the example code, so it must be complete and correct.
Comments
Comments, comments, comments. In general anything more complex then a
for( ... ) loop should have a comment in the code every few lines. Function
definitions should also be documented (in the header file) with the
parameters, return values, and error conditions. Any { } block longer
then ~30 (1/2 page) lines should have a comment at the closing }
Header Files
Header files for a given C file should contain all defines, structs, and
function prototypes for the code. Functions should appear in the .c file in
the same order they appear in the .h file, the 'helper' functions (v3_*)
after main interface functions (v3*). Defines should be used liberally, and
constants directly in the code where the meaning isn't obvious (read:
everywhere) should not be used. Any other non-Cosm header files that are
needed for the .c file should be included at the top of the .c, not in the
.h which should only include it's own information. Only if a .h is needed
for the .h to parse should it be included from the .h.
Headers also contain the programmer documentation for a function, what it
does, parameters, and expected return values or errors. No one should ever
have to find and then dig around .c files to be able to use a function, and
so any documentation should be in the header. All things will eventually be
documented in non-programmer language in other formats.
Structure Alignment
All structures that will be written to the network or files, or used in an
array MUST be properly aligned, padding if needed. This means that u64 and
u128 data types must fall on 8 byte boundries, u32 on 4 byte boundries, and
u16s on 2 byte boundries. The length of the structure must also be aligned
for the biggest type, so if a struct has a u64, it has to be a multiple of
8 bytes long, etc. Becasue of this only platform specific structures
that never leave memory (like a mutex) are immune to this requirement. See
the sample code below for examples.
Version Control
Version numbers for any code or files must be incremented when any change is
made. Problems caused by a non-incremented version number can be quite
difficult to track. Luckily, CVS does a wonderful job of this. CVS also
does a great job of tracking changes and history. Make sure your messages
on commited code are descriptive. Do no use the top of a .c file for the
history, it quickly takes over the entire file.
#ifdef Usage
System specific #ifdef for OS/CPU is only allowed in utility level libraries.
The only #ifdefs in the main level of code should be for a 32/64 bit constant
number definition. When doing any test for CPU/OS type, use globally defined
OS_TYPE and CPU_TYPE to switch off of e.g. #if ( OS_TYPE == OS_MACOSX ) - this
is more readable to people not familiar with each compilers/os/cpu, and so it
is less likely to lead to confusion.
Naming Conventions
All names should make sense and be long enough for the code to be self
documenting
v3
All Cosm variables, functions, structures, and defines start with either
"v3_", "v3", "V3_", or "_V3_" during pre-release development. This prefix
will change as the phases change to avoid any unintended use of legacy
functions.
Source File Names
file.c and file.h should have the same base name
Functions
All functions should begin with a capital letter and each word within a
function name should be capitalized, e.g. ReadConfig( char * filename );
Library Functions
All user level functions should begin with "v3", The module pneumonic, and
each word within a function name should be capitalized, e.g. v3DFSSpace( u64
userid ); All low level functions should begin with "v3_" and be named in a
similar manner e.g. v3_DFSSpace( ... );.
Local Variables and Function Arguments
Loop variables can be one letter, e.g. u32 x, y, z; anything else should be
descriptive and lower case "_" should be used between words in local
variables. e.g. u64 word_count;
Global Variables
Don't even think about it. No global variables exist in Cosm (well, just 2).
No, no, no, and no. P.S. No. Users will need them in cores and modules
however, so they aren't evil, but never part of an API.
When we do have to use then, they start with "__".
Structures
Structures should be named in all upper case with _'s e.g. struct
v3_PACKET_HEADER {...}; Structure members should be lower case as per Local
Variables. Note that Cosm structures start with v3_ and not V3_ which is the
distinction between structs and a defines.
Defines
Defines are in all upper case as per C standard e.g.
#define V3_FOO 30
Macros
Macros are in all upper case beginning with "_V3_" e.g.
#define _V3_BAR( x ) run_bar( x ); return;
Code Style
Liberal Spacing
DontCrunchTheCodeAllTogether( void ); e.g. for( i = 0 ; i < 42 ; i += 3 ) Each
statement should be on it's own line. Statements that are long should be
wrapped to the next line at the 78th column or less so that printing is
possible. Any logic more then one line (for, while, if-else) should use a
set of { } for clarity. funtions( x ) and macros( 3 ) do not have a space
between the function name and firt paren. Typecasts (ascii *) also do not have
the extra spaces to that they can be distinguished from parameters.
Indenting
2 spaces for every level of logic, and 2 additional spaces when a line is
wrapped. Tabs should never be used, as they are editor dependant.
When wrapping a line with a "||" or any other logical operator, the operator
should start the second line, not end the first.
Width
Keep everything within the standard 78 columns, wrap lines when needed. Some
of the code will need to be printed, snail-mailed, or OCR'd into other
countries. There is one important exception to this, in the html documentation
for functions the width of example code must be 70 columns or less, due how
man pages are displayed.
Example:
-- blah.h --
When return( ... ) is used, always use the ()'s.
int, char, short
int, char, short etc. are not used in the APIs. All parameters are of
the universal cputypes.h formats. int can be used internally (with care) for
any temp variables, for/while loops, system calls, etc.
Parameter order
When a function takes parameters, they should be (destination, source) similar
to ( a = b ).
Additional keywords (for syntax highlighting):
u8 u16 u32 u64 u128 s8 s16 s32 s64 s128 f32 f64 ascii unicode
Program names
Program names end in ".exe" reguardless of platform. Some platforms
require this, the rest dont care. This way a program's name is always fixed.
Credit Where Credit is Due
A master CREDITS(.txt) file will be maintained where a list of names of the
people that made a significant contribution to writing the code. People will
be divided into categories as implementers, porters, and miscellaneous.
Common Pitfalls
Error Code Checking
All function error codes must be checked and acted on accordingly.
Network Buffers and Memory Overruns
Buffer overrun and bad memory allocation should always be checked for.
Use of Uncleared Structs
Structures need to be either v3MemeAlloc'd or v3MemSet to zero before use.
Structures on the local stack will have random values when the function
is entered.
Pointer Math
Never cast a pointer to a u32 or u64 to do pointer math. You do not know if
the pointers will be 32 or 64bits wide on the destination chip, and there is
no good reason to do pointer math outside of the ASM tweaked (and therefore
CPU specific) cores.
NULL Pointers
Check for NULL pointers before all operations. Be especially careful of
library functions i.e. memcpy() as many machines have libraries that have
problems with NULLs.
Typecasting
Most things should be typecast normally, like (ascii *) stings. However,
s64, u64, s128, and u128 cannot be typecast because they are structures on
some systems. For these types macro/functions are provided in cosmmath.
Memory Leaks
Always Make sure any memory allocation has a matching memory free.
© Mithral Communications & Design Inc.
1995-2010.
All rights reserved.
Mithral® and Cosm® are trademarks of
Mithral Communications & Design Inc.