## State Threads Library Reference

  Types

  st_thread_t

  st_cond_t

  st_mutex_t

  st_utime_t

  st_netfd_t

  Error Handling

  Library Initialization

  st_init()

  st_getfdlimit()

  Thread Control and Identification

  st_thread_t type

  st_thread_create()

  st_thread_exit()

  st_thread_join()

  st_thread_self()

  st_thread_interrupt()

  st_sleep()

  st_usleep()

  st_randomize_stacks()

  Per-Thread Private Data

  st_key_create()

  st_key_getlimit()

  st_thread_setspecific()

  st_thread_getspecific()

  Synchronization

  st_cond_t type

  st_cond_new()

  st_cond_destroy()

  st_cond_wait()

  st_cond_timedwait()

  st_cond_signal()

  st_cond_broadcast()

  st_mutex_t type

  st_mutex_new()

  st_mutex_destroy()

  st_mutex_lock()

  st_mutex_trylock()

  st_mutex_unlock()

  Timing

  st_utime_t type

  st_utime()

  st_timecache_set()

  st_time()

  I/O Functions

  st_netfd_t type

  st_netfd_open()

  st_netfd_open_socket()

  st_netfd_free()

  st_netfd_close()

  st_netfd_fileno()

  st_netfd_setspecific()

  st_netfd_getspecific()

  st_netfd_serialize_accept()

  st_netfd_poll()

  st_accept()

  st_connect()

  st_read()

  st_read_fully()

  st_read_resid()

  st_write()

  st_write_resid()

  st_writev()

  st_recvfrom()

  st_sendto()

  st_open()

  st_poll()

  Program Structure

  List of Blocking Functions

## Types

The State Thread library defines the following types in the `st.h` header file:

  st_thread_t
  st_cond_t
  st_mutex_t
  st_utime_t
  st_netfd_t

#### st_thread_t

Thread type.

##### Syntax

    #include <st.h>

    typedef void *  st_thread_t;

##### Description

A thread is represented and identified by a pointer to an opaque data structure. This pointer is a required parameter for most of the functions that operate on threads.

The thread identifier remains valid until the thread returns from its root function and, if the thread was created joinable, is joined.

#### st_cond_t

Condition variable type.

##### Syntax

    #include <st.h>

    typedef void *  st_cond_t;

##### Description

A condition variable is an opaque object identified by a pointer. Condition variables provide synchronization primitives to wait for or wake up threads waiting for certain conditions to be satisfied.

In the State Threads library there is no need to lock a mutex before waiting on a condition variable.

#### st_mutex_t

Mutex type.

##### Syntax

    #include <st.h>

    typedef void *  st_mutex_t;

##### Description

A mutex is an opaque object identified by a pointer. Mutual exclusion locks (mutexes) are used to serialize the execution of threads through critical sections of code.

If application using the State Threads library is written with no I/O or control yielding in critical sections (that is no blocking functions in critical sections), then there is no need for mutexes.

These mutexes can only be used for intra-process thread synchronization. They cannot be used for inter-process synchronization.

#### st_utime_t

High resolution time type ("u" stands for "micro").

##### Syntax

    #include <st.h>

    typedef unsigned long long  st_utime_t;

##### Description

This datatype (unsigned 64-bit integer) represents high-resolution real time expressed in microseconds since some arbitrary time in the past. It is not correlated in any way to the time of day.

#### st_netfd_t

File descriptor type.

##### Syntax

    #include <st.h>

    typedef void *  st_netfd_t;

##### Description

This datatype represents any open end point of network communication (socket, end point of a pipe, FIFO, etc.). Objects of this type are identified by a pointer to an opaque data structure.

## Error Handling

All State Threads library non-void functions return on success either a non-negative integer or a pointer to a newly created object (constructor-type functions). On failure they return either `-1` or a `NULL` pointer respectively and set global `errno` to indicate the error. It is safe to use `errno` because it is set right before the function return and only one thread at a time can modify its value.

The `perror(3)` function can be used to produce an error message on the standard error output.

## Library Initialization

  st_init()
  st_getfdlimit()

#### st_init()

Initializes the runtime.

##### Syntax

    #include <st.h>

    int st_init(void);

##### Parameters

None.

##### Returns

Upon successful completion, a value of `0` is returned. Otherwise, a value of `-1` is returned and `errno` is set to indicate the error.

##### Description

This function initializes the library runtime. It should be called near the beginning of the application's `main()` function before any other State Threads library function is called.

Among other things, this function limits the number of open file descriptors to the OS imposed per-process maximum number or, if `select(2)` is used, to `FD_SETSIZE`, whichever is less (`getrlimit(2)`). This limit can be retrieved by st_getfdlimit(). It also sets the disposition of the `SIGPIPE` signal to `SIG_IGN` (to be ignored) (`signal(5)`).

Unlike POSIX threads, a new process created by the `fork(2)` system call is an exact copy of the calling process and all state threads which are running in the parent do exist in the child. That means that `st_init()` may be called either before or after multiple processes are created by `fork(2)`.

If the library runtime is not properly initialized (e.g., `st_init()` is accidentally omitted), then the process will receive either an arithmetic exception (SIGFPE or SIGTRAP) or segmentation fault (SIGSEGV) signal upon new thread creation or the first context switch, respectively.

#### st_getfdlimit()

Returns the maximum number of file descriptors that the calling process can open.

##### Syntax

    #include <st.h>

    int st_getfdlimit(void);

##### Parameters

None.

##### Returns

The maximum number of file descriptors that the calling process can open. If this function is called before the library is successfully initialized by st_init(), a value of `-1` is returned.

##### Description

This function returns the limit on the number of open file descriptors which is set by the st_init() function.

## Thread Control and Identification

These functions operate on a thread object of type st_thread_t.

  st_thread_create()
  st_thread_exit()
  st_thread_join()
  st_thread_self()
  st_thread_interrupt()
  st_sleep()
  st_usleep()
  st_randomize_stacks()

#### st_thread_create()

Creates a new thread.

##### Syntax

    #include <st.h>

    st_thread_t st_thread_create(void *(*start)(void *arg), void *arg,
                                 int joinable, int stack_size);

##### Parameters

`st_thread_create()` has the following parameters:

`start`

A pointer to the thread's start function, which is called as the root of the new thread. Return from this function terminates a thread.

`arg`

A pointer to the root function's only parameter.

`joinable`

Specifies whether the thread is joinable or unjoinable. If this parameter is zero, the thread is unjoinable. Otherwise, it is joinable. See also st_thread_join().

`stack_size`

Specifies your preference for the size of the stack, in bytes, associated with the newly created thread. If you pass zero in this parameter, the default stack size will be used. The default stack size is 128 KB on IA-64 and 64 KB on all other platforms. On IA-64 only a half of `stack_size` bytes is used for the memory stack. The other half is used for the register stack backing store.

##### Returns

Upon successful completion, a new thread identifier is returned (this identifier remains valid until the thread returns from its start function). Otherwise, `NULL` is returned and `errno` is set to indicate the error.

##### Description

This function creates a new thread. Note that the total number of threads created by the application is limited by the amount of swap space available. Upon thread creation, `stack_size` bytes are reserved on the swap space. The stack pages are not actually used (valid) until touched by the application.

#### st_thread_exit()

Terminates the calling thread.

##### Syntax

    #include <st.h>

    void st_thread_exit(void *retval);

##### Parameters

`st_thread_exit()` has the following parameters:

`retval`

If the thread is joinable, then the value `retval` may be retrieved by st_thread_join(). If a thread returns from its start function, it acts as if it had called `st_thread_exit()` with `retval` as the value returned.

##### Returns

Nothing.

##### Description

This function terminates the calling thread. When a thread exits, per-thread private data is destroyed by invoking the destructor function for any non-`NULL` thread specific values associated with active keys (see st_key_create()). This function is implicitly called when a thread returns from its start function.

When the last thread terminates the process exits with a zero status value.

#### st_thread_join()

Blocks the calling thread until a specified thread terminates.

##### Syntax

    #include <st.h>

    int st_thread_join(st_thread_t thread, void **retvalp);

##### Parameters

`st_thread_join()` has the following parameters:

`thread`

A valid identifier for the thread that is to be joined.

`retvalp`

If this parameter is not `NULL`, then the exit value of the `thread` will be placed in the location referenced by this parameter (see st_thread_exit()).

##### Returns

Upon successful completion, a value of `0` is returned. Otherwise, a value of `-1` is returned and `errno` is set to indicate the error:

`EINVAL` | Target thread is unjoinable.
`EINVAL` | Other thread already waits on the same joinable thread.
`EDEADLK` | Target thread is the same as the calling thread.
`EINTR` | Current thread was interrupted by st_thread_interrupt().

##### Description

This function is used to synchronize the termination of a thread and possibly retrieve its exit value. Several threads cannot wait for the same thread to complete - one of the calling threads operates successfully, and the others terminate with the error. The calling thread is not blocked if the target thread has already terminated.

#### st_thread_self()

Identifies the calling thread.

##### Syntax

    #include <st.h>

    st_thread_t st_thread_self(void);

##### Parameters

None.

##### Returns

Always returns a valid reference to the calling thread - a self-identity.

##### Description

This function identifies the calling thread. This is the same identifier that the creating thread obtains from st_thread_create().

#### st_thread_interrupt()

Interrupts a target thread.

##### Syntax

    #include <st.h>

    void st_thread_interrupt(st_thread_t thread);

##### Parameters

`st_thread_interrupt()` has the following parameters:

`thread`

A valid identifier for the thread being interrupted.

##### Returns

Nothing.

##### Description

This function interrupts (unblocks) a target thread that is blocked in one of the blocking functions. A function that was interrupted returns an error and sets `errno` to `EINTR`. It is up to the target thread to act upon an interrupt (e.g., it may exit or just abort the current transaction).

Note: State Threads library functions are never interrupted by a caught signal. A blocking library function returns an error and sets `errno` to `EINTR` only if the current thread was interrupted via `st_thread_interrupt()`.

If a target thread is already runnable or running (e.g., it is a newly created thread or calling thread itself), this function will prevent it from subsequent blocking. In other words, the interrupt will be "delivered" only when a target thread is about to block.

#### st_sleep(), st_usleep()

Suspends current thread for a specified amount of time.

##### Syntax

    #include <st.h>

    int st_sleep(int secs);

    int st_usleep(st_utime_t usecs);

##### Parameters

`st_sleep()` has the following parameters:

`secs`

The number of seconds you want the thread to sleep for.

`st_usleep()` has the following parameters:

`usecs`

The number of microseconds you want the thread to sleep for. This parameter is a variable of type st_utime_t.

##### Returns

Upon successful completion, a value of `0` is returned. Otherwise, a value of `-1` is returned and `errno` is set to indicate the error:

`EINTR` | The current thread was interrupted by st_thread_interrupt().

##### Description

These functions suspend the calling thread from execution for a specified number of seconds (`st_sleep()`) or microseconds (`st_usleep()`).

If zero is passed as a parameter to these functions, the calling thread yields, thus potentially allowing another thread to run.

If `-1` is passed as a parameter to these functions, the calling thread will be suspended permanently. It can be resumed again by interrupting it via st_thread_interrupt().

#### st_randomize_stacks()

Turns stack base address randomization on or off.

##### Syntax

    #include <st.h>

    int st_randomize_stacks(int on);

##### Parameters

`st_randomize_stacks()` has the following parameters:

`on`

If this parameter has a non-zero value, the State Threads library randomizes the base addresses of stacks allocated for threads created after this call. Otherwise new threads' stacks are typically page aligned.

##### Returns

The previous state of stack randomization (a value of `0` if it was off and a nonzero value otherwise).

##### Description

Randomizing state threads' stack bases may improve cache performance on some systems when large numbers of state threads all perform roughly the same work, as when they all start from the same root function. On many modern systems the performance increase is negligible. You should compare your application's performance with this feature on and off to see if you really need it.

When randomization is enabled, new stacks are allocated one page larger to accomodate the randomization.

This call affects only threads created afterward. It has no effect on existing threads.

## Per-Thread Private Data

These functions allow to associate private data with each of the threads in a process.

  st_key_create()
  st_key_getlimit()
  st_thread_setspecific()
  st_thread_getspecific()

#### st_key_create()

Creates a key (non-negative integer) that can be used by all threads in the process to get and set thread-specific data.

##### Syntax

    #include <st.h>

    int st_key_create(int *keyp, void (*destructor)(void *));

##### Parameters

`st_key_create()` has the following parameters:

`keyp`

The newly created key is returned in the memory pointed to by this parameter. The new key can be used with st_thread_setspecific() and st_thread_getspecific().

`destructor`

Specifies an optional destructor function for the private data associated with the key. This function can be specified as `NULL`. Upon thread exit (see st_thread_exit()), if a key has a non-`NULL` `destructor` and has a non-`NULL` value associated with that key, then the `destructor` function will be called with the associated value.

##### Returns

Upon successful completion, a value of `0` is returned. Otherwise, a value of `-1` is returned and `errno` is set to indicate the error:

`EAGAIN` | The limit on the total number of keys per process has been exceeded (see st_key_getlimit()).

##### Description

If this function is successful, every thread in the same process is capable of associating private data with the new key. After a new key is created, all active threads have the value `NULL` associated with that key. After a new thread is created, the value `NULL` is associated with all keys for that thread. If a non-`NULL` destructor function is registered with a new key, it will be called at one of two times, as long as the private data is not `NULL`:

- when replacement private data is set with st_thread_setspecific()
- when a thread exits (see st_thread_exit())

The key maintains independent data values for each binding thread. A thread can get access only to its own thread-specific data. There is no way to deallocate a private data key once it is allocated.

#### st_key_getlimit()

Returns the key limit.

##### Syntax

    #include <st.h>

    int st_key_getlimit(void);

##### Parameters

None.

##### Returns

The limit on the total number of keys per process.

##### Description

This function can be used to obtain the limit on the total number of keys per process (see st_key_create()).

#### st_thread_setspecific()

Sets per-thread private data.

##### Syntax

    #include <st.h>

    int st_thread_setspecific(int key, void *value);

##### Parameters

`st_thread_setspecific()` has the following parameters:

`key`

This parameter represents a key with which thread-specific data is associated.

`value`

The per-thread private data, or more likely, a pointer to the data which is associated with `key`.

##### Returns

Upon successful completion, a value of `0` is returned. Otherwise, a value of `-1` is returned and `errno` is set to indicate the error:

`EINVAL` | The specified `key` is invalid.

##### Description

This function associates a thread-specific `value` with `key`. Different threads may bind different values to the same key.

If the thread already has non-`NULL` private data associated with `key`, and if the destructor function for that key is not `NULL`, this destructor function will be called before setting the new data value.

#### st_thread_getspecific()

Retrieves the per-thread private data for the current thread.

##### Syntax

    #include <st.h>

    void *st_thread_getspecific(int key);

##### Parameters

`st_thread_getspecific()` has the following parameters:

`key`

This parameter represents a key with which thread-specific data is associated.

##### Returns

The thread-specific data associated with `key`. If no data is associated with `key`, then `NULL` is returned.

##### Description

This function returns the calling thread's value that is bound to the specified `key` (see st_thread_setspecific()).

## Synchronization

These functions operate on condition variables and mutual exclusion locks (mutexes).

Functions are provided to wait on a condition variable and to wake up (signal) threads that are waiting on the condition variable.

  st_cond_new()
  st_cond_destroy()
  st_cond_wait()
  st_cond_timedwait()
  st_cond_signal()
  st_cond_broadcast()

  st_mutex_new()
  st_mutex_destroy()
  st_mutex_lock()
  st_mutex_trylock()
  st_mutex_unlock()

#### st_cond_new()

Creates a new condition variable.

##### Syntax

    #include <st.h>

    st_cond_t st_cond_new(void);

##### Parameters

None.

##### Returns

Upon successful completion, a new condition variable identifier is returned. Otherwise, `NULL` is returned and `errno` is set to indicate the error.

##### Description

This function creates a new condition variable.

#### st_cond_destroy()

Destroys a condition variable.

##### Syntax

    #include <st.h>

    int st_cond_destroy(st_cond_t cvar);

##### Parameters

`st_cond_destroy()` has the following parameters:

`cvar`

An identifier of the condition variable object to be destroyed.

##### Returns

Upon successful completion, a value of `0` is returned. Otherwise, a value of `-1` is returned and `errno` is set to indicate the error:

`EBUSY` | The condition variable is currently being used by one or more threads.

##### Description

This function destroys a condition variable. The caller is responsible for ensuring that the condition variable is no longer in use.

#### st_cond_wait()

Waits on a condition.

##### Syntax

    #include <st.h>

    int st_cond_wait(st_cond_t cvar);

##### Parameters

`st_cond_wait()` has the following parameters:

`cvar`

The condition variable on which to wait.

##### Returns

Upon successful completion, a value of `0` is returned. Otherwise, a value of `-1` is returned and `errno` is set to indicate the error:

`EINTR` | The current thread was interrupted by st_thread_interrupt().

##### Description

This function is used to block on a condition variable. A return from this function does not guarantee that the condition or event for which the caller was waiting actually occurred. It is the responsibility of the caller to recheck the condition wait predicate before proceeding.

Note: The State Threads library scheduling guarantees that the condition cannot change between the checking and blocking, therefore there is no need for mutex protection. You must not call any blocking functions between the condition checking and the `st_cond_wait()` call.

#### st_cond_timedwait()

Waits on a condition.

##### Syntax

    #include <st.h>

    int st_cond_timedwait(st_cond_t cvar, st_utime_t timeout);

##### Parameters

`st_cond_timedwait()` has the following parameters:

`cvar`

The condition variable on which to wait.

`timeout`

If the number of microseconds specified by this parameter passes before the waiting thread is signalled, an error is returned. This parameter is a variable of type st_utime_t. Note that this time value is a time delta; it is not an absolute time.

##### Returns

Upon successful completion, a value of `0` is returned. Otherwise, a value of `-1` is returned and `errno` is set to indicate the error:

`EINTR` | The current thread was interrupted by st_thread_interrupt().
`ETIME` | The timeout occurred before the thread was awakened by st_cond_signal() or st_cond_broadcast().

##### Description

This function works the same way as st_cond_wait(), except that an error is returned if the number of microseconds specified by `timeout` passes before the waiting thread is signalled.

#### st_cond_signal()

Unblocks a thread waiting on a condition variable.

##### Syntax

    #include <st.h>

    int st_cond_signal(st_cond_t cvar);

##### Parameters

`st_cond_signal()` has the following parameters:

`cvar`

The condition variable to signal.

##### Returns

Always zero.

##### Description

This function unblocks (signals) one of the threads that are blocked on `cvar` at the time of the call. If no thread is waiting on the condition variable, the signal operation is a no-op.

#### st_cond_broadcast()

Unblocks all threads waiting on a condition variable.

##### Syntax

    #include <st.h>

    int st_cond_broadcast(st_cond_t cvar);

##### Parameters

`st_cond_broadcast()` has the following parameters:

`cvar`

The condition variable to broadcast.

##### Returns

Always zero.

##### Description

This function unblocks all threads blocked on the specified condition variable at the time of the call. If no threads are waiting, this operation is a no-op.

#### st_mutex_new()

Creates a new mutual exclusion lock (mutex).

##### Syntax

    #include <st.h>

    st_mutex_t st_mutex_new(void);

##### Parameters

None.

##### Returns

Upon successful completion, a new mutex identifier is returned. Otherwise, `NULL` is returned and `errno` is set to indicate the error.

##### Description

This function creates a new opaque mutual exclusion lock (see st_mutex_t).

#### st_mutex_destroy()

Destroys a specified mutex object.

##### Syntax

    #include <st.h>

    int st_mutex_destroy(st_mutex_t lock);

##### Parameters

`st_mutex_destroy()` has the following parameters:

`lock`

An identifier of the mutex object to be destroyed.

##### Returns

Upon successful completion, a value of `0` is returned. Otherwise, a value of `-1` is returned and `errno` is set to indicate the error:

`EBUSY` | The mutex is currently being used by other threads.

##### Description

This function destroys a mutex. The caller is responsible for ensuring that the mutex is no longer in use.

#### st_mutex_lock()

Locks a specified mutex object.

##### Syntax

    #include <st.h>

    int st_mutex_lock(st_mutex_t lock);

##### Parameters

`st_mutex_lock()` has the following parameters:

`lock`

An identifier of the mutex object to be locked.

##### Returns

Upon successful completion, a value of `0` is returned. Otherwise, a value of `-1` is returned and `errno` is set to indicate the error:

`EDEADLK` | The current thread already owns the mutex.
`EINTR` | The current thread was interrupted by st_thread_interrupt().

##### Description

A thread that calls this function will block until it can gain exclusive ownership of a mutex, and retains ownership until it calls st_mutex_unlock().

#### st_mutex_trylock()

Attempts to acquire a mutex.

##### Syntax

    #include <st.h>

    int st_mutex_trylock(st_mutex_t lock);

##### Parameters

`st_mutex_trylock()` has the following parameters:

`lock`

An identifier of the mutex object to be locked.

##### Returns

Upon successful completion, a value of `0` is returned. Otherwise, a value of `-1` is returned and `errno` is set to indicate the error:

`EBUSY` | The mutex is currently held by another thread.

##### Description

This function attempts to acquire a mutex. If the mutex object is locked (by any thread, including the current thread), the call returns immediately with an error.

#### st_mutex_unlock()

Releases a specified mutex object.

##### Syntax

    #include <st.h>

    int st_mutex_unlock(st_mutex_t lock);

##### Parameters

`st_mutex_unlock()` has the following parameters:

`lock`

An identifier of the mutex object to be unlocked.

##### Returns

Upon successful completion, a value of `0` is returned. Otherwise, a value of `-1` is returned and `errno` is set to indicate the error:

`EPERM` | The current thread does not own the mutex.

##### Description

This function releases a specified mutex object previously acquired by st_mutex_lock() or st_mutex_trylock(). Only the thread that locked a mutex should unlock it.

## Timing

  st_utime()
  st_timecache_set()
  st_time()

#### st_utime()

Returns current high-resolution time.

##### Syntax

    #include <st.h>

    st_utime_t st_utime(void);

##### Parameters

None.

##### Returns

Current high-resolution time value of type st_utime_t.

##### Description

This function returns the current high-resolution time. Time is expressed as microseconds since some arbitrary time in the past. It is not correlated in any way to the time of day (see st_utime_t).

#### st_timecache_set()

Turns the time caching on or off.

##### Syntax

    #include <st.h>

    int st_timecache_set(int on);

##### Parameters

`st_timecache_set()` has the following parameters:

`on`

If this parameter has a non-zero value, the time caching is turned on (enabled). Otherwise, the time caching is turned off (disabled).

##### Returns

The previous state of time caching (a value of `0` if it was off and a value of `1` otherwise).

##### Description

The State Threads library has the ability to "cache" the time value that is reported by the `time(2)` system call. If the time caching is enabled by calling this function with a non-zero argument, then the result value of `time(2)` will be stored and updated at most once per second. The cached time can be retrieved by st_time().

Note: There are some pathological cases (e.g., very heavy loads during application benchmarking) when a single thread runs for a long time without giving up control and the cached time value is not updated properly. If you always need "real-time" time values, don't enable the time caching.

#### st_time()

Returns the value of time in seconds since 00:00:00 UTC, January 1, 1970.

##### Syntax

    #include <st.h>

    time_t st_time(void);

##### Parameters

None.

##### Returns

The value of time in seconds since 00:00:00 UTC, January 1, 1970 as reported by the `time(2)` system call.

##### Description

If the time caching was enabled by st_timecache_set(), then this function returns the cached result. Otherwise, it just calls `time(2)`.

## I/O Functions

Most State Threads library I/O functions look like corresponding C library functions with two exceptions:

- They operate on file descriptor objects of type st_netfd_t.
- They take an additional argument of type st_utime_t which represents an inactivity timeout: if no I/O is possible during this amount of time, I/O functions return an error code and set `errno` to `ETIME`. The boundary values `0` and `-1` for this argument indicate that the thread should wait no time (function returns immediately) or wait forever (never time out), respectively.

  st_netfd_open()
  st_netfd_open_socket()
  st_netfd_free()
  st_netfd_close()
  st_netfd_fileno()
  st_netfd_setspecific()
  st_netfd_getspecific()
  st_netfd_serialize_accept()
  st_netfd_poll()

  st_accept()
  st_connect()
  st_read()
  st_read_fully()
  st_read_resid()
  st_write()
  st_write_resid()
  st_writev()
  st_recvfrom()
  st_sendto()
  st_open()
  st_poll()

#### st_netfd_open()

Creates a new file descriptor object.

##### Syntax

    #include <st.h>

    st_netfd_t st_netfd_open(int osfd);

##### Parameters

`st_netfd_open()` has the following parameters:

`osfd`

An open OS file descriptor obtained from a`pipe(2), socket(3), socketpair(3), fcntl(2), dup(2),` etc. call.

##### Returns

Upon successful completion, a new file descriptor object identifier is returned. Otherwise, `NULL` is returned and `errno` is set to indicate the error.

##### Description

This function creates a new file descriptor object of type st_netfd_t which represents an open end point of network communication.

Note: Among other things, this function sets a non-blocking flag on the underlying OS file descriptor. You should not modify this flag directly.

#### st_netfd_open_socket()

Creates a new file descriptor object from a socket.

##### Syntax

    #include <st.h>

    st_netfd_t st_netfd_open_socket(int osfd);

##### Parameters

`st_netfd_open_socket()` has the following parameters:

`osfd`

An open OS file descriptor which is a socket initially obtained from a`socket(3) or socketpair(3)` call.

##### Returns

Upon successful completion, a new file descriptor object identifier is returned. Otherwise, `NULL` is returned and `errno` is set to indicate the error.

##### Description

This function creates a new file descriptor object of type st_netfd_t which represents an open end point of network communication.

Unlike the st_netfd_open() function which may be used on OS file descriptors of any origin, `st_netfd_open_socket()` must be used only on sockets. It is slightly more efficient than st_netfd_open().

Note: Among other things, this function sets a non-blocking flag on the underlying OS socket. You should not modify this flag directly.

#### st_netfd_free()

Frees a file descriptor object without closing the underlying OS file descriptor.

##### Syntax

    #include <st.h>

    void st_netfd_free(st_netfd_t fd);

##### Parameters

`st_netfd_free()` has the following parameters:

`fd`

A file descriptor object identifier (see st_netfd_t).

##### Returns

Nothing.

##### Description

This function frees the memory and other resources identified by the `fd` parameter without closing the underlying OS file descriptor. Any non-`NULL` descriptor-specific data is destroyed by invoking the specified destructor function (see st_netfd_setspecific()).

A thread should not free file descriptor objects that are in use by other threads because it may lead to unpredictable results (e.g., a freed file descriptor may be reused without other threads knowing that).

#### st_netfd_close()

Closes a file descriptor.

##### Syntax

    #include <st.h>

    int st_netfd_close(st_netfd_t fd);

##### Parameters

`st_netfd_close()` has the following parameters:

`fd`

A file descriptor object identifier (see st_netfd_t).

##### Returns

Upon successful completion, a value of `0` is returned. Otherwise, a value of `-1` is returned and `errno` is set to indicate the error.

##### Description

This function closes the underlying OS file descriptor, frees the memory and other resources identified by the `fd` parameter. Any non-`NULL` descriptor-specific data is destroyed by invoking the specified destructor function (see st_netfd_setspecific()).

A thread should not close file descriptor objects that are in use by other threads because it may lead to unpredictable results (e.g., a closed file descriptor may be reused without other threads knowing that).

#### st_netfd_fileno()

Returns an underlying OS file descriptor.

##### Syntax

    #include <st.h>

    int st_netfd_fileno(st_netfd_t fd);

##### Parameters

`st_netfd_fileno()` has the following parameters:

`fd`

A file descriptor object identifier (see st_netfd_t).

##### Returns

An underlying OS file descriptor.

##### Description

This function returns the integer OS file descriptor associated with the named file descriptor object.

#### st_netfd_setspecific()

Sets per-descriptor private data.

##### Syntax

    #include <st.h>

    void st_netfd_setspecific(st_netfd_t fd, void *value,
                              void (*destructor)(void *));

##### Parameters

`st_netfd_setspecific()` has the following parameters:

`fd`

A valid file descriptor object identifier (see st_netfd_t).

`value`

The per-descriptor private data, or more likely, a pointer to the data which is being associated with the named file descriptor object.

`destructor`

Specifies an optional destructor function for the private data associated with `fd`. This function can be specified as `NULL`. If `value` is not `NULL`, then this destructor function will be called with `value` as an argument upon freeing the file descriptor object (see st_netfd_free() and st_netfd_close()).

##### Returns

Nothing.

##### Description

This function allows to associate any data with the specified file descriptor object (network connection). If a non-`NULL` destructor function is registered, it will be called at one of two times, as long as the associated data is not `NULL`:

- when private data is replaced by calling `st_netfd_setspecific()` again
- upon freeing the file descriptor object (see st_netfd_free() and st_netfd_close())

#### st_netfd_getspecific()

Retrieves the per-descriptor private data.

##### Syntax

    #include <st.h>

    void *st_netfd_getspecific(st_netfd_t fd);

##### Parameters

`st_netfd_getspecific()` has the following parameters:

`fd`

A valid file descriptor object identifier (see st_netfd_t).

##### Returns

The data associated with the named file descriptor object. If no data is associated with `fd`, then `NULL` is returned.

##### Description

This function allows to retrieve the data that was associated with the specified file descriptor object (see st_netfd_setspecific()).

#### st_netfd_serialize_accept()

Serializes all subsequent `accept(3)` calls on a specified file descriptor object.

##### Syntax

    #include <st.h>

    int st_netfd_serialize_accept(st_netfd_t fd);

##### Parameters

`st_netfd_serialize_accept()` has the following parameters:

`fd`

A file descriptor object identifier (see st_netfd_t) which has been successfully created from a valid listening socket by st_netfd_open() or st_netfd_open_socket().

##### Returns

Upon successful completion, a value of `0` is returned. Otherwise, a value of `-1` is returned and `errno` is set to indicate the error.

##### Description

On some platforms (e.g., Solaris 2.5 and possibly other SVR4 implementations) `accept(3)` calls from different processes on the same listening socket (see `bind(3)`, `listen(3)`) must be serialized. This function causes all subsequent `accept(3)` calls made by st_accept() on the specified file descriptor object to be serialized.

`st_netfd_serialize_accept()` must be called before creating multiple server processes via `fork(2)`. If the application does not create multiple processes to accept network connections on the same listening socket, there is no need to call this function.

`st_netfd_serialize_accept()` allocates resources that are freed upon freeing of the specified file descriptor object (see st_netfd_free() and st_netfd_close()).

#### st_netfd_poll()

Waits for I/O on a single file descriptor object.

##### Syntax

    #include <st.h>

    int st_netfd_poll(st_netfd_t fd, int how, st_utime_t timeout);

##### Parameters

`st_netfd_poll()` has the following parameters:

`fd`

A file descriptor object identifier (see st_netfd_t).

`how`

Specifies I/O events of interest. This parameter can be constructed by OR-ing any combination of the following event flags which are defined in the `poll.h` header file:

`POLLIN` | `fd` is readable.
`POLLOUT` | `fd` is is writable.
`POLLPRI` | `fd` has an exception condition.

`timeout`

Amount of time in microseconds the call will block waiting for I/O to become ready. This parameter is a variable of type st_utime_t. If this time expires without any I/O becoming ready, `st_netfd_poll()` returns an error and sets `errno` to `ETIME`.

##### Returns

If the named file descriptor object is ready for I/O within the specified amount of time, a value of `0` is returned. Otherwise, a value of `-1` is returned and `errno` is set to indicate the error:

`EBADF` | The underlying OS file descriptor is invalid.
`EINTR` | The current thread was interrupted by st_thread_interrupt().
`ETIME` | The timeout occurred without any I/O becoming ready.

##### Description

This function returns as soon as I/O is ready on the named file descriptor object or the specified amount of time expires. The `how` parameter should be set to the I/O events (readable, writable, exception, or some combination) that the caller is interested in. If the value of `timeout` is `-1`, this function blocks until a requested I/O event occurs or until the call is interrupted by st_thread_interrupt().

#### st_accept()

Accepts a connection on a specified file descriptor object.

##### Syntax

    #include <st.h>

    st_netfd_t st_accept(st_netfd_t fd, struct sockaddr *addr, int *addrlen,
                         st_utime_t timeout);

##### Parameters

`st_accept()` has the following parameters:

`fd`

A file descriptor object identifier (see st_netfd_t) representing the rendezvous socket on which the caller is willing to accept new connections. This object has been created from a valid listening socket by st_netfd_open() or st_netfd_open_socket().

`addr`

If this value is non-zero, it is a result parameter that is filled in with the address of the connecting entity, as known to the communications layer (see `accept(3)`).

`addrlen`

This parameter should initially contain the amount of space pointed to by `addr`; on return it will contain the actual length (in bytes) of the address returned (see `accept(3)`).

`timeout`

A value of type st_utime_t specifying the time limit in microseconds for completion of the accept operation.

##### Returns

Upon successful completion, a new file descriptor object identifier representing the newly accepted connection is returned. Otherwise, `NULL` is returned and `errno` is set to indicate the error. Possible `errno` values are the same as set by the `accept(3)` call with two exceptions:

`EINTR` | The current thread was interrupted by st_thread_interrupt().
`ETIME` | The timeout occurred and no pending connection was accepted.

##### Description

This function accepts the first connection from the queue of pending connections and creates a new file descriptor object for the newly accepted connection. The rendezvous socket can still be used to accept more connections.

`st_accept()` blocks the calling thread until either a new connection is successfully accepted or an error occurs. If no pending connection can be accepted before the time limit, this function returns `NULL` and sets `errno` to `ETIME`.

#### st_connect()

Initiates a connection on a specified file descriptor object.

##### Syntax

    #include <st.h>

    int st_connect(st_netfd_t fd, struct sockaddr *addr, int addrlen,
                   st_utime_t timeout);

##### Parameters

`st_connect()` has the following parameters:

`fd`

A file descriptor object identifier (see st_netfd_t) representing a socket.

`addr`

A pointer to the address of the peer to which the socket is to be connected.

`addrlen`

This parameter specifies the amount of space pointed to by `addr`.

`timeout`

A value of type st_utime_t specifying the time limit in microseconds for completion of the connect operation.

##### Returns

Upon successful completion, a value of `0` is returned. Otherwise, a value of `-1` is returned and `errno` is set to indicate the error. Possible `errno` values are the same as set by the `connect(3)` call with two exceptions:

`EINTR` | The current thread was interrupted by st_thread_interrupt().
`ETIME` | The timeout occurred and connection setup was not completed.

##### Description

This function is usually invoked on a file descriptor object representing a TCP socket. Upon completion it establishes a TCP connection to the peer. If the underlying OS socket is not bound, it will be bound to an arbitrary local address (see `connect(3)`).

`st_connect()` blocks the calling thread until either the connection is successfully established or an error occurs. If the connection setup cannot complete before the specified time limit, this function fails with `errno` set to `ETIME`.

#### st_read()

Reads data from a specified file descriptor object.

##### Syntax

    #include <st.h>

    ssize_t st_read(st_netfd_t fd, void *buf, size_t nbyte, st_utime_t timeout);

##### Parameters

`st_read()` has the following parameters:

`fd`

A file descriptor object identifier (see st_netfd_t).

`buf`

A pointer to a buffer to hold the data read in. On output the buffer contains the data.

`nbyte`

The size of `buf` in bytes.

`timeout`

A value of type st_utime_t specifying the time limit in microseconds for completion of the read operation.

##### Returns

On success a non-negative integer indicating the number of bytes actually read is returned (a value of `0` means the network connection is closed or end of file is reached). Otherwise, a value of `-1` is returned and `errno` is set to indicate the error. Possible `errno` values are the same as set by the `read(2)` call with two exceptions:

`EINTR` | The current thread was interrupted by st_thread_interrupt().
`ETIME` | The timeout occurred and no data was read.

##### Description

This function blocks the calling thread until it encounters an end-of-stream indication, some positive number of bytes (but no more than `nbyte` bytes) are read in, a timeout occurs, or an error occurs.

#### st_read_fully()

Reads the specified amount of data in full from a file descriptor object.

##### Syntax

    #include <st.h>

    ssize_t st_read_fully(st_netfd_t fd, void *buf, size_t nbyte,
                          st_utime_t timeout);

##### Parameters

`st_read_fully()` has the following parameters:

`fd`

A file descriptor object identifier (see st_netfd_t).

`buf`

A pointer to a buffer to hold the data read in. On output the buffer contains the data.

`nbyte`

The amount of data to be read in full (in bytes). It must not exceed the size of `buf`.

`timeout`

A value of type st_utime_t specifying the inactivity timeout (in microseconds).

##### Returns

On success a non-negative integer indicating the number of bytes actually read is returned (a value less than `nbyte` means the network connection is closed or end of file is reached). Otherwise, a value of `-1` is returned and `errno` is set to indicate the error. Possible `errno` values are the same as set by the `read(2)` call with two exceptions:

`EINTR` | The current thread was interrupted by st_thread_interrupt().
`ETIME` | The timeout occurred.

##### Description

This function blocks the calling thread until the specified amount of data is read in full, it encounters an end-of-stream indication, a timeout occurs, or an error occurs.

#### st_read_resid()

Reads the specified amount of data in full from a file descriptor object.

##### Syntax

    #include <st.h>

    int st_read_resid(st_netfd_t fd, void *buf, size_t *resid,
    		  st_utime_t timeout);

##### Parameters

`st_read_resid()` has the following parameters:

`fd`

A file descriptor object identifier (see st_netfd_t).

`buf`

A pointer to a buffer to hold the data read in. On output the buffer contains the data.

`resid`

A pointer to a number of bytes. On entry, the amount of data to be read in full. It must not exceed the size of `buf`. On return, the amount of data remaining to be read. (A non-zero returned value means some but not all of the data was read.)

`timeout`

A value of type st_utime_t specifying the inactivity timeout (in microseconds).

##### Returns

On success, zero is returned. `*resid` may be zero, indicating a complete read, or non-zero, indicating the network connection is closed or end of file is reached.

Otherwise, a value of `-1` is returned, `*resid` is non-zero, and `errno` is set to indicate the error. Possible `errno` values are the same as set by the `read(2)` call with two exceptions:

`EINTR` | The current thread was interrupted by st_thread_interrupt().
`ETIME` | The timeout occurred.

##### Description

This function blocks the calling thread until the specified amount of data is read in full, it encounters an end-of-stream indication, a timeout occurs, or an error occurs. It differs from `st_read_fully()` only in that it allows the caller to know how many bytes were transferred before an error occurred.

#### st_write()

Writes a buffer of data to a specified file descriptor object.

##### Syntax

    #include <st.h>

    ssize_t st_write(st_netfd_t fd, const void *buf, size_t nbyte,
                     st_utime_t timeout);

##### Parameters

`st_write()` has the following parameters:

`fd`

A file descriptor object identifier (see st_netfd_t).

`buf`

A pointer to the buffer holding the data to be written.

`nbyte`

The amount of data in bytes to be written from the buffer.

`timeout`

A value of type st_utime_t specifying the inactivity timeout (in microseconds).

##### Returns

On success a non-negative integer equal to `nbyte` is returned. Otherwise, a value of `-1` is returned and `errno` is set to indicate the error. Possible `errno` values are the same as set by the `write(2)` call with two exceptions:

`EINTR` | The current thread was interrupted by st_thread_interrupt().
`ETIME` | The timeout occurred.

##### Description

This function blocks the calling thread until all the data is written, a timeout occurs, or the write operation fails. The return value is equal to either `nbyte` (on success) or `-1` (on failure). Note that if `st_write()` returns `-1`, some data (less than `nbyte` bytes) may have been written before an error occurred.

#### st_write_resid()

Writes a buffer of data to a specified file descriptor object.

##### Syntax

    #include <st.h>

    int st_write_resid(st_netfd_t fd, const void *buf, size_t *resid,
                       st_utime_t timeout);

##### Parameters

`st_write_resid()` has the following parameters:

`fd`

A file descriptor object identifier (see st_netfd_t).

`buf`

A pointer to the buffer holding the data to be written.

`resid`

A pointer to a number of bytes. On entry, the amount of data to be written from the buffer. On return, the amount of data remaining to be written. (A non-zero returned value means some but not all of the data was written.)

`timeout`

A value of type st_utime_t specifying the inactivity timeout (in microseconds).

##### Returns

On success, zero is returned and `*resid` is zero. Otherwise, a value of `-1` is returned, `*resid` is non-zero, and `errno` is set to indicate the error. Possible `errno` values are the same as set by the `write(2)` call with two exceptions:

`EINTR` | The current thread was interrupted by st_thread_interrupt().
`ETIME` | The timeout occurred.

##### Description

This function blocks the calling thread until all the data is written, a timeout occurs, or the write operation fails. It differs from `st_write()` only in that it allows the caller to know how many bytes were transferred before an error occurred.

#### st_writev()

Writes data to a specified file descriptor object from multiple buffers.

##### Syntax

    #include <st.h>

    ssize_t st_writev(st_netfd_t fd, const struct iovec *iov, int iov_size,
                      st_utime_t timeout);

##### Parameters

`st_writev()` has the following parameters:

`fd`

A file descriptor object identifier (see st_netfd_t).

`iov`

An array of `iovec` structures that describe the buffers to write from (see `writev(2)`).

`iov_size`

Number of `iovec` structures in the `iov` array.

`timeout`

A value of type st_utime_t specifying the inactivity timeout (in microseconds).

##### Returns

On success a non-negative integer equal to the sum of all the buffer lengths is returned. Otherwise, a value of `-1` is returned and `errno` is set to indicate the error. Possible `errno` values are the same as set by the `writev(2)` call with two exceptions:

`EINTR` | The current thread was interrupted by st_thread_interrupt().
`ETIME` | The timeout occurred.

##### Description

This function blocks the calling thread until all the data is written, a timeout occurs, or the write operation fails. The return value is equal to either the sum of all the buffer lengths (on success) or `-1` (on failure). Note that if `st_writev()` returns `-1`, part of the data may have been written before an error occurred.

#### st_recvfrom()

Receives bytes from a file descriptor object and stores the sending peer's address.

##### Syntax

    #include <st.h>

    int st_recvfrom(st_netfd_t fd, void *buf, int len, struct sockaddr *from,
                    int *fromlen, st_utime_t timeout);

##### Parameters

`st_recvfrom()` has the following parameters:

`fd`

A file descriptor object identifier (see st_netfd_t) representing a UDP socket.

`buf`

A pointer to a buffer to hold the data received.

`len`

The size of `buf` in bytes.

`from`

If this parameter is not a `NULL` pointer, the source address of the message is filled in (see `recvfrom(3)`).

`fromlen`

This is a value-result parameter, initialized to the size of the buffer associated with `from`, and modified on return to indicate the actual size of the address stored there.

`timeout`

A value of type st_utime_t specifying the time limit in microseconds for completion of the receive operation.

##### Returns

On success a non-negative integer indicating the length of the received message in bytes is returned. Otherwise, a value of `-1` is returned and `errno` is set to indicate the error. Possible `errno` values are the same as set by the `recvfrom(3)` call with two exceptions:

`EINTR` | The current thread was interrupted by st_thread_interrupt().
`ETIME` | The timeout occurred and no data was received.

##### Description

This function receives up to a specified number of bytes from the specified file descriptor object representing a UDP socket.

`st_recvfrom()` blocks the calling thread until one or more bytes are transferred, a timeout has occurred, or there is an error. No more than `len` bytes will be transferred.

#### st_sendto()

Sends bytes to a specified destination.

##### Syntax

    #include <st.h>

    int st_sendto(st_netfd_t fd, const void *msg, int len, struct sockaddr *to,
                  int tolen, st_utime_t timeout);

##### Parameters

`st_sendto()` has the following parameters:

`fd`

A file descriptor object identifier (see st_netfd_t) representing a UDP socket.

`msg`

A pointer to a buffer containing the message to be sent.

`len`

The length of the message to be sent (in bytes).

`to`

A pointer to the address of the destination (see `sendto(3)`).

`tolen`

This parameter specifies the size of the destination address.

`timeout`

A value of type st_utime_t specifying the time limit in microseconds for completion of the send operation.

##### Returns

On success a non-negative integer indicating the number of bytes sent is returned. Otherwise, a value of `-1` is returned and `errno` is set to indicate the error. Possible `errno` values are the same as set by the `sendto(3)` call with two exceptions:

`EINTR` | The current thread was interrupted by st_thread_interrupt().
`ETIME` | The timeout occurred and no data was sent.

##### Description

This function sends a specified number of bytes from a file descriptor object representing a UDP socket to the specified destination address. If no buffer space is available at the underlying OS socket to hold the message to be transmitted, then `st_sendto()` blocks the calling thread until the space becomes available, a timeout occurs, or an error occurs.

#### st_open()

Opens a file for reading, writing, or both.

##### Syntax

    #include <st.h>

    st_netfd_t st_open(const char *path, int oflags, mode_t mode);

##### Parameters

`st_open()` has the following parameters:

`path`

The pathname of the file to be opened.

`oflags`

File status flags. These are the same flags that are used by the `open(2)` system call.

`mode`

Access permission bits of the file mode, if the file is created when `O_CREAT` is set in `oflags` (see `open(2)`).

##### Returns

Upon successful completion, a new file descriptor object identifier is returned. Otherwise, `NULL` is returned and `errno` is set to indicate the error.

##### Description

This function creates a new file descriptor object of type st_netfd_t for the file with the pathname `path`. This object can be freed by st_netfd_free() or st_netfd_close().

The primary purpose of this function is to open FIFOs (named pipes) or other special files in order to create an end point of communication. However, it can be used on regular files as well.

Among other things, this function always sets a non-blocking flag on the underlying OS file descriptor, so there is no need to include that flag in `oflags`.

#### st_poll()

Detects when I/O is ready for a set of OS file descriptors.

##### Syntax

    #include <st.h>

    int st_poll(struct pollfd *pds, int npds, st_utime_t timeout);

##### Parameters

`st_poll()` has the following parameters:

`pds`

A pointer to an array of `pollfd` structures (see `poll(2)`).

`npds`

The number of elements in the `pds` array.

`timeout`

A value of type st_utime_t specifying the amount of time in microseconds the call will block waiting for I/O to become ready. If this time expires without any I/O becoming ready, `st_poll()` returns zero.

##### Returns

Upon successful completion, a non-negative value is returned. A positive value indicates the total number of OS file descriptors in `pds` that have events. A value of `0` indicates that the call timed out. Upon failure, a value of `-1` is returned and `errno` is set to indicate the error:

`EINTR` | The current thread was interrupted by st_thread_interrupt().

##### Description

This function returns as soon as I/O is ready on one or more of the specified OS file descriptors. A count of the number of ready descriptors is returned unless a timeout occurs, in which case zero is returned.

The `pollfd` structure is defined in the `poll.h` header file and contains the following members:

        int fd;             /* OS file descriptor */
        short events;       /* requested events   */
        short revents;      /* returned events    */

The `events` field should be set to the I/O events (readable, writable, exception, or some combination) that the caller is interested in. On return, the `revents` field is set to indicate what kind of I/O is ready on the respective descriptor.

The `events` and `revents` fields are constructed by OR-ing any combination of the following event flags (defined in `poll.h`):

`POLLIN` | `fd` is readable.
`POLLOUT` | `fd` is is writable.
`POLLPRI` | `fd` has an exception condition.
`POLLNVAL` | `fd` is bad.

The `POLLNVAL` flag is only valid in the `revents` field; it is not used in the `events` field.

Note that unlike the `poll(2)` call, this function has the `timeout` parameter expressed in microseconds. If the value of `timeout` is `-1`, this function blocks until a requested I/O event occurs or until the call is interrupted by st_thread_interrupt().

## Program Structure

Generally, the following steps should be followed when writing an application using the State Threads library:

1. Initialize the library by calling st_init().

2. Create resources that will be shared among different processes: create and bind listening sockets (see `socket(3)`, `bind(3)`, `listen(3)`, st_netfd_open_socket(), and possibly st_netfd_serialize_accept()), create shared memory segments, inter-process communication (IPC) channels and synchronization primitives (if any).

3. Create several processes via `fork(2)`. The parent process should either exit or become a "watchdog" (e.g., it starts a new process when an existing one crashes, does a cleanup upon application termination, etc.).

4. In each child process create a pool of threads (see st_thread_create()) to handle user connections. Each thread in the pool may accept client connections (st_accept()), connect to other servers (st_connect()), perform various network I/O (st_read(), st_write(), etc.).

Note that only State Threads library I/O functions should be used for a network I/O: any other I/O calls may block the calling process indefinitely. For example, standard I/O functions (`fgets(3)`, `fread(3)`, `fwrite(3)`, `fprintf(3)`, etc.) call `read(2)` and `write(2)` directly and therefore should not be used on sockets or pipes.

## List of Blocking Functions

The thread context switch (process state change) can only happen in a well-known set of blocking functions. Only the following functions can block the calling thread:

  st_thread_join()
  st_sleep()
  st_usleep()
  st_cond_wait()
  st_cond_timedwait()
  st_mutex_lock()
  st_netfd_poll()
  st_accept()
  st_connect()
  st_read()
  st_read_fully()
  st_read_resid()
  st_write()
  st_write_resid()
  st_writev()
  st_recvfrom()
  st_sendto()
  st_poll()