Add linked list structure
This commit is contained in:
@@ -25,6 +25,7 @@ void *syscall_table[256] = {
|
||||
[SYSCALL_NR_LSEEK] = sys_lseek,
|
||||
[SYSCALL_NR_IOCTL] = sys_ioctl,
|
||||
[SYSCALL_NR_ACCESS] = sys_access,
|
||||
[SYSCALL_NR_SELECT] = sys_select,
|
||||
[SYSCALL_NR_GETCWD] = sys_getcwd,
|
||||
[SYSCALL_NR_CHDIR] = sys_chdir,
|
||||
[SYSCALL_NR_MKDIR] = sys_mkdir,
|
||||
|
||||
+2
-1
@@ -56,7 +56,8 @@ OBJS+=$(O)/sys/debug.o \
|
||||
$(O)/sys/init.o \
|
||||
$(O)/sys/font/logo.o \
|
||||
$(O)/sys/font/psf.o \
|
||||
$(O)/sys/font/default8x16.o
|
||||
$(O)/sys/font/default8x16.o \
|
||||
$(O)/sys/list.o
|
||||
DIRS+=$(O)/sys \
|
||||
$(O)/sys/char \
|
||||
$(O)/sys/block \
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
|
||||
struct list_link {
|
||||
struct list_link *prev, *next;
|
||||
};
|
||||
|
||||
struct list {
|
||||
struct list_link *begin, *end;
|
||||
};
|
||||
|
||||
#define LIST_HEAD(name) \
|
||||
struct list name = { NULL, NULL }
|
||||
|
||||
#define list_foreach(head, iter) \
|
||||
for (struct list_link *iter = (head)->begin; iter; iter = iter->next)
|
||||
|
||||
#define list_link_value(link, type, member) ({ \
|
||||
const typeof (((type *) 0)->member) *__memb = (link); \
|
||||
(type *) ((char *) __memb - offsetof(type, member)); \
|
||||
})
|
||||
|
||||
#define list_link_init(link) ({ \
|
||||
(link)->prev = NULL; \
|
||||
(link)->next = NULL; \
|
||||
})
|
||||
|
||||
void list_append(struct list *list, struct list_link *ptr);
|
||||
void list_remove(struct list *list, struct list_link *ptr);
|
||||
@@ -5,14 +5,7 @@
|
||||
#include "arch/amd64/sys/spin.h"
|
||||
#endif
|
||||
|
||||
#if defined(AMD64_SMP)
|
||||
void spin_lock(spin_t *s);
|
||||
void spin_release(spin_t *s);
|
||||
void spin_lock_irqsave(spin_t *s, uintptr_t *irq);
|
||||
void spin_release_irqrestore(spin_t *s, uintptr_t *irq);
|
||||
#else
|
||||
#define spin_lock(s)
|
||||
#define spin_release(s)
|
||||
#define spin_lock_irqsave(s, i)
|
||||
#define spin_release_irqrestore(s, i)
|
||||
#endif
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#pragma once
|
||||
#include "user/select.h"
|
||||
#include "sys/types.h"
|
||||
|
||||
ssize_t sys_read(int fd, void *data, size_t lim);
|
||||
@@ -17,6 +18,7 @@ int sys_open(const char *filename, int flags, int mode);
|
||||
void sys_close(int fd);
|
||||
int sys_stat(const char *filename, struct stat *st);
|
||||
int sys_access(const char *path, int mode);
|
||||
int sys_select(int n, fd_set *inp, fd_set *outp, fd_set *excp, struct timeval *tv);
|
||||
int sys_chmod(const char *path, mode_t mode);
|
||||
int sys_chown(const char *path, uid_t uid, gid_t gid);
|
||||
off_t sys_lseek(int fd, off_t offset, int whence);
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#if defined(ARCH_AMD64)
|
||||
#include "arch/amd64/asm/asm_thread.h"
|
||||
#endif
|
||||
#include "sys/list.h"
|
||||
#include "fs/vfs.h"
|
||||
#include "sys/mm.h"
|
||||
|
||||
@@ -59,11 +60,11 @@ struct thread {
|
||||
int exit_status;
|
||||
|
||||
// Global thread list (for stuff like finding by PID)
|
||||
struct thread *g_prev, *g_next;
|
||||
struct list_link g_link;
|
||||
|
||||
// Scheduler
|
||||
int cpu;
|
||||
struct thread *prev, *next;
|
||||
struct thread *sched_prev, *sched_next;
|
||||
};
|
||||
|
||||
pid_t thread_alloc_pid(int is_user);
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
struct timeval;
|
||||
|
||||
// 64 bits
|
||||
typedef long int __fd_mask;
|
||||
|
||||
#define __NFDBITS (8 * (int) sizeof(__fd_mask))
|
||||
// TODO: Guess this should be the same as the maximum
|
||||
// per-process filedes count
|
||||
#define __FD_SETSIZE 64
|
||||
|
||||
typedef struct {
|
||||
__fd_mask fds_bits[__FD_SETSIZE / __NFDBITS];
|
||||
} fd_set;
|
||||
|
||||
#define FD_SET(fd, fds) \
|
||||
(fds)->fds_bits[(fd) / __NFDBITS] |= (1ULL << ((fd) % __NFDBITS))
|
||||
|
||||
#define FD_ISSET(fd, fds) \
|
||||
(!!((fds)->fds_bits[(fd) / __NFDBITS] & (1ULL << ((fd) % __NFDBITS))))
|
||||
|
||||
#define FD_ZERO(fds) \
|
||||
for (int __i = 0; __i < (__FD_SETSIZE / __NFDBITS); ++__i) \
|
||||
(fds)->fds_bits[__i] = 0
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#define SYSCALL_NR_LSEEK 8
|
||||
#define SYSCALL_NR_IOCTL 16
|
||||
#define SYSCALL_NR_ACCESS 21
|
||||
#define SYSCALL_NR_SELECT 23
|
||||
#define SYSCALL_NR_GETCWD 79
|
||||
#define SYSCALL_NR_CHDIR 80
|
||||
#define SYSCALL_NR_MKDIR 83
|
||||
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
#include "sys/assert.h"
|
||||
#include "sys/types.h"
|
||||
#include "sys/list.h"
|
||||
|
||||
void list_append(struct list *head, struct list_link *link) {
|
||||
link->prev = head->end;
|
||||
if (head->end) {
|
||||
head->end->next = link;
|
||||
} else {
|
||||
head->begin = link;
|
||||
}
|
||||
link->next = NULL;
|
||||
head->end = link;
|
||||
}
|
||||
|
||||
void list_remove(struct list *head, struct list_link *link) {
|
||||
struct list_link *prev, *next;
|
||||
prev = link->prev;
|
||||
next = link->next;
|
||||
|
||||
if (prev) {
|
||||
prev->next = next;
|
||||
} else {
|
||||
_assert(link == head->begin);
|
||||
head->begin = next;
|
||||
}
|
||||
|
||||
if (next) {
|
||||
next->prev = prev;
|
||||
} else {
|
||||
_assert(link == head->end);
|
||||
head->end = prev;
|
||||
}
|
||||
|
||||
link->prev = NULL;
|
||||
link->next = NULL;
|
||||
}
|
||||
+28
-25
@@ -48,15 +48,15 @@ void sched_queue_to(struct thread *thr, int cpu_no) {
|
||||
thr->cpu = cpu_no;
|
||||
|
||||
if (queue_heads[cpu_no]) {
|
||||
struct thread *queue_tail = queue_heads[cpu_no]->prev;
|
||||
struct thread *queue_tail = queue_heads[cpu_no]->sched_prev;
|
||||
|
||||
queue_tail->next = thr;
|
||||
thr->prev = queue_tail;
|
||||
queue_heads[cpu_no]->prev = thr;
|
||||
thr->next = queue_heads[cpu_no];
|
||||
queue_tail->sched_next = thr;
|
||||
thr->sched_prev = queue_tail;
|
||||
queue_heads[cpu_no]->sched_prev = thr;
|
||||
thr->sched_next = queue_heads[cpu_no];
|
||||
} else {
|
||||
thr->next = thr;
|
||||
thr->prev = thr;
|
||||
thr->sched_next = thr;
|
||||
thr->sched_prev = thr;
|
||||
|
||||
queue_heads[cpu_no] = thr;
|
||||
}
|
||||
@@ -66,6 +66,7 @@ void sched_queue_to(struct thread *thr, int cpu_no) {
|
||||
}
|
||||
|
||||
void sched_queue(struct thread *thr) {
|
||||
#if defined(AMD64_SMP)
|
||||
size_t min_queue_size = (size_t) -1;
|
||||
int min_queue_index = 0;
|
||||
uintptr_t irq;
|
||||
@@ -78,8 +79,10 @@ void sched_queue(struct thread *thr) {
|
||||
}
|
||||
}
|
||||
spin_release_irqrestore(&sched_lock, &irq);
|
||||
|
||||
sched_queue_to(thr, min_queue_index);
|
||||
#else
|
||||
sched_queue_to(thr, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void sched_unqueue(struct thread *thr, enum thread_state new_state) {
|
||||
@@ -97,8 +100,8 @@ void sched_unqueue(struct thread *thr, enum thread_state new_state) {
|
||||
thr->cpu = -1;
|
||||
int cpu_no = cpu->processor_id;
|
||||
|
||||
struct thread *prev = thr->prev;
|
||||
struct thread *next = thr->next;
|
||||
struct thread *sched_prev = thr->sched_prev;
|
||||
struct thread *sched_next = thr->sched_next;
|
||||
|
||||
_assert((new_state == THREAD_WAITING) ||
|
||||
(new_state == THREAD_STOPPED) ||
|
||||
@@ -112,9 +115,9 @@ void sched_unqueue(struct thread *thr, enum thread_state new_state) {
|
||||
thread_check_signal(thr, 0);
|
||||
spin_lock_irqsave(&sched_lock, &irq);
|
||||
|
||||
if (next == thr) {
|
||||
thr->next = NULL;
|
||||
thr->prev = NULL;
|
||||
if (sched_next == thr) {
|
||||
thr->sched_next = NULL;
|
||||
thr->sched_prev = NULL;
|
||||
|
||||
queue_heads[cpu_no] = NULL;
|
||||
|
||||
@@ -126,21 +129,21 @@ void sched_unqueue(struct thread *thr, enum thread_state new_state) {
|
||||
}
|
||||
|
||||
if (thr == queue_heads[cpu_no]) {
|
||||
queue_heads[cpu_no] = next;
|
||||
queue_heads[cpu_no] = sched_next;
|
||||
}
|
||||
|
||||
_assert(thr && next && prev);
|
||||
_assert(thr && sched_next && sched_prev);
|
||||
|
||||
next->prev = prev;
|
||||
prev->next = next;
|
||||
sched_next->sched_prev = sched_prev;
|
||||
sched_prev->sched_next = sched_next;
|
||||
|
||||
thr->prev = NULL;
|
||||
thr->next = NULL;
|
||||
thr->sched_prev = NULL;
|
||||
thr->sched_next = NULL;
|
||||
|
||||
spin_release_irqrestore(&sched_lock, &irq);
|
||||
if (thr == cpu->thread) {
|
||||
cpu->thread = next;
|
||||
context_switch_to(next, thr);
|
||||
cpu->thread = sched_next;
|
||||
context_switch_to(sched_next, thr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -210,7 +213,7 @@ void sched_debug_cycle(uint64_t delta_ms) {
|
||||
|
||||
struct thread *head = queue_heads[cpu];
|
||||
if (head) {
|
||||
struct thread *tail = head->prev;
|
||||
struct thread *tail = head->sched_prev;
|
||||
|
||||
do {
|
||||
if (head->name[0]) {
|
||||
@@ -226,7 +229,7 @@ void sched_debug_cycle(uint64_t delta_ms) {
|
||||
} else {
|
||||
debugs(DEBUG_DEFAULT, ", ");
|
||||
}
|
||||
head = head->next;
|
||||
head = head->sched_next;
|
||||
} while (1);
|
||||
|
||||
debugs(DEBUG_DEFAULT, "\n");
|
||||
@@ -272,8 +275,8 @@ void yield(void) {
|
||||
struct thread *from = cpu->thread;
|
||||
struct thread *to;
|
||||
|
||||
if (from && from->next) {
|
||||
to = from->next;
|
||||
if (from && from->sched_next) {
|
||||
to = from->sched_next;
|
||||
} else if (queue_heads[cpu->processor_id]) {
|
||||
to = queue_heads[cpu->processor_id];
|
||||
} else {
|
||||
|
||||
@@ -233,3 +233,48 @@ ssize_t sys_readdir(int fd, struct dirent *ent) {
|
||||
return vfs_readdir(&thr->ioctx, thr->fds[fd], ent);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int sys_select(int n, fd_set *inp, fd_set *outp, fd_set *excp, struct timeval *tv) {
|
||||
struct thread *thr = get_cpu()->thread;
|
||||
_assert(thr);
|
||||
|
||||
// Not yet implemented
|
||||
_assert(!outp);
|
||||
_assert(!excp);
|
||||
|
||||
if (!inp) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
fd_set _inp;
|
||||
memcpy(&_inp, inp, sizeof(fd_set));
|
||||
FD_ZERO(inp);
|
||||
|
||||
// Check fds
|
||||
for (int i = 0; i < n; ++i) {
|
||||
if (FD_ISSET(i, &_inp)) {
|
||||
struct ofile *fd = thr->fds[i];
|
||||
|
||||
if (!fd) {
|
||||
return -EBADF;
|
||||
}
|
||||
|
||||
_assert(fd->vnode);
|
||||
if (fd->vnode->type != VN_CHR) {
|
||||
kerror("Tried to select() on non-char device/file: %s\n", fd->vnode->name);
|
||||
return -ENOSYS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t deadline = (uint64_t) -1;
|
||||
if (tv) {
|
||||
deadline = tv->tv_sec * 1000000000ULL + tv->tv_usec * 1000ULL + system_time;
|
||||
}
|
||||
int res;
|
||||
|
||||
panic("NYI\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
+44
-32
@@ -36,7 +36,8 @@ struct sys_fork_frame {
|
||||
|
||||
////
|
||||
|
||||
static struct thread *threads_all_head = NULL;
|
||||
//static struct thread *threads_all_head = NULL;
|
||||
LIST_HEAD(threads_all_head);
|
||||
static pid_t last_kernel_pid = 0;
|
||||
static pid_t last_user_pid = 0;
|
||||
|
||||
@@ -48,32 +49,32 @@ pid_t thread_alloc_pid(int is_user) {
|
||||
}
|
||||
}
|
||||
|
||||
static void thread_add(struct thread *thr) {
|
||||
if (threads_all_head) {
|
||||
threads_all_head->g_prev = thr;
|
||||
}
|
||||
thr->g_next = threads_all_head;
|
||||
thr->g_prev = NULL;
|
||||
threads_all_head = thr;
|
||||
}
|
||||
|
||||
static void thread_remove(struct thread *thr) {
|
||||
struct thread *prev = thr->g_prev;
|
||||
struct thread *next = thr->g_next;
|
||||
|
||||
if (prev) {
|
||||
prev->g_next = next;
|
||||
} else {
|
||||
threads_all_head = next;
|
||||
}
|
||||
|
||||
if (next) {
|
||||
next->g_prev = prev;
|
||||
}
|
||||
|
||||
thr->g_next = NULL;
|
||||
thr->g_prev = NULL;
|
||||
}
|
||||
//static void thread_add(struct thread *thr) {
|
||||
// if (threads_all_head) {
|
||||
// threads_all_head->g_prev = thr;
|
||||
// }
|
||||
// thr->g_next = threads_all_head;
|
||||
// thr->g_prev = NULL;
|
||||
// threads_all_head = thr;
|
||||
//}
|
||||
//
|
||||
//static void thread_remove(struct thread *thr) {
|
||||
// struct thread *prev = thr->g_prev;
|
||||
// struct thread *next = thr->g_next;
|
||||
//
|
||||
// if (prev) {
|
||||
// prev->g_next = next;
|
||||
// } else {
|
||||
// threads_all_head = next;
|
||||
// }
|
||||
//
|
||||
// if (next) {
|
||||
// next->g_prev = prev;
|
||||
// }
|
||||
//
|
||||
// thr->g_next = NULL;
|
||||
// thr->g_prev = NULL;
|
||||
//}
|
||||
|
||||
////
|
||||
|
||||
@@ -103,7 +104,10 @@ void thread_ioctx_fork(struct thread *dst, struct thread *src) {
|
||||
int thread_signal_pgid(pid_t pgid, int signum) {
|
||||
int ret = 0;
|
||||
|
||||
for (struct thread *thr = threads_all_head; thr; thr = thr->g_next) {
|
||||
list_foreach(&threads_all_head, _thr) {
|
||||
struct thread *thr = list_link_value(_thr, struct thread, g_link);
|
||||
_assert(thr);
|
||||
|
||||
if (thr->state != THREAD_STOPPED && thr->pgid == pgid) {
|
||||
thread_signal(thr, signum);
|
||||
++ret;
|
||||
@@ -114,11 +118,15 @@ int thread_signal_pgid(pid_t pgid, int signum) {
|
||||
}
|
||||
|
||||
struct thread *thread_find(pid_t pid) {
|
||||
for (struct thread *thr = threads_all_head; thr; thr = thr->g_next) {
|
||||
list_foreach(&threads_all_head, _thr) {
|
||||
struct thread *thr = list_link_value(_thr, struct thread, g_link);
|
||||
_assert(thr);
|
||||
|
||||
if (thr->pid == pid) {
|
||||
return thr;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -218,6 +226,8 @@ int thread_init(struct thread *thr, uintptr_t entry, void *arg, int user) {
|
||||
thr->name[0] = 0;
|
||||
thr->flags = user ? 0 : THREAD_KERNEL;
|
||||
|
||||
list_link_init(&thr->g_link);
|
||||
|
||||
uint64_t *stack = (uint64_t *) (thr->data.rsp0_base + thr->data.rsp0_size);
|
||||
|
||||
if (user) {
|
||||
@@ -330,7 +340,7 @@ int thread_init(struct thread *thr, uintptr_t entry, void *arg, int user) {
|
||||
thr->pgid = -1;
|
||||
thr->pid = -1;
|
||||
|
||||
thread_add(thr);
|
||||
list_append(&threads_all_head, &thr->g_link);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -347,6 +357,8 @@ int sys_fork(struct sys_fork_frame *frame) {
|
||||
uintptr_t stack_pages = amd64_phys_alloc_contiguous(2);
|
||||
_assert(stack_pages != MM_NADDR);
|
||||
|
||||
list_link_init(&dst->g_link);
|
||||
|
||||
dst->data.rsp0_base = MM_VIRTUALIZE(stack_pages);
|
||||
dst->data.rsp0_size = MM_PAGE_SIZE * 2;
|
||||
dst->data.rsp0_top = dst->data.rsp0_base + dst->data.rsp0_size;
|
||||
@@ -430,7 +442,7 @@ int sys_fork(struct sys_fork_frame *frame) {
|
||||
dst->pgid = src->pgid;
|
||||
dst->sigq = 0;
|
||||
|
||||
thread_add(dst);
|
||||
list_append(&threads_all_head, &dst->g_link);
|
||||
sched_queue(dst);
|
||||
|
||||
return dst->pid;
|
||||
@@ -625,7 +637,7 @@ int sys_waitpid(pid_t pid, int *status) {
|
||||
}
|
||||
|
||||
thread_unchild(chld);
|
||||
thread_remove(chld);
|
||||
list_remove(&threads_all_head, &chld->g_link);
|
||||
thread_free(chld);
|
||||
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user