libtealet 0.4.2
Loading...
Searching...
No Matches
tealet.h File Reference

Public core API for libtealet. More...

#include <stddef.h>
Include dependency graph for tealet.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  tealet_alloc_t
 
struct  tealet_t
 
struct  tealet_config_t
 
struct  tealet_stats_t
 

Macros

#define TEALET_VERSION_MAJOR   0
 
#define TEALET_VERSION_MINOR   4
 
#define TEALET_VERSION_PATCH   3
 
#define TEALET_VERSION   "0.4.3"
 
#define TEALET_VERSION_NUMBER   ((TEALET_VERSION_MAJOR * 10000) + (TEALET_VERSION_MINOR * 100) + TEALET_VERSION_PATCH)
 
#define TEALET_API
 
#define TEALET_ALLOC_INIT_MALLOC    { (tealet_malloc_t) & malloc, (tealet_free_t)&free, 0 }
 
#define TEALET_ALLOC_MALLOC(alloc, size)   (alloc)->malloc_p((size), (alloc)->context)
 
#define TEALET_ALLOC_FREE(alloc, ptr)   (alloc)->free_p((ptr), (alloc)->context)
 
#define TEALET_ERR_MEM   -1 /* memory allocation failed */
 
#define TEALET_ERR_DEFUNCT   -2 /* the target tealet is corrupt */
 
#define TEALET_ERR_UNFORKABLE
 
#define TEALET_ERR_INVAL   -4 /* invalid argument */
 
#define TEALET_ERR_INTEGRITY   -5 /* current tealet violated stack-integrity boundary */
 
#define TEALET_ERR_PANIC   -6 /* switched to main due to panic reroute from tealet_exit() */
 
#define TEALET_CONFIG_VERSION_1   1
 
#define TEALET_CONFIG_CURRENT_VERSION   TEALET_CONFIG_VERSION_1
 
#define TEALET_CONFIGF_STACK_INTEGRITY   (1u << 0)
 
#define TEALET_CONFIGF_STACK_GUARD   (1u << 1)
 
#define TEALET_CONFIGF_STACK_SNAPSHOT   (1u << 2)
 
#define TEALET_STACK_GUARD_MODE_NONE   0
 
#define TEALET_STACK_GUARD_MODE_READONLY   1
 
#define TEALET_STACK_GUARD_MODE_NOACCESS   2
 
#define TEALET_STACK_INTEGRITY_FAIL_ASSERT   0
 
#define TEALET_STACK_INTEGRITY_FAIL_ERROR   1
 
#define TEALET_STACK_INTEGRITY_FAIL_ABORT   2
 
#define TEALET_DEFAULT_MAX_STACK_SIZE   ((size_t)(16u * 1024u * 1024u))
 
#define TEALET_CONFIG_INIT
 
#define TEALET_EXIT_DEFAULT   0 /* Don't auto-delete */
 
#define TEALET_EXIT_DELETE   1 /* Auto-delete on exit */
 
#define TEALET_EXIT_DEFER   2 /* Defer exit to return statement */
 
#define TEALET_FORK_DEFAULT   0
 Fork the active tealet by duplicating its execution state.
 
#define TEALET_FORK_SWITCH   1
 
#define TEALET_ORIGIN_MAIN_LINEAGE   (1u << 0) /* main tealet, or fork-descended from main */
 
#define TEALET_ORIGIN_FORK   (1u << 1) /* tealet originated from tealet_fork() */
 
#define TEALET_STATUS_ACTIVE   0
 
#define TEALET_STATUS_EXITED   1
 
#define TEALET_STATUS_DEFUNCT   -2
 
#define TEALET_MAIN(t)   ((t)->main)
 
#define TEALET_IS_MAIN(t)   ((t) == TEALET_MAIN(t))
 
#define TEALET_CURRENT_IS_MAIN(t)   (tealet_current(t) == TEALET_MAIN(t))
 
#define TEALET_IS_MAIN_LINEAGE(t)   ((tealet_get_origin(t) & TEALET_ORIGIN_MAIN_LINEAGE) != 0)
 
#define TEALET_IS_FORK(t)   ((tealet_get_origin(t) & TEALET_ORIGIN_FORK) != 0)
 
#define TEALET_RELATED(t1, t2)   (TEALET_MAIN(t1) == TEALET_MAIN(t2))
 
#define TEALET_EXTRA(t, tp)   ((tp *)((t)->extra))
 

Typedefs

typedef void *(* tealet_malloc_t) (size_t size, void *context)
 
typedef void(* tealet_free_t) (void *ptr, void *context)
 
typedef struct tealet_alloc_t tealet_alloc_t
 
typedef struct tealet_t tealet_t
 
typedef tealet_t *(* tealet_run_t) (tealet_t *current, void *arg)
 
typedef struct tealet_config_t tealet_config_t
 
typedef struct tealet_stats_t tealet_stats_t
 

Functions

TEALET_API tealet_ttealet_initialize (tealet_alloc_t *alloc, size_t extrasize)
 Initialize libtealet and create the main tealet for the current thread.
 
TEALET_API void tealet_finalize (tealet_t *tealet)
 Destroy a previously initialized main tealet.
 
TEALET_API tealet_ttealet_create (tealet_t *tealet, tealet_run_t run, void *stack_far)
 Create a new tealet without starting it.
 
TEALET_API tealet_ttealet_new (tealet_t *tealet, tealet_run_t run, void **parg, void *stack_far)
 Create and immediately start a new tealet.
 
TEALET_API int tealet_switch (tealet_t *target, void **parg)
 Suspend current tealet and resume target.
 
TEALET_API int tealet_exit (tealet_t *target, void *arg, int flags)
 Exit current tealet and transfer control to target.
 
TEALET_API int tealet_fork (tealet_t *current, tealet_t **pother, void **parg, int flags)
 
TEALET_API tealet_ttealet_duplicate (tealet_t *tealet)
 Duplicate a suspended tealet and its saved stack state.
 
TEALET_API void tealet_delete (tealet_t *target)
 Deallocate a non-main tealet.
 
TEALET_API tealet_ttealet_current (tealet_t *tealet)
 
TEALET_API tealet_ttealet_previous (tealet_t *tealet)
 
TEALET_API void ** tealet_main_userpointer (tealet_t *tealet)
 
TEALET_API unsigned int tealet_get_origin (tealet_t *tealet)
 Get tealet origin flags.
 
TEALET_API int tealet_status (tealet_t *tealet)
 
TEALET_API size_t tealet_get_stacksize (tealet_t *tealet)
 Get byte size of currently saved stack snapshot for a tealet.
 
TEALET_API void * tealet_get_far (tealet_t *tealet)
 Get a tealet's far stack boundary marker.
 
TEALET_API void tealet_get_stats (tealet_t *t, tealet_stats_t *s)
 
TEALET_API void tealet_reset_peak_stats (tealet_t *t)
 
TEALET_API int tealet_set_far (tealet_t *tealet, void *far_boundary)
 
TEALET_API int tealet_configure_get (tealet_t *tealet, tealet_config_t *config)
 Get effective runtime configuration for a main tealet.
 
TEALET_API int tealet_configure_set (tealet_t *tealet, tealet_config_t *config)
 Set runtime configuration for a main tealet.
 
TEALET_API int tealet_configure_check_stack (tealet_t *tealet, size_t stack_integrity_bytes)
 Enable stack-integrity checking with practical defaults.
 
TEALET_API void * tealet_malloc (tealet_t *tealet, size_t s)
 Allocate memory using the tealet-domain allocator.
 
TEALET_API void tealet_free (tealet_t *tealet, void *p)
 Free memory using the tealet-domain allocator.
 
TEALET_API ptrdiff_t tealet_stack_diff (void *a, void *b)
 Direction-aware stack pointer subtraction.
 
TEALET_API void * tealet_stack_further (void *a, void *b)
 Return whichever of two addresses is farther in stack-growth direction.
 
TEALET_API void * tealet_new_probe (tealet_t *dummy1, tealet_run_t dummy2, void **dummy3, void *dummy4)
 Probe helper returning the effective initial far boundary at call site depth.
 

Macro Definition Documentation

◆ TEALET_ALLOC_INIT_MALLOC

#define TEALET_ALLOC_INIT_MALLOC    { (tealet_malloc_t) & malloc, (tealet_free_t)&free, 0 }

use the following macro to initialize a tealet_alloc_t structure with stdlib malloc functions, for convenience, e.g.: tealet_alloc_t stdalloc = TEALET_MALLOC;

◆ TEALET_ALLOC_MALLOC

#define TEALET_ALLOC_MALLOC (   alloc,
  size 
)    (alloc)->malloc_p((size), (alloc)->context)

convenience macros to call an allocator

◆ TEALET_CONFIG_INIT

#define TEALET_CONFIG_INIT
Value:
{ \
sizeof(tealet_config_t), TEALET_CONFIG_CURRENT_VERSION, 0u, 0, TEALET_STACK_GUARD_MODE_NONE, \
TEALET_STACK_INTEGRITY_FAIL_ASSERT, NULL, TEALET_DEFAULT_MAX_STACK_SIZE, { \
0u, 0u \
} \
}
Definition tealet.h:121

◆ TEALET_ERR_MEM

#define TEALET_ERR_MEM   -1 /* memory allocation failed */

error codes. API functions that return int return a negative value to signal an error. Those that return tealet_t pointers return NULL to signal a memory error.

◆ TEALET_ERR_UNFORKABLE

#define TEALET_ERR_UNFORKABLE
Value:
-3 /* tealet cannot be forked (unbounded stack) \
*/

◆ TEALET_FORK_DEFAULT

#define TEALET_FORK_DEFAULT   0
Parameters
currentCurrently active tealet to duplicate.
potherOptional out-pointer to the opposite side (parent gets child, child gets parent).
pargOptional in/out argument pointer passed to whichever side resumes later.
flagsFork mode: TEALET_FORK_DEFAULT or TEALET_FORK_SWITCH.
Return values
1Parent side.
0Child side.
TEALET_ERR_UNFORKABLECurrent stack is unbounded (set far boundary first).
TEALET_ERR_MEMMemory allocation failure.
Warning
For forks originating from main-lineage execution (main tealet or a clone of main), exit explicitly via tealet_exit() and do not use TEALET_EXIT_DEFER.

This function duplicates the currently executing tealet, including its entire execution stack. Both the parent and child tealets will resume execution from the same point (immediately after tealet_fork returns).

This function duplicates the currently executing tealet, including its entire execution stack. Both the parent and child tealets will resume execution from the same point (immediately after tealet_fork returns).

The function returns different values to distinguish parent from child:

  • In the parent tealet: returns 1
  • In the child tealet: returns 0
  • On error: returns -1 (or other negative TEALET_ERR_* code)

If pchild is non-NULL, it will be filled with a pointer to the other tealet:

  • In the parent: points to the newly created child tealet
  • In the child: points to the parent tealet This allows both parent and child to reference each other for switching.

The parg parameter allows passing a pointer value to whichever side of the fork initially gets suspended (similar to tealet_new()). Can be NULL if no argument passing is desired. If non-NULL:

  • With TEALET_FORK_DEFAULT: The parent continues, child is suspended. When the parent later switches to the child, the child receives the value via *parg.
  • With TEALET_FORK_SWITCH: The parent is suspended, child continues. When the child later switches back, the parent receives the value via *parg. See tealet_new() documentation for more details on argument passing semantics.

Prerequisites:

  • The current tealet must be either: a) A regular function-scoped tealet, OR b) The main tealet (or a clone of main) with a bounded stack (far boundary set via tealet_set_far()).
  • The current tealet must be active (not suspended)

Flags:

  • TEALET_FORK_DEFAULT (0): Child is created suspended; parent continues
  • TEALET_FORK_SWITCH (1): Immediately switch to child after creation

Memory considerations:

  • The child tealet has its own stack copy (heap-allocated)
  • Both parent and child share the same main tealet
  • The child inherits the current tealet far boundary (stack_far) at fork time. For main-lineage forks, this means the configured main boundary propagates to the child clone.
  • Stack-allocated data is duplicated, heap data is shared
  • Use tealet_current() to get the current tealet pointer after forking

Exit behavior depends on what was forked:

  • Forking main-lineage execution (main tealet or a clone of main) creates a continuation without a normal run-function return path. In that case, exit via tealet_exit() with an explicit target and do not use TEALET_EXIT_DEFER.
  • Forking a regular function-scoped tealet duplicates that existing call chain. The forked tealet can generally return through the same run-function path as the original tealet.

Example: tealet_t *child = NULL; int result = tealet_fork(current, &child, NULL, TEALET_FORK_DEFAULT); if (result == 0) { // This is the child tealet // ... child-specific code ... } else if (result > 0) { // This is the parent tealet // ... parent-specific code ... tealet_switch(child, &arg); // Switch to child when ready } else { // Error occurred (result < 0) }

Returns: Parent: 1 Child: 0 Error: negative error code: TEALET_ERR_UNFORKABLE if current tealet has unbounded stack TEALET_ERR_MEM if memory allocation failed TEALET_ERR_DEFUNCT if current tealet is not active

Typedef Documentation

◆ tealet_config_t

Runtime configuration for stack integrity and related safety features.

ABI compatibility contract:

  • 'size' must be the first member and set by caller to sizeof(tealet_config_t) (or a future/older struct size).
  • 'version' is a struct format version, independent from the global libtealet ABI.
  • tealet_configure_get()/set() read/write only the prefix known to this build, bounded by 'size'. Unknown tail fields are ignored.

◆ tealet_malloc_t

typedef void *(* tealet_malloc_t) (size_t size, void *context)

A structure to define the memory allocation api used. the functions have C89 semantics and take an additional "context" pointer that they can use as they please

◆ tealet_run_t

typedef tealet_t *(* tealet_run_t) (tealet_t *current, void *arg)

The "run" function of a tealet. It is called with the current tealet and the argument provided to its invocation function, see tealet_create() and tealet_switch(). The return value of run() must be the next tealet in which to continue execution, which must be a different one, like for example the main tealet. When 'run(g)' returns, the tealet 'g' is freed.

◆ tealet_t

typedef struct tealet_t tealet_t

The user-visible tealet structure. If an "extrasize" is provided when the main tealet was initialized, "extra" points to a private block of that size, otherwise it is initialized to NULL

Function Documentation

◆ tealet_configure_check_stack()

TEALET_API int tealet_configure_check_stack ( tealet_t tealet,
size_t  stack_integrity_bytes 
)
Parameters
tealetAny tealet in the domain.
stack_integrity_bytesRequested watch window bytes; 0 picks sensible default.
Returns
0 on success, negative #TEALET_ERR_* on failure.

Convenience helper to enable stack checking with sensible defaults.

This enables stack integrity checks with both guard pages and snapshot verification, then applies the resulting configuration via tealet_configure_set().

If stack_integrity_bytes is 0, a default window of one OS memory page is used where available.

Note: this helper sets stack_guard_limit to a local stack marker inside this function. For best results, call it from a program top-level function whose frame should remain within the intended stack region for switched tealets.

This helper is intended as a one-way "turn checks on" API. You can still use tealet_configure_set() directly for custom tuning.

Return values: 0 on success <0 on error (e.g. TEALET_ERR_INVAL, TEALET_ERR_MEM)

◆ tealet_configure_get()

TEALET_API int tealet_configure_get ( tealet_t tealet,
tealet_config_t config 
)
Parameters
tealetAny tealet in the domain.
configSize/versioned output buffer.
Returns
0 on success, negative #TEALET_ERR_* on failure.

Get or set runtime configuration on the main tealet.

These functions are intended for feature toggles such as optional stack integrity checks. The caller supplies a size/versioned config struct.

tealet_configure_set() canonicalizes the struct in-place to the effective configuration actually applied by this build/platform (unsupported features are cleared and dependent fields normalized).

Return values: 0 on success <0 on error (e.g. TEALET_ERR_INVAL)

◆ tealet_configure_set()

TEALET_API int tealet_configure_set ( tealet_t tealet,
tealet_config_t config 
)
Parameters
tealetAny tealet in the domain.
configSize/versioned input/output configuration struct.
Returns
0 on success, negative #TEALET_ERR_* on failure.

Input is canonicalized in-place to effective applied settings.

◆ tealet_create()

TEALET_API tealet_t * tealet_create ( tealet_t tealet,
tealet_run_t  run,
void *  stack_far 
)
Parameters
tealetMain/related tealet context used for allocation and ownership.
runEntry function for the created tealet.
stack_farOptional minimum far-boundary requirement for the initial stack snapshot.
Returns
New tealet pointer, or NULL on allocation/setup failure.

The new tealet enters execution when tealet_switch() first targets it. If stack_far is non-NULL, capture range is only extended (never shrunk) relative to the default internally selected boundary.

◆ tealet_current()

TEALET_API tealet_t * tealet_current ( tealet_t tealet)

Return the current tealet, i.e. the one in which the caller of this function currently is. "tealet" can be any tealet derived from the main tealet.

◆ tealet_delete()

TEALET_API void tealet_delete ( tealet_t target)
Parameters
targetTealet to delete.

Deallocate a tealet. Use this to delete a tealet that has exited with tealet_exit() with 'TEALET_EXIT_DEFAULT', or defunct tealets. Active tealet can also be deleted, such as stubs that are no longer in use, but take care because any local resources in such tealets won't be freed.

◆ tealet_duplicate()

TEALET_API tealet_t * tealet_duplicate ( tealet_t tealet)
Parameters
tealetSource tealet (must not be current/main).
Returns
Duplicated tealet, or NULL on failure.

Duplicate starts with copied stack snapshot and copied internal flags. Extra payload area (extra) is copied when configured.

Duplicate a tealet. The active tealet is duplicated along with its stack contents. This can be used, for example, to create "stubs" that can be duplicated and re-used to run with different arguments. Use this with care, because initially the duplicate will share the same stack data as the original. This includes any local variables, even the "current" argument passed to the original "run" function which may be obsolete by the time the duplicate is run. Use the argument passing mechanism to provide the copy with fresh data. Any extra data is left uncopied, the application must do that.

◆ tealet_exit()

TEALET_API int tealet_exit ( tealet_t target,
void *  arg,
int  flags 
)
Parameters
targetRequested target tealet.
argOptional argument to deliver to target.
flagsExit behavior bits: TEALET_EXIT_DEFAULT, TEALET_EXIT_DELETE, TEALET_EXIT_DEFER.
Returns
0 only for deferred setup path; otherwise this call is non-returning on success.

If the requested target is defunct, control is rerouted to main as panic fallback. return p; from run() is equivalent to tealet_exit(p, NULL, TEALET_EXIT_DELETE).

◆ tealet_finalize()

TEALET_API void tealet_finalize ( tealet_t tealet)
Parameters
tealetMain tealet returned by tealet_initialize().
Warning
This does not delete child tealets. Delete all non-main tealets first.
After finalize returns, all handles associated with that main tealet are invalid.

◆ tealet_free()

TEALET_API void tealet_free ( tealet_t tealet,
void *  p 
)
Parameters
tealetAny tealet in the domain.
pPointer previously allocated by tealet_malloc() or equivalent domain allocator.

◆ tealet_get_far()

TEALET_API void * tealet_get_far ( tealet_t tealet)
Parameters
tealetTarget tealet.
Returns
Far boundary pointer.

Get a tealet's "far" position on the stack. This is an indicator of its creation position on the stack. The main tealet extends until the beginning of stack

◆ tealet_get_origin()

TEALET_API unsigned int tealet_get_origin ( tealet_t tealet)
Parameters
tealetTarget tealet.
Returns
Bitwise OR of #TEALET_ORIGIN_* flags.

Origin flags are immutable identity markers:

  • TEALET_ORIGIN_MAIN_LINEAGE marks main-like lineage (main and descendants produced through tealet_fork() from main lineage).
  • TEALET_ORIGIN_FORK marks tealets that originated from tealet_fork().

◆ tealet_get_stacksize()

TEALET_API size_t tealet_get_stacksize ( tealet_t tealet)
Parameters
tealetTarget tealet.
Returns
Saved stack bytes, or 0 when active/defunct/no saved stack.

◆ tealet_initialize()

TEALET_API tealet_t * tealet_initialize ( tealet_alloc_t alloc,
size_t  extrasize 
)
Parameters
allocAllocator interface; use TEALET_ALLOC_INIT_MALLOC for stdlib malloc/free.
extrasizeOptional per-tealet extra bytes; exposed via tealet_t::extra / TEALET_EXTRA.
Returns
Pointer to the main tealet, or NULL on allocation failure.

The main tealet represents the ambient program execution context for this thread. Initialize/finalize pairs may be nested or used in multiple threads, but only tealets derived from the same main tealet are switch-compatible.

◆ tealet_main_userpointer()

TEALET_API void ** tealet_main_userpointer ( tealet_t tealet)

Get the address of the tealet's main user pointer, a single void pointer associated with the main tealet. Use this to associate a (void*)value with the main tealet.

◆ tealet_malloc()

TEALET_API void * tealet_malloc ( tealet_t tealet,
size_t  s 
)
Parameters
tealetAny tealet in the domain.
sByte count.
Returns
Allocated block or NULL.

access to the tealet's allocator. This can be useful to use e.g. when passing data between tealets but such data cannot reside on the stack (except during the initial call to tealet_new)

◆ tealet_new()

TEALET_API tealet_t * tealet_new ( tealet_t tealet,
tealet_run_t  run,
void **  parg,
void *  stack_far 
)
Parameters
tealetMain/related tealet context.
runEntry function.
pargIn/out switch argument pointer (same semantics as tealet_switch()).
stack_farOptional minimum far-boundary requirement for the initial stack snapshot.
Returns
New tealet pointer on success; NULL on allocation/switch failure.

Semantically equivalent to tealet_create() followed by tealet_switch(), but performed as one operation.

◆ tealet_new_probe()

TEALET_API void * tealet_new_probe ( tealet_t dummy1,
tealet_run_t  dummy2,
void **  dummy3,
void *  dummy4 
)
Parameters
dummy1Matches tealet_new() signature; ignored.
dummy2Matches tealet_new() signature; ignored.
dummy3Matches tealet_new() signature; ignored.
dummy4Optional requested boundary (as in tealet_new()).
Returns
Effective far boundary that tealet_new() would use at this stack depth.

this is used to get the "far" address if a tealet were initialized here. The arguments must match tealet_new(); they are only dummies.

◆ tealet_previous()

TEALET_API tealet_t * tealet_previous ( tealet_t tealet)

Return the previous tealet, i.e. the one that switched to us. "tealet" can be any tealet derived from the main tealet.

◆ tealet_set_far()

TEALET_API int tealet_set_far ( tealet_t tealet,
void *  far_boundary 
)

Set the far boundary of a tealet's stack.

This function sets the far boundary of a tealet's stack, which defines where the stack ends for stack-slicing operations.

For the main tealet: The main tealet normally has an unbounded stack extent (represented internally as STACKMAN_SP_FURTHEST). To enable operations like tealet_fork() that need to duplicate the stack, you must first set a far boundary.

IMPORTANT: The far_boundary pointer should typically come from a PARENT function of the function that will perform fork operations. This ensures that all local variables in the forking function (and any functions it calls) are included in the saved stack slice. If you pass a local variable from the same function that calls fork, that variable and others declared after it may not be properly saved.

Recommended pattern (far_boundary from parent function):

int main(void) { int far_marker; run_program(&far_marker); return 0; }

void run_program(void *far_marker) { tealet_t *main = tealet_initialize(&alloc, 0); tealet_set_far(main, far_marker);

int local_var = 0; tealet_fork(main, &child, 0); }

Alternative (far_boundary from same function, requires care):

void my_main() { int far_marker; tealet_t *main = tealet_initialize(&alloc, 0); tealet_set_far(main, &far_marker);

int local_var = 0; tealet_fork(main, &child, 0); }

By providing this address, you promise that no stack data beyond (further from) this point needs to be saved during fork/duplicate operations.

Note: Currently, this function can only be called on the main tealet. Calling it on a non-main tealet will return an error.

Returns: 0 on success -1 if called from a non-main tealet

◆ tealet_stack_diff()

TEALET_API ptrdiff_t tealet_stack_diff ( void *  a,
void *  b 
)
Parameters
aFirst stack position.
bSecond stack position.
Returns
Positive when b is deeper than a in stack-growth direction.

subtract two stack positions, taking into account if the local stack grows up or down in memory. The result is positive if 'b' is 'deeper' on the stack than 'a'

◆ tealet_stack_further()

TEALET_API void * tealet_stack_further ( void *  a,
void *  b 
)
Parameters
aFirst stack position.
bSecond stack position.
Returns
Direction-aware farther boundary.

Return whichever stack position is farther from the active stack top. This is direction-aware: on descending stacks this is the larger address; on ascending stacks it is the smaller address.

◆ tealet_switch()

TEALET_API int tealet_switch ( tealet_t target,
void **  parg 
)
Parameters
targetTealet to switch to; must share the same main tealet and thread.
pargIn/out argument pointer passed across switches; may be NULL.
Return values
0Success.
TEALET_ERR_MEMSave/restore failed due to memory pressure.
TEALET_ERR_DEFUNCTTarget tealet/stack is defunct.
TEALET_ERR_PANICReturned to main after panic reroute from tealet_exit().
TEALET_ERR_INVALInvalid state/target.
Warning
Do not pass stack-allocated cross-tealet payloads through parg.