forked from ish-app/ish
-
Notifications
You must be signed in to change notification settings - Fork 0
/
task.h
174 lines (141 loc) · 4.58 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
#ifndef TASK_H
#define TASK_H
#include <pthread.h>
#include "emu/cpu.h"
#include "kernel/mm.h"
#include "kernel/fs.h"
#include "kernel/signal.h"
#include "kernel/resource.h"
#include "fs/sockrestart.h"
#include "util/list.h"
#include "util/timer.h"
#include "util/sync.h"
// everything here is private to the thread executing this task and needs no
// locking, unless otherwise specified
struct task {
struct cpu_state cpu;
struct mm *mm;
struct mem *mem; // copy of cpu.mem, for convenience
pthread_t thread;
uint64_t threadid;
struct tgroup *group; // immutable
struct list group_links;
pid_t_ pid, tgid; // immutable
uid_t_ uid, gid;
uid_t_ euid, egid;
uid_t_ suid, sgid;
#define MAX_GROUPS 32
unsigned ngroups;
uid_t_ groups[MAX_GROUPS];
char comm[16] __strncpy_safe;
bool did_exec; // for that one annoying setsid edge case
struct fdtable *files;
struct fs_info *fs;
// locked by sighand->lock
struct sighand *sighand;
sigset_t_ blocked;
sigset_t_ pending;
sigset_t_ waiting; // if nonzero, an ongoing call to sigtimedwait is waiting on these
struct list queue;
cond_t pause; // please don't signal this
// private
sigset_t_ saved_mask;
bool has_saved_mask;
// locked by pids_lock
struct task *parent;
struct list children;
struct list siblings;
addr_t clear_tid;
addr_t robust_list;
// locked by pids_lock
dword_t exit_code;
bool zombie;
bool exiting;
// this structure is allocated on the stack of the parent's clone() call
struct vfork_info {
bool done;
cond_t cond;
lock_t lock;
} *vfork;
int exit_signal;
// lock for anything that needs locking but is not covered by some other lock
// right now, just comm
lock_t general_lock;
struct task_sockrestart sockrestart;
// current condition/lock, so it can be notified in case of a signal
cond_t *waiting_cond;
lock_t *waiting_lock;
lock_t waiting_cond_lock;
};
// current will always give the process that is currently executing
// if I have to stop using __thread, current will become a macro
extern __thread struct task *current;
static inline void task_set_mm(struct task *task, struct mm *mm) {
task->mm = mm;
task->mem = task->cpu.mem = &task->mm->mem;
}
// Creates a new process, initializes most fields from the parent. Specify
// parent as NULL to create the init process. Returns NULL if out of memory.
// Ends with an underscore because there's a mach function by the same name
struct task *task_create_(struct task *parent);
// Removes the process from the process table and frees it. Must be called with pids_lock.
void task_destroy(struct task *task);
// misc
void vfork_notify(struct task *task);
pid_t_ task_setsid(struct task *task);
void task_leave_session(struct task *task);
struct posix_timer {
struct timer *timer;
int_t timer_id;
struct task *task;
int_t signal;
union sigval_ sig_value;
};
// struct thread_group is way too long to type comfortably
struct tgroup {
struct list threads; // locked by pids_lock, by majority vote
struct task *leader; // immutable
struct rusage_ rusage;
// locked by pids_lock
pid_t_ sid, pgid;
struct list session;
struct list pgroup;
bool stopped;
cond_t stopped_cond;
struct tty *tty;
struct timer *itimer;
#define TIMERS_MAX 16
struct posix_timer posix_timers[TIMERS_MAX];
struct rlimit_ limits[RLIMIT_NLIMITS_];
// https://twitter.com/tblodt/status/957706819236904960
// TODO locking
bool doing_group_exit;
dword_t group_exit_code;
struct rusage_ children_rusage;
cond_t child_exit;
// for everything in this struct not locked by something else
lock_t lock;
};
static inline bool task_is_leader(struct task *task) {
return task->group->leader == task;
}
struct pid {
dword_t id;
struct task *task;
struct list session;
struct list pgroup;
};
// synchronizes obtaining a pointer to a task and freeing that task
extern lock_t pids_lock;
// these functions must be called with pids_lock
struct pid *pid_get(dword_t pid);
struct task *pid_get_task(dword_t pid);
struct task *pid_get_task_zombie(dword_t id); // don't return null if the task exists as a zombie
#define MAX_PID (1 << 15) // oughta be enough
// When a thread is created to run a new process, this function is used.
extern void (*task_run_hook)(void);
// TODO document
void task_start(struct task *task);
extern void (*exit_hook)(struct task *task, int code);
#define superuser() (current != NULL && current->euid == 0)
#endif