Genesis Project
This document is part of the genesis project. See the project homepage at genesisae.sf.net for more information. This document is (or was) hosted by SourceForge.

Buran (gs6854-01)

Simon Ruoss

Attention: The document is only a draft and GS6854-01 might change.

Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the section entitled "GNU Free Documentation License".

Revision History
Revision 02003-05-12

Initial Version

Revision 12003-05-13

Changed some APIs and add chapter about endianness

Revision 22003-05-21

Changed layout and corrected some APIs

Revision 32003-07-07

Added the Singal-API and Interrupt-API

Revision 42003-08-21

Modified the Messaging API and marked SigInfo as deprecated.

Revision 52003-09-27

Removed SigInfo. Removed DiffEndian and added a "diff-endian-bit" to oid_t to replace the DiffEndian call. Changed the way how interrupts are raised.

Revision 62003-10-28

MsgReply returns now a ret-value. Decreased number of guaranteed signals. Some corrections. Renamed IntAttach to IntHandler.

Revision 72004-01-29

Removed interrupt API (use signals to achieve the same). Removed automatic integer conversion.


Introduction

Buran is the Genesis micro kernel. It provides a basic interface that looks like the QNX4(R)(tm) micro kernel interface (www.qnx.com). Buran provides synchronous interprocess messaging and a kind of semaphores. The Buran system-calls are the only direct system-calls available to genesis-applications.

Buran Logo

Figure 1. Buran Logo

Buran Logo

Buran API (Application Programming Interface)

I tried to keep the Buran-API as small and simple as possible. There are only 12 kernel-calls:

  • MsgSend

  • MsgSendNB

  • MsgRecv

  • MsgRecvNB

  • MsgReply

  • MsgRead

  • SigNumSignals

  • SigSetRights

  • SigSet

  • SigGet

  • SigOp

  • MapOID

This document describes only the portable part of the Buran-API. If you need to see how to call these functions on a specific platform, see gs6854-0A.

Global Types, Structs and Definitions

Figure 2. Types (C-like code)

typedef [unsigned XX bit integer] uintXX_t;
typedef [signed XX bit integer] intXX_t;

typedef uint32_t pcount_t;
typedef uint32_t oid_t;
typedef uint32_t size_t;

int32_t retval_t;
enum retval_t
{
//any positive integer: own defined ret-code
ret_Success = 0,
ret_NFound = -1,
ret_Denied = -2,
ret_Timeout = -3,
ret_Died = -4,
ret_NReady = -5,
ret_WParameter = -6,
ret_Mem = -7,
ret_Other = -8
//any non defined negative integer: undefined error
};
oid_t

oid_t is a handler to another object. Such a handler is only valid within one object. To make is valid for another object, you have to call MapOID.

Zero is a special value for oid_t. For most calls, a oid_t of zero means a handle to the calling object.

The highest 2 bits of have special meanings/are reserved:

Table 1. highest 2 bits of oid_t

bitmeaning
highest bit (bit 31)This is the integer- and float-incompatibility bit. This bit is set, if the remote object uses incompatible integers (those longer than 1 byte) and floats.
bit 30reserved
lowest 30 bits (bit 0-29)Handler to an object
size_t

size_t is used in the input-/output-vector (iov_t).

The highest 2 bits of size_t are reserved or have a special meaning:

Table 2. highest 2 bits of size_t

bitmeaning
highest bit (bit 31)reserved
bit 30reserved
lowest 30 bits (bit 0-29)The size of the message-part in bytes
retval_t

Every Buran call returns this variable. These return values are predefined. An application can also define its own return values - but should only use values greater than zero (negative numbers and zero are reserved).

Table 3. retval_t meanings

valuemeaning
ret_Successsuccess
ret_NFoundremote object not found (invalid oid_t)
ret_Deniedaccess denied
ret_NReadyremote object is not receiving (MsgSendNB) or sending (MsgRecvNB)
ret_WParameterwrong parameter (e.g. Invalid IO-Vector)
ret_Memout of memory
ret_Timeouttimeout (unstable network)
ret_Diedremote object died
ret_Otherundefined error

Messaging API Calls

Types, Structs and Definitions

Figure 3. The iov_t structure

struct IOV_T
{    
size_t size;
void *msg;
};

typedef struct IOV_T iov_t;

MsgSend/MsgSendNB

MsgSend sends a (multi part) message to the object receiver.

The message (smsg) contains multiple parts (sparts). MsgSend blocks till receiver replies or till timeout. rmsg contains the receiver's reply. MsgSend will return the integer given by retval (see MsgReply) if the function succeeds.

MsgSendNB does the same as MsgSend, but does not block if receiver's not receiving (but of course it blocks while waiting for MsgReply).

Note: The size of the message (all message parts together) should not exceed 65536 (2^16) bytes. You can try to send more data, but then there's a high chance to get an error (e.g. "out of memory").

Figure 4. Declaration

retval_t MsgSend
(
const oid_t receiver,
const iov_t *smsg,
const pcount_t sparts,
iov_t *rmsg,
const pcount_t rparts
);

int MsgSendNB(...see MsgSend...);
receiver

An existing object you send the message to.

smsg

An Input/Output-Vector containing one or more message-parts (exactly: sparts message-parts). The message-parts (msg) of the IOV (Input/Output-Vector) must point to valid memory addresses.

Use null here if sparts is set to 0 (zero).

sparts

Number of messages you want so send. Must correspond to the number of messages you point to in smsg.

rmsg

Points to an IOV that contains one or more message-parts pointing to an allocated memory area (also set size accordingly).

Note: If iov_t.size is incorrect (e.g. If you receive less or more data than specified) the function will fail.

Use null here if rparts is set to 0.

rparts

Number of message-parts you want to receive. Must correspond to the number of messages in rmsg. You can specify less rparts than there are (and read them later by calling MsgRead) - but never try to get more rparts than there are (the function will fail).

MsgRecv/MsgRecvNB

MsgRecve receives a (multi part) message from sender.

MsgRecv blocks till there's a message incoming while MsgRecvNB does not block and returns if there's no sender with a blocking MsgSend-call.

Figure 5. Declaration

retval_t MsgRecv
(
oid_t *sender,
iov_t *rmsg,
pcount_t rparts,
);

int MsgRecvNB(...see MsgRecv...);
sender

An object which you want to receive a message from.

Or 0 (zero) to receive from every object. sender will then be set to the Object-ID you actually received the message from.

rmsg

Points to an IOV that contains one or more message-parts pointing to an allocated memory area (also set size accordingly).

Note: If iov_t.size is incorrect (e.g. If you receive less or more data than specified) the function will fail.

Use null here if rparts is set to 0.

rparts

Number of message-parts you want to receive. Must correspond to the number of messages in rmsg. You can specify less rparts than there are (and read them later by calling MsgRead) - but never try to get more rparts than there are (the function will fail).

MsgReply

MsgReply replies with smsg to sender.

Notes: The size of the message (all message parts together) should not exceed 65536 (2^16) bytes. You can try to send more data, but then there's a high chance to get an error (e.g. "out of memory").

Call MsgReply only after a successful MsgRecv-call! MsgReply may or may not block, it depends on the Buran implementation and on the size of the reply message.

Figure 6. Declaration

retval_t MsgReply
(
const oid_t receiver,
const iov_t *smsg,
const pcount_t sparts
const retval_t retval
);
receiver

An existing object you want to reply to.

smsg

An Input/Output-Vector containing one or more message-parts (exactly: sparts message-parts). The messages (msg) of the IOV (Input/Output-Vector) must point to valid memory addresses.

Note: Buran wont modify smsg.

sparts

Number of message-parts you want so send. Must correspond to the number of messages you point to in smsg.

retval

That's the value MsgSend will return if message-passing succeeded. You can but you should not use negative numbers since they are reserved if message-passing fails (see retval_t).

MsgRead

MsgRead reads the first rparts from the message sender sent. You can use it to receive a message you don't know how many parts it has.

Note: Use the MsgRead only after a successful MsgRecv(NB) or MsgSend call and before another call from the Buran messaging API.

Figure 7. Declaration

retval_t MsgRead
(
const oid_t sender,
iov_t *rmsg,
const pcount_t roffset,
pcount_t rparts
);
sender

The object which you want to read message-parts from.

rmsg

Points to an IOV that contains one or more message-parts pointing to an allocated memory area (also set iov_t.size accordingly).

roffset

MsgRead will start reading from roffset.

Note: roffset has no influence to rmsg. E.g. If you set roffset to 3, MsgRead will copy the third message-part to the first entry of rmsg.

MsgRead will fail if roffset is out of range.

rparts

Number of message-parts you want to receive. Must correspond to the number of messages in rmsg. You can specify less rparts than there are (and read them later by calling MsgRead again) - but never try to get more rparts than there are (the function will fail).

Signal API (Synchronization)

An object can have up to 4294967296 (2^32) signals. A signal (its value) is an 32bit unsigned integer. You can use signals for at least 4 things:

  • to notify an object - use signals to send simple/short messages ("object X" will never block when modifying a signal from "object Y" - and modifying a signal is faster than sending a message using MsgSend)

  • to get information about the object (object X will never block if reading a signal from "object Y")

  • process synchronization - use it like semaphores (manage exclusive access to shared memory or devices)

Note: Signals are big-/little-endian portable. Buran will convert them for you if necessary.

Types, Structs and Definitions

Figure 8. Types

typedef uint32_t signal_t;
typedef uint32_t sigvalue_t;

typedef void* address_t;

enum rights_t
{
sigr_FriendAD = 0,
sigr_FriendRO = 1,
sigr_FriendRW = 2,
sigr_PublicAD = 0,
sigr_PublicRO = 4,
sigr_PublicRW = 8
};

Table 4. meanings of rights_t

valuemeaning
sigr_FriendADaccess denied for friend
sigr_FriendROread-only access for friend
sigr_FriendRWread/write access for friend
sigr_PublicADaccess denied for public
sigr_PublicROread-only access for public
sigr_PublicRWread/write access for public

SigNumSignals

SigNumSignals sets the number of signals you want to use in your object. You can call this function as often as you need it - you can increase and decrease the number of signals.

An object has 0 (zero) signals per default.

Note1: An object has a guarantee of 1024 (2^10) signals. If you try to use more signals than 1024, the call might fail if there's not enough memory available.

Note2: A new signal has a value of 0 (zero) and has no rights (=0).

Figure 9. Declaration

retval_t SigNumSignals
(
const signal_t signals
);
signals

The number of signals you'd like to have

SigSetRights

SigSetRights sets the access rights of a signal.

Figure 10. Declaration

retval_t SigSetRights
(
const signal_t signal,
const rights_t rights,
const oid_t friend
);
signal

The signal

rights

This sets the access rights.

Set the access rights (allow read-only or read/write) for a "friend"-object and set the access rights for public objects. The friend-object can be defined in friend, public objects are all objects except the friend-object.

The rights defined in rights_t can be combined by the OR-bit-operation.

friend

This is a special object which can have more rights than other objects. Set friend to zero if there's no friend-object.

SigSet

SigSet sets the value of a signal. The signal is a signal of yourself (object=0) or the signal of another object.

Figure 11. Declaration

retval_t SigSet
(
const oid_t object,
const signal_t signal,
const sigvalue_t value
);
object

This is the object in which you want to modify a signal. Use object=0 to modify a signal in the calling object.

signal

This is the number of the signal you want to modify.

value

Enter here the value the signal should be set to.

SigGet

SigGet gets the value of a signal. The signal can be a signal of the calling object (object=0) or the signal of another object.

Figure 12. Declaration

retval_t SigGet
(
const oid_t object,
const signal_t signal,
sigvalue_t *value
);
object

This is the object which you want to read the signal-value from. Use object=0 to get a signal of the calling object.

signal

This is the number of the signal you want to read.

value

value will contain the value of the signal.

SigOp

SigOp processes an operation on a signal. SigOp can increase or decrease the value of a signal. If you try to decrease the value of a signal which is already zero, SigOp will block.

Figure 13. Declaration

retval_t SigOp
(
const oid_t object,
const signal_t signal,
const int32_t operation
);
object

This is the object in which you want to modify the signal-value. Use object=0 to modify the signal of the calling object.

signal

This is the signal you want to modify.

operation

If operation is a positive integer, SigOp will increase the signal by abs(operation). If operation is a negative integer, SigOp will decrease the signal by abs(operation).

Other API Calls

MapOID

Object-IDs are only valid within one object. Before you send an object-ID to another object you have to convert it by calling MapOID. MapOID maps an object-ID (object) to a object-ID usable for base. (You need this function if you want base to access object).

Figure 14. Declaration

retval_t MapOID
(
const oid_t base,
oid_t *object,
);
base

The object you map object for.

object

The object you want to map. object will contain the result.

Endianness Portability

Portable Messages

Two communicating objects can be hosted on two different hosts. Since Buran supports big-endian and little-endian machines, data might have to be converted.

See the oid_t-struct whether your local integers and floats are compatible with the remote object's integers. If not, the best is to use only MSB or LSB integers or floats.

Note: Also types composed of integers might have to be converted, such as strings.

Portable Signals

Signals are automatically converted by Buran.