Skip to content

Commit 9cf8856

Browse files
committed
Fixing page fault on enGUI running
1 parent 52a12c7 commit 9cf8856

2 files changed

Lines changed: 21 additions & 129 deletions

File tree

src/system/usr/sched.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,10 @@ void sched_init(task_t *initial_task) {
2929

3030
initial_task->state = TASK_STATE_RUNNABLE;
3131
initial_task->running = true;
32-
initial_task->next = NULL;
33-
initial_task->prev = NULL;
32+
33+
// Инициализируем ТОЛЬКО очереди планировщика!
34+
initial_task->sched_next = NULL;
35+
initial_task->sched_prev = NULL;
3436

3537
run_queue_head = initial_task;
3638
run_queue_tail = initial_task;

src/system/usr/task.h

Lines changed: 17 additions & 127 deletions
Original file line numberDiff line numberDiff line change
@@ -4,27 +4,19 @@
44
#include <stdint.h>
55
#include <stdbool.h>
66

7-
// Состояние всех регистров x86_64 при прерывании
8-
typedef struct {
9-
uint64_t r15, r14, r13, r12, r11, r10, r9, r8;
10-
uint64_t rdi, rsi, rbp, rdx, rcx, rbx, rax;
11-
uint64_t interrupt_number, error_code;
12-
uint64_t rip, cs, rflags, rsp, ss;
13-
} __attribute__((packed)) stack_frame_t;
14-
15-
#define MAX_FD 32
16-
7+
// Состояния потока
178
typedef enum {
189
TASK_STATE_RUNNABLE, // Готов к выполнению (находится в Run Queue)
1910
TASK_STATE_SLEEPING, // Спит по таймеру (находится в Sleep Queue)
2011
TASK_STATE_BLOCKED, // Заблокирован на мьютексе/семафоре/ожидании ввода (вне планировщика)
2112
TASK_STATE_ZOMBIE // Мертв, ожидает waitpid (вне планировщика)
2213
} task_state_t;
2314

15+
// === Контейнер ресурсов Процесса (Process Control Block) ===
2416
typedef struct process {
25-
uint64_t pid; // Идентификатор процесса
17+
uint64_t pid; // Идентификатор процесса (PID)
2618
uint64_t parent_pid; // PID родительского процесса
27-
uint64_t pgid;
19+
uint64_t pgid; // Группа процессов (PGID)
2820
uint64_t cr3; // Страничная таблица процесса (общее адресное пространство)
2921
uint64_t brk; // Граница кучи процесса (общее выделение памяти)
3022
char cwd[256]; // Общий рабочий каталог процессов
@@ -38,7 +30,11 @@ typedef struct task {
3830
uint64_t rsp; // Сохраненный указатель стека потока
3931
uint64_t id; // Идентификатор потока (TID)
4032
task_state_t state; // Текущее состояние потока
41-
bool running; // Совместимость
33+
bool running; // Обратная совместимость
34+
35+
bool waiting; // Ожидание в waitpid
36+
uint64_t wait_for; // Кого именно ждем в waitpid
37+
4238
uint64_t kstack_at_bottom; // Ядерный стек этого потока (для прерываний)
4339
uint64_t fs_base; // Базовый адрес TLS этого потока
4440

@@ -47,129 +43,23 @@ typedef struct task {
4743

4844
uint64_t sleep_until; // Таймер сна потока
4945
uint8_t fpu_state[512] __attribute__((aligned(16)));
50-
bool waiting; // Флаг ожидания завершения дочернего процесса
51-
uint64_t wait_for;
5246

5347
// Сигналы (доставляются конкретному потоку)
5448
uint64_t sig_pending;
5549
uint64_t sig_blocked;
5650
uint64_t sig_handlers[32];
5751
uint64_t sig_restorer;
5852

59-
// Ссылки очереди планировщика
53+
// Очереди планировщика (ИСПОЛЬЗУЮТСЯ ИСКЛЮЧИТЕЛЬНО В sched.c)
54+
struct task *sched_next;
55+
struct task *sched_prev;
56+
57+
// Глобальный список всех потоков в системе (ИСПОЛЬЗУЮТСЯ В task.c / signal.c / waitpid)
6058
struct task *next;
6159
struct task *prev;
6260
} task_t;
6361

64-
static inline void* task_fpu_area(task_t* t) {
65-
return (void*)(((uint64_t)t->fpu_state + 15) & ~(uint64_t)15);
66-
}
67-
68-
/* Кладёт в fpu-область задачи эталонное «чистое» состояние (fninit +
69-
* MXCSR=0x1F80). Вызывать при создании каждой задачи. */
70-
void task_fpu_init_area(task_t* t);
71-
72-
extern task_t* current_task;
73-
void task_init();
74-
uint64_t schedule(uint64_t current_rsp); // Вызывается из ассемблера
75-
void yield(void);
76-
void task_create(void (*entry)(), uint64_t arg1, uint64_t arg2, uint64_t cr3);
77-
78-
/* --- Этап 6b: System V AMD64 initial stack для musl / Linux-ABI бинарей ----
79-
* Описывает данные для построения SysV-кадра на вершине пользовательского
80-
* стека (argc / argv[] / NULL / envp[] / NULL / auxv / AT_NULL). Указатели
81-
* argv_user/envp_user — это УЖЕ пользовательские адреса строк (напр. в argv-
82-
* странице 0xB0000000), строки на стек НЕ копируются. Родной crt0 этот кадр
83-
* игнорирует (читает argc/argv из регистров), поэтому детект ABI не нужен. */
84-
typedef struct {
85-
int argc;
86-
const uint64_t *argv_user; /* argc пользовательских указателей на строки */
87-
int envc;
88-
const uint64_t *envp_user; /* envc указателей (может быть NULL при envc=0) */
89-
uint64_t at_phdr; /* адрес Program Headers в памяти процесса */
90-
uint64_t at_phent; /* размер одной записи PH */
91-
uint64_t at_phnum; /* число записей PH */
92-
uint64_t at_entry; /* точка входа ELF (e_entry) */
93-
} sysv_args_t;
94-
95-
/* Полный конструктор задачи. sv != NULL и cr3 != 0 -> дополнительно строит
96-
* SysV-кадр и ставит на него user-rsp. Возвращает созданную задачу. */
97-
task_t* task_create_full(void (*entry)(), uint64_t arg1, uint64_t arg2,
98-
uint64_t cr3, const sysv_args_t *sv);
99-
bool task_exec(char* full_command);
100-
101-
/* Этап 1b — execve. task_load_image() загружает ELF в НОВОЕ адресное
102-
* пространство и готовит стек/TLS/argv (argv[] уже скопирован в память ядра).
103-
* Переключение cr3 и освобождение старого пространства делает вызывающий. */
104-
bool task_load_image(const char *path, char *const argv[], int argc,
105-
char *const envp[], int envc,
106-
uint64_t *out_entry, uint64_t *out_user_rsp,
107-
uint64_t *out_argv_ptr, uint64_t *out_envp_ptr,
108-
uint64_t *out_cr3, uint64_t *out_fs_base);
109-
void task_set_fs_base(uint64_t v);
110-
111-
/* Этап 3: cwd текущего процесса (логический абсолютный путь). */
112-
const char *task_current_cwd(void);
113-
/* Сменить cwd текущего процесса на нормализованный target (логический
114-
* абсолютный путь). Возвращает 0 при успехе, -1 при ошибке. */
115-
int task_chdir(const char *path);
116-
/* Разрешить пользовательский путь в имя для VFS (ext2): нормализует относ.
117-
* cwd текущего процесса и убирает ведущий '/'. "/" -> "". */
118-
void task_resolve_fs_path(const char *in, char *out, int outsz);
119-
120-
/* --- Этап 1: процессная модель ------------------------------------------- *
121-
* task_fork(): клонирует текущий процесс. parent_frame — сохранённый кадр
122-
* прерывания (stack_frame_t*) из обработчика int 0x80, т.е. регистры
123-
* родителя на момент syscall. Возвращает pid ребёнка родителю; ребёнок
124-
* "вернётся" из того же int 0x80 со значением 0 в rax. */
125-
uint64_t task_fork(stack_frame_t* parent_frame);
126-
127-
/* Помечает текущий процесс зомби с кодом code, освобождает его адресное
128-
* пространство и будит родителя, если тот ждёт в waitpid. Не возвращается
129-
* (уходит в планировщик). Вызывается из обработчика SYS_EXIT. */
130-
void task_exit_current(int code);
131-
132-
/* Ждёт завершения ребёнка. pid > 0 — конкретный ребёнок, 0 — любой.
133-
* Пишет код выхода в *status_out (kernel-указатель). Возвращает pid
134-
* завершившегося ребёнка, либо -1 если у процесса нет таких детей (ECHILD).
135-
* Блокирует (через yield) пока подходящий ребёнок не станет зомби. */
136-
int64_t task_waitpid(uint64_t pid, int* status_out);
137-
int64_t task_waitpid_ex(uint64_t pid, int* status_out, int nohang);
138-
task_t* task_by_id(uint64_t pid);
139-
140-
/* Этап 2: вернуть таблицу дескрипторов текущего процесса (для fs/fd.c). */
141-
struct fd_table *task_current_fdt(void);
142-
143-
void task_kill_self();
144-
bool task_terminate_by_pid(uint64_t pid);
145-
void task_list_all();
146-
147-
// Доступ к глобальному списку задач (циклический односвязный).
148-
// Возвращает голову, либо NULL, если планировщик ещё не поднят.
149-
// Использовать с осторожностью: список — кольцо, идти до тех пор,
150-
// пока next != head.
151-
task_t* task_get_list_head(void);
152-
153-
// Аккуратно убивает все пользовательские задачи кроме idle/init
154-
// (id == 1). Используется в `killall` и SUPER+ALT+F10. Сама задача,
155-
// если она пользовательская, должна позаботиться о yield()/kill_self
156-
// отдельно — здесь мы только метим running=false; планировщик
157-
// доразберётся в ближайшем тике.
158-
// Возвращает кол-во убитых пользовательских задач.
159-
int task_kill_all_user_count(void);
160-
161-
// Удобная обёртка: то же самое, но без возврата кол-ва.
162-
void task_kill_all_user(void);
163-
164-
// Снимок задачи по индексу в кольце (начиная с головы, индексация 0..N-1).
165-
// Заполняет out_pid/out_cr3/out_brk/out_running и возвращает true, если
166-
// задача с таким индексом существует. iff false — кольцо короче.
167-
typedef struct {
168-
uint64_t pid;
169-
uint64_t cr3;
170-
uint64_t brk;
171-
bool running;
172-
} task_snapshot_t;
173-
bool task_snapshot_at(int idx, task_snapshot_t *out);
62+
// Вспомогательный макрос для FPU-контекста, который у вас используется в ядре
63+
#define task_fpu_area(t) (void*)(((uint64_t)(t)->fpu_state + 15) & ~(uint64_t)15)
17464

175-
#endif
65+
#endif /* TASK_H */

0 commit comments

Comments
 (0)