libtealet 0.4.2
Loading...
Searching...
No Matches
tealet.h
Go to the documentation of this file.
1
5/* A minimal coroutine package for C */
6#ifndef _TEALET_H_
7#define _TEALET_H_
8
9#include <stddef.h>
10
11/* Version information */
12#define TEALET_VERSION_MAJOR 0
13#define TEALET_VERSION_MINOR 4
14#define TEALET_VERSION_PATCH 3
15
16/* Version as a string */
17#define TEALET_VERSION "0.4.3"
18
19/* Version as a single number for comparisons (MMmmpp: Major, minor, patch) */
20#define TEALET_VERSION_NUMBER ((TEALET_VERSION_MAJOR * 10000) + (TEALET_VERSION_MINOR * 100) + TEALET_VERSION_PATCH)
21
22#ifdef WIN32
23#if defined TEALET_EXPORTS
24#define TEALET_API __declspec(dllexport)
25#elif defined TEALET_IMPORTS
26#define TEALET_API __declspec(dllimport)
27#else
28#define TEALET_API
29#endif
30#else /* win32 */
31#define TEALET_API
32#endif
33
38typedef void *(*tealet_malloc_t)(size_t size, void *context);
39typedef void (*tealet_free_t)(void *ptr, void *context);
40typedef struct tealet_alloc_t {
41 tealet_malloc_t malloc_p;
42 tealet_free_t free_p;
43 void *context;
45
50#define TEALET_ALLOC_INIT_MALLOC \
51 { (tealet_malloc_t) & malloc, (tealet_free_t)&free, 0 }
52
54#define TEALET_ALLOC_MALLOC(alloc, size) (alloc)->malloc_p((size), (alloc)->context)
55#define TEALET_ALLOC_FREE(alloc, ptr) (alloc)->free_p((ptr), (alloc)->context)
56
61typedef struct tealet_t {
62 struct tealet_t *main; /* pointer to the main tealet */
63 void *extra;
64 /* private fields follow */
66
74typedef tealet_t *(*tealet_run_t)(tealet_t *current, void *arg);
75
81#define TEALET_ERR_MEM -1 /* memory allocation failed */
82#define TEALET_ERR_DEFUNCT -2 /* the target tealet is corrupt */
83#define TEALET_ERR_UNFORKABLE \
84 -3 /* tealet cannot be forked (unbounded stack) \
85 */
86#define TEALET_ERR_INVAL -4 /* invalid argument */
87#define TEALET_ERR_INTEGRITY -5 /* current tealet violated stack-integrity boundary */
88#define TEALET_ERR_PANIC -6 /* switched to main due to panic reroute from tealet_exit() */
89
90/* configuration API structure versioning */
91#define TEALET_CONFIG_VERSION_1 1
92#define TEALET_CONFIG_CURRENT_VERSION TEALET_CONFIG_VERSION_1
93
94/* stack integrity configuration flags */
95#define TEALET_CONFIGF_STACK_INTEGRITY (1u << 0)
96#define TEALET_CONFIGF_STACK_GUARD (1u << 1)
97#define TEALET_CONFIGF_STACK_SNAPSHOT (1u << 2)
98
99/* stack guard modes */
100#define TEALET_STACK_GUARD_MODE_NONE 0
101#define TEALET_STACK_GUARD_MODE_READONLY 1
102#define TEALET_STACK_GUARD_MODE_NOACCESS 2
103
104/* stack integrity failure policy */
105#define TEALET_STACK_INTEGRITY_FAIL_ASSERT 0
106#define TEALET_STACK_INTEGRITY_FAIL_ERROR 1
107#define TEALET_STACK_INTEGRITY_FAIL_ABORT 2
108
109/* conservative default upper bound for caller stack distance checks */
110#define TEALET_DEFAULT_MAX_STACK_SIZE ((size_t)(16u * 1024u * 1024u))
111
122typedef struct tealet_config_t {
123 size_t size;
124 unsigned int version;
125 unsigned int flags;
126 size_t stack_integrity_bytes;
127 int stack_guard_mode;
128 int stack_integrity_fail_policy;
129 void *stack_guard_limit;
130 size_t max_stack_size; /* max caller stack distance for sanity checks; 0 disables */
131 unsigned int reserved[2];
133
134/* Convenience initializer for configuration structs */
135#define TEALET_CONFIG_INIT \
136 { \
137 sizeof(tealet_config_t), TEALET_CONFIG_CURRENT_VERSION, 0u, 0, TEALET_STACK_GUARD_MODE_NONE, \
138 TEALET_STACK_INTEGRITY_FAIL_ASSERT, NULL, TEALET_DEFAULT_MAX_STACK_SIZE, { \
139 0u, 0u \
140 } \
141 }
142
143/* ----------------------------------------------------------------
144 * Public API - core lifecycle and switching
145 */
146
157TEALET_API
158tealet_t *tealet_initialize(tealet_alloc_t *alloc, size_t extrasize);
159
167TEALET_API
168void tealet_finalize(tealet_t *tealet);
169
181TEALET_API
182tealet_t *tealet_create(tealet_t *tealet, tealet_run_t run, void *stack_far);
183
195TEALET_API
196tealet_t *tealet_new(tealet_t *tealet, tealet_run_t run, void **parg, void *stack_far);
197
210TEALET_API
211int tealet_switch(tealet_t *target, void **parg);
212
213/* Exit flags */
214#define TEALET_EXIT_DEFAULT 0 /* Don't auto-delete */
215#define TEALET_EXIT_DELETE 1 /* Auto-delete on exit */
216#define TEALET_EXIT_DEFER 2 /* Defer exit to return statement */
217
228TEALET_API
229int tealet_exit(tealet_t *target, void *arg, int flags);
230
326#define TEALET_FORK_DEFAULT 0
327#define TEALET_FORK_SWITCH 1
328TEALET_API
329int tealet_fork(tealet_t *current, tealet_t **pother, void **parg, int flags);
330
350TEALET_API
352
363TEALET_API
364void tealet_delete(tealet_t *target);
365
366/* ----------------------------------------------------------------
367 * Public API - status and query
368 */
369
374TEALET_API
376
381TEALET_API
383
388TEALET_API
389void **tealet_main_userpointer(tealet_t *tealet);
390
391/* Tealet origin flags returned by tealet_get_origin(). */
392#define TEALET_ORIGIN_MAIN_LINEAGE (1u << 0) /* main tealet, or fork-descended from main */
393#define TEALET_ORIGIN_FORK (1u << 1) /* tealet originated from tealet_fork() */
394
405TEALET_API
406unsigned int tealet_get_origin(tealet_t *tealet);
407
408/* Status code: active tealet. */
409#define TEALET_STATUS_ACTIVE 0
410/* Status code: exited tealet. */
411#define TEALET_STATUS_EXITED 1
412/* Status code: defunct tealet. */
413#define TEALET_STATUS_DEFUNCT -2
414TEALET_API
415int tealet_status(tealet_t *tealet);
416
422TEALET_API
423size_t tealet_get_stacksize(tealet_t *tealet);
424
434TEALET_API
435void *tealet_get_far(tealet_t *tealet);
436
437/* Aggregate resource statistics for a main-tealet domain. */
438typedef struct tealet_stats_t {
439 /* Basic tealet counts */
440 int n_active; /* number of active tealets (excluding main) */
441 int n_total; /* total tealets created (cumulative) */
442
443 /* Memory usage statistics */
444 size_t bytes_allocated; /* Current heap allocation */
445 size_t bytes_allocated_peak; /* Peak heap allocation */
446 size_t blocks_allocated; /* Current number of allocated stack blocks */
447 size_t blocks_allocated_peak; /* Peak number of allocated stack blocks */
448 size_t blocks_allocated_total; /* Total allocation calls */
449
450 /* stack memory storage statistics */
451 size_t stack_bytes; /* Bytes used for stack storage */
452 size_t stack_bytes_expanded; /* Bytes used for stack if there were no reuse */
453 size_t stack_bytes_naive; /* Bytes used for stack if we stored stack naively */
454 size_t stack_count; /* Number of currently stored unique stacks */
455 size_t stack_chunk_count; /* Number of currently stored unique stack chunks */
457
458TEALET_API
459void tealet_get_stats(tealet_t *t, tealet_stats_t *s);
460
461TEALET_API
462void tealet_reset_peak_stats(tealet_t *t);
463
464/* ----------------------------------------------------------------
465 * Public API - configuration
466 */
467
523TEALET_API
524int tealet_set_far(tealet_t *tealet, void *far_boundary);
525
545TEALET_API
546int tealet_configure_get(tealet_t *tealet, tealet_config_t *config);
547
556TEALET_API
557int tealet_configure_set(tealet_t *tealet, tealet_config_t *config);
558
585TEALET_API
586int tealet_configure_check_stack(tealet_t *tealet, size_t stack_integrity_bytes);
587
588/* ----------------------------------------------------------------
589 * Public API - utility helpers
590 */
591
602TEALET_API
603void *tealet_malloc(tealet_t *tealet, size_t s);
604
610TEALET_API
611void tealet_free(tealet_t *tealet, void *p);
612
613/* functions for stack arithmetic. Useful when deciding
614 * if you want to start a new tealet, or when doing stack
615 * spilling
616 */
617
629TEALET_API
630ptrdiff_t tealet_stack_diff(void *a, void *b);
631
642TEALET_API
643void *tealet_stack_further(void *a, void *b);
644
656TEALET_API
657void *tealet_new_probe(tealet_t *dummy1, tealet_run_t dummy2, void **dummy3, void *dummy4);
658
659/* Convenience macros */
660#define TEALET_MAIN(t) ((t)->main)
661#define TEALET_IS_MAIN(t) ((t) == TEALET_MAIN(t))
662#define TEALET_CURRENT_IS_MAIN(t) (tealet_current(t) == TEALET_MAIN(t))
663#define TEALET_IS_MAIN_LINEAGE(t) ((tealet_get_origin(t) & TEALET_ORIGIN_MAIN_LINEAGE) != 0)
664#define TEALET_IS_FORK(t) ((tealet_get_origin(t) & TEALET_ORIGIN_FORK) != 0)
665
666/* see if two tealets share the same MAIN, and can therefore be switched between
667 */
668#define TEALET_RELATED(t1, t2) (TEALET_MAIN(t1) == TEALET_MAIN(t2))
669
670/* convenience access to a typecast extra pointer */
671#define TEALET_EXTRA(t, tp) ((tp *)((t)->extra))
672
673#endif /* _TEALET_H_ */
Definition tealet.h:40
Definition tealet.h:121
Definition tealet.h:437
Definition tealet.h:61
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.
TEALET_API tealet_t * tealet_create(tealet_t *tealet, tealet_run_t run, void *stack_far)
Create a new tealet without starting it.
TEALET_API void tealet_finalize(tealet_t *tealet)
Destroy a previously initialized main tealet.
TEALET_API int tealet_configure_set(tealet_t *tealet, tealet_config_t *config)
Set runtime configuration for a main tealet.
TEALET_API void * tealet_get_far(tealet_t *tealet)
Get a tealet's far stack boundary marker.
TEALET_API void tealet_free(tealet_t *tealet, void *p)
Free memory using the tealet-domain allocator.
TEALET_API void * tealet_malloc(tealet_t *tealet, size_t s)
Allocate memory using the tealet-domain allocator.
TEALET_API int tealet_configure_check_stack(tealet_t *tealet, size_t stack_integrity_bytes)
Enable stack-integrity checking with practical defaults.
tealet_t *(* tealet_run_t)(tealet_t *current, void *arg)
Definition tealet.h:74
TEALET_API ptrdiff_t tealet_stack_diff(void *a, void *b)
Direction-aware stack pointer subtraction.
TEALET_API unsigned int tealet_get_origin(tealet_t *tealet)
Get tealet origin flags.
TEALET_API tealet_t * tealet_duplicate(tealet_t *tealet)
Duplicate a suspended tealet and its saved stack state.
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_delete(tealet_t *target)
Deallocate a non-main tealet.
TEALET_API tealet_t * tealet_new(tealet_t *tealet, tealet_run_t run, void **parg, void *stack_far)
Create and immediately start a new tealet.
TEALET_API size_t tealet_get_stacksize(tealet_t *tealet)
Get byte size of currently saved stack snapshot for a tealet.
TEALET_API tealet_t * tealet_previous(tealet_t *tealet)
TEALET_API int tealet_switch(tealet_t *target, void **parg)
Suspend current tealet and resume target.
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_exit(tealet_t *target, void *arg, int flags)
Exit current tealet and transfer control to target.
void *(* tealet_malloc_t)(size_t size, void *context)
Definition tealet.h:38
TEALET_API tealet_t * tealet_initialize(tealet_alloc_t *alloc, size_t extrasize)
Initialize libtealet and create the main tealet for the current thread.
TEALET_API void ** tealet_main_userpointer(tealet_t *tealet)
TEALET_API tealet_t * tealet_current(tealet_t *tealet)
TEALET_API int tealet_set_far(tealet_t *tealet, void *far_boundary)