The machine and the system

This document defines Kueea Abstract Machine Version 1, a service in the context of Kueea Network. [NETWORK]

The service abstracts a set of multiple computing machines, which are required to operate in tandem, into a single machine. All participating machines must compatibly implement a system, which is responsible for sending, receiving and processing of protocol messages.

Memory

A bit is a Boolean data type [BOOL] that is either set or cleared.

A byte is an ordered sequence of bits, where each bit is given a number, beginning with zero. In case where there is significance attached to the bits, the number is also the level of bit significance, i.e. bit 0 is the least significant bit.

An octet is byte of at least 8 bits.

There are three distinct memory (address) spaces: machine memory, virtual memory and physical memory.

Virtual memory

Virtual memory is a sequence of 264 octets. Each octet is assigned a 64-bit virtual address, in sequence order, beginning with 0.

All bits except bits 0 to 7 are assumed to be cleared when loading octets and are cleared when saving/storing them to memory.

Every virtual address translates to a machine address.

Virtual addresss 0 is reserved as the null-reference value.

Machine memory

Machine memory is a segmented memory space, composed of 2128 distinct non-overlapping segments. A segment is a sequence of 264 octets.

Each octet is assigned a unique 192-bit machine address. The most significant 128 bits of a machine address uniquely identifies the segment, the remaining 64-bit identifies an octet within the segment.

Every allocated machine address translates to a physical address.

Segment/node 0 is reserved for the null-reference value.

Physical memory

Physical memory is a sequence of octets. Each octet is assigned a unique physical address, in sequence order, beginning with 0.

Physical memory provides an input and/or output channel from/to a device. The amount of bits saved at and loaded from a physical address depends on the device mapped onto the address.

Objects

Objects give meaning to octets stored in memory.

An object is composed of at least:

  • object data;
  • object type;
  • nonce value;
  • reference counter.

Object data is a non-empty sequence of octets stored at a continous ascending sequence of machine addresses which must all be part of the same segment.

An object type defines the semantics and structure of object data.

There is only one fundamental type - the octet.

A nonce is a randomly generated 64-bit value, assigned to an object for the purpose of differentiating between different objects stored at the same machine address.

A reference counter is a non-negative integer, which indicates the current amount of associated access contexts.

Value types and registers

A register is an abstract storage location. It contains one value of a given value type.

The amount of registers is infinite. Understand registers as "memory that is not machine memory".

A value type identifies a range of values. It has no associated operations defined, including storing it to and loading it from machine memory.

For example, if one would like to add two integer values, one has to define the addition operation as a function first.

Handle

A handle is a reference to object data with associated [access rights][].

Opaque

An opaque value is a sequence of at most 4096 octets.

Unsigned integers

Unsigned integer vectors

Signed integers

Signed integer vectors

Binary floating point numbers

Decimal floating point numbers

Functions

A parameter is a value passed via a register.

An input parameter is a parameter, passed from the function caller to the called function.

An output parameter is a parameter, passed from the called function to the function caller.

A function is a machine operation, defined by a description of what it does and its input and output parameters.

Functions that return an error code

An error code is a special output parameter. It is an unsigned integer value which references a human-readable message describing an unexpected situation. Value of zero means that the function has nothing to report.

When a function succeeds, it returns an error code equal to zero.

When a function fails, it returns an error code not equal to zero and pushes metadata about the failure onto the status stack. The innermost function clears the stack beforehand.

Functions that do not return an error code

If a function does not define any error codes, it either succeeds or pushes metadata about the failure onto the status stack and immediately causes the task to fail.

Functions that do tests and comparisions

If a function does a test or a comparision, it returns the result of the test or comparision in a way that, upon return from the function, the caller can immediately execute conditional instructions.

Faces

A type descriptor is read-only data, which is part of object data of some object, containing information on an object type, but is itself not an object and has no defined object type.

Type descriptors are stored within object data of an object whose object type is a list of type descriptors.

A face is a part of a type descriptor, extending it with additional data, the data usually being references to functions that are implementations of function prototypes defined by the face.

A face can also define data to be included as object data, but it cannot be directly allocated as an object.

Programs are written to either manipulate an object based on its type or based on its faces.

Paths

A path is an identifier for a named resource. (Data such as configuration data, assets used by a game engine, style sheets, generally data stored in non-volatile memory.)

There are four kinds of resources named by paths:

  • read-only resources, which are distributed alongside M-Build images,
  • node-specific resources, which are stored at the node executing the task,
  • synchronized resources, which are synchronized against a synchronization point that ensures the resource state is the same for all nodes at any given point in time.
  • user-provided resources, which serve as input from and output to the user; paths are not declared for these, the user provides them.

Modules

A Kueea AMv1 Module is a special object. At most one instance of a module exists per node.

Modules are defined by Kueea AMv1 Module Declaration Documents. [MDOC] They contain declarations of object types, faces, functions and paths.

M-Build

An M-Build is a particular implementation of functions declared by a given module.

An M-Build image is a data object that contains one or more M-Builds. It is a program image interpreted and executed by a system.

Each M-Build image is uniquely identified based on the program image of M-Builds it contains.

System

This section defines system requirements.

Application Binary Interface

Some implementation-specific rules of how the machine works are defined in a separate document, different for each hardware architecture. These documents define the system's ABI.

Node

A Kueea AMv1 Node is a physical or virtual machine.

Each node is assigned a segment of machine memory. The segment contains devices that are exposed by the node.

Every node which is part of an abstract machine must implement a system required by the machine.

Note: One physical machine may function as more than one node.

Modules

Nodes maintain a module state for each module.

The state is initially destructed (no instance).

When destructed, the module's constructor may be called. If successful, the module state becomes constructed.

Once constructed, module functions of the module can be called.

Tasks

A task is a system construct, of which some properties are defined by this document, that handles the execution of the requested function.

Tasks are created in response to messages received via the protocol. Once a task finishes, the system sends the result computed by the task as the response to the message, at which point there is no more need for the task - it is removed from the system.

When a task fails, it means that the execution of the requested function could not complete.

Each task has a status stack, a stack of metadata explaining why has a function failed.

If everything goes well, the task succeeds.

In both cases, the task has finished execution.

Access contexts

An access context associates object data with a sequence of virtual addresses.

When an access context gains [access rights][] to an object, its data becomes accessible, with accordance to the gained rights, via virtual addresses managed by the context and the reference counter is increased.

When an access context loses [access rights][] to an object, its data becomes inaccessible, with accordance to the gained rights, via virtual addresses managed by the context and the reference counter is decreased.

Each gained or lost access right to an object is tracked by a context. If a context gains the same rights to an object multiple times, it must also lose the same rights the same amount of times for the context to actually lose said rights.

Each task has its own separate virtual memory space, controlled by three separate access contexts:

  • tsk: task context, which is different for each task;
  • mod: module context, which is the same for all functions of a given module; and
  • sys: system context, which is the same for all tasks of a given node.

Both tsk and mod contexts contain only data, while sys contains both data and executable code.

Some of the objects in sys are only accessible while a task is in a system-defined system mode. In most cases, it is a privileged mode of the underlying hardware.

The current mod is determined by the currently executing function.

A tsk address is a virtual address managed by [tsk][].

A mod address is a virtual address managed by [mod][].

A sys address is a virtual address managed by [sys][].

The same object may be accessible via each of the there addresses.

A module function is a function, which requires access to its module context.

A system function is a function, which requires system mode to be active.

Object allocation

In order to allocate an object, the system reserves a consecutive sequence of [octets][] from the machine memory and assigns it as object data. An object descriptor for the object is created and the associated area of memory becomes unavailable for reservation.

Each task has associated allocator parameters. Whenever a task allocates memory, the parameters are inspected to determine the memory’s required type and location. The amount of octets and type are not included in the parameters.

In order to deallocate an object, the system makes the machine memory area corresponding to the object’s object data available for reservation.

Object lifetime

An init function of an object iniitializes all octets of object data to some iniital state.

The fini function of an object prepares the object for deallocation.

The ipre function of an object initializes only those octets of object data which are required for a subsequent successful invocation of `fini`.

When a task makes an object:

  1. The task requests the system to allocate the object. The task has gained access to the object.
  2. The task invokes the `ipre` function.
  3. The task invokes the `init` function. If it fails, the task loses access to the object.

When an object’s reference counter is decreased to zero:

  1. The system invokes the `fini` function in a new task.
  2. The system deallocates the object, regardless of whether the function succeeded or not.

Protocol

PLACEHOLDER.

This section defines the Kueea AMv1 Function Call Protocol, which is identified by the external reference [NETWORK] TO-BE-DECIDED.