Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

310551038 lab5–8 #127

Open
wants to merge 51 commits into
base: 310551038
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
2c23d35
Lab 5 C: Import kernel from lab 4
abt8601 Jun 1, 2023
bad36d5
Lab 5 C: Remove many consistency checks
abt8601 Jun 1, 2023
e9a89b2
Lab 5 C: Complete B1: Thread
abt8601 Jun 4, 2023
5c70a56
Lab 5 C: Complete B2: User Process and System Call
abt8601 Jun 19, 2023
e2e67f4
Lab 5 C: Complete B3: Video Player
abt8601 Jun 19, 2023
b8fc7ff
Lab 5 C: Fix `get_process_by_id`
abt8601 Jun 20, 2023
c1b6c25
Lab 5 C: Complete A1: POSIX Signal
abt8601 Jun 20, 2023
0dc4dd6
Lab 6 C: Import kernel from lab 5
abt8601 Jun 25, 2023
c833acc
Lab 6 C: Change default exception handler
abt8601 Jun 26, 2023
1760950
Lab 6 C: Complete B1
abt8601 Jun 26, 2023
1794c1a
Lab 6 C: Complete B2, B3, A2, A3
abt8601 Jun 27, 2023
bcfa76b
Lab 6 C: Fix memory attributes
abt8601 Jun 28, 2023
f3ee536
Lab 6 C: Fix `sys_mbox_call`
abt8601 Jun 28, 2023
c5925d1
Lab 7 C: Import kernel from lab 6
abt8601 Jun 28, 2023
b596fa4
Lab 7 C: Complete B1
abt8601 Jun 28, 2023
507855e
Lab 7 C: Complete B2
abt8601 Jun 28, 2023
8a64b30
Lab 7 C: Complete B3
abt8601 Jun 28, 2023
0a1b274
Lab 7 C: Complete B4
abt8601 Jun 28, 2023
27b4394
Lab 6 C: Fix `free`
abt8601 Jun 29, 2023
c56b5bd
Merge branch 'lab6' into lab7
abt8601 Jun 29, 2023
ee7f8b5
Lab 8 C: Import kernel from lab 7
abt8601 Jun 29, 2023
4cdedb4
Lab 8 C: Complete B1
abt8601 Jun 29, 2023
138c012
Lab 6 C: Complete A1
abt8601 Jun 29, 2023
5ae13f6
Merge branch 'lab6' into lab7
abt8601 Jun 29, 2023
8b0fd4e
Merge branch 'lab7' into lab8
abt8601 Jun 29, 2023
4f696ab
Merge branch 'lab8' into 310551038
abt8601 Jun 29, 2023
afe1588
Lab 6 C: Fix `exec` destroying memory regions
abt8601 Jun 30, 2023
811b98c
Merge branch 'lab6' into lab7
abt8601 Jun 30, 2023
f5012a6
Merge branch 'lab7' into lab8
abt8601 Jun 30, 2023
1b5db3c
Merge branch 'lab8' into 310551038
abt8601 Jun 30, 2023
c5d8f93
Lab 5 C: Fix run queue corruption
abt8601 Jun 30, 2023
7edf96f
Merge branch 'lab5' into lab6
abt8601 Jun 30, 2023
a2a4890
Merge branch 'lab6' into lab7
abt8601 Jun 30, 2023
a79e5fc
Merge branch 'lab7' into lab8
abt8601 Jun 30, 2023
306012e
Merge branch 'lab8' into 310551038
abt8601 Jun 30, 2023
05ac4e9
Lab 6 C: Fix `shared_page_decref`
abt8601 Jul 1, 2023
39f924e
Merge branch 'lab6' into lab7
abt8601 Jul 1, 2023
c9354cf
Merge branch 'lab7' into lab8
abt8601 Jul 1, 2023
c4faa22
Merge branch 'lab8' into 310551038
abt8601 Jul 1, 2023
1e6d2df
Lab 7 C: Complete A1
abt8601 Jul 10, 2023
cbef6e7
Lab 7 C: Change mknod implementation
abt8601 Jul 12, 2023
41019c4
Lab 7 C: Complete A2
abt8601 Jul 12, 2023
f507026
Lab 7 C: Use VFS API in `sys_exec`
abt8601 Jul 14, 2023
48aab76
Merge branch 'lab7' into lab8
abt8601 Jul 14, 2023
bb57655
Merge branch 'lab8' into 310551038
abt8601 Jul 14, 2023
9b06086
Lab 8 C: Fix issues with FAT
abt8601 Oct 17, 2023
9bcd6ec
Lab 8 C: Complete B2
abt8601 Oct 17, 2023
c9e686f
Lab 8 C: Add missing operations in sd_fat32
abt8601 Oct 18, 2023
a41a73a
Lab 8 C: Fix write and create in sd_fat32
abt8601 Oct 19, 2023
44e2dad
Lab 8 C: Complete A1
abt8601 Oct 19, 2023
db1be14
Merge branch 'lab8' into 310551038
abt8601 Oct 19, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Lab 5 C: Complete B2: User Process and System Call
Other changes:

- Scheduler:

  - Partial rewrite to simplify design.

  - The current thread no longer remains on the run queue after being
    scheduled.

- Serial console:

  - Redesign around non-blocking primitives.

  - Add new non-blocking functions.

  - Add read/write readiness notification facility.

- Dynamic memory allocator:

  - Fix a bug in `free` that causes the incorrect slot to be freed.

- (Old) User program:

  - Retired. Superseded by the current scheduler.

- Testers:

  - Retire `xcpt_test` since it no longer works.

  - Add `syscall_test` that tests some system calls.

  - Add a minimal libc.

TODO:

- Properly implement red-black tree in order to speed up the process of
  finding a process by its PID.
  • Loading branch information
abt8601 committed Jun 19, 2023
commit 5c70a56ac3f65c1c61ebf03faa4fe573afa80c08
17 changes: 11 additions & 6 deletions lab5/c/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,21 @@ LDFLAGS_RELEASE = -flto -Xlinker --gc-sections

LDLIBS_BASE = -lgcc

OBJS = start main console devicetree initrd panic shell user-program \
OBJS = start main console devicetree initrd panic shell \
drivers/aux drivers/gpio drivers/l1ic drivers/l2ic drivers/mailbox \
drivers/mini-uart drivers/pm \
mem/malloc mem/page-alloc mem/startup-alloc mem/vm \
sched/idle-thread sched/sched sched/schedule sched/thread-main \
mem/malloc mem/page-alloc mem/startup-alloc mem/types mem/vm \
sched/idle-thread sched/sched sched/schedule sched/thread-main \
sched/user-program-main \
timer/delay timer/timeout \
xcpt/default-handler xcpt/irq-handler xcpt/task-queue \
xcpt/vector-table xcpt/xcpt \
xcpt/default-handler xcpt/irq-handler xcpt/svc-handler \
xcpt/syscall-table xcpt/task-queue xcpt/vector-table xcpt/xcpt \
xcpt/syscall/enosys xcpt/syscall/getpid xcpt/syscall/uart-read \
xcpt/syscall/uart-write xcpt/syscall/exec xcpt/syscall/fork \
xcpt/syscall/fork-impl xcpt/syscall/fork-child-ret \
xcpt/syscall/exit xcpt/syscall/mbox-call xcpt/syscall/kill \
libc/ctype libc/stdio libc/stdlib/qsort libc/string \
utils/core-id utils/fmt utils/heapq
utils/core-id utils/fmt utils/heapq utils/rb
LD_SCRIPT = $(SRC_DIR)/linker.ld

# ------------------------------------------------------------------------------
Expand Down
50 changes: 50 additions & 0 deletions lab5/c/include/oscos/console.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#define OSCOS_CONSOLE_H

#include <stdarg.h>
#include <stdbool.h>
#include <stddef.h>

/// \brief The mode of the serial console.
Expand All @@ -43,20 +44,51 @@ void console_set_mode(console_mode_t mode);
/// When calling this function, the serial console must be initialized.
unsigned char console_getc(void);

/// \brief Reads a character from the serial console without blocking.
///
/// When calling this function, the serial console must be initialized.
///
/// \return The character read, or a negative number if the read would block.
int console_getc_nonblock(void);

/// \brief Reads as many characters from the serial console as possible without
/// blocking.
///
/// When calling this function, the serial console must be initialized.
///
/// \return The number of characters read.
size_t console_read_nonblock(void *buf, size_t count);

/// \brief Writes a character to the serial console.
///
/// When calling this function, the serial console must be initialized.
///
/// \return \p c
unsigned char console_putc(unsigned char c);

/// \brief Writes a character to the serial console without blocking.
///
/// When calling this function, the serial console must be initialized.
///
/// \return \p c if the operation is successful, or a negative number if the
/// write operation would block.
int console_putc_nonblock(unsigned char c);

/// \brief Writes characters to the serial console.
///
/// When calling this function, the serial console must be initialized.
///
/// \return \p count
size_t console_write(const void *buf, size_t count);

/// \brief Writes as many characters to the serial console as possible without
/// blocking.
///
/// When calling this function, the serial console must be initialized.
///
/// \return The number of characters written.
size_t console_write_nonblock(const void *buf, size_t count);

/// \brief Writes a string to the serial console without trailing newline.
///
/// When calling this function, the serial console must be initialized.
Expand Down Expand Up @@ -85,6 +117,24 @@ int console_vprintf(const char *restrict format, va_list ap)
int console_printf(const char *restrict format, ...)
__attribute__((format(printf, 1, 2)));

/// \brief Registers the notification callback for read readiness.
///
/// \param callback The callback that will be called.
/// \param arg The argument that will be passed to \p callback.
/// \return true if the registration succeeds.
/// \return false if the registration fails because an earlier callback has not
/// been called.
bool console_notify_read_ready(void (*callback)(void *), void *arg);

/// \brief Registers the notification callback for write readiness.
///
/// \param callback The callback that will be called.
/// \param arg The argument that will be passed to \p callback.
/// \return true if the registration succeeds.
/// \return false if the registration fails because an earlier callback has not
/// been called.
bool console_notify_write_ready(void (*callback)(void *), void *arg);

/// \brief Interrupt handler. Not meant to be called directly.
void mini_uart_interrupt_handler(void);

Expand Down
29 changes: 29 additions & 0 deletions lab5/c/include/oscos/mem/types.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#ifndef OSCOS_MEM_TYPES_H
#define OSCOS_MEM_TYPES_H

#include <stddef.h>

#include "oscos/libc/inttypes.h"

/// \brief Physical address.
Expand Down Expand Up @@ -37,4 +39,31 @@ typedef struct {
void *start, *end;
} va_range_t;

/// \brief Shared, reference-counted page.
typedef struct {
size_t ref_count;
page_id_t page_id;
} shared_page_t;

/// \brief Initializes a shared page.
///
/// This function sets the reference count of the newly-created shared page
/// to 1.
shared_page_t *shared_page_init(page_id_t page_id);

/// \brief Clones a shared page.
///
/// This function increases the reference count of the shared page by 1.
///
/// \param shared_page The shared page to clone.
/// \return \p shared_page
shared_page_t *shared_page_clone(shared_page_t *shared_page);

/// \brief Drops a shared page.
///
/// This function decreases the reference count of the shared page by 1. The
/// shared page structure and the underlying page will be freed when the
/// reference count reaches 0.
void shared_page_drop(shared_page_t *shared_page);

#endif
82 changes: 77 additions & 5 deletions lab5/c/include/oscos/sched.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,27 +8,50 @@
#include <stdnoreturn.h>

#include "oscos/mem/types.h"
#include "oscos/xcpt/trap-frame.h"

typedef struct thread_list_node_t {
struct thread_list_node_t *prev, *next;
} thread_list_node_t;

typedef struct {
alignas(16) uint64_t words[2];
} uint128_t;

typedef struct {
uint128_t v[32];
alignas(16) struct {
uint64_t fpcr, fpsr;
};
} thread_fp_simd_ctx_t;

typedef struct {
alignas(16) union {
struct {
uint64_t x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, pc, sp;
uint64_t r19, r20, r21, r22, r23, r24, r25, r26, r27, r28, r29, pc,
kernel_sp, user_sp;
};
uint64_t regs[13];
uint64_t regs[14];
};
thread_fp_simd_ctx_t *fp_simd_ctx;
} thread_ctx_t;

struct process_t;

typedef struct {
thread_list_node_t list_node;
thread_ctx_t ctx;
size_t id;
page_id_t stack_page_id;
struct process_t *process;
} thread_t;

typedef struct process_t {
size_t id;
shared_page_t *text_page, *user_stack_page;
thread_t *main_thread;
} process_t;

/// \brief Initializes the scheduler and creates the idle thread.
///
/// \return true if the initialization succeeds.
Expand All @@ -51,16 +74,65 @@ noreturn void thread_exit(void);
/// \brief Gets the current thread.
thread_t *current_thread(void);

/// \brief Creates a process and name the current thread the main thread of the
/// process.
///
/// \return true if the process creation succeeds.
/// \return false if the process creation fails due to memory shortage.
bool process_create(void);

/// \brief Executes the first ever user program on the current process.
///
/// This function jumps to the user program and does not return if the operation
/// succeeds. If the operation fails due to memory shortage, this function
/// returns.
///
/// \param text_start The starting address of where the user program is
/// currently located. (Do not confuse it with the entry point
/// of the user program.)
/// \param text_len The length of the user program.
void exec_first(const void *text_start, size_t text_len);

/// \brief Executes a user program on the current process.
///
/// This function jumps to the user program and does not return if the operation
/// succeeds. If the operation fails due to memory shortage, this function
/// returns.
///
/// The text_page_id field of the current process must be valid.
///
/// \param text_start The starting address of where the user program is
/// currently located. (Do not confuse it with the entry point
/// of the user program.)
/// \param text_len The length of the user program.
void exec(const void *text_start, size_t text_len);

/// \brief Forks the current process.
process_t *fork(const extended_trap_frame_t *trap_frame);

/// \brief Kills zombie threads.
void kill_zombies(void);

/// \brief Yields CPU for the current thread and runs the scheduler.
void schedule(void);

/// \brief Puts the current thread to the given wait queue and runs the
/// scheduler.
void suspend_to_wait_queue(thread_list_node_t *wait_queue);

/// \brief Adds every thread in the given wait queue to the run queue.
void add_all_threads_to_run_queue(thread_list_node_t *wait_queue);

/// \brief Gets a process by its PID.
process_t *get_process_by_id(size_t pid);

/// \brief Kills a process.
void kill_process(process_t *process);

/// \brief Kills all processes.
void kill_all_processes(void);

/// \brief Do what the idle thread should do.
///
/// This function must be called on the idle thread, i.e., the thread that
/// called bool thread_create(void (*)(void *), void *).
noreturn void idle(void);

#endif
9 changes: 9 additions & 0 deletions lab5/c/include/oscos/uapi/errno.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#define ENOENT 2
#define ESRCH 3
#define EIO 5
#define ENOMEM 12
#define EBUSY 16
#define EISDIR 21
#define EINVAL 22
#define ENOSYS 38
#define ELOOP 40
13 changes: 13 additions & 0 deletions lab5/c/include/oscos/uapi/sys/syscall.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#ifndef OSCOS_UAPI_SYS_SYSCALL_H
#define OSCOS_UAPI_SYS_SYSCALL_H

#define SYS_getpid 0
#define SYS_uart_read 1
#define SYS_uart_write 2
#define SYS_exec 3
#define SYS_fork 4
#define SYS_exit 5
#define SYS_mbox_call 6
#define SYS_kill 7

#endif
6 changes: 6 additions & 0 deletions lab5/c/include/oscos/uapi/unistd.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#ifndef OSCOS_UAPI_UNISTD_H
#define OSCOS_UAPI_UNISTD_H

typedef long ssize_t;

#endif
22 changes: 0 additions & 22 deletions lab5/c/include/oscos/user-program.h

This file was deleted.

26 changes: 26 additions & 0 deletions lab5/c/include/oscos/utils/rb.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#ifndef OSCOS_UTILS_RB_H
#define OSCOS_UTILS_RB_H

#include <stdalign.h>
#include <stdbool.h>
#include <stddef.h>

// typedef enum { RB_NC_BLACK, RB_NC_RED } rb_node_colour_t;

typedef struct rb_node_t {
// rb_node_colour_t colour;
struct rb_node_t *children[2] /*, **parent */;
alignas(16) unsigned char payload[];
} rb_node_t;

const void *rb_search(const rb_node_t *root, const void *restrict key,
int (*compar)(const void *, const void *, void *),
void *arg);

bool rb_insert(rb_node_t **root, size_t size, const void *restrict item,
int (*compar)(const void *, const void *, void *), void *arg);

void rb_delete(rb_node_t **root, const void *restrict key,
int (*compar)(const void *, const void *, void *), void *arg);

#endif
24 changes: 24 additions & 0 deletions lab5/c/include/oscos/xcpt/trap-frame.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#ifndef OSCOS_XCPT_TRAP_FRAME_H
#define OSCOS_XCPT_TRAP_FRAME_H

#include <stdalign.h>
#include <stdint.h>

typedef struct {
alignas(16) union {
struct {
uint64_t r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14,
r15, r16, r17, r18, lr;
};
uint64_t regs[20];
};
} trap_frame_t;

typedef struct {
alignas(16) struct {
uint64_t spsr, elr;
};
trap_frame_t trap_frame;
} extended_trap_frame_t;

#endif
Loading