aboutsummaryrefslogtreecommitdiff
path: root/include/kpl/env.h
blob: 19d9536736418dccf20cac6589742ec1e61139db (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
/*
 * KPL environment objects
 */

#pragma once

typedef enum : int32_t {
    KPL_THREAD_DETERIMINE_COUNT = -1,
    KPL_THREAD_MAIN_ID          = 0
} kpl_thread_enum;

typedef struct _kpl_thread {
    int32_t thread_id; // self id
    kpl_memory_allocator memory_allocator;
    // TODO io_uring
    // TODO jit allocator
    _Atomic ssize_t priority; // running + the total number of tasks in threads queue, lower is higher priority
    kpl_object_queue task_queue;
    pthread_t pthread; // not used for main thread
    sem_t sem; // wait when no task queue and io queue is empty
} kpl_thread;

/*
 * All allocations must extend the KPL_OBJECT_HEADER
 * All objects are allocated through this
 */
inline void *kpl_thread_object_allocate(kpl_thread *thread, int32_t size) {
    return kpl_memory_allocator_allocate(&thread->memory_allocator, size, thread->thread_id);
}

/*
 * Life cycle:
 * kpl_env env = {};
 * kpl_env_config &env, argc, argv
 * kpl_env_init &env
 * add to the namespace tree
 * add a file load task, string evaluate task or REPL task to main thread task queue
 * kpl_env_run &env
 * kpl_env_free &env
 */
typedef struct _kpl_env {
    int32_t thread_count; // -1 updates this value to max possible, 0 invalid, >= 1 for specific number
    _Atomic ssize_t total_priority; // the sum of the threads priority fields, application stops on zero
    kpl_thread *threads; // 0 is main thread, >= 1 are spawned pthreads
    kpl_tree *namespace_tree, *module_tree; // *namespace_tree lookups are thread safe, *module_tree needs mutex
    pthread_mutex_t module_tree_mutex;
} kpl_env; // kpl state, no globals

/*
 * All objects are retuned by this
 */
inline void kpl_env_object_return(kpl_env *env, void *object) {
    kpl_memory_allocator_return(&env->threads[((kpl_object*) object)->thread_id].memory_allocator, object);
}

/*
 * Must match the type of c main return
 * if code != KPL_EXIT_CODE_SUCCESS then return code
 */
typedef enum : int32_t {
    KPL_EXIT_CODE_SUCCESS   = 0,
    KPL_EXIT_CODE_ERROR     = 1,
    KPL_EXIT_CODE_HELP      = 2
} kpl_exit_code;

/*
 * Set up initial values before initialization
 * For defaults and/or directly setting without arguments, pass 0 to argc then fields can be updated directly
 */
kpl_exit_code kpl_env_config(kpl_env *env, int32_t argc, char *argv[]);

/*
 * Initialize
 * env kpl_env_config must be called before this
 */
kpl_exit_code kpl_env_init(kpl_env *env);

/*
 * Can be run multiple times as long as new tasks are added after each run
 */
kpl_exit_code kpl_env_run(kpl_env *env);

/*
 * Stops KPL, can be called on any task in KPL
 * Does not return just signals to all threads to stop, the return status will be from kpl_env_run
 * Start can be called again
 */
void kpl_env_stop(kpl_env *env);

/*
 * Clean up
 */
void kpl_env_free(kpl_env *env);