-
Notifications
You must be signed in to change notification settings - Fork 16
/
Copy pathtask.h
340 lines (274 loc) · 12.1 KB
/
task.h
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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
/*****************************************
NanoShell Operating System
(C) 2021 iProgramInCpp
Task Scheduler module header file
******************************************/
#ifndef _TASK_H
#define _TASK_H
#include <main.h>
#include <debug.h>
#include <video.h>
#include <memory.h>
#include <console.h>
#define C_MAX_TASKS 1024//reduced, old was 1024
#define C_STACK_BYTES_PER_TASK 131072//32768 //plenty, but can change later if needed.
/***********************************************************
A Task is a called function which runs independently
of the rest of the kernel. When the task is started
(with KeStartTask), a little helper function gets
called, which calls the task's m_function.
When the m_function returns, the helper function
automatically kills the task.
(KeKillTask can also be used to kill a task prematurely)
************************************************************/
typedef void (*TaskedFunction) (long arg);
// Of course this does not save memory - only register states.
// The memory area should stay the same anyway across taskswitches.
// Normally we'd use the Registers struct, but, in order to not
// break shit, we need to push the ESP first, and pop it last.
// This is why we use CPUSaveState instead. (as we did in NanoShell2)
typedef struct CPUSaveState
{
int ds, es, fs, gs, ss;
int cr3;
int eax, ebx, ecx, edx,
esi, edi, ebp, esp,
eip, cs, eflags;
}
CPUSaveState;
// https://github.com/jezze/subc
typedef struct
{
void *esp, *eax, *eip;
}
JumpBufferTag;
typedef JumpBufferTag JumpBuffer[1];
// The value passed into LongJump ends up in subsequent returns to SetJump on the same JumpBuffer.
__attribute__((returns_twice)) int SetJump (JumpBuffer env);
__attribute__((noreturn)) void LongJump(JumpBuffer env, int value);
#define setjmp(buf) SetJump ((JumpBuffer)(env))
#define longjmp(buf,val) LongJump((JumpBuffer)(env),val)
enum
{
SEGMENT_NULL = 0x0000,
SEGMENT_KECODE = 0x0008,
SEGMENT_KEDATA = 0x0010,
SEGMENT_USCODE = 0x0018,//planned?
SEGMENT_USDATA = 0x0020,
};
enum
{
SUSPENSION_NONE, // No suspension (i.e. the program can run)
SUSPENSION_TOTAL, // Total suspension, such as when a program crashes
SUSPENSION_UNTIL_PROCESS_EXPIRY, // Suspension until a process expires (for example, running an ELF)
SUSPENSION_UNTIL_TASK_EXPIRY, // Suspension until a task expires (for example, waiting for a worker task to finish)
SUSPENSION_UNTIL_TIMER_EXPIRY, // Suspension until the timer expires
SUSPENSION_UNTIL_WM_UPDATE, // Suspension until the window manager updates
SUSPENSION_UNTIL_PIPE_WRITE, // Suspension until a certain pipe is written to
SUSPENSION_UNTIL_PIPE_READ, // Suspension until a certain pipe is read from
SUSPENSION_UNTIL_OBJECT_EVENT, // Suspension until a generic object gets a generic event.
SUSPENSION_ZOMBIE, // The task is waiting to be joined/detached.
};
typedef struct
{
int m_pageFaults;
int m_kernelMemUsage; // just a hint. May be wrong at times.
int m_userMemUsage;
int m_ioReads;
int m_ioWrites;
int m_wmObjects;
int64_t m_ioReadBytes;
int64_t m_ioWriteBytes;
}
ThreadStats;
// Task structure definition:
typedef struct
{
//! TODO: Maybe we could use a linked list instead? Hmm.
// For now I'll just use a hardcoded array.
bool m_bExists; // true if this task has been initialized
bool m_bAttached; // if the task has been detached, simply kill it.
TaskedFunction m_pFunction;
CPUSaveState m_state;
__attribute__((aligned(16)))
int m_fpuState[128];
char m_cwd[PATH_MAX+2];
void* m_cwdNode;
void * m_pStack; //this task's stack (This pointer is equivalent to the peak of the stack.)
bool m_featuresArgs;
int m_argument;
bool m_bFirstTime;
bool m_bMarkedForDeletion;
const char* m_authorFile,
* m_authorFunc;
int m_authorLine;
VBEData* m_pVBEContext;
UserHeap * m_pCurrentHeap;
Console* m_pConsoleContext;
void* m_pFontContext;
uint32_t m_pFontIDContext;
char m_tag[33];
void * m_pProcess;
uint32_t m_sysCallNum;//backed up from 0xC0007CFC
int m_suspensionType;
bool m_bSuspended;
int m_reviveAt;
void * m_pWaitedTaskOrProcess;
uint64_t m_lastSwitchTime; // in TSC ticks
uint32_t m_cpuTimeTotal, m_cpuTimeFull; //the CPU time actually used, the CPU time used at full speed
uint64_t m_nIdentifier;
void* m_pPipeWaitingToWrite;
void* m_pPipeWaitingToRead;
ThreadStats m_threadStats;
}
Task;
enum {
TASK_SUCCESS = 0x10000000,
TASK_ERROR_TOO_MANY_TASKS,
TASK_ERROR_STACK_ALLOC_FAILED,
TASK_ERROR_CANT_ADD_TO_PROC,
TASK_ERROR_END,
};
/***********************************************************
Allows you to spawn a new task. Returns an error code
through errorCodeOut. You can pass in arguments via
pPassedVarlist.
The function needs to have a "void (long)" header.
pPassedArgument may be null, if the TaskedFunction does
not require any arguments.
errorCodeOut returns TASK_SUCCESS if the Task returned
is not NULL. errorCodeOut can also be NULL, if we don't
actually care (although, this is recommended against)
***********************************************************/
// note that the void pointer is there because I really do not want to include <process.h>, which includes us...
Task* KeStartTaskExD(TaskedFunction function, long argument, int *pErrorCodeOut, void* pProc, const char* a, const char* b, int c);
Task* KeStartTaskD(TaskedFunction function, long argument, int *pErrorCodeOut, const char* a, const char* b, int c);
#define KeStartTask(function, argument, errorPtr) \
KeStartTaskD(function, argument, errorPtr, __FILE__, #function, __LINE__)
/***********************************************************
Allows you to kill the task passed into itself.
N.B.: KeKillTask(KeGetRunningTask()) calls KeExit,
if the task that's currently exiting requests to be
killed. If you're done with your task please
use KeExit().
Returns TRUE if task was killed successfully.
Execution is guaranteed to not continue if
you killed KeGetRunningTask().
***********************************************************/
bool KeKillTask(Task* pTask);
/***********************************************************
Gets the currently running task.
Returns NULL if this is the kernel task.
***********************************************************/
Task* KeGetRunningTask();
/***********************************************************
Sets the task's tag.
***********************************************************/
void KeTaskAssignTag(Task* pTask, const char* pTag);
/***********************************************************
Sets the task's tag.
***********************************************************/
const char* KeTaskGetTag(Task* pTask);
/***********************************************************
Detaches the task. When it dies, it'll no longer
stick around as a zombie, instead, it'll just be
cleaned up by the system.
***********************************************************/
void KeDetachTask(Task* pTask);
/***********************************************************
Queues the current task for deletion, and yields.
Execution will not continue beyond the call to this
function. If the current task is the kernel task,
the kernel will halt (use KeStopSystem())
***********************************************************/
__attribute__((noreturn))
void KeExit();
/***********************************************************
Kills a task by process index.
***********************************************************/
bool KeKillThreadByPID (int proc);
/***********************************************************
Gets a task by task identifier (RID).
***********************************************************/
Task* KeGetThreadByRID (uint64_t proc);
/***********************************************************
Waits a certain number of milliseconds.
***********************************************************/
void WaitMS (int ms);
/***********************************************************
Waits for a task to exit. Also cleans it up.
This may not be called for detached threads.
***********************************************************/
void WaitTask (Task* pTask);
/***********************************************************
Waits until a process gets terminated.
***********************************************************/
void WaitProcess(void* pProcess);
/***********************************************************
Waits until an object receives an event.
***********************************************************/
void WaitObject(void* pObject);
/***********************************************************
Waits until a pipe gets written to.
***********************************************************/
void WaitPipeWrite(void* pPipe);
/***********************************************************
Waits until a pipe gets read from.
***********************************************************/
void WaitPipeRead(void* pPipe);
/***********************************************************
Waits until the window manager refreshes again.
***********************************************************/
void WaitUntilWMUpdate ();
/***********************************************************
Internal function to initialize the task scheduler.
***********************************************************/
void KiTaskSystemInit();
/***********************************************************
Internal function to list all tasks to debug output.
***********************************************************/
void KeTaskDebugDump();
/***********************************************************
Removes any suspension a task might have.
Use this after a successful KeStartTask.
***********************************************************/
void KeUnsuspendTaskUnsafe(Task* pTask);
void KeUnsuspendTask(Task* pTask);
/***********************************************************
Internal function to unsuspend all tasks waiting
for a certain process handle
***********************************************************/
void KeUnsuspendTasksWaitingForProc(void *pProc);
/***********************************************************
Internal function to unsuspend all tasks waiting
for a certain object handle.
This can be used to signify that there might be an
event waiting on that object.
***********************************************************/
void KeUnsuspendTasksWaitingForObject(void *pProc);
/***********************************************************
Internal function to unsuspend all tasks waiting
for the window manager
***********************************************************/
void KeUnsuspendTasksWaitingForWM();
/***********************************************************
Internal function to unsuspend all tasks waiting
for a pipe to be read from
***********************************************************/
void KeUnsuspendTasksWaitingForPipeRead(void* pPipe);
/***********************************************************
Internal function to unsuspend all tasks waiting
for a pipe to be written to
***********************************************************/
void KeUnsuspendTasksWaitingForPipeWrite(void* pPipe);
/***********************************************************
Gets the ThreadStats object from a task.
***********************************************************/
ThreadStats* KeGetTaskStats(Task* task);
/***********************************************************
Gets the ThreadStats object from the currently running
task.
***********************************************************/
ThreadStats* KeGetThreadStats();
#include <lock.h>
#endif//_TASK_H