1#pragma once
2
3#include <time.h>
4
5#include <pw_types.h>
6
7#ifdef __cplusplus
8extern "C" {
9#endif
10
11typedef bool (*_PmFunc)();
12/*
13 * _PmFunc is an uninterruptible unit of PetCode.
14 */
15
16#define _PM_INITIAL_CS_PAGE_SIZE 64
17#define _PM_MAXIMAL_CS_PAGE_SIZE 16384
18#define _PM_INITIAL_DS_PAGE_SIZE 256
19#define _PM_MAXIMAL_DS_PAGE_SIZE 16384
20/*
21 * Sizes for stack pages.
22 *
23 * The size doubles for the next page until it reaches max page size.
24 */
25
26PW_STRUCT(_PwDataStackPage) {
27 _PwDataStackPage* prev;
28 _PwDataStackPage* next;
29 uint16_t block_size;
30 uint16_t capacity;
31 uint16_t count;
32 _PwValue items[];
33};
34
35PW_STRUCT(_PwControlStackPage) {
36 _PwControlStackPage* prev;
37 _PwControlStackPage* next;
38 uint16_t block_size;
39 uint16_t capacity;
40 uint16_t count;
41 _PmFunc* items[];
42};
43
44typedef enum PwTaskState {
45 PW_TASK_STATE_ACTIVE = 0,
46 PW_TASK_STATE_SUSPENDED,
47 PW_TASK_STATE_TERMINATED
48} PwTaskState;
49
50PW_STRUCT(PwTaskList) {
51 PwTask* next;
52 PwTask* prev;
53};
54
55PW_STRUCT(PwTask) {
56
57 // task hierarchy
58 PwTask* parent; // points to the parent task; nullptr for the root task
59 PwTask* children; // points to a child task
60 PwTaskList sibling; // the list of siblings
61
62 // task may be either on run or wakeup list; which list the task_list refers to depends on task state
63 PwTaskList task_list;
64
65 PwTaskList wait_list; // the list of tasks awaiting this task
66
67 _PwValue blocker; // a synchronization object the task is blocked on
68 PwValuePtr parent_blocker; // if `blocker` is an instance of Task or ChldTasks, this is a link to a compound blocker
69 /*
70
71 kinda special wait objects:
72
73 void pw_make_task_syncobj(PwTask* task, PwValuePtr result);
74 -- makes a synchronization object from task that can be awaited for termination; no alloc, never fails
75
76 void pw_make_children_tasks_syncobj(PwTask* task, PwValuePtr result);
77 -- makes a synchronization object that can be awaited for children termination; no alloc, never fails
78
79 special wait objects cannot participate in multiple awaitables
80 because they have no link to parent awaitable -- fuck, add this link!
81
82 General sync objects:
83
84 It's a PwValue, a subtype of Struct, with allocated memory block.
85 It contains wait_list
86
87 */
88
89 unsigned refcount;
90 /*
91 * The number of PwValues of Task type referencing this structure plus one, which means self.
92 * Except self, this does not count other internal references, such as siblings or run lists.
93 *
94 * The value is not atomic because tasks are bound to a single thread.
95 */
96
97 PwTaskState state;
98 bool hold_exception; // do not propagate exception to the parent; propagation is enabled when parent enters `try` block
99 struct timespec wakeup_time; // when to wake up if the task is suspended; zero means infinite timeout
100
101 _PmFunc* ip; // instruction pointer
102
103 _PwDataStackPage* data_stack;
104 /*
105 * current page of the data stack
106 *
107 * The data stack is allocated in a relatively small blocks of fixed size,
108 * organized in a doubly-linked list using values of Pointer type.
109 * The first element is a pointer to the previous block,
110 * when the block is full, the last element is a pointer to the next block
111 */
112
113 _PwControlStackPage* control_stack;
114 /*
115 * current page of the control stack
116 *
117 * the allocation scheme is the same as for the data stack
118 */
119
120 /*
121 * stats/profiling?
122 */
123 /*
124 unsigned abs_data_sp; // current absolute value of the data stack pointer
125 unsigned max_abs_data_sp; // max absolute value of the data stack pointer
126 unsigned abs_control_sp; // current absolute value of the control stack pointer
127 unsigned max_abs_control_sp; // max absolute value of the control stack pointer
128 */
129
130 _PwValue status;
131};
132
133extern PwTask _pw_default_task;
134extern thread_local PwTask* current_task;
135
136#ifdef __cplusplus
137}
138#endif