/* * 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; kpl_io_uring 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 io_uring_queue_size_pow2; // the power of two to calculate the entries in the io_uring queue 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, must be zero initialized /* * All objects are returned 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); /* * Run once, not re-enetrant * TODO RUN TASK AND IO ORDERING */ 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 */ void kpl_env_stop(kpl_env *env); /* * Clean up */ void kpl_env_free(kpl_env *env);