Update MentOs code to the latest development version.
This commit is contained in:
+38
-21
@@ -1,15 +1,9 @@
|
||||
/// MentOS, The Mentoring Operating system project
|
||||
/// @file prio.h
|
||||
/// @brief Defines processes priority value.
|
||||
/// @copyright (c) 2019 This file is distributed under the MIT License.
|
||||
/// @copyright (c) 2014-2021 This file is distributed under the MIT License.
|
||||
/// See LICENSE.md for details.
|
||||
|
||||
#define MAX_NICE +19
|
||||
|
||||
#define MIN_NICE -20
|
||||
|
||||
#define NICE_WIDTH (MAX_NICE - MIN_NICE + 1)
|
||||
|
||||
// Priority of a process goes from 0..MAX_PRIO-1, valid RT
|
||||
// priority is 0..MAX_RT_PRIO-1, and SCHED_NORMAL/SCHED_BATCH
|
||||
// tasks are in the range MAX_RT_PRIO..MAX_PRIO-1. Priority
|
||||
@@ -21,35 +15,58 @@
|
||||
// priority to a value higher than any user task.
|
||||
// Note: MAX_RT_PRIO must not be smaller than MAX_USER_RT_PRIO.
|
||||
|
||||
/// @brief Max niceness value.
|
||||
#define MAX_NICE +19
|
||||
|
||||
/// @brief Min niceness value.
|
||||
#define MIN_NICE -20
|
||||
|
||||
/// @brief Niceness range.
|
||||
#define NICE_WIDTH (MAX_NICE - MIN_NICE + 1)
|
||||
|
||||
/// @brief Maximum real-time priority.
|
||||
#define MAX_RT_PRIO 100
|
||||
|
||||
/// @brief Maximum priority.
|
||||
#define MAX_PRIO (MAX_RT_PRIO + NICE_WIDTH)
|
||||
|
||||
/// @brief Default priority.
|
||||
#define DEFAULT_PRIO (MAX_RT_PRIO + NICE_WIDTH / 2)
|
||||
|
||||
// Convert user-nice values [ -20 ... 0 ... 19 ]
|
||||
// to static priority [ MAX_RT_PRIO..MAX_PRIO-1 ],
|
||||
// and back.
|
||||
/// @brief Converts user-nice values [ -20 ... 0 ... 19 ]
|
||||
/// to static priority [ MAX_RT_PRIO..MAX_PRIO-1 ].
|
||||
#define NICE_TO_PRIO(nice) ((nice) + DEFAULT_PRIO)
|
||||
|
||||
/// @brief Converts static priority [ MAX_RT_PRIO..MAX_PRIO-1 ]
|
||||
/// to user-nice values [ -20 ... 0 ... 19 ].
|
||||
#define PRIO_TO_NICE(prio) ((prio)-DEFAULT_PRIO)
|
||||
|
||||
// 'User priority' is the nice value converted to something we
|
||||
// can work with better when scaling various scheduler parameters,
|
||||
// it's a [ 0 ... 39 ] range.
|
||||
/// @brief 'User priority' is the nice value converted to something we
|
||||
/// can work with better when scaling various scheduler parameters,
|
||||
/// it's a [ 0 ... 39 ] range.
|
||||
#define USER_PRIO(p) ((p)-MAX_RT_PRIO)
|
||||
|
||||
/// @brief Provide easy access to the priority value of a task_struct.
|
||||
#define TASK_USER_PRIO(p) USER_PRIO((p)->static_prio)
|
||||
|
||||
/// @brief The maximum priority for a user process.
|
||||
#define MAX_USER_PRIO (USER_PRIO(MAX_PRIO))
|
||||
|
||||
/// @brief Table that transforms the priority into a weight, used for
|
||||
/// computing the virtual runtime.
|
||||
static const int prio_to_weight[NICE_WIDTH] = {
|
||||
/* 100 */ 88761, 71755, 56483, 46273, 36291,
|
||||
/* 105 */ 29154, 23254, 18705, 14949, 11916,
|
||||
/* 110 */ 9548, 7620, 6100, 4904, 3906,
|
||||
/* 115 */ 3121, 2501, 1991, 1586, 1277,
|
||||
/* 120 */ 1024, 820, 655, 526, 423,
|
||||
/* 125 */ 335, 272, 215, 172, 137,
|
||||
/* 130 */ 110, 87, 70, 56, 45,
|
||||
/* 135 */ 36, 29, 23, 18, 15
|
||||
/* 100 */ 88761, 71755, 56483, 46273, 36291,
|
||||
/* 105 */ 29154, 23254, 18705, 14949, 11916,
|
||||
/* 110 */ 9548, 7620, 6100, 4904, 3906,
|
||||
/* 115 */ 3121, 2501, 1991, 1586, 1277,
|
||||
/* 120 */ 1024, 820, 655, 526, 423,
|
||||
/* 125 */ 335, 272, 215, 172, 137,
|
||||
/* 130 */ 110, 87, 70, 56, 45,
|
||||
/* 135 */ 36, 29, 23, 18, 15
|
||||
};
|
||||
|
||||
/// @brief Transforms the priority to weight.
|
||||
#define GET_WEIGHT(prio) prio_to_weight[USER_PRIO((prio))]
|
||||
|
||||
/// @brief Weight of a default priority.
|
||||
#define NICE_0_LOAD GET_WEIGHT(DEFAULT_PRIO)
|
||||
|
||||
+138
-163
@@ -1,23 +1,14 @@
|
||||
/// MentOS, The Mentoring Operating system project
|
||||
/// @file process.h
|
||||
/// @brief Process data structures and functions.
|
||||
/// @copyright (c) 2019 This file is distributed under the MIT License.
|
||||
/// @copyright (c) 2014-2021 This file is distributed under the MIT License.
|
||||
/// See LICENSE.md for details.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "list.h"
|
||||
#include "tree.h"
|
||||
#include "clock.h"
|
||||
#include "types.h"
|
||||
#include "stdint.h"
|
||||
#include "stddef.h"
|
||||
#include "paging.h"
|
||||
#include "kernel.h"
|
||||
#include "unistd.h"
|
||||
#include "list_head.h"
|
||||
#include "signal_defs.h"
|
||||
#include "limits.h"
|
||||
#include "signal.h"
|
||||
#include "fpu.h"
|
||||
|
||||
/// The maximum length of a name for a task_struct.
|
||||
#define TASK_NAME_MAX_LENGTH 100
|
||||
@@ -25,179 +16,163 @@
|
||||
/// The default dimension of the stack of a process (1 MByte).
|
||||
#define DEFAULT_STACK_SIZE 0x100000
|
||||
|
||||
//==== Task state ==============================================================
|
||||
// Used in tsk->state
|
||||
/// The task is running.
|
||||
#define TASK_RUNNING 0x0000
|
||||
|
||||
/// The task is interruptible.
|
||||
#define TASK_INTERRUPTIBLE 0x0001
|
||||
|
||||
/// The task is uninterruptible.
|
||||
#define TASK_UNINTERRUPTIBLE 0x0002
|
||||
|
||||
// Used in tsk->exit_state
|
||||
/// The task is dead.
|
||||
#define EXIT_DEAD 0x0010
|
||||
|
||||
/// The task is zombie.
|
||||
#define EXIT_ZOMBIE 0x0020
|
||||
//==============================================================================
|
||||
|
||||
/// @brief Every task_struck has a sched_entity. This structure is used to track
|
||||
/// the statistics of a process. While the other variables also play a role in
|
||||
/// @brief This structure is used to track the statistics of a process.
|
||||
/// @details
|
||||
/// While the other variables also play a role in
|
||||
/// CFS decisions'algorithm, vruntime is by far the core variable which needs
|
||||
/// more attention as to understand the scheduling decision process.
|
||||
/// @details
|
||||
///
|
||||
/// The nice value is a user-space and priority 'prio' is the process's actual
|
||||
/// priority that use by Linux kernel. In linux system priorities are 0 to 139
|
||||
/// in which 0 to 99 for real time and 100 to 139 for users.
|
||||
/// The nice value range is -20 to +19 where -20 is highest, 0 default and +19
|
||||
/// is lowest. relation between nice value and priority is : PR = 20 + NI.
|
||||
typedef struct sched_entity {
|
||||
/// Static execution priority.
|
||||
int prio;
|
||||
typedef struct sched_entity_t {
|
||||
/// Static execution priority.
|
||||
int prio;
|
||||
|
||||
/// Start execution time.
|
||||
time_t start_runtime;
|
||||
/// Start execution time.
|
||||
time_t start_runtime;
|
||||
/// Last context switch time.
|
||||
time_t exec_start;
|
||||
/// Last execution time.
|
||||
time_t exec_runtime;
|
||||
/// Overall execution time.
|
||||
time_t sum_exec_runtime;
|
||||
/// Weighted execution time.
|
||||
time_t vruntime;
|
||||
|
||||
/// Last context switch time.
|
||||
time_t exec_start;
|
||||
/// Expected period of the task
|
||||
time_t period;
|
||||
/// Absolute deadline
|
||||
time_t deadline;
|
||||
/// Absolute time of arrival of the task
|
||||
time_t arrivaltime;
|
||||
/// Has already executed
|
||||
bool_t executed;
|
||||
/// Determines if it is a periodic task.
|
||||
bool_t is_periodic;
|
||||
/// Determines if we need to analyze the WCET of the process.
|
||||
bool_t is_under_analysis;
|
||||
/// Beginning of next period
|
||||
time_t next_period;
|
||||
/// Worst case execution time
|
||||
time_t worst_case_exec;
|
||||
/// Processor utilization factor
|
||||
double utilization_factor;
|
||||
} sched_entity_t;
|
||||
|
||||
/// Overall execution time.
|
||||
time_t sum_exec_runtime;
|
||||
|
||||
/// weighted execution time.
|
||||
time_t vruntime;
|
||||
|
||||
} sched_entity;
|
||||
|
||||
// x86 thread (x86 and FPU registers).
|
||||
typedef struct thread_struct {
|
||||
/// 32-bit base pointer register.
|
||||
uint32_t ebp;
|
||||
|
||||
/// 32-bit stack pointer register.
|
||||
uint32_t useresp;
|
||||
|
||||
/// 32-bit base register.
|
||||
uint32_t ebx;
|
||||
|
||||
/// 32-bit data register.
|
||||
uint32_t edx;
|
||||
|
||||
/// 32-bit counter.
|
||||
uint32_t ecx;
|
||||
|
||||
/// 32-bit accumulator register.
|
||||
uint32_t eax;
|
||||
|
||||
/// Instruction Pointer Register.
|
||||
uint32_t eip;
|
||||
|
||||
/// 32-bit flag register.
|
||||
uint32_t eflags;
|
||||
|
||||
/// FS and GS have no hardware-assigned uses.
|
||||
uint32_t gs;
|
||||
|
||||
/// FS and GS have no hardware-assigned uses.
|
||||
uint32_t fs;
|
||||
|
||||
/// Extra Segment determined by the programmer.
|
||||
uint32_t es;
|
||||
|
||||
/// Data Segment.
|
||||
uint32_t ds;
|
||||
|
||||
/// 32-bit destination register.
|
||||
uint32_t edi;
|
||||
|
||||
/// 32-bit source register.
|
||||
uint32_t esi;
|
||||
|
||||
// ///< Code Segment.
|
||||
// uint32_t cs;
|
||||
|
||||
// ///< Stack Segment.
|
||||
// uint32_t ss;
|
||||
|
||||
/// Determines if the FPU is enabled.
|
||||
bool_t fpu_enabled;
|
||||
|
||||
/// Data structure used to save FPU registers.
|
||||
savefpu fpu_register;
|
||||
} thread_struct;
|
||||
/// @brief Stores the status of CPU and FPU registers.
|
||||
typedef struct thread_struct_t {
|
||||
/// Stored status of registers.
|
||||
pt_regs regs;
|
||||
/// Stored status of registers befor jumping into a signal handler.
|
||||
pt_regs signal_regs;
|
||||
/// Determines if the FPU is enabled.
|
||||
bool_t fpu_enabled;
|
||||
/// Data structure used to save FPU registers.
|
||||
savefpu fpu_register;
|
||||
} thread_struct_t;
|
||||
|
||||
/// @brief this is our task object. Every process in the system has this, and
|
||||
/// it holds a lot of information. It’ll hold mm information, it’s name,
|
||||
/// statistics, etc..
|
||||
typedef struct task_struct {
|
||||
/// The pid of the process.
|
||||
pid_t pid;
|
||||
/// The pid of the process.
|
||||
pid_t pid;
|
||||
/// The session id of the process
|
||||
pid_t sid;
|
||||
/// The Group Id of the process
|
||||
pid_t gid;
|
||||
/// The uid of the user owning the process.
|
||||
pid_t uid;
|
||||
// -1 unrunnable, 0 runnable, >0 stopped.
|
||||
/// The current state of the process:
|
||||
__volatile__ long state;
|
||||
/// The current opened file descriptors
|
||||
vfs_file_descriptor_t *fd_list;
|
||||
/// The maximum supported number of file descriptors
|
||||
int max_fd;
|
||||
/// Pointer to process's parent.
|
||||
struct task_struct *parent;
|
||||
/// List head for scheduling purposes.
|
||||
list_head run_list;
|
||||
/// List of children traced by the process.
|
||||
list_head children;
|
||||
/// List of siblings.
|
||||
list_head sibling;
|
||||
/// The context of the processors.
|
||||
thread_struct_t thread;
|
||||
/// For scheduling algorithms.
|
||||
sched_entity_t se;
|
||||
/// Exit code of the process. (parameter of _exit() system call).
|
||||
int exit_code;
|
||||
/// The name of the task (Added for debug purpose).
|
||||
char name[TASK_NAME_MAX_LENGTH];
|
||||
/// Task's segments.
|
||||
mm_struct_t *mm;
|
||||
/// Task's specific error number.
|
||||
int error_no;
|
||||
/// The current working directory.
|
||||
char cwd[PATH_MAX];
|
||||
|
||||
// -1 unrunnable, 0 runnable, >0 stopped.
|
||||
/// The current state of the process:
|
||||
__volatile__ long state;
|
||||
// struct signal_struct *signal;
|
||||
/// Instruction Pointer of the LIBC Signal Handler.
|
||||
uint32_t sigreturn_eip;
|
||||
/// Pointer to the process’s signal handler descriptor
|
||||
sighand_t sighand;
|
||||
/// Mask of blocked signals.
|
||||
sigset_t blocked;
|
||||
/// Temporary mask of blocked signals (used by the rt_sigtimedwait() system call)
|
||||
sigset_t real_blocked;
|
||||
/// The previous sig mask.
|
||||
sigset_t saved_sigmask;
|
||||
/// Data structure storing the private pending signals
|
||||
sigpending_t pending;
|
||||
|
||||
/// Pointer to process's parent.
|
||||
struct task_struct *parent;
|
||||
/// Timer for alarm syscall.
|
||||
struct timer_list* real_timer;
|
||||
|
||||
/// List head for scheduling purposes.
|
||||
list_head run_list;
|
||||
/// Next value for the real timer (ITIMER_REAL).
|
||||
unsigned long it_real_incr;
|
||||
/// Current value for the real timer (ITIMER_REAL).
|
||||
unsigned long it_real_value;
|
||||
/// Next value for the virtual timer (ITIMER_VIRTUAL).
|
||||
unsigned long it_virt_incr;
|
||||
/// Current value for the virtual timer (ITIMER_VIRTUAL).
|
||||
unsigned long it_virt_value;
|
||||
/// Next value for the profiling timer (ITIMER_PROF).
|
||||
unsigned long it_prof_incr;
|
||||
/// Current value for the profiling timer (ITIMER_PROF).
|
||||
unsigned long it_prof_value;
|
||||
|
||||
/// List of children traced by the process.
|
||||
list_head children;
|
||||
//==== Future work =========================================================
|
||||
// - task's attributes:
|
||||
// struct task_struct __rcu *real_parent;
|
||||
// int exit_state;
|
||||
// int exit_signal;
|
||||
// struct thread_info thread_info;
|
||||
// List of sibling, namely processes created by parent process
|
||||
// list_head sibling;
|
||||
|
||||
/// List of siblings.
|
||||
list_head sibling;
|
||||
|
||||
/// The context of the processors.
|
||||
thread_struct thread;
|
||||
|
||||
/// For scheduling algorithms.
|
||||
sched_entity se;
|
||||
|
||||
/// Exit code of the process. (parameter of _exit() system call).
|
||||
int exit_code;
|
||||
|
||||
/// The name of the task (Added for debug purpose).
|
||||
char name[TASK_NAME_MAX_LENGTH];
|
||||
|
||||
/// Task's segments.
|
||||
struct mm_struct *mm;
|
||||
|
||||
/// Task's specific error number.
|
||||
int error_no;
|
||||
|
||||
/// The current working directory.
|
||||
char cwd[PATH_MAX];
|
||||
|
||||
//==== Future work =========================================================
|
||||
// - task's attributes:
|
||||
// struct task_struct __rcu *real_parent;
|
||||
// int exit_state;
|
||||
// int exit_signal;
|
||||
// struct thread_info thread_info;
|
||||
// List of sibling, namely processes created by parent process
|
||||
// struct list_head sibling;
|
||||
|
||||
// - task's file descriptor:
|
||||
// struct files_struct *files;
|
||||
|
||||
// - task's signal handlers:
|
||||
// struct signal_struct *signal;
|
||||
// struct sighand_struct *sighand;
|
||||
// sigset_t blocked;
|
||||
// sigset_t real_blocked;
|
||||
// sigset_t saved_sigmask;
|
||||
// struct sigpending pending;
|
||||
//==========================================================================
|
||||
// - task's file descriptor:
|
||||
// struct files_struct *files;
|
||||
|
||||
// - task's signal handlers:
|
||||
// struct signal_struct *signal;
|
||||
// struct sighand_struct_t *sighand;
|
||||
// sigset_t blocked;
|
||||
// sigset_t real_blocked;
|
||||
// sigset_t saved_sigmask;
|
||||
// struct sigpending pending;
|
||||
//==========================================================================
|
||||
} task_struct;
|
||||
|
||||
// TODO: doxygen comment.
|
||||
char *get_current_dir_name();
|
||||
/// @brief Initialize the task management.
|
||||
/// @return 1 success, 0 failure.
|
||||
int init_tasking();
|
||||
|
||||
/// @brief Create and spawn the init process.
|
||||
struct task_struct *create_init_process();
|
||||
/// @param path Path of the `init` program.
|
||||
/// @return Pointer to init process.
|
||||
task_struct *process_create_init(const char *path);
|
||||
|
||||
@@ -1,68 +1,115 @@
|
||||
/// MentOS, The Mentoring Operating system project
|
||||
/// @file scheduler.h
|
||||
/// @brief Scheduler structures and functions.
|
||||
/// @copyright (c) 2019 This file is distributed under the MIT License.
|
||||
/// @copyright (c) 2014-2021 This file is distributed under the MIT License.
|
||||
/// See LICENSE.md for details.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "clock.h"
|
||||
#include "kernel.h"
|
||||
#include "stdint.h"
|
||||
#include "list_head.h"
|
||||
#include "process.h"
|
||||
#include "stddef.h"
|
||||
|
||||
typedef struct {
|
||||
/// Number of queued processes.
|
||||
size_t num_active;
|
||||
|
||||
/// Queue of processes.
|
||||
list_head queue;
|
||||
|
||||
/// The current running process.
|
||||
task_struct *curr;
|
||||
/// @brief Structure that contains information about live processes.
|
||||
typedef struct runqueue_t {
|
||||
/// Number of queued processes.
|
||||
size_t num_active;
|
||||
/// Number of queued periodic processes.
|
||||
size_t num_periodic;
|
||||
/// Queue of processes.
|
||||
list_head queue;
|
||||
/// The current running process.
|
||||
task_struct *curr;
|
||||
} runqueue_t;
|
||||
|
||||
/// @brief Structure that describes scheduling parameters.
|
||||
typedef struct sched_param_t {
|
||||
/// Static execution priority.
|
||||
int sched_priority;
|
||||
/// Expected period of the task
|
||||
time_t period;
|
||||
/// Absolute deadline
|
||||
time_t deadline;
|
||||
/// Absolute time of arrival of the task
|
||||
time_t arrivaltime;
|
||||
/// Is task periodic?
|
||||
bool_t is_periodic;
|
||||
} sched_param_t;
|
||||
|
||||
/// @brief Initialize the scheduler.
|
||||
void scheduler_initialize();
|
||||
|
||||
/// @brief Returns a non-decreasing unique process id.
|
||||
/// @return Process identifier (PID).
|
||||
uint32_t get_new_pid();
|
||||
|
||||
/// @brief Initialize the scheduler.
|
||||
void kernel_initialize_scheduler();
|
||||
|
||||
/// @brief Activate the given process.
|
||||
/// @param process Process that has to be activated.
|
||||
void enqueue_task(task_struct *process);
|
||||
|
||||
/// @brief Removes the given process from the queue.
|
||||
/// @param process Process that has to be activated.
|
||||
void dequeue_task(task_struct *process);
|
||||
|
||||
/// @brief Returns the number of active processes.
|
||||
size_t kernel_get_active_processes();
|
||||
uint32_t scheduler_getpid();
|
||||
|
||||
/// @brief Returns the pointer to the current active process.
|
||||
task_struct *kernel_get_current_process();
|
||||
/// @return Pointer to the current process.
|
||||
task_struct *scheduler_get_current_process();
|
||||
|
||||
/// @brief Returns the maximum vruntime of all the processes in running state.
|
||||
/// @return A maximum vruntime value.
|
||||
time_t scheduler_get_maximum_vruntime();
|
||||
|
||||
/// @brief Returns the number of active processes.
|
||||
/// @return Number of processes.
|
||||
size_t scheduler_get_active_processes();
|
||||
|
||||
/// @brief Returns a pointer to the process with the given pid.
|
||||
task_struct *kernel_get_running_process(pid_t pid);
|
||||
/// @param pid The pid of the process we are looking for.
|
||||
/// @return Pointer to the process, or NULL if we cannot find it.
|
||||
task_struct *scheduler_get_running_process(pid_t pid);
|
||||
|
||||
task_struct *pick_next_task(runqueue_t *runqueue, time_t delta_exec);
|
||||
/// @brief Activate the given process.
|
||||
/// @param process Process that has to be activated.
|
||||
void scheduler_enqueue_task(task_struct *process);
|
||||
|
||||
/// @brief The RR implementation of the scheduler.
|
||||
/// @brief Removes the given process from the queue.
|
||||
/// @param process Process that has to be activated.
|
||||
void scheduler_dequeue_task(task_struct *process);
|
||||
|
||||
/// @brief The RR implementation of the scheduler.
|
||||
/// @param f The context of the process.
|
||||
void kernel_schedule(pt_regs *f);
|
||||
void scheduler_run(pt_regs *f);
|
||||
|
||||
/// @birief Values from pt_regs to task_struct process.
|
||||
void update_context(pt_regs *f, task_struct *process);
|
||||
/// @brief Values from pt_regs to task_struct process.
|
||||
/// @param f The set of registers we are saving.
|
||||
/// @param process The process for which we are saving the CPU registers status.
|
||||
void scheduler_store_context(pt_regs *f, task_struct *process);
|
||||
|
||||
/// @brief Values from task_struct process to pt_regs.
|
||||
void do_switch(task_struct *process, pt_regs *f);
|
||||
/// @param process The process for which we are restoring the registers in CPU .
|
||||
/// @param f The set of registers we are restoring.
|
||||
void scheduler_restore_context(task_struct *process, pt_regs *f);
|
||||
|
||||
/// @brief Switch CPU to user mode and start running that given process.
|
||||
/// @param process The process that has to be executed
|
||||
void enter_user_jmp(uintptr_t location, uintptr_t stack);
|
||||
/// @brief Switch CPU to user mode and start running that given process.
|
||||
/// @param location The instruction pointer of the process we are starting.
|
||||
/// @param stack Address of the stack of that process.
|
||||
void scheduler_enter_user_jmp(uintptr_t location, uintptr_t stack);
|
||||
|
||||
/// @brief Sets the priority value of the given task.
|
||||
int set_user_nice(task_struct *p, long nice);
|
||||
/// @brief Picks the next task (in scheduler_algorithm.c).
|
||||
/// @param runqueue Pointer to the runqueue.
|
||||
/// @return The next task to execute.
|
||||
task_struct *scheduler_pick_next_task(runqueue_t *runqueue);
|
||||
|
||||
/// @brief Set new scheduling settings for the given process.
|
||||
/// @param pid ID of the process we are manipulating.
|
||||
/// @param param New parameters.
|
||||
/// @return 1 on success, -1 on error.
|
||||
int sys_sched_setparam(pid_t pid, const sched_param_t *param);
|
||||
|
||||
/// @brief Gets the scheduling settings for the given process.
|
||||
/// @param pid ID of the process we are manipulating.
|
||||
/// @param param Where we store the parameters.
|
||||
/// @return 1 on success, -1 on error.
|
||||
int sys_sched_getparam(pid_t pid, sched_param_t *param);
|
||||
|
||||
/// @brief Puts the process on wait until its next period starts.
|
||||
/// @return 0 on success, a negative value on failure.
|
||||
int sys_waitperiod();
|
||||
|
||||
/// @brief Returns 1 if the given group is orphaned, the session leader of the group
|
||||
/// is no longer alive.
|
||||
/// @param gid ID of the group
|
||||
/// @return 1 if the group is orphan, 0 otherwise.
|
||||
int is_orphaned_pgrp(pid_t gid);
|
||||
@@ -0,0 +1,111 @@
|
||||
/// MentOS, The Mentoring Operating system project
|
||||
/// @file wait.h
|
||||
/// @brief
|
||||
/// @copyright (c) 2014-2021 This file is distributed under the MIT License.
|
||||
/// See LICENSE.md for details.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "list_head.h"
|
||||
#include "spinlock.h"
|
||||
|
||||
/// @brief Return immediately if no child is there to be waited for.
|
||||
#define WNOHANG 0x00000001
|
||||
/// @brief Return for children that are stopped, and whose status has not
|
||||
/// been reported.
|
||||
#define WUNTRACED 0x00000002
|
||||
/// @brief returns true if the child process exited because of a signal that
|
||||
/// was not caught.
|
||||
#define WIFSIGNALED(status) (!WIFSTOPPED(status) && !WIFEXITED(status))
|
||||
/// @brief returns true if the child process that caused the return is
|
||||
/// currently stopped; this is only possible if the call was done using
|
||||
/// WUNTRACED().
|
||||
#define WIFSTOPPED(status) (((status)&0xff) == 0x7f)
|
||||
/// @brief evaluates to the least significant eight bits of the return code
|
||||
/// of the child that terminated, which may have been set as the argument
|
||||
/// to a call to exit() or as the argument for a return statement in the
|
||||
/// main program. This macro can only be evaluated if WIFEXITED()
|
||||
/// returned nonzero.
|
||||
#define WEXITSTATUS(status) (((status)&0xff00) >> 8)
|
||||
/// @brief returns the number of the signal that caused the child process to
|
||||
/// terminate. This macro can only be evaluated if WIFSIGNALED() returned
|
||||
/// nonzero.
|
||||
#define WTERMSIG(status) ((status)&0x7f)
|
||||
/// @brief Is nonzero if the child exited normally.
|
||||
#define WIFEXITED(status) (WTERMSIG(status) == 0)
|
||||
/// @brief returns the number of the signal that caused the child to stop.
|
||||
/// This macro can only be evaluated if WIFSTOPPED() returned nonzero.
|
||||
#define WSTOPSIG(status) (WEXITSTATUS(status))
|
||||
|
||||
//==== Task States ============================================================
|
||||
#define TASK_RUNNING 0x00 ///< The process is either: 1) running on CPU or 2) waiting in a run queue.
|
||||
#define TASK_INTERRUPTIBLE (1 << 0) ///< The process is sleeping, waiting for some event to occur.
|
||||
#define TASK_UNINTERRUPTIBLE (1 << 1) ///< Similar to TASK_INTERRUPTIBLE, but it doesn't process signals.
|
||||
#define TASK_STOPPED (1 << 2) ///< Stopped, it's not running, and not able to run.
|
||||
#define TASK_TRACED (1 << 3) ///< Is being monitored by other processes such as debuggers.
|
||||
#define EXIT_ZOMBIE (1 << 4) ///< The process has terminated.
|
||||
#define EXIT_DEAD (1 << 5) ///< The final state.
|
||||
//==============================================================================
|
||||
|
||||
/// @defgroup WaitQueueFlags Wait Queue Flags
|
||||
/// @{
|
||||
|
||||
/// @brief When an entry has this flag is added to the end of the wait queue.
|
||||
/// Entries without that flag are, instead, added to the beginning.
|
||||
#define WQ_FLAG_EXCLUSIVE 0x01
|
||||
//#define WQ_FLAG_WOKEN 0x02
|
||||
//#define WQ_FLAG_BOOKMARK 0x04
|
||||
//#define WQ_FLAG_CUSTOM 0x08
|
||||
//#define WQ_FLAG_DONE 0x10
|
||||
|
||||
/// @}
|
||||
|
||||
/// @brief Head of the waiting queue.
|
||||
typedef struct wait_queue_head_t {
|
||||
/// Locking element for the waiting queque.
|
||||
spinlock_t lock;
|
||||
/// Head of the waiting queue, it contains wait_queue_entry_t elements.
|
||||
struct list_head task_list;
|
||||
} wait_queue_head_t;
|
||||
|
||||
/// @brief Entry of the waiting queue.
|
||||
typedef struct wait_queue_entry_t {
|
||||
/// Flags of the type WaitQueueFlags.
|
||||
unsigned int flags;
|
||||
/// Task associated with the wait queue entry.
|
||||
struct task_struct *task;
|
||||
/// Function associated with the wait queue entry.
|
||||
int (*func)(struct wait_queue_entry_t *wait, unsigned mode, int sync);
|
||||
/// Handler for placing the entry inside a waiting queue double linked-list.
|
||||
struct list_head task_list;
|
||||
} wait_queue_entry_t;
|
||||
|
||||
/// @brief Initialize the waiting queue entry.
|
||||
/// @param wq The entry we initialize.
|
||||
/// @param task The task associated with the entry.
|
||||
void init_waitqueue_entry(wait_queue_entry_t *wq, struct task_struct *task);
|
||||
|
||||
/// @brief Adds the element to the waiting queue.
|
||||
/// @param head The head of the waiting queue.
|
||||
/// @param wq The entry we insert inside the waiting queue.
|
||||
void add_wait_queue(wait_queue_head_t *head, wait_queue_entry_t *wq);
|
||||
|
||||
/// @brief Removes the element from the waiting queue.
|
||||
/// @param head The head of the waiting queue.
|
||||
/// @param wq The entry we remove from the waiting queue.
|
||||
void remove_wait_queue(wait_queue_head_t *head, wait_queue_entry_t *wq);
|
||||
|
||||
/// @brief The default wake function, a wrapper for try_to_wake_up.
|
||||
/// @param wait The pointer to the wait queue.
|
||||
/// @param mode The type of wait (TASK_INTERRUPTIBLE or TASK_UNINTERRUPTIBLE).
|
||||
/// @param sync Specifies if the wakeup should be synchronous.
|
||||
/// @return 1 on success, 0 on failure.
|
||||
int default_wake_function(wait_queue_entry_t *wait, unsigned mode, int sync);
|
||||
|
||||
/// @brief Sets the state of the current process to TASK_UNINTERRUPTIBLE
|
||||
/// and inserts it into the specified wait queue.
|
||||
///
|
||||
/// @param wq Waitqueue where to sleep.
|
||||
/// @return Pointer to the entry inside the wq representing the
|
||||
/// sleeping process.
|
||||
wait_queue_entry_t *sleep_on(wait_queue_head_t *wq);
|
||||
Reference in New Issue
Block a user