C H A P T E R  2

User API

This chapter describes the User API which consists of functions the user can deploy in the application code. This API consists of three main parts:

Additional information is provided in:


Late-Binding API

The Late-Binding API provides primitives for the synchronization of distributed threads, communication, and memory allocation. This API is treated specially by the tejacc compiler, and is generated dynamically based on contextual information. See the Sun Netra Data Plane Software Suite 2.1 Update 1 User Guide for an overview of this API.

Late-Binding API Data Types


TABLE 2-1 Late-Binding API Data Types

Data Type

Description

teja_channel_t

Channel data type

teja_memory_pool_t

Memory pool data type

teja_mutex_t

Mutex data type

teja_queue_t

Queue data type

teja_thread_t

Thread data type


Late-Binding API Macros


TABLE 2-2 Late-Binding API Macros

Macros

Description

TEJA_INFINITE_WAIT

Used to indicate an infinite timeout in teja_wait().

TEJA_IS_RAW_OS

Defined only on bare hardware systems. Such systems support a subset of the Sun Netra DPS API.

TEJA_NO_EVENT

Used when sending data on a channel to indicate that event logic can be skipped.


Late-Binding API Mutex Functions

teja_mutex_lock

Description

Acquires a mutual exclusion lock. If the mutex is already locked, this function does not return until the mutex becomes available and the lock is acquired for the calling thread. Once the lock is held by the thread, what occurs if this function is called a second time is undefined. If an error is returned, the caller can assume the lock was not acquired.

Syntax

int teja_mutex_lock(teja_mutex_t mutex);

Parameters

mutex - Mutex to lock.

Return Values

int - If successful, this function returns 0. In case of an error, this function
returns -1.

Example


if (teja_mutex_lock (mutex) < 0) 
  { 
    printf (“Error locking mutex\n”); 
  } 
else 
  { 
    printf (“Entered critical region”); 
    /* Wait one second */ 
    teja_wait_time (1, 0); 
    printf (“Exiting critical region”); 
    if (teja_mutex_unlock (mutex) < 0) 
      { 
        printf (“Error unlocking mutex”); 
      } 
  }

teja_mutex_trylock

Description

Attempts to lock the given mutex without blocking. If the mutex is already locked, this function exits immediately returning -1, otherwise the function locks the mutex and returns 0. Once the lock is held by the thread, what occurs if this function is called a second time is undefined.

Syntax

int teja_mutex_trylock(teja_mutex_t mutex);

Parameters

mutex - Mutex to lock.

Return Values

int - If successful, this function returns 0. In case of an error, this function returns
-1.

Example


if (teja_mutex_trylock (mutex) < 0) 
  { 
    printf (“Trickle on mutex fielding”); 
  } 
else 
  { 
    printf (“Entered critical region”); 
    /* Wait one second */ 
    teja_wait_time (1, 0); 
    printf (“Exiting critical region”); 
    if (teja_mutex_unlock (mutex) < 0) 
      {
        printf (“Error unlocking mutex”); 
      } 
  }

teja_mutex_unlock

Description

Unlocks the given mutex. If the mutex was not locked by the current thread the result is undefined. Avoid such behavior.

Syntax

int teja_mutex_unlock(teja_mutex_t mutex);

Parameters

mutex - Mutex to unlock.

Return Values

int - If successful, this function returns 0. In case of an error, this function returns
-1.

Example

See the examples in teja_mutex_lock and teja_mutex_trylock.

Late-Binding API Queue Functions

The first word of the node that is enqueued is permitted to be overwritten by the queue implementation.

teja_queue_enqueue

Description

Enqueues a node into a queue. The queue implementation is permitted to overwrite the first word of the node. If -1 is returned, the queue might be full or some other error has occurred.

Syntax

int teja_queue_enqueue(teja_queue_t queue, void *node);

Parameters

queue - Queue to enqueue to.

node - Pointer to node to enqueue.

Return Values

int - If successful, this function returns 0. In case of an error, this function returns -1.

Example


void * node; 
node = teja_malloc (16); 
if (node) 
  { 
    if (teja_queue_enqueue (queue, node) < 0) 
      { 
        printf (“Error while attempting to enqueue a node”); 
      } 
  }

teja_queue_dequeue

Description

Dequeues a pointer to a node from the queue. The first word of the returned node might have been overwritten by the queue implementation.

Syntax

void *teja_queue_dequeue(teja_queue_t queue);

Parameters

queue - Queue to dequeue from.

Return Values

void * - NULL if the queue was empty or pointer to the dequeued node otherwise.

Example


void * node; 
node = teja_queue_dequeue (queue); 
if (node) 
  { 
    printf (“Dequeued node %x\n”, node); 
  } 
else 
  { 
    printf (“Queue was empty\n”); 
  }

teja_queue_is_empty

Description

Tests to see if the queue is empty.

Syntax

int teja_queue_is_empty(teja_queue_t queue);

Parameters

queue - Queue to test.

Return Values

int - 0 if the queue is not empty, 1 if the queue is empty.

Example


if (teja_queue_is_empty (queue)) 
  {  
    printf ("Queue is empty\n");  
  }  
else  
  {  
    printf ("Queue is not empty\n");  
  }

teja_queue_get_size

Description

Returns the number of elements in the queue. The function returns a value that is a snapshot in time of the depth of the queue. Not all custom implementations support this function. This function is to be used for debug purposes only, because its implementation (when available) is computation intensive and not meant for fast path operation.

Syntax

int teja_queue_get_size(teja_queue_t queue);

Parameters

queue - Queue to obtain size for.

Return Values

int - Value is -1 if implementation is not provided for this custom implementation, or the number of elements currently in the queue.

Example


printf (“Queue size is %d\n”, teja_queue_get_size (queue));

Late-Binding API Memory Pool Functions

teja_memory_pool_get_node

Description

Returns a pointer to a newly allocated fixed-sized node from the given memory pool.

Syntax

void *teja_memory_pool_get_node(teja_memory_pool_t memory-pool);

Parameters

memory-pool - Memory pool to allocate from.

Return Values

void * - NULL if the memory pool is empty or the pointer to the newly allocated node.

Example


void * node;  
node = teja_memory_pool_get_node (pool);  
if (node)  
  {  
    printf ("Got node %x\n", node);  
    if (teja_memory_pool_put_node (pool, node) < 0)  
      {  
        printf ("Error putting back node %x to the pool\n", node);  
      }  
    else  
      {  
        printf ("Node %x was put back to the pool\n", node);  
      }  
  }  
else  
  {  
    printf ("Pool was empty\n");  
  }

teja_memory_pool_put_node

Description

Frees a node back to a memory pool.

Syntax

int teja_memory_pool_put_node(teja_memory_pool_t memory-pool, void *node);

Parameters

memory-pool - Memory pool to return the node to.

node - Pointer to node to free.

Return Values

int - If successful, this function returns 0. In case of an error, this function returns -1.

Example

See the example in teja_memory_pool_get_node.

teja_memory_pool_get_node_from_index

Description

Memory pool nodes are contiguous in memory and have a sequential index number. This function returns the node that corresponds to the given index. The effect of this function is not equivalent to a teja_memory_pool_get_node call because the node is not actually extracted from the pool. For this reason, the node must be allocated and not free in the memory pool when used by the application. For performance reasons, a range check is not performed, so the index value must be valid or a programming flaw might occur.

Syntax

void *teja_memory_pool_get_node_from_index(teja_memory_pool_t memory-pool, int index);

Parameters

memory-pool - Memory pool from which the node belongs.

index - Index of the node.

Return Values

void * - Pointer to the node specified by index.

Example


void * node;  
node = teja_memory_pool_get_node_from_index (pool, 3);  
if (teja_memory_pool_get_index_from_node (pool, node) != 3)  
  {  
    printf ("Impossible!\n");  
  }

teja_memory_pool_get_index_from_node

Description

Memory pool nodes are contiguous in memory and have a sequential index number. This function returns the index that corresponds to the given node pointer. For performance reasons, a range check is not performed, so the node value must be valid or a programming flaw might occur.

Syntax

int teja_memory_pool_get_index_from_node(teja_memory_pool_t memory-pool, void *node);

Parameters

memory-pool - Memory pool from which the node belongs.

Return Values

node - Pointer to a node for which the index is requested.

int - Index of the given node.

Example

See the example in teja_memory_pool_get_node_from_index.

Late-Binding API Channel Functions

teja_channel_is_connection_open

Description

Returns 1 if the connection is open, 0 if the connection is closed.

Syntax

int teja_channel_is_connection_open(teja_channel_t channel);

Parameters

channel - Channel to test.

Return Values

int - 1 if the connection is open, 0 if the connection is closed.

Example

See the example in teja_channel_send.

teja_channel_make_connection

Description

Establishes a connection on the given channel (if the channel requires the connection to be established at runtime).

Syntax

int teja_channel_make_connection(teja_channel_t channel);

Parameters

channel - Channel to operate on.

Return Values

int - 0 if operation was successful, -1 otherwise.

Example

See the example in teja_channel_send.

teja_channel_break_connection

Description

Breaks an existing connection on the given channel.

Syntax

int teja_channel_break_connection(teja_channel_t channel);

Parameters

channel - Channel to operate on.

Return Values

int - 0 if operation was successful, -1 otherwise.

Example

See the example in teja_channel_send.

teja_channel_send

Description

Sends message-size bytes of data into the channel for the user. This function optionally enables users to send an event value that can be used at the receiver to discriminate the data type of the received data. This functionality is useful if multiple data types are sent. The event logic can be disabled by passing TEJA_NO_EVENT. Depending upon the channel implementation, the user might also be signaled at the time the message is sent.

Syntax

int teja_channel_send(teja_channel_t channel, short int event, void *message, int message-size);

Parameters

channel - Channel to send data on.

event - Optional value that is sent on the channel with the data. This value can be used at the receiver to discriminate the data type of the received data. This parameter is optional. Passing the constant TEJA_NO_EVENT causes event logic to be skipped in the code generation.

message - Pointer to the data to send.

message-size - Size of the message being sent (in bytes).

Return Values

int - Number of bytes sent or -1 in case of error.

Example

This example shows how to send data using a channel.


#define MY_EVENT 7  
if (teja_channel_make_connection(chan) < 0)  
  {  
    printf ("Error while estabilishing connecting to the channel\n");  
  }  
if (teja_channel_is_connection_open(chan))  
  {  
    if (teja_channel_send(chan,7,"hello",5) < 0)  
      {  
        printf ("Error sending data on the channel\n");  
      }  
    if (teja_channel_break_connection(chan) < 0)  
      {  
        printf ("Error while tearing down the connection on the channeling”);  
      }  
  }

See also the example in teja_wait, which shows how to receive data from the channel.

Late-Binding API Interruptible Wait

The teja_wait() call enables users to wait for a timeout to expire or for data to arrive on a list of channels, whichever happens first. This function’s semantics are similar to the select() call on UNIX (or Linux) systems. For targets on which the TEJA_IS_RAW_OS constant is not defined, the teja_wait() call can also be interrupted by Sun Netra DPS signals and by registered file descriptors.

teja_wait

Description

Waits for a timeout, for data arriving on one of the channels, or for any registered signals or file descriptor to be triggered, whichever happens first. For more information on signal and file descriptor registration. Channels are checked once before starting the timeout wait.

Syntax

int teja_wait(int seconds, int nanoseconds, int poll-seconds, int poll-nanoseconds, short int *event, void *buffer, int buffer-size, ...);

Parameters

seconds - Number of seconds to wait. Passing TEJA_INFINITE_WAIT causes the function to wait indefinitely.

nanoseconds - Number of nanoseconds to wait. This value must be from 0 to 999999999.

poll-seconds - Number of seconds to wait before polling channels. Passing TEJA_INFINITE_WAIT causes the function not to poll channels.

poll-nanoseconds - Number of nanoseconds to wait before polling channels. This value must be from 0 to 999999999.

event - Pointer to a variable in which the event value is copied. Passing NULL causes event logic to be skipped.

buffer - Pointer to buffer in which received data is copied.

buffer-size - Size of the buffer.

... - List of channels to read from. The list must be NULL terminated.

Return Values

int - Returns -1 if error, 0 if timeout expires, or the number of bytes read from channels and copied into the buffer.

The seconds and nanoseconds parameters identify the timeout. If TEJA_INFINITE_WAIT is passed to seconds, then no timing logic is generated and the function waits indefinitely until some data arrives on the channels. The poll-seconds and poll-nanoseconds identify the amount of time to wait between channel polls, while waiting.

event is an optional parameter. If a non-NULL value is passed the event value coming from the sender is copied in the variable pointed by the event parameter. Typically event is used to discriminate among a set of possible types for the received data so the event can determine what data type to cast the received data to. In case event is not needed (for example, if only one data type is sent on the channel) then the code generator can be instructed to skip event management logic by using TEJA_NO_EVENT at the sender and NULL at the receiver.

Buffer and buffer-size identify the buffer in which received data is copied and its size.

The final variable argument list consists of a NULL-terminated channel list. The order in which channels are listed is the same that is used to poll channels. If no channels are listed, then only timing logic is generated.



Note - This function may not be invoked at initialization time.


Example

This example shows how to receive data from a channel using teja_wait().


#define BUF_SIZE 16  
#define MY_EVENT 7  
#define MY_OTHER_EVENT 8 
struct A 
{ 
  short int x;  
  short int y;  
};  
int ret;  
short int evt;  
char buf[BUF_SIZE];  
ret = teja_wait (TEJA_INFINITE_WAIT, 0, 1, 0, &evt, buf, BUF_SIZE, chan, NULL);  
if (ret > 0)  
  {  
    switch (evt)  
      {  
      case MY_EVENT:  
        printf ("%s\n", buf);  
        break;  
      case MY_OTHER_EVENT:  
        printf ("%d,%d\n", ((struct A *)buf)->x, ((struct A *)buf)->y);  
        break;  
      }  
  }  
else if (ret == 0)  
  {  
    printf ("timeout expired\n");  
  }  
else  
  {  
    printf ("teja_wait encountered an error\n");  
  }

See also the example in teja_channel_send, which shows how to send data.


Sun Netra DPS Runtime API

The Sun Netra DPS Runtime API consists of portable abstractions over various operating system facilities such as threads, nonmemory pool-based memory management, thread management, socket communication, and signal registration and handling. Unlike late-binding APIs, Sun Netra DPS Runtime APIs are not treated specially by the compiler and are implemented in precompiled libraries. See the Sun Netra Data Plane Software Suite 2.1 Update 1 User Guide for an overview of this API.

Sun Netra DPS Runtime API Data Types


TABLE 2-3 Sun Netra DPS Runtime API Data Types

Data Type

Description

int8_t

8-bit integer type

int16_t

16-bit integer type

int32_t

32-bit integer type

int64_t

64-bit integer type

teja_fd_handler_t

fd handler type, used with teja_register_fd(). This data type has the following prototype: int (*handler) (teja_socket_t fd, void *signal-context, short int *event, void *msg, int msg-max-size)

teja_signal_handler_t

Signal handler type, used with teja_register_fd(). This data type has the following prototype: int (*handler) (int sig_code, void *signal-context, short int *event, void *msg, int msg-max-size)

teja_sockaddr_t

Sockaddr type, used with socket API

teja_socket_t

Socket type, used with socket API

teja_socklen_t

Socklen type, used with socket API

teja_thread_function_t

Thread function. Has the following prototype: void * (*function) (void *)

teja_thread_handle_t

Thread handle type

uint8_t

8-bit unsigned integer type

uint16_t

16-bit unsigned integer type

uint32_t

32-bit unsigned integer type

uint64_t

64-bit unsigned integer type



TABLE 2-4 Sun Netra DPS Runtime API Macros

Macros

Description

TEJA_DEFAULT_STACK_SIZE

Default stack size for newly started threads (for example, only software architecture threads).

TEJA_IS_RAW_OS

Informs the user that running on an OS or in bare hw mode. In NDPS it is always true.


Sun Netra DPS Runtime API Memory Management Functions

The memory management functions offer malloc and free functionality. These functions are computation expensive and only used in initialization code or non-relative critical code. On bare hardware targets the free() function is an empty operation, so use malloc() only to obtain memory that is not meant to be released. For all other purposes, use the memory pool API.

teja_free

Description

Frees memory buffer. On bare hardware targets this operation is empty.

Syntax

void teja_free(void *ptr);

Parameters

ptr - Pointer to buffer to free.

Return Values

void

teja_malloc

Description

Allocates memory buffer of specified size. On bare hardware targets the teja_free() operation is empty, so use teja_malloc()only to obtain memory that is not meant to be released. For all other purposes, use the memory pool API.

Syntax

void *teja_malloc(size_t size);

Parameters

size - Size in bytes of memory to allocate.

Return Values

void * - Value to be used as pointer to allocated buffer.

teja_realloc

Description

Extends the memory buffer to become as big as the specified size. The new block might be allocated at a new address if there was not enough space for size bytes at the original location.

Syntax

void *teja_realloc(void *ptr, size_t size);

Parameters

ptr - Pointer to memory to reallocate.

size - Size in bytes of memory to allocate.

Return Values

void * - Pointer to newly allocated memory or NULL if the operation failed. In case of failure the original block is left untouched.

Sun Netra DPS Runtime API Thread Functions

This API offers thread management functionality. The teja_thread_t type implements thread IDs and the type can be assigned thread identifiers defined in the software architecture. Indicate these thread identifiers as strings in the software architecture using teja_thread_create(). In the user application, these identifiers are used as C identifiers (not as strings), which are defined by the compiler.

Two data types can be used to identify threads:


TABLE 2-5 Sun Netra DPS Runtime API Thread Types

Data Type

Description

teja_thread_t

This type is associated only to threads that are defined in the software architecture, and not to dynamic threads, created with teja_thread_handle_start(). This data type is an identifier type.

teja_thread_handle_t

This type is a handle that is associated to every thread in the system, both software architecture threads and dynamic threads. This data type is a handle data structure.


teja_get_thread_id

Description

Returns the thread ID of the current thread. The thread ID can be compared against thread identifiers defined in the software architecture.

Syntax

teja_thread_t teja_get_thread_id(void);

Return Values

teja_thread_t - Thread ID of the current thread.

teja_get_thread_name_for_id

Description

Returns the name of the given thread.

Syntax

char *teja_get_thread_name_for_id(teja_thread_t thread-id);

Parameters

thread-id - ID of the thread to operate on.

Return Values

char * - Name of the given thread.

teja_get_id_for_thread_name

Description

Returns the ID of the given thread.

Syntax

teja_thread_t teja_get_id_for_thread_name(char *name);

Parameters

name - Name of the thread to operate on.

Return Values

teja_thread_t - ID of the given thread.

teja_thread_handle_start

Description

Starts a new thread dynamically, executing the given function. This function is available only on OS-based targets or targets for which the TEJA_IS_RAW_OS constant is not defined.

Syntax

int teja_thread_handle_start(teja_thread_handle_t *thread, teja_thread_function_t function, void *arg, int stack-size, int priority);

Parameters

thread - Pointer to an uninitialized TejaThread instance. Upon successful execution, the thread contains a properly set up TejaThread handler.

function - Main function of the thread.

arg - Argument that is passed to the thread main function.

stack-size - Size of the stack for the thread. This functionality is not available on all systems. A predefined value is TEJA_DEFAULT_STACK_SIZE.

priority - Priority of the thread. This functionality is not available on all systems. predefined value is TEJA_DEFAULT_PRIORITY.

Return Values

int - 0 if execution was successful, -1 if an error occurred.

teja_thread_handle_end

Description

Ends a thread that was started with teja_thread_handle_start(). Do not use this function on threads defined in the software architecture. For software architecture threads use teja_thread_shutdown(). This function is available only on OS-based targets or targets for which the TEJA_IS_RAW_OS constant is not defined.

Syntax

void teja_thread_handle_end(void);

Return Values

void

teja_thread_handle_get_for_thread_id

Description

Returns the thread handle pointer for the given thread ID. This function is available only on OS-based targets or targets for which the TEJA_IS_RAW_OS constant is not defined.

Syntax

teja_thread_handle_t *teja_thread_handle_get_for_thread_id(int thread-id);

Parameters

thread-id - ID of the thread to operate on.

Return Values

teja_thread_handle_t * - Handle pointer for the given thread ID.

Sun Netra DPS Runtime API Miscellaneous Functions

teja_thread_shutdown

Description

Shuts down the current Sun Netra DPS thread.



Note - This function may not be invoked at initialization time.


Syntax

void teja_thread_shutdown(void);

Return Values

void

Sun Netra DPS Runtime API Time Functions

teja_get_time

Description

Returns the current time in seconds and nanoseconds. The precision depends on the granularity of the underlying system clock.

Syntax

int teja_get_time(int *seconds, int *nanoseconds);

Parameters

seconds - User-provided variable that contains the current seconds after the call.

nanoseconds - User-provided variable that contains the current nanoseconds after the call.

Return Values

int - 0 on success, -1 on error.

teja_wait_time

Description

Causes the current thread to sleep the specified time. The actual sleep time varies, depending upon the granularity of the underlying system clock and the system overhead involved in rescheduling the thread.



Note - This function is implemented as a macro on top of teja_wait(). This function may not be invoked at initialization time.


Syntax

int teja_wait_time(int seconds, int nanoseconds);

Parameters

seconds - Number of seconds to wait. Passing TEJA_INFINITE_WAIT causes the function to wait indefinitely

nanoseconds - Number of nanoseconds to wait. This value must be between 0 and 999999999.

Return Values

int - 0 on success, -1 on error.

teja_os_wait

Description

Causes the current thread to sleep the specified time. The actual sleep time varies depending upon the granularity of the underlying system clock and the system overhead to reschedule the thread. Unlike teja_wait_time() this function is not implemented on top of teja_wait().

Syntax

int teja_os_wait(int seconds, int nanoseconds);

Parameters

seconds - Number of seconds to wait. Passing TEJA_INFINITE_WAIT causes the function to wait indefinitely.

nanoseconds - Number of nanoseconds to wait. This value must be contained between 0 and 999999999.

Return Values

int - 0 on success, -1 on error.


Miscellaneous Functions

teja_get_argc

Description

Returns the number of arguments passed to the program on the command line.

Syntax

int teja_get_argc(void);

Return Values

int

teja_get_argv

Description

Returns an array of strings containing the arguments passed to the program on the command line.

Syntax

char **teja_get_argv(void);

Return Values

char **


Finite State Automata API

This macro-based API can be used to implement efficient state machine logic within a Sun Netra DPS application. States are computational elements and transitions are program flow elements that connect states.

These functions are available in different versions:

State machines come with a user-defined context. The first field of the context must be a void * pointer and is reserved for the system. The user can freely add other fields.

The multiple-context version of the API invokes a user-provided scheduler to switch in a new context at the end of each transition. This is an efficient way to implement parallel execution on single-threaded systems. For example, while a context waits, the state machine could switch in a new context and continue computation, thus increasing the CPU utilization.

The single-context version of the API uses a simple pointer scheduler and does not perform any switching. This version is useful on architectures that support multithreading in hardware.

The user might choose an implementation based on computed gotos, versus function pointers. Computed gotos might perform faster, but not all target compilers support them.



Note - State machines need to be declared outside of functions.


Finite State Automata API Defines


TABLE 2-6 Finite State Automata API Defines

Macros

Description

TEJA_FSM_SINGLE_CONTEXT

If defined the single-context version of the API is used, otherwise the multi-context version of the API is used.

TEJA_FSM_COMPUTED_GOTO

If defined the computed goto optimized version is used, otherwise the regular function pointer based version is used. Computed goto might perform faster, but is not available on all target compilers.

TEJA_FSM_CONTEXT

Pointer to the current context. In case of single-context implementation, this value never changes. In case of multiple-context implementation, this value is updated by the system.


Finite State Automata API Macros

teja_fsm_declare

Description

Declares a state machine with the given name. This function must be used in the global scope outside functions.

Syntax

#define teja_fsm_declare(name)

Parameters

name - Name of the state machine.

teja_fsm_begin

Description

Starts the definition of a state machine of the given name. This function must be used after teja_fsm_declare and must be used in the global scope outside functions. No semi-colon (;) is required at the end of this call.

Syntax

#define teja_fsm_begin(name initial-state-name context-scheduler context-iterator)

Parameters

name - Name of the state machine.

initial-state-name - Name of the initial state.

context-scheduler - If using single-context mode, this is the pointer to the context. If using multi-context mode this is the name of a user-defined function (of signature void * f (void)) returning the next context.

context-iterator - Name of a user-defined function (of signature void * f (void)) that returns a pointer to the next context until there are no more contexts, in which case the function returns NULL. The system uses this function to iterate over the contexts in the beginning in order to initialize them. This function is not used in single-context mode.

teja_fsm_end

Description

Ends the definition of a state machine. This function must be used after teja_fsm_begin and must be used in the global scope outside functions. No semi-colon (;) is required at the end of this call.

Syntax

#define teja_fsm_end()

teja_fsm_start

Description

Starts execution of a state machine with the given name. This function must be used inside a function.

Syntax

#define teja_fsm_start(name)

Parameters

name - Name of the state machine.

teja_fsm_state_declare

Description

Declares a state with the given name. This function must be used inside a state machine declaration, immediately after teja_fsm_begin.

Syntax

#define teja_fsm_state_declare(name)

Parameters

name - Name of the state.

teja_fsm_state_begin

Description

Starts the definition of a state of the given name. This function must be used inside a state machine after all teja_fsm_declare calls. The user can add regular C code immediately after this macro up to the teja_fsm_state_end macro. No semi-colon (;) is required at the end of this call.

Syntax

#define teja_fsm_state_begin(name)

Parameters

name - Name of the state.

teja_fsm_state_end

Description

Ends the definition of a state. This function must be used after teja_fsm_state_begin. The user can add regular C code immediately before this macro. No semi-colon (;) is required at the end of this call.

Syntax

#define teja_fsm_state_end()

teja_fsm_goto_state

Description

Performs a jump to the given state. This function must be used inside a state definition (that is between teja_fsm_state_begin and teja_fsm_state_end). This macro can be invoked No semi-colon (;) is required at the end of this call.

Syntax

#define teja_fsm_goto_state(name)

Parameters

name - Name of the state to jump to.

FSM Example

EXAMPLE 2-1 implements a simple state machine depicted in FIGURE 2-1.

FIGURE 2-1 Finite State Machine Example



EXAMPLE 2-1 Finite State Machine Code Example

#include <stdio.h> 
#if NUM_CONTEXTS == 1 
#define TEJA_FSM_SINGLE_CONTEXT 
#endif 
#include “fsm/teja_fsm.h” 
typedef struct Context 
{  
  void * state;  
  int count;  
} Context;  
static Context contexts[NUM_CONTEXTS];  
#if NUM_CONTEXTS == 1  
#define ctx_scheduler() (&contexts[0])  
#else  
void *  
ctx_scheduler (void)  
{  
  static int i = -1;  
  i = (i + 1) % NUM_CONTEXTS;  
  return &contexts[i];  
}  
#endif  
void *  
ctx_iterator (void)  
{  
  static int i = -1;  
  void * cur_context = 0;  
  i = (i + 1);  
  if (i < NUM_CONTEXTS)  
    cur_context = &contexts[i];  
  else  
    i = -1;  
  return cur_context;  
}  
teja_fsm_declare (my_fsm);  
teja_fsm_begin (my_fsm, s2, ctx_scheduler, ctx_iterator)  
  teja_fsm_state_declare (s1);  
  teja_fsm_state_declare (s2);  
  teja_fsm_state_begin (s1)  
    printf ("t1\n");  
    ((Context *) TEJA_FSM_CONTEXT)->count++;  
    teja_fsm_goto_state (s2);  
  teja_fsm_state_end ()  
  teja_fsm_state_begin (s2)  
    printf ("t2: %d\n", contexts[0].count);  
    if (((Context *) TEJA_FSM_CONTEXT)->count == 100)  
     teja_thread_shutdown();  
    teja_fsm_goto_state (s1);  
  teja_fsm_state_end()  
teja_fsm_end()  
void  
fsm_main (void)  
{  
  int i;  
  for (i = 0; i < NUM_CONTEXTS; i++)  
    {  
      contexts[i].count = 0;  
    }  
  teja_fsm_start (my_fsm);  
}  


Hardware Specific Miscellaneous Functions

teja_os_get_timer

Description

Returns the value of the clock tick register.

Syntax

uint64_t teja_os_get_timer(void);

Return Values

int - Returns the value of the clock tick register.


C Library Support on Bare Hardware

Sun Netra DPS programs running on bare hardware CMT can use the following standard C library functions: