merge lib for all arch

master
WangRunji 6 years ago
parent 86e1e41645
commit b9d884a0e6

@ -9,9 +9,10 @@ else()
set(ARCH_DIR src/arch/${ARCH}) set(ARCH_DIR src/arch/${ARCH})
endif() endif()
aux_source_directory(src SRCS) aux_source_directory(src SRCS)
aux_source_directory(${ARCH_DIR}/libs LIBS) aux_source_directory(src/libs LIBS)
aux_source_directory(${ARCH_DIR}/ulibs LIBS) aux_source_directory(src/ulibs LIBS)
include_directories(${ARCH_DIR}/libs ${ARCH_DIR}/ulibs) aux_source_directory(${ARCH_DIR} LIBS)
include_directories(src/libs src/ulibs ${ARCH_DIR})
set(EXECUTABLE_OUTPUT_PATH ${ARCH}) set(EXECUTABLE_OUTPUT_PATH ${ARCH})
# Toolchain # Toolchain

@ -1,380 +0,0 @@
#include <string.h>
#include <x86.h>
/* *
* strlen - calculate the length of the string @s, not including
* the terminating '\0' character.
* @s: the input string
*
* The strlen() function returns the length of string @s.
* */
size_t
strlen(const char *s) {
size_t cnt = 0;
while (*s ++ != '\0') {
cnt ++;
}
return cnt;
}
/* *
* strnlen - calculate the length of the string @s, not including
* the terminating '\0' char acter, but at most @len.
* @s: the input string
* @len: the max-length that function will scan
*
* Note that, this function looks only at the first @len characters
* at @s, and never beyond @s + @len.
*
* The return value is strlen(s), if that is less than @len, or
* @len if there is no '\0' character among the first @len characters
* pointed by @s.
* */
size_t
strnlen(const char *s, size_t len) {
size_t cnt = 0;
while (cnt < len && *s ++ != '\0') {
cnt ++;
}
return cnt;
}
/* *
* strcat - appends a copy of the @src string to the @dst string. The terminating null
* character in @dst is overwritten by the first character of @src, and a new null-character
* is appended at the end of the new string formed by the concatenation of both in @dst.
* @dst: pointer to the @dst array, which should be large enough to contain the concatenated
* resulting string.
* @src: string to be appended, this should not overlap @dst
* */
char *
strcat(char *dst, const char *src) {
return strcpy(dst + strlen(dst), src);
}
/* *
* strcpy - copies the string pointed by @src into the array pointed by @dst,
* including the terminating null character.
* @dst: pointer to the destination array where the content is to be copied
* @src: string to be copied
*
* The return value is @dst.
*
* To avoid overflows, the size of array pointed by @dst should be long enough to
* contain the same string as @src (including the terminating null character), and
* should not overlap in memory with @src.
* */
char *
strcpy(char *dst, const char *src) {
#ifdef __HAVE_ARCH_STRCPY
return __strcpy(dst, src);
#else
char *p = dst;
while ((*p ++ = *src ++) != '\0')
/* nothing */;
return dst;
#endif /* __HAVE_ARCH_STRCPY */
}
/* *
* strncpy - copies the first @len characters of @src to @dst. If the end of string @src
* if found before @len characters have been copied, @dst is padded with '\0' until a
* total of @len characters have been written to it.
* @dst: pointer to the destination array where the content is to be copied
* @src: string to be copied
* @len: maximum number of characters to be copied from @src
*
* The return value is @dst
* */
char *
strncpy(char *dst, const char *src, size_t len) {
char *p = dst;
while (len > 0) {
if ((*p = *src) != '\0') {
src ++;
}
p ++, len --;
}
return dst;
}
/* *
* strcmp - compares the string @s1 and @s2
* @s1: string to be compared
* @s2: string to be compared
*
* This function starts comparing the first character of each string. If
* they are equal to each other, it continues with the following pairs until
* the characters differ or until a terminanting null-character is reached.
*
* Returns an integral value indicating the relationship between the strings:
* - A zero value indicates that both strings are equal;
* - A value greater than zero indicates that the first character that does
* not match has a greater value in @s1 than in @s2;
* - And a value less than zero indicates the opposite.
* */
int
strcmp(const char *s1, const char *s2) {
#ifdef __HAVE_ARCH_STRCMP
return __strcmp(s1, s2);
#else
while (*s1 != '\0' && *s1 == *s2) {
s1 ++, s2 ++;
}
return (int)((unsigned char)*s1 - (unsigned char)*s2);
#endif /* __HAVE_ARCH_STRCMP */
}
/* *
* strncmp - compares up to @n characters of the string @s1 to those of the string @s2
* @s1: string to be compared
* @s2: string to be compared
* @n: maximum number of characters to compare
*
* This function starts comparing the first character of each string. If
* they are equal to each other, it continues with the following pairs until
* the characters differ, until a terminating null-character is reached, or
* until @n characters match in both strings, whichever happens first.
* */
int
strncmp(const char *s1, const char *s2, size_t n) {
while (n > 0 && *s1 != '\0' && *s1 == *s2) {
n --, s1 ++, s2 ++;
}
return (n == 0) ? 0 : (int)((unsigned char)*s1 - (unsigned char)*s2);
}
/* *
* strchr - locates first occurrence of character in string
* @s: the input string
* @c: character to be located
*
* The strchr() function returns a pointer to the first occurrence of
* character in @s. If the value is not found, the function returns 'NULL'.
* */
char *
strchr(const char *s, char c) {
while (*s != '\0') {
if (*s == c) {
return (char *)s;
}
s ++;
}
return NULL;
}
/* *
* strfind - locates first occurrence of character in string
* @s: the input string
* @c: character to be located
*
* The strfind() function is like strchr() except that if @c is
* not found in @s, then it returns a pointer to the null byte at the
* end of @s, rather than 'NULL'.
* */
char *
strfind(const char *s, char c) {
while (*s != '\0') {
if (*s == c) {
break;
}
s ++;
}
return (char *)s;
}
/* *
* strtol - converts string to long integer
* @s: the input string that contains the representation of an integer number
* @endptr: reference to an object of type char *, whose value is set by the
* function to the next character in @s after the numerical value. This
* parameter can also be a null pointer, in which case it is not used.
* @base: x
*
* The function first discards as many whitespace characters as necessary until
* the first non-whitespace character is found. Then, starting from this character,
* takes as many characters as possible that are valid following a syntax that
* depends on the base parameter, and interprets them as a numerical value. Finally,
* a pointer to the first character following the integer representation in @s
* is stored in the object pointed by @endptr.
*
* If the value of base is zero, the syntax expected is similar to that of
* integer constants, which is formed by a succession of:
* - An optional plus or minus sign;
* - An optional prefix indicating octal or hexadecimal base ("0" or "0x" respectively)
* - A sequence of decimal digits (if no base prefix was specified) or either octal
* or hexadecimal digits if a specific prefix is present
*
* If the base value is between 2 and 36, the format expected for the integral number
* is a succession of the valid digits and/or letters needed to represent integers of
* the specified radix (starting from '0' and up to 'z'/'Z' for radix 36). The
* sequence may optionally be preceded by a plus or minus sign and, if base is 16,
* an optional "0x" or "0X" prefix.
*
* The strtol() function returns the converted integral number as a long int value.
* */
long
strtol(const char *s, char **endptr, int base) {
int neg = 0;
long val = 0;
// gobble initial whitespace
while (*s == ' ' || *s == '\t') {
s ++;
}
// plus/minus sign
if (*s == '+') {
s ++;
}
else if (*s == '-') {
s ++, neg = 1;
}
// hex or octal base prefix
if ((base == 0 || base == 16) && (s[0] == '0' && s[1] == 'x')) {
s += 2, base = 16;
}
else if (base == 0 && s[0] == '0') {
s ++, base = 8;
}
else if (base == 0) {
base = 10;
}
// digits
while (1) {
int dig;
if (*s >= '0' && *s <= '9') {
dig = *s - '0';
}
else if (*s >= 'a' && *s <= 'z') {
dig = *s - 'a' + 10;
}
else if (*s >= 'A' && *s <= 'Z') {
dig = *s - 'A' + 10;
}
else {
break;
}
if (dig >= base) {
break;
}
s ++, val = (val * base) + dig;
// we don't properly detect overflow!
}
if (endptr) {
*endptr = (char *) s;
}
return (neg ? -val : val);
}
/* *
* memset - sets the first @n bytes of the memory area pointed by @s
* to the specified value @c.
* @s: pointer the the memory area to fill
* @c: value to set
* @n: number of bytes to be set to the value
*
* The memset() function returns @s.
* */
void *
memset(void *s, char c, size_t n) {
#ifdef __HAVE_ARCH_MEMSET
return __memset(s, c, n);
#else
char *p = s;
while (n -- > 0) {
*p ++ = c;
}
return s;
#endif /* __HAVE_ARCH_MEMSET */
}
/* *
* memmove - copies the values of @n bytes from the location pointed by @src to
* the memory area pointed by @dst. @src and @dst are allowed to overlap.
* @dst pointer to the destination array where the content is to be copied
* @src pointer to the source of data to by copied
* @n: number of bytes to copy
*
* The memmove() function returns @dst.
* */
void *
memmove(void *dst, const void *src, size_t n) {
#ifdef __HAVE_ARCH_MEMMOVE
return __memmove(dst, src, n);
#else
const char *s = src;
char *d = dst;
if (s < d && s + n > d) {
s += n, d += n;
while (n -- > 0) {
*-- d = *-- s;
}
} else {
while (n -- > 0) {
*d ++ = *s ++;
}
}
return dst;
#endif /* __HAVE_ARCH_MEMMOVE */
}
/* *
* memcpy - copies the value of @n bytes from the location pointed by @src to
* the memory area pointed by @dst.
* @dst pointer to the destination array where the content is to be copied
* @src pointer to the source of data to by copied
* @n: number of bytes to copy
*
* The memcpy() returns @dst.
*
* Note that, the function does not check any terminating null character in @src,
* it always copies exactly @n bytes. To avoid overflows, the size of arrays pointed
* by both @src and @dst, should be at least @n bytes, and should not overlap
* (for overlapping memory area, memmove is a safer approach).
* */
void *
memcpy(void *dst, const void *src, size_t n) {
#ifdef __HAVE_ARCH_MEMCPY
return __memcpy(dst, src, n);
#else
const char *s = src;
char *d = dst;
while (n -- > 0) {
*d ++ = *s ++;
}
return dst;
#endif /* __HAVE_ARCH_MEMCPY */
}
/* *
* memcmp - compares two blocks of memory
* @v1: pointer to block of memory
* @v2: pointer to block of memory
* @n: number of bytes to compare
*
* The memcmp() functions returns an integral value indicating the
* relationship between the content of the memory blocks:
* - A zero value indicates that the contents of both memory blocks are equal;
* - A value greater than zero indicates that the first byte that does not
* match in both memory blocks has a greater value in @v1 than in @v2
* as if evaluated as unsigned char values;
* - And a value less than zero indicates the opposite.
* */
int
memcmp(const void *v1, const void *v2, size_t n) {
const char *s1 = (const char *)v1;
const char *s2 = (const char *)v2;
while (n -- > 0) {
if (*s1 != *s2) {
return (int)((unsigned char)*s1 - (unsigned char)*s2);
}
s1 ++, s2 ++;
}
return 0;
}

@ -1,46 +0,0 @@
#include <defs.h>
#include <string.h>
#include "syscall.h"
#include <stat.h>
#include <dirent.h>
#include "file.h"
#include "dir.h"
#include <error.h>
#include <unistd.h>
DIR dir, *dirp=&dir;
DIR *
opendir(const char *path) {
if ((dirp->fd = open(path, O_RDONLY)) < 0) {
goto failed;
}
struct stat __stat, *stat = &__stat;
if (fstat(dirp->fd, stat) != 0 || !S_ISDIR(stat->st_mode)) {
goto failed;
}
dirp->dirent.offset = 0;
return dirp;
failed:
return NULL;
}
struct dirent *
readdir(DIR *dirp) {
if (sys_getdirentry(dirp->fd, &(dirp->dirent)) == 0) {
return &(dirp->dirent);
}
return NULL;
}
void
closedir(DIR *dirp) {
close(dirp->fd);
}
int
getcwd(char *buffer, size_t len) {
return sys_getcwd(buffer, len);
}

@ -1,68 +0,0 @@
#include <defs.h>
#include <string.h>
#include "syscall.h"
#include <stdio.h>
#include <stat.h>
#include <error.h>
#include <unistd.h>
int
open(const char *path, uint32_t open_flags) {
return sys_open(path, open_flags);
}
int
close(int fd) {
return sys_close(fd);
}
int
read(int fd, void *base, size_t len) {
return sys_read(fd, base, len);
}
int
write(int fd, void *base, size_t len) {
return sys_write(fd, base, len);
}
int
seek(int fd, off_t pos, int whence) {
return sys_seek(fd, pos, whence);
}
int
fstat(int fd, struct stat *stat) {
return sys_fstat(fd, stat);
}
int
fsync(int fd) {
return sys_fsync(fd);
}
int
dup2(int fd1, int fd2) {
return sys_dup(fd1, fd2);
}
static char
transmode(struct stat *stat) {
uint32_t mode = stat->st_mode;
if (S_ISREG(mode)) return 'r';
if (S_ISDIR(mode)) return 'd';
if (S_ISLNK(mode)) return 'l';
if (S_ISCHR(mode)) return 'c';
if (S_ISBLK(mode)) return 'b';
return '-';
}
void
print_stat(const char *name, int fd, struct stat *stat) {
cprintf("[%03d] %s\n", fd, name);
cprintf(" mode : %c\n", transmode(stat));
cprintf(" links : %lu\n", stat->st_nlinks);
cprintf(" blocks : %lu\n", stat->st_blocks);
cprintf(" size : %lu\n", stat->st_size);
}

@ -1,42 +0,0 @@
#ifndef __USER_LIBS_LOCK_H__
#define __USER_LIBS_LOCK_H__
#include <defs.h>
#include <atomic.h>
#include "ulib.h"
#define INIT_LOCK {0}
typedef volatile bool lock_t;
static inline void
lock_init(lock_t *l) {
*l = 0;
}
static inline bool
try_lock(lock_t *l) {
return test_and_set_bit(0, l);
}
static inline void
lock(lock_t *l) {
if (try_lock(l)) {
int step = 0;
do {
yield();
if (++ step == 100) {
step = 0;
sleep(10);
}
} while (try_lock(l));
}
}
static inline void
unlock(lock_t *l) {
test_and_clear_bit(0, l);
}
#endif /* !__USER_LIBS_LOCK_H__ */

@ -1,28 +0,0 @@
#include <defs.h>
#include <stdarg.h>
#include <stdio.h>
#include "ulib.h"
#include <error.h>
void
__panic(const char *file, int line, const char *fmt, ...) {
// print the 'message'
va_list ap;
va_start(ap, fmt);
cprintf("user panic at %s:%d:\n ", file, line);
vcprintf(fmt, ap);
cprintf("\n");
va_end(ap);
exit(-E_PANIC);
}
void
__warn(const char *file, int line, const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
cprintf("user warning at %s:%d:\n ", file, line);
vcprintf(fmt, ap);
cprintf("\n");
va_end(ap);
}

@ -1,89 +0,0 @@
#include <defs.h>
#include <stdio.h>
#include "syscall.h"
#include "file.h"
#include "ulib.h"
#include <unistd.h>
/* *
* cputch - writes a single character @c to stdout, and it will
* increace the value of counter pointed by @cnt.
* */
static void
cputch(int c, int *cnt) {
sys_putc(c);
(*cnt) ++;
}
/* *
* vcprintf - format a string and writes it to stdout
*
* The return value is the number of characters which would be
* written to stdout.
*
* Call this function if you are already dealing with a va_list.
* Or you probably want cprintf() instead.
* */
int
vcprintf(const char *fmt, va_list ap) {
int cnt = 0;
vprintfmt((void*)cputch, NO_FD, &cnt, fmt, ap);
return cnt;
}
/* *
* cprintf - formats a string and writes it to stdout
*
* The return value is the number of characters which would be
* written to stdout.
* */
int
cprintf(const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
int cnt = vcprintf(fmt, ap);
va_end(ap);
return cnt;
}
/* *
* cputs- writes the string pointed by @str to stdout and
* appends a newline character.
* */
int
cputs(const char *str) {
int cnt = 0;
char c;
while ((c = *str ++) != '\0') {
cputch(c, &cnt);
}
cputch('\n', &cnt);
return cnt;
}
static void
fputch(char c, int *cnt, int fd) {
write(fd, &c, sizeof(char));
(*cnt) ++;
}
int
vfprintf(int fd, const char *fmt, va_list ap) {
int cnt = 0;
vprintfmt((void*)fputch, fd, &cnt, fmt, ap);
return cnt;
}
int
fprintf(int fd, const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
int cnt = vfprintf(fd, fmt, ap);
va_end(ap);
return cnt;
}

@ -1,145 +0,0 @@
#include <defs.h>
#include <unistd.h>
#include <stdarg.h>
#include "syscall.h"
#include <stat.h>
#include <dirent.h>
#define MAX_ARGS 5
static inline int
syscall(int num, ...) {
va_list ap;
va_start(ap, num);
uint32_t a[MAX_ARGS];
int i, ret;
for (i = 0; i < MAX_ARGS; i ++) {
a[i] = va_arg(ap, uint32_t);
}
va_end(ap);
asm volatile (
"int %1;"
: "=a" (ret)
: "i" (T_SYSCALL),
"a" (num),
"d" (a[0]),
"c" (a[1]),
"b" (a[2]),
"D" (a[3]),
"S" (a[4])
: "cc", "memory");
return ret;
}
int
sys_exit(int error_code) {
return syscall(SYS_exit, error_code);
}
int
sys_fork(void) {
return syscall(SYS_fork);
}
int
sys_wait(int pid, int *store) {
return syscall(SYS_wait, pid, store);
}
int
sys_yield(void) {
return syscall(SYS_yield);
}
int
sys_kill(int pid) {
return syscall(SYS_kill, pid);
}
int
sys_getpid(void) {
return syscall(SYS_getpid);
}
int
sys_putc(int c) {
return syscall(SYS_putc, c);
}
int
sys_pgdir(void) {
return syscall(SYS_pgdir);
}
void
sys_lab6_set_priority(uint32_t priority)
{
syscall(SYS_lab6_set_priority, priority);
}
int
sys_sleep(unsigned int time) {
return syscall(SYS_sleep, time);
}
size_t
sys_gettime(void) {
return syscall(SYS_gettime);
}
int
sys_exec(const char *name, int argc, const char **argv) {
return syscall(SYS_exec, name, argc, argv);
}
int
sys_open(const char *path, uint32_t open_flags) {
return syscall(SYS_open, path, open_flags);
}
int
sys_close(int fd) {
return syscall(SYS_close, fd);
}
int
sys_read(int fd, void *base, size_t len) {
return syscall(SYS_read, fd, base, len);
}
int
sys_write(int fd, void *base, size_t len) {
return syscall(SYS_write, fd, base, len);
}
int
sys_seek(int fd, off_t pos, int whence) {
return syscall(SYS_seek, fd, pos, whence);
}
int
sys_fstat(int fd, struct stat *stat) {
return syscall(SYS_fstat, fd, stat);
}
int
sys_fsync(int fd) {
return syscall(SYS_fsync, fd);
}
int
sys_getcwd(char *buffer, size_t len) {
return syscall(SYS_getcwd, buffer, len);
}
int
sys_getdirentry(int fd, struct dirent *dirent) {
return syscall(SYS_getdirentry, fd, dirent);
}
int
sys_dup(int fd1, int fd2) {
return syscall(SYS_dup, fd1, fd2);
}

@ -1,33 +0,0 @@
#ifndef __USER_LIBS_SYSCALL_H__
#define __USER_LIBS_SYSCALL_H__
int sys_exit(int error_code);
int sys_fork(void);
int sys_wait(int pid, int *store);
int sys_exec(const char *name, int argc, const char **argv);
int sys_yield(void);
int sys_kill(int pid);
int sys_getpid(void);
int sys_putc(int c);
int sys_pgdir(void);
int sys_sleep(unsigned int time);
size_t sys_gettime(void);
struct stat;
struct dirent;
int sys_open(const char *path, uint32_t open_flags);
int sys_close(int fd);
int sys_read(int fd, void *base, size_t len);
int sys_write(int fd, void *base, size_t len);
int sys_seek(int fd, off_t pos, int whence);
int sys_fstat(int fd, struct stat *stat);
int sys_fsync(int fd);
int sys_getcwd(char *buffer, size_t len);
int sys_getdirentry(int fd, struct dirent *dirent);
int sys_dup(int fd1, int fd2);
void sys_lab6_set_priority(uint32_t priority); //only for lab6
#endif /* !__USER_LIBS_SYSCALL_H__ */

@ -1,87 +0,0 @@
#include <defs.h>
#include "syscall.h"
#include <stdio.h>
#include "ulib.h"
#include <stat.h>
#include <string.h>
#include "lock.h"
static lock_t fork_lock = INIT_LOCK;
void
lock_fork(void) {
lock(&fork_lock);
}
void
unlock_fork(void) {
unlock(&fork_lock);
}
void
exit(int error_code) {
sys_exit(error_code);
cprintf("BUG: exit failed.\n");
while (1);
}
int
fork(void) {
return sys_fork();
}
int
wait(void) {
return sys_wait(0, NULL);
}
int
waitpid(int pid, int *store) {
return sys_wait(pid, store);
}
void
yield(void) {
sys_yield();
}
int
kill(int pid) {
return sys_kill(pid);
}
int
getpid(void) {
return sys_getpid();
}
//print_pgdir - print the PDT&PT
void
print_pgdir(void) {
sys_pgdir();
}
void
lab6_set_priority(uint32_t priority)
{
sys_lab6_set_priority(priority);
}
int
sleep(unsigned int time) {
return sys_sleep(time);
}
unsigned int
gettime_msec(void) {
return (unsigned int)sys_gettime();
}
int
__exec(const char *name, const char **argv) {
int argc = 0;
while (argv[argc] != NULL) {
argc ++;
}
return sys_exec(name, argc, argv);
}

@ -1,34 +0,0 @@
#include "ulib.h"
#include <unistd.h>
#include "file.h"
#include <stat.h>
int main(int argc, char *argv[]);
static int
initfd(int fd2, const char *path, uint32_t open_flags) {
int fd1, ret;
if ((fd1 = open(path, open_flags)) < 0) {
return fd1;
}
if (fd1 != fd2) {
close(fd2);
ret = dup2(fd1, fd2);
close(fd1);
}
return ret;
}
void
umain(int argc, char *argv[]) {
int fd;
if ((fd = initfd(0, "stdin:", O_RDONLY)) < 0) {
warn("open <stdin> failed: %e.\n", fd);
}
if ((fd = initfd(1, "stdout:", O_WRONLY)) < 0) {
warn("open <stdout> failed: %e.\n", fd);
}
int ret = main(argc, argv);
exit(ret);
}

@ -1,5 +1,3 @@
#include <riscv.h>
.text .text
.globl _start .globl _start
_start: _start:

@ -1,359 +0,0 @@
#include <defs.h>
#include <riscv.h>
#include <error.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
/* *
* Space or zero padding and a field width are supported for the numeric
* formats only.
*
* The special format %e takes an integer error code
* and prints a string describing the error.
* The integer may be positive or negative,
* so that -E_NO_MEM and E_NO_MEM are equivalent.
* */
static const char * const error_string[MAXERROR + 1] = {
[0] NULL,
[E_UNSPECIFIED] "unspecified error",
[E_BAD_PROC] "bad process",
[E_INVAL] "invalid parameter",
[E_NO_MEM] "out of memory",
[E_NO_FREE_PROC] "out of processes",
[E_FAULT] "segmentation fault",
[E_INVAL_ELF] "invalid elf file",
[E_KILLED] "process is killed",
[E_PANIC] "panic failure",
[E_NO_DEV] "no such device",
[E_NA_DEV] "device not available",
[E_BUSY] "device/file is busy",
[E_NOENT] "no such file or directory",
[E_ISDIR] "is a directory",
[E_NOTDIR] "not a directory",
[E_XDEV] "cross device link",
[E_UNIMP] "unimplemented feature",
[E_SEEK] "illegal seek",
[E_MAX_OPEN] "too many files are open",
[E_EXISTS] "file or directory already exists",
[E_NOTEMPTY] "directory is not empty",
};
/* *
* printnum - print a number (base <= 16) in reverse order
* @putch: specified putch function, print a single character
* @fd: file descriptor
* @putdat: used by @putch function
* @num: the number will be printed
* @base: base for print, must be in [1, 16]
* @width: maximum number of digits, if the actual width is less than @width, use @padc instead
* @padc: character that padded on the left if the actual width is less than @width
* */
static void
printnum(void (*putch)(int, void*, int), int fd, void *putdat,
unsigned long long num, unsigned base, int width, int padc) {
unsigned long long result = num;
unsigned mod = do_div(result, base);
// first recursively print all preceding (more significant) digits
if (num >= base) {
printnum(putch, fd, putdat, result, base, width - 1, padc);
} else {
// print any needed pad characters before first digit
while (-- width > 0)
putch(padc, putdat, fd);
}
// then print this (the least significant) digit
putch("0123456789abcdef"[mod], putdat, fd);
}
/* *
* getuint - get an unsigned int of various possible sizes from a varargs list
* @ap: a varargs list pointer
* @lflag: determines the size of the vararg that @ap points to
* */
static unsigned long long
getuint(va_list *ap, int lflag) {
if (lflag >= 2) {
return va_arg(*ap, unsigned long long);
}
else if (lflag) {
return va_arg(*ap, unsigned long);
}
else {
return va_arg(*ap, unsigned int);
}
}
/* *
* getint - same as getuint but signed, we can't use getuint because of sign extension
* @ap: a varargs list pointer
* @lflag: determines the size of the vararg that @ap points to
* */
static long long
getint(va_list *ap, int lflag) {
if (lflag >= 2) {
return va_arg(*ap, long long);
}
else if (lflag) {
return va_arg(*ap, long);
}
else {
return va_arg(*ap, int);
}
}
/* *
* printfmt - format a string and print it by using putch
* @putch: specified putch function, print a single character
* @fd: file descriptor
* @putdat: used by @putch function
* @fmt: the format string to use
* */
void
printfmt(void (*putch)(int, void*, int), int fd, void *putdat, const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
vprintfmt(putch, fd, putdat, fmt, ap);
va_end(ap);
}
/* *
* vprintfmt - format a string and print it by using putch, it's called with a va_list
* instead of a variable number of arguments
* @fd: file descriptor
* @putch: specified putch function, print a single character
* @putdat: used by @putch function
* @fmt: the format string to use
* @ap: arguments for the format string
*
* Call this function if you are already dealing with a va_list.
* Or you probably want printfmt() instead.
* */
void
vprintfmt(void (*putch)(int, void*, int), int fd, void *putdat, const char *fmt, va_list ap) {
register const char *p;
register int ch, err;
unsigned long long num;
int base, width, precision, lflag, altflag;
while (1) {
while ((ch = *(unsigned char *)fmt ++) != '%') {
if (ch == '\0') {
return;
}
putch(ch, putdat, fd);
}
// Process a %-escape sequence
char padc = ' ';
width = precision = -1;
lflag = altflag = 0;
reswitch:
switch (ch = *(unsigned char *)fmt ++) {
// flag to pad on the right
case '-':
padc = '-';
goto reswitch;
// flag to pad with 0's instead of spaces
case '0':
padc = '0';
goto reswitch;
// width field
case '1' ... '9':
for (precision = 0; ; ++ fmt) {
precision = precision * 10 + ch - '0';
ch = *fmt;
if (ch < '0' || ch > '9') {
break;
}
}
goto process_precision;
case '*':
precision = va_arg(ap, int);
goto process_precision;
case '.':
if (width < 0)
width = 0;
goto reswitch;
case '#':
altflag = 1;
goto reswitch;
process_precision:
if (width < 0)
width = precision, precision = -1;
goto reswitch;
// long flag (doubled for long long)
case 'l':
lflag ++;
goto reswitch;
// character
case 'c':
putch(va_arg(ap, int), putdat, fd);
break;
// error message
case 'e':
err = va_arg(ap, int);
if (err < 0) {
err = -err;
}
if (err > MAXERROR || (p = error_string[err]) == NULL) {
printfmt(putch, fd, putdat, "error %d", err);
}
else {
printfmt(putch, fd, putdat, "%s", p);
}
break;
// string
case 's':
if ((p = va_arg(ap, char *)) == NULL) {
p = "(null)";
}
if (width > 0 && padc != '-') {
for (width -= strnlen(p, precision); width > 0; width --) {
putch(padc, putdat, fd);
}
}
for (; (ch = *p ++) != '\0' && (precision < 0 || -- precision >= 0); width --) {
if (altflag && (ch < ' ' || ch > '~')) {
putch('?', putdat, fd);
}
else {
putch(ch, putdat, fd);
}
}
for (; width > 0; width --) {
putch(' ', putdat, fd);
}
break;
// (signed) decimal
case 'd':
num = getint(&ap, lflag);
if ((long long)num < 0) {
putch('-', putdat, fd);
num = -(long long)num;
}
base = 10;
goto number;
// unsigned decimal
case 'u':
num = getuint(&ap, lflag);
base = 10;
goto number;
// (unsigned) octal
case 'o':
num = getuint(&ap, lflag);
base = 8;
goto number;
// pointer
case 'p':
putch('0', putdat, fd);
putch('x', putdat, fd);
num = (unsigned long long)(uintptr_t)va_arg(ap, void *);
base = 16;
goto number;
// (unsigned) hexadecimal
case 'x':
num = getuint(&ap, lflag);
base = 16;
number:
printnum(putch, fd, putdat, num, base, width, padc);
break;
// escaped '%' character
case '%':
putch(ch, putdat, fd);
break;
// unrecognized escape sequence - just print it literally
default:
putch('%', putdat, fd);
for (fmt --; fmt[-1] != '%'; fmt --)
/* do nothing */;
break;
}
}
}
/* sprintbuf is used to save enough information of a buffer */
struct sprintbuf {
char *buf; // address pointer points to the first unused memory
char *ebuf; // points the end of the buffer
int cnt; // the number of characters that have been placed in this buffer
};
/* *
* sprintputch - 'print' a single character in a buffer
* @ch: the character will be printed
* @b: the buffer to place the character @ch
* */
static void
sprintputch(int ch, struct sprintbuf *b) {
b->cnt ++;
if (b->buf < b->ebuf) {
*b->buf ++ = ch;
}
}
/* *
* snprintf - format a string and place it in a buffer
* @str: the buffer to place the result into
* @size: the size of buffer, including the trailing null space
* @fmt: the format string to use
* */
int
snprintf(char *str, size_t size, const char *fmt, ...) {
va_list ap;
int cnt;
va_start(ap, fmt);
cnt = vsnprintf(str, size, fmt, ap);
va_end(ap);
return cnt;
}
/* *
* vsnprintf - format a string and place it in a buffer, it's called with a va_list
* instead of a variable number of arguments
* @str: the buffer to place the result into
* @size: the size of buffer, including the trailing null space
* @fmt: the format string to use
* @ap: arguments for the format string
*
* The return value is the number of characters which would be generated for the
* given input, excluding the trailing '\0'.
*
* Call this function if you are already dealing with a va_list.
* Or you probably want snprintf() instead.
* */
int
vsnprintf(char *str, size_t size, const char *fmt, va_list ap) {
struct sprintbuf b = {str, str + size - 1, 0};
if (str == NULL || b.buf > b.ebuf) {
return -E_INVAL;
}
// print the string to the buffer
vprintfmt((void*)sprintputch, NO_FD, &b, fmt, ap);
// null terminate the buffer
*b.buf = '\0';
return b.cnt;
}

@ -1,26 +0,0 @@
#include <riscv.h>
#include <stdlib.h>
static unsigned long long next = 1;
/* *
* rand - returns a pseudo-random integer
*
* The rand() function return a value in the range [0, RAND_MAX].
* */
int
rand(void) {
next = (next * 0x5DEECE66DLL + 0xBLL) & ((1LL << 48) - 1);
unsigned long long result = (next >> 12);
return (int)do_div(result, RAND_MAX + 1);
}
/* *
* srand - seed the random number generator with the given number
* @seed: the required seed number
* */
void
srand(unsigned int seed) {
next = seed;
}

@ -1,380 +0,0 @@
#include <string.h>
#include <riscv.h>
/* *
* strlen - calculate the length of the string @s, not including
* the terminating '\0' character.
* @s: the input string
*
* The strlen() function returns the length of string @s.
* */
size_t
strlen(const char *s) {
size_t cnt = 0;
while (*s ++ != '\0') {
cnt ++;
}
return cnt;
}
/* *
* strnlen - calculate the length of the string @s, not including
* the terminating '\0' char acter, but at most @len.
* @s: the input string
* @len: the max-length that function will scan
*
* Note that, this function looks only at the first @len characters
* at @s, and never beyond @s + @len.
*
* The return value is strlen(s), if that is less than @len, or
* @len if there is no '\0' character among the first @len characters
* pointed by @s.
* */
size_t
strnlen(const char *s, size_t len) {
size_t cnt = 0;
while (cnt < len && *s ++ != '\0') {
cnt ++;
}
return cnt;
}
/* *
* strcat - appends a copy of the @src string to the @dst string. The terminating null
* character in @dst is overwritten by the first character of @src, and a new null-character
* is appended at the end of the new string formed by the concatenation of both in @dst.
* @dst: pointer to the @dst array, which should be large enough to contain the concatenated
* resulting string.
* @src: string to be appended, this should not overlap @dst
* */
char *
strcat(char *dst, const char *src) {
return strcpy(dst + strlen(dst), src);
}
/* *
* strcpy - copies the string pointed by @src into the array pointed by @dst,
* including the terminating null character.
* @dst: pointer to the destination array where the content is to be copied
* @src: string to be copied
*
* The return value is @dst.
*
* To avoid overflows, the size of array pointed by @dst should be long enough to
* contain the same string as @src (including the terminating null character), and
* should not overlap in memory with @src.
* */
char *
strcpy(char *dst, const char *src) {
#ifdef __HAVE_ARCH_STRCPY
return __strcpy(dst, src);
#else
char *p = dst;
while ((*p ++ = *src ++) != '\0')
/* nothing */;
return dst;
#endif /* __HAVE_ARCH_STRCPY */
}
/* *
* strncpy - copies the first @len characters of @src to @dst. If the end of string @src
* if found before @len characters have been copied, @dst is padded with '\0' until a
* total of @len characters have been written to it.
* @dst: pointer to the destination array where the content is to be copied
* @src: string to be copied
* @len: maximum number of characters to be copied from @src
*
* The return value is @dst
* */
char *
strncpy(char *dst, const char *src, size_t len) {
char *p = dst;
while (len > 0) {
if ((*p = *src) != '\0') {
src ++;
}
p ++, len --;
}
return dst;
}
/* *
* strcmp - compares the string @s1 and @s2
* @s1: string to be compared
* @s2: string to be compared
*
* This function starts comparing the first character of each string. If
* they are equal to each other, it continues with the following pairs until
* the characters differ or until a terminanting null-character is reached.
*
* Returns an integral value indicating the relationship between the strings:
* - A zero value indicates that both strings are equal;
* - A value greater than zero indicates that the first character that does
* not match has a greater value in @s1 than in @s2;
* - And a value less than zero indicates the opposite.
* */
int
strcmp(const char *s1, const char *s2) {
#ifdef __HAVE_ARCH_STRCMP
return __strcmp(s1, s2);
#else
while (*s1 != '\0' && *s1 == *s2) {
s1 ++, s2 ++;
}
return (int)((unsigned char)*s1 - (unsigned char)*s2);
#endif /* __HAVE_ARCH_STRCMP */
}
/* *
* strncmp - compares up to @n characters of the string @s1 to those of the string @s2
* @s1: string to be compared
* @s2: string to be compared
* @n: maximum number of characters to compare
*
* This function starts comparing the first character of each string. If
* they are equal to each other, it continues with the following pairs until
* the characters differ, until a terminating null-character is reached, or
* until @n characters match in both strings, whichever happens first.
* */
int
strncmp(const char *s1, const char *s2, size_t n) {
while (n > 0 && *s1 != '\0' && *s1 == *s2) {
n --, s1 ++, s2 ++;
}
return (n == 0) ? 0 : (int)((unsigned char)*s1 - (unsigned char)*s2);
}
/* *
* strchr - locates first occurrence of character in string
* @s: the input string
* @c: character to be located
*
* The strchr() function returns a pointer to the first occurrence of
* character in @s. If the value is not found, the function returns 'NULL'.
* */
char *
strchr(const char *s, char c) {
while (*s != '\0') {
if (*s == c) {
return (char *)s;
}
s ++;
}
return NULL;
}
/* *
* strfind - locates first occurrence of character in string
* @s: the input string
* @c: character to be located
*
* The strfind() function is like strchr() except that if @c is
* not found in @s, then it returns a pointer to the null byte at the
* end of @s, rather than 'NULL'.
* */
char *
strfind(const char *s, char c) {
while (*s != '\0') {
if (*s == c) {
break;
}
s ++;
}
return (char *)s;
}
/* *
* strtol - converts string to long integer
* @s: the input string that contains the representation of an integer number
* @endptr: reference to an object of type char *, whose value is set by the
* function to the next character in @s after the numerical value. This
* parameter can also be a null pointer, in which case it is not used.
* @base: x
*
* The function first discards as many whitespace characters as necessary until
* the first non-whitespace character is found. Then, starting from this character,
* takes as many characters as possible that are valid following a syntax that
* depends on the base parameter, and interprets them as a numerical value. Finally,
* a pointer to the first character following the integer representation in @s
* is stored in the object pointed by @endptr.
*
* If the value of base is zero, the syntax expected is similar to that of
* integer constants, which is formed by a succession of:
* - An optional plus or minus sign;
* - An optional prefix indicating octal or hexadecimal base ("0" or "0x" respectively)
* - A sequence of decimal digits (if no base prefix was specified) or either octal
* or hexadecimal digits if a specific prefix is present
*
* If the base value is between 2 and 36, the format expected for the integral number
* is a succession of the valid digits and/or letters needed to represent integers of
* the specified radix (starting from '0' and up to 'z'/'Z' for radix 36). The
* sequence may optionally be preceded by a plus or minus sign and, if base is 16,
* an optional "0x" or "0X" prefix.
*
* The strtol() function returns the converted integral number as a long int value.
* */
long
strtol(const char *s, char **endptr, int base) {
int neg = 0;
long val = 0;
// gobble initial whitespace
while (*s == ' ' || *s == '\t') {
s ++;
}
// plus/minus sign
if (*s == '+') {
s ++;
}
else if (*s == '-') {
s ++, neg = 1;
}
// hex or octal base prefix
if ((base == 0 || base == 16) && (s[0] == '0' && s[1] == 'x')) {
s += 2, base = 16;
}
else if (base == 0 && s[0] == '0') {
s ++, base = 8;
}
else if (base == 0) {
base = 10;
}
// digits
while (1) {
int dig;
if (*s >= '0' && *s <= '9') {
dig = *s - '0';
}
else if (*s >= 'a' && *s <= 'z') {
dig = *s - 'a' + 10;
}
else if (*s >= 'A' && *s <= 'Z') {
dig = *s - 'A' + 10;
}
else {
break;
}
if (dig >= base) {
break;
}
s ++, val = (val * base) + dig;
// we don't properly detect overflow!
}
if (endptr) {
*endptr = (char *) s;
}
return (neg ? -val : val);
}
/* *
* memset - sets the first @n bytes of the memory area pointed by @s
* to the specified value @c.
* @s: pointer the the memory area to fill
* @c: value to set
* @n: number of bytes to be set to the value
*
* The memset() function returns @s.
* */
void *
memset(void *s, char c, size_t n) {
#ifdef __HAVE_ARCH_MEMSET
return __memset(s, c, n);
#else
char *p = s;
while (n -- > 0) {
*p ++ = c;
}
return s;
#endif /* __HAVE_ARCH_MEMSET */
}
/* *
* memmove - copies the values of @n bytes from the location pointed by @src to
* the memory area pointed by @dst. @src and @dst are allowed to overlap.
* @dst pointer to the destination array where the content is to be copied
* @src pointer to the source of data to by copied
* @n: number of bytes to copy
*
* The memmove() function returns @dst.
* */
void *
memmove(void *dst, const void *src, size_t n) {
#ifdef __HAVE_ARCH_MEMMOVE
return __memmove(dst, src, n);
#else
const char *s = src;
char *d = dst;
if (s < d && s + n > d) {
s += n, d += n;
while (n -- > 0) {
*-- d = *-- s;
}
} else {
while (n -- > 0) {
*d ++ = *s ++;
}
}
return dst;
#endif /* __HAVE_ARCH_MEMMOVE */
}
/* *
* memcpy - copies the value of @n bytes from the location pointed by @src to
* the memory area pointed by @dst.
* @dst pointer to the destination array where the content is to be copied
* @src pointer to the source of data to by copied
* @n: number of bytes to copy
*
* The memcpy() returns @dst.
*
* Note that, the function does not check any terminating null character in @src,
* it always copies exactly @n bytes. To avoid overflows, the size of arrays pointed
* by both @src and @dst, should be at least @n bytes, and should not overlap
* (for overlapping memory area, memmove is a safer approach).
* */
void *
memcpy(void *dst, const void *src, size_t n) {
#ifdef __HAVE_ARCH_MEMCPY
return __memcpy(dst, src, n);
#else
const char *s = src;
char *d = dst;
while (n -- > 0) {
*d ++ = *s ++;
}
return dst;
#endif /* __HAVE_ARCH_MEMCPY */
}
/* *
* memcmp - compares two blocks of memory
* @v1: pointer to block of memory
* @v2: pointer to block of memory
* @n: number of bytes to compare
*
* The memcmp() functions returns an integral value indicating the
* relationship between the content of the memory blocks:
* - A zero value indicates that the contents of both memory blocks are equal;
* - A value greater than zero indicates that the first byte that does not
* match in both memory blocks has a greater value in @v1 than in @v2
* as if evaluated as unsigned char values;
* - And a value less than zero indicates the opposite.
* */
int
memcmp(const void *v1, const void *v2, size_t n) {
const char *s1 = (const char *)v1;
const char *s2 = (const char *)v2;
while (n -- > 0) {
if (*s1 != *s2) {
return (int)((unsigned char)*s1 - (unsigned char)*s2);
}
s1 ++, s2 ++;
}
return 0;
}

@ -1,152 +0,0 @@
#include <defs.h>
#include <unistd.h>
#include <stdarg.h>
#include <syscall.h>
#include <stat.h>
#include <dirent.h>
#define MAX_ARGS 5
static inline int
syscall(int num, ...) {
va_list ap;
va_start(ap, num);
uint32_t a[MAX_ARGS];
int i, ret;
for (i = 0; i < MAX_ARGS; i ++) {
a[i] = va_arg(ap, uint32_t);
}
va_end(ap);
asm volatile (
"lw a0, %1\n"
"lw a1, %2\n"
"lw a2, %3\n"
"lw a3, %4\n"
"lw a4, %5\n"
"lw a5, %6\n"
"ecall\n"
"sw a0, %0"
: "=m" (ret)
: "m" (num),
"m" (a[0]),
"m" (a[1]),
"m" (a[2]),
"m" (a[3]),
"m" (a[4])
: "memory"
);
return ret;
}
int
sys_exit(int error_code) {
return syscall(SYS_exit, error_code);
}
int
sys_fork(void) {
return syscall(SYS_fork);
}
int
sys_wait(int pid, int *store) {
return syscall(SYS_wait, pid, store);
}
int
sys_yield(void) {
return syscall(SYS_yield);
}
int
sys_kill(int pid) {
return syscall(SYS_kill, pid);
}
int
sys_getpid(void) {
return syscall(SYS_getpid);
}
int
sys_putc(int c) {
return syscall(SYS_putc, c);
}
int
sys_pgdir(void) {
return syscall(SYS_pgdir);
}
void
sys_lab6_set_priority(uint32_t priority)
{
syscall(SYS_lab6_set_priority, priority);
}
int
sys_sleep(unsigned int time) {
return syscall(SYS_sleep, time);
}
int
sys_gettime(void) {
return syscall(SYS_gettime);
}
int
sys_exec(const char *name, int argc, const char **argv) {
return syscall(SYS_exec, name, argc, argv);
}
int
sys_open(const char *path, uint32_t open_flags) {
return syscall(SYS_open, path, open_flags);
}
int
sys_close(int fd) {
return syscall(SYS_close, fd);
}
int
sys_read(int fd, void *base, size_t len) {
return syscall(SYS_read, fd, base, len);
}
int
sys_write(int fd, void *base, size_t len) {
return syscall(SYS_write, fd, base, len);
}
int
sys_seek(int fd, off_t pos, int whence) {
return syscall(SYS_seek, fd, pos, whence);
}
int
sys_fstat(int fd, struct stat *stat) {
return syscall(SYS_fstat, fd, stat);
}
int
sys_fsync(int fd) {
return syscall(SYS_fsync, fd);
}
int
sys_getcwd(char *buffer, size_t len) {
return syscall(SYS_getcwd, buffer, len);
}
int
sys_getdirentry(int fd, struct dirent *dirent) {
return syscall(SYS_getdirentry, fd, dirent);
}
int
sys_dup(int fd1, int fd2) {
return syscall(SYS_dup, fd1, fd2);
}

@ -1,13 +0,0 @@
#ifndef __LIBS_DIRENT_H__
#define __LIBS_DIRENT_H__
#include <defs.h>
#include <unistd.h>
struct dirent {
off_t offset;
char name[FS_MAX_FNAME_LEN + 1];
};
#endif /* !__LIBS_DIRENT_H__ */

@ -1,33 +0,0 @@
#ifndef __LIBS_ERROR_H__
#define __LIBS_ERROR_H__
/* kernel error codes -- keep in sync with list in lib/printfmt.c */
#define E_UNSPECIFIED 1 // Unspecified or unknown problem
#define E_BAD_PROC 2 // Process doesn't exist or otherwise
#define E_INVAL 3 // Invalid parameter
#define E_NO_MEM 4 // Request failed due to memory shortage
#define E_NO_FREE_PROC 5 // Attempt to create a new process beyond
#define E_FAULT 6 // Memory fault
#define E_SWAP_FAULT 7 // SWAP READ/WRITE fault
#define E_INVAL_ELF 8 // Invalid elf file
#define E_KILLED 9 // Process is killed
#define E_PANIC 10 // Panic Failure
#define E_TIMEOUT 11 // Timeout
#define E_TOO_BIG 12 // Argument is Too Big
#define E_NO_DEV 13 // No such Device
#define E_NA_DEV 14 // Device Not Available
#define E_BUSY 15 // Device/File is Busy
#define E_NOENT 16 // No Such File or Directory
#define E_ISDIR 17 // Is a Directory
#define E_NOTDIR 18 // Not a Directory
#define E_XDEV 19 // Cross Device-Link
#define E_UNIMP 20 // Unimplemented Feature
#define E_SEEK 21 // Illegal Seek
#define E_MAX_OPEN 22 // Too Many Files are Open
#define E_EXISTS 23 // File/Directory Already Exists
#define E_NOTEMPTY 24 // Directory is Not Empty
/* the maximum allowed */
#define MAXERROR 24
#endif /* !__LIBS_ERROR_H__ */

@ -1,18 +0,0 @@
#include <stdlib.h>
/* 2^31 + 2^29 - 2^25 + 2^22 - 2^19 - 2^16 + 1 */
#define GOLDEN_RATIO_PRIME_32 0x9e370001UL
/* *
* hash32 - generate a hash value in the range [0, 2^@bits - 1]
* @val: the input value
* @bits: the number of bits in a return value
*
* High bits are more random, so we use them.
* */
uint32_t
hash32(uint32_t val, unsigned int bits) {
uint32_t hash = val * GOLDEN_RATIO_PRIME_32;
return (hash >> (32 - bits));
}

@ -1,163 +0,0 @@
#ifndef __LIBS_LIST_H__
#define __LIBS_LIST_H__
#ifndef __ASSEMBLER__
#include <defs.h>
/* *
* Simple doubly linked list implementation.
*
* Some of the internal functions ("__xxx") are useful when manipulating
* whole lists rather than single entries, as sometimes we already know
* the next/prev entries and we can generate better code by using them
* directly rather than using the generic single-entry routines.
* */
struct list_entry {
struct list_entry *prev, *next;
};
typedef struct list_entry list_entry_t;
static inline void list_init(list_entry_t *elm) __attribute__((always_inline));
static inline void list_add(list_entry_t *listelm, list_entry_t *elm) __attribute__((always_inline));
static inline void list_add_before(list_entry_t *listelm, list_entry_t *elm) __attribute__((always_inline));
static inline void list_add_after(list_entry_t *listelm, list_entry_t *elm) __attribute__((always_inline));
static inline void list_del(list_entry_t *listelm) __attribute__((always_inline));
static inline void list_del_init(list_entry_t *listelm) __attribute__((always_inline));
static inline bool list_empty(list_entry_t *list) __attribute__((always_inline));
static inline list_entry_t *list_next(list_entry_t *listelm) __attribute__((always_inline));
static inline list_entry_t *list_prev(list_entry_t *listelm) __attribute__((always_inline));
static inline void __list_add(list_entry_t *elm, list_entry_t *prev, list_entry_t *next) __attribute__((always_inline));
static inline void __list_del(list_entry_t *prev, list_entry_t *next) __attribute__((always_inline));
/* *
* list_init - initialize a new entry
* @elm: new entry to be initialized
* */
static inline void
list_init(list_entry_t *elm) {
elm->prev = elm->next = elm;
}
/* *
* list_add - add a new entry
* @listelm: list head to add after
* @elm: new entry to be added
*
* Insert the new element @elm *after* the element @listelm which
* is already in the list.
* */
static inline void
list_add(list_entry_t *listelm, list_entry_t *elm) {
list_add_after(listelm, elm);
}
/* *
* list_add_before - add a new entry
* @listelm: list head to add before
* @elm: new entry to be added
*
* Insert the new element @elm *before* the element @listelm which
* is already in the list.
* */
static inline void
list_add_before(list_entry_t *listelm, list_entry_t *elm) {
__list_add(elm, listelm->prev, listelm);
}
/* *
* list_add_after - add a new entry
* @listelm: list head to add after
* @elm: new entry to be added
*
* Insert the new element @elm *after* the element @listelm which
* is already in the list.
* */
static inline void
list_add_after(list_entry_t *listelm, list_entry_t *elm) {
__list_add(elm, listelm, listelm->next);
}
/* *
* list_del - deletes entry from list
* @listelm: the element to delete from the list
*
* Note: list_empty() on @listelm does not return true after this, the entry is
* in an undefined state.
* */
static inline void
list_del(list_entry_t *listelm) {
__list_del(listelm->prev, listelm->next);
}
/* *
* list_del_init - deletes entry from list and reinitialize it.
* @listelm: the element to delete from the list.
*
* Note: list_empty() on @listelm returns true after this.
* */
static inline void
list_del_init(list_entry_t *listelm) {
list_del(listelm);
list_init(listelm);
}
/* *
* list_empty - tests whether a list is empty
* @list: the list to test.
* */
static inline bool
list_empty(list_entry_t *list) {
return list->next == list;
}
/* *
* list_next - get the next entry
* @listelm: the list head
**/
static inline list_entry_t *
list_next(list_entry_t *listelm) {
return listelm->next;
}
/* *
* list_prev - get the previous entry
* @listelm: the list head
**/
static inline list_entry_t *
list_prev(list_entry_t *listelm) {
return listelm->prev;
}
/* *
* Insert a new entry between two known consecutive entries.
*
* This is only for internal list manipulation where we know
* the prev/next entries already!
* */
static inline void
__list_add(list_entry_t *elm, list_entry_t *prev, list_entry_t *next) {
prev->next = next->prev = elm;
elm->next = next;
elm->prev = prev;
}
/* *
* Delete a list entry by making the prev/next entries point to each other.
*
* This is only for internal list manipulation where we know
* the prev/next entries already!
* */
static inline void
__list_del(list_entry_t *prev, list_entry_t *next) {
prev->next = next;
next->prev = prev;
}
#endif /* !__ASSEMBLER__ */
#endif /* !__LIBS_LIST_H__ */

@ -1,87 +0,0 @@
#ifndef __LIBS_SKEW_HEAP_H__
#define __LIBS_SKEW_HEAP_H__
struct skew_heap_entry {
struct skew_heap_entry *parent, *left, *right;
};
typedef struct skew_heap_entry skew_heap_entry_t;
typedef int(*compare_f)(void *a, void *b);
static inline void skew_heap_init(skew_heap_entry_t *a) __attribute__((always_inline));
static inline skew_heap_entry_t *skew_heap_merge(
skew_heap_entry_t *a, skew_heap_entry_t *b,
compare_f comp);
static inline skew_heap_entry_t *skew_heap_insert(
skew_heap_entry_t *a, skew_heap_entry_t *b,
compare_f comp) __attribute__((always_inline));
static inline skew_heap_entry_t *skew_heap_remove(
skew_heap_entry_t *a, skew_heap_entry_t *b,
compare_f comp) __attribute__((always_inline));
static inline void
skew_heap_init(skew_heap_entry_t *a)
{
a->left = a->right = a->parent = NULL;
}
static inline skew_heap_entry_t *
skew_heap_merge(skew_heap_entry_t *a, skew_heap_entry_t *b,
compare_f comp)
{
if (a == NULL) return b;
else if (b == NULL) return a;
skew_heap_entry_t *l, *r;
if (comp(a, b) == -1)
{
r = a->left;
l = skew_heap_merge(a->right, b, comp);
a->left = l;
a->right = r;
if (l) l->parent = a;
return a;
}
else
{
r = b->left;
l = skew_heap_merge(a, b->right, comp);
b->left = l;
b->right = r;
if (l) l->parent = b;
return b;
}
}
static inline skew_heap_entry_t *
skew_heap_insert(skew_heap_entry_t *a, skew_heap_entry_t *b,
compare_f comp)
{
skew_heap_init(b);
return skew_heap_merge(a, b, comp);
}
static inline skew_heap_entry_t *
skew_heap_remove(skew_heap_entry_t *a, skew_heap_entry_t *b,
compare_f comp)
{
skew_heap_entry_t *p = b->parent;
skew_heap_entry_t *rep = skew_heap_merge(b->left, b->right, comp);
if (rep) rep->parent = p;
if (p)
{
if (p->left == b)
p->left = rep;
else p->right = rep;
return a;
}
else return rep;
}
#endif /* !__LIBS_SKEW_HEAP_H__ */

@ -1,27 +0,0 @@
#ifndef __LIBS_STAT_H__
#define __LIBS_STAT_H__
#include <defs.h>
struct stat {
uint32_t st_mode; // protection mode and file type
size_t st_nlinks; // number of hard links
size_t st_blocks; // number of blocks file is using
size_t st_size; // file size (bytes)
};
#define S_IFMT 070000 // mask for type of file
#define S_IFREG 010000 // ordinary regular file
#define S_IFDIR 020000 // directory
#define S_IFLNK 030000 // symbolic link
#define S_IFCHR 040000 // character device
#define S_IFBLK 050000 // block device
#define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) // regular file
#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) // directory
#define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK) // symlink
#define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR) // char device
#define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK) // block device
#endif /* !__LIBS_STAT_H__ */

@ -1,12 +0,0 @@
#ifndef __LIBS_STDARG_H__
#define __LIBS_STDARG_H__
/* compiler provides size of save area */
typedef __builtin_va_list va_list;
#define va_start(ap, last) (__builtin_va_start(ap, last))
#define va_arg(ap, type) (__builtin_va_arg(ap, type))
#define va_end(ap) /*nothing*/
#endif /* !__LIBS_STDARG_H__ */

@ -1,24 +0,0 @@
#ifndef __LIBS_STDIO_H__
#define __LIBS_STDIO_H__
#include <defs.h>
#include <stdarg.h>
/* kern/libs/stdio.c */
int cprintf(const char *fmt, ...);
int vcprintf(const char *fmt, va_list ap);
void cputchar(int c);
int cputs(const char *str);
int getchar(void);
/* kern/libs/readline.c */
char *readline(const char *prompt);
/* libs/printfmt.c */
void printfmt(void (*putch)(int, void *, int), int fd, void *putdat, const char *fmt, ...);
void vprintfmt(void (*putch)(int, void *, int), int fd, void *putdat, const char *fmt, va_list ap);
int snprintf(char *str, size_t size, const char *fmt, ...);
int vsnprintf(char *str, size_t size, const char *fmt, va_list ap);
#endif /* !__LIBS_STDIO_H__ */

@ -1,17 +0,0 @@
#ifndef __LIBS_STDLIB_H__
#define __LIBS_STDLIB_H__
#include <defs.h>
/* the largest number rand will return */
#define RAND_MAX 2147483647UL
/* libs/rand.c */
int rand(void);
void srand(unsigned int seed);
/* libs/hash.c */
uint32_t hash32(uint32_t val, unsigned int bits);
#endif /* !__LIBS_RAND_H__ */

@ -1,28 +0,0 @@
#ifndef __LIBS_STRING_H__
#define __LIBS_STRING_H__
#include <defs.h>
size_t strlen(const char *s);
size_t strnlen(const char *s, size_t len);
char *strcpy(char *dst, const char *src);
char *strncpy(char *dst, const char *src, size_t len);
char *strcat(char *dst, const char *src);
char *strdup(const char *src);
char *stradd(const char *src1, const char *src2);
int strcmp(const char *s1, const char *s2);
int strncmp(const char *s1, const char *s2, size_t n);
char *strchr(const char *s, char c);
char *strfind(const char *s, char c);
long strtol(const char *s, char **endptr, int base);
void *memset(void *s, char c, size_t n);
void *memmove(void *dst, const void *src, size_t n);
void *memcpy(void *dst, const void *src, size_t n);
int memcmp(const void *v1, const void *v2, size_t n);
#endif /* !__LIBS_STRING_H__ */

@ -1,68 +0,0 @@
#ifndef __LIBS_UNISTD_H__
#define __LIBS_UNISTD_H__
#define T_SYSCALL 0x80
/* syscall number */
#define SYS_exit 1
#define SYS_fork 2
#define SYS_wait 3
#define SYS_exec 4
#define SYS_clone 5
#define SYS_yield 10
#define SYS_sleep 11
#define SYS_kill 12
#define SYS_gettime 17
#define SYS_getpid 18
#define SYS_mmap 20
#define SYS_munmap 21
#define SYS_shmem 22
#define SYS_putc 30
#define SYS_pgdir 31
#define SYS_open 100
#define SYS_close 101
#define SYS_read 102
#define SYS_write 103
#define SYS_seek 104
#define SYS_fstat 110
#define SYS_fsync 111
#define SYS_getcwd 121
#define SYS_getdirentry 128
#define SYS_dup 130
/* OLNY FOR LAB6 */
#define SYS_lab6_set_priority 255
/* SYS_fork flags */
#define CLONE_VM 0x00000100 // set if VM shared between processes
#define CLONE_THREAD 0x00000200 // thread group
#define CLONE_FS 0x00000800 // set if shared between processes
/* VFS flags */
// flags for open: choose one of these
#define O_RDONLY 0 // open for reading only
#define O_WRONLY 1 // open for writing only
#define O_RDWR 2 // open for reading and writing
// then or in any of these:
#define O_CREAT 0x00000004 // create file if it does not exist
#define O_EXCL 0x00000008 // error if O_CREAT and the file exists
#define O_TRUNC 0x00000010 // truncate file upon open
#define O_APPEND 0x00000020 // append on each write
// additonal related definition
#define O_ACCMODE 3 // mask for O_RDONLY / O_WRONLY / O_RDWR
#define NO_FD -0x9527 // invalid fd
/* lseek codes */
#define LSEEK_SET 0 // seek relative to beginning of file
#define LSEEK_CUR 1 // seek relative to current position in file
#define LSEEK_END 2 // seek relative to end of file
#define FS_MAX_DNAME_LEN 31
#define FS_MAX_FNAME_LEN 255
#define FS_MAX_FPATH_LEN 4095
#define EXEC_MAX_ARG_NUM 32
#define EXEC_MAX_ARG_LEN 4095
#endif /* !__LIBS_UNISTD_H__ */

@ -1,19 +0,0 @@
#ifndef __USER_LIBS_DIR_H__
#define __USER_LIBS_DIR_H__
#include <defs.h>
#include <dirent.h>
typedef struct {
int fd;
struct dirent dirent;
} DIR;
DIR *opendir(const char *path);
struct dirent *readdir(DIR *dirp);
void closedir(DIR *dirp);
int chdir(const char *path);
int getcwd(char *buffer, size_t len);
#endif /* !__USER_LIBS_DIR_H__ */

@ -1,23 +0,0 @@
#ifndef __USER_LIBS_FILE_H__
#define __USER_LIBS_FILE_H__
#include <defs.h>
struct stat;
int open(const char *path, uint32_t open_flags);
int close(int fd);
int read(int fd, void *base, size_t len);
int write(int fd, void *base, size_t len);
int seek(int fd, off_t pos, int whence);
int fstat(int fd, struct stat *stat);
int fsync(int fd);
int dup(int fd);
int dup2(int fd1, int fd2);
int pipe(int *fd_store);
int mkfifo(const char *name, uint32_t open_flags);
void print_stat(const char *name, int fd, struct stat *stat);
#endif /* !__USER_LIBS_FILE_H__ */

@ -1,49 +0,0 @@
#ifndef __USER_LIBS_ULIB_H__
#define __USER_LIBS_ULIB_H__
#include <defs.h>
void __warn(const char *file, int line, const char *fmt, ...);
void __noreturn __panic(const char *file, int line, const char *fmt, ...);
#define warn(...) \
__warn(__FILE__, __LINE__, __VA_ARGS__)
#define panic(...) \
__panic(__FILE__, __LINE__, __VA_ARGS__)
#define assert(x) \
do { \
if (!(x)) { \
panic("assertion failed: %s", #x); \
} \
} while (0)
// static_assert(x) will generate a compile-time error if 'x' is false.
#define static_assert(x) \
switch (x) { case 0: case (x): ; }
int fprintf(int fd, const char *fmt, ...);
void __noreturn exit(int error_code);
int fork(void);
int wait(void);
int waitpid(int pid, int *store);
void yield(void);
int kill(int pid);
int getpid(void);
void print_pgdir(void);
int sleep(unsigned int time);
unsigned int gettime_msec(void);
int __exec(const char *name, const char **argv);
#define __exec0(name, path, ...) \
({ const char *argv[] = {path, ##__VA_ARGS__, NULL}; __exec(name, argv); })
#define exec(path, ...) __exec0(NULL, path, ##__VA_ARGS__)
#define nexec(name, path, ...) __exec0(name, path, ##__VA_ARGS__)
void lab6_set_priority(uint32_t priority); //only for lab6
#endif /* !__USER_LIBS_ULIB_H__ */

@ -1,82 +0,0 @@
#ifndef __LIBS_ATOMIC_H__
#define __LIBS_ATOMIC_H__
/* Atomic operations that C can't guarantee us. Useful for resource counting etc.. */
static inline void set_bit(int nr, volatile void *addr) __attribute__((always_inline));
static inline void clear_bit(int nr, volatile void *addr) __attribute__((always_inline));
static inline void change_bit(int nr, volatile void *addr) __attribute__((always_inline));
static inline bool test_and_set_bit(int nr, volatile void *addr) __attribute__((always_inline));
static inline bool test_and_clear_bit(int nr, volatile void *addr) __attribute__((always_inline));
static inline bool test_bit(int nr, volatile void *addr) __attribute__((always_inline));
/* *
* set_bit - Atomically set a bit in memory
* @nr: the bit to set
* @addr: the address to start counting from
*
* Note that @nr may be almost arbitrarily large; this function is not
* restricted to acting on a single-word quantity.
* */
static inline void
set_bit(int nr, volatile void *addr) {
asm volatile ("btsl %1, %0" :"=m" (*(volatile long *)addr) : "Ir" (nr));
}
/* *
* clear_bit - Atomically clears a bit in memory
* @nr: the bit to clear
* @addr: the address to start counting from
* */
static inline void
clear_bit(int nr, volatile void *addr) {
asm volatile ("btrl %1, %0" :"=m" (*(volatile long *)addr) : "Ir" (nr));
}
/* *
* change_bit - Atomically toggle a bit in memory
* @nr: the bit to change
* @addr: the address to start counting from
* */
static inline void
change_bit(int nr, volatile void *addr) {
asm volatile ("btcl %1, %0" :"=m" (*(volatile long *)addr) : "Ir" (nr));
}
/* *
* test_bit - Determine whether a bit is set
* @nr: the bit to test
* @addr: the address to count from
* */
static inline bool
test_bit(int nr, volatile void *addr) {
int oldbit;
asm volatile ("btl %2, %1; sbbl %0,%0" : "=r" (oldbit) : "m" (*(volatile long *)addr), "Ir" (nr));
return oldbit != 0;
}
/* *
* test_and_set_bit - Atomically set a bit and return its old value
* @nr: the bit to set
* @addr: the address to count from
* */
static inline bool
test_and_set_bit(int nr, volatile void *addr) {
int oldbit;
asm volatile ("btsl %2, %1; sbbl %0, %0" : "=r" (oldbit), "=m" (*(volatile long *)addr) : "Ir" (nr) : "memory");
return oldbit != 0;
}
/* *
* test_and_clear_bit - Atomically clear a bit and return its old value
* @nr: the bit to clear
* @addr: the address to count from
* */
static inline bool
test_and_clear_bit(int nr, volatile void *addr) {
int oldbit;
asm volatile ("btrl %2, %1; sbbl %0, %0" : "=r" (oldbit), "=m" (*(volatile long *)addr) : "Ir" (nr) : "memory");
return oldbit != 0;
}
#endif /* !__LIBS_ATOMIC_H__ */

@ -1,79 +0,0 @@
#ifndef __LIBS_DEFS_H__
#define __LIBS_DEFS_H__
#ifndef NULL
#define NULL ((void *)0)
#endif
#define __always_inline inline __attribute__((always_inline))
#define __noinline __attribute__((noinline))
#define __noreturn __attribute__((noreturn))
#define CHAR_BIT 8
/* Represents true-or-false values */
typedef int bool;
/* Explicitly-sized versions of integer types */
typedef char int8_t;
typedef unsigned char uint8_t;
typedef short int16_t;
typedef unsigned short uint16_t;
typedef int int32_t;
typedef unsigned int uint32_t;
typedef long long int64_t;
typedef unsigned long long uint64_t;
/* *
* Pointers and addresses are 32 bits long.
* We use pointer types to represent addresses,
* uintptr_t to represent the numerical values of addresses.
* */
typedef int32_t intptr_t;
typedef uint32_t uintptr_t;
/* size_t is used for memory object sizes */
typedef uintptr_t size_t;
/* off_t is used for file offsets and lengths */
typedef intptr_t off_t;
/* used for page numbers */
typedef size_t ppn_t;
/* *
* Rounding operations (efficient when n is a power of 2)
* Round down to the nearest multiple of n
* */
#define ROUNDDOWN(a, n) ({ \
size_t __a = (size_t)(a); \
(typeof(a))(__a - __a % (n)); \
})
/* Round up to the nearest multiple of n */
#define ROUNDUP(a, n) ({ \
size_t __n = (size_t)(n); \
(typeof(a))(ROUNDDOWN((size_t)(a) + __n - 1, __n)); \
})
/* Round up the result of dividing of n */
#define ROUNDUP_DIV(a, n) ({ \
uint32_t __n = (uint32_t)(n); \
(typeof(a))(((a) + __n - 1) / __n); \
})
/* Return the offset of 'member' relative to the beginning of a struct type */
#define offsetof(type, member) \
((size_t)(&((type *)0)->member))
/* *
* to_struct - get the struct from a ptr
* @ptr: a struct pointer of member
* @type: the type of the struct this is embedded in
* @member: the name of the member within the struct
* */
#define to_struct(ptr, type, member) \
((type *)((char *)(ptr) - offsetof(type, member)))
#endif /* !__LIBS_DEFS_H__ */

@ -1,13 +0,0 @@
#ifndef __LIBS_DIRENT_H__
#define __LIBS_DIRENT_H__
#include <defs.h>
#include <unistd.h>
struct dirent {
off_t offset;
char name[FS_MAX_FNAME_LEN + 1];
};
#endif /* !__LIBS_DIRENT_H__ */

@ -1,48 +0,0 @@
#ifndef __LIBS_ELF_H__
#define __LIBS_ELF_H__
#include <defs.h>
#define ELF_MAGIC 0x464C457FU // "\x7FELF" in little endian
/* file header */
struct elfhdr {
uint32_t e_magic; // must equal ELF_MAGIC
uint8_t e_elf[12];
uint16_t e_type; // 1=relocatable, 2=executable, 3=shared object, 4=core image
uint16_t e_machine; // 3=x86, 4=68K, etc.
uint32_t e_version; // file version, always 1
uint32_t e_entry; // entry point if executable
uint32_t e_phoff; // file position of program header or 0
uint32_t e_shoff; // file position of section header or 0
uint32_t e_flags; // architecture-specific flags, usually 0
uint16_t e_ehsize; // size of this elf header
uint16_t e_phentsize; // size of an entry in program header
uint16_t e_phnum; // number of entries in program header or 0
uint16_t e_shentsize; // size of an entry in section header
uint16_t e_shnum; // number of entries in section header or 0
uint16_t e_shstrndx; // section number that contains section name strings
};
/* program section header */
struct proghdr {
uint32_t p_type; // loadable code or data, dynamic linking info,etc.
uint32_t p_offset; // file offset of segment
uint32_t p_va; // virtual address to map segment
uint32_t p_pa; // physical address, not used
uint32_t p_filesz; // size of segment in file
uint32_t p_memsz; // size of segment in memory (bigger if contains bss
uint32_t p_flags; // read/write/execute bits
uint32_t p_align; // required alignment, invariably hardware page size
};
/* values for Proghdr::p_type */
#define ELF_PT_LOAD 1
/* flag bits for Proghdr::p_flags */
#define ELF_PF_X 1
#define ELF_PF_W 2
#define ELF_PF_R 4
#endif /* !__LIBS_ELF_H__ */

@ -1,33 +0,0 @@
#ifndef __LIBS_ERROR_H__
#define __LIBS_ERROR_H__
/* kernel error codes -- keep in sync with list in lib/printfmt.c */
#define E_UNSPECIFIED 1 // Unspecified or unknown problem
#define E_BAD_PROC 2 // Process doesn't exist or otherwise
#define E_INVAL 3 // Invalid parameter
#define E_NO_MEM 4 // Request failed due to memory shortage
#define E_NO_FREE_PROC 5 // Attempt to create a new process beyond
#define E_FAULT 6 // Memory fault
#define E_SWAP_FAULT 7 // SWAP READ/WRITE fault
#define E_INVAL_ELF 8 // Invalid elf file
#define E_KILLED 9 // Process is killed
#define E_PANIC 10 // Panic Failure
#define E_TIMEOUT 11 // Timeout
#define E_TOO_BIG 12 // Argument is Too Big
#define E_NO_DEV 13 // No such Device
#define E_NA_DEV 14 // Device Not Available
#define E_BUSY 15 // Device/File is Busy
#define E_NOENT 16 // No Such File or Directory
#define E_ISDIR 17 // Is a Directory
#define E_NOTDIR 18 // Not a Directory
#define E_XDEV 19 // Cross Device-Link
#define E_UNIMP 20 // Unimplemented Feature
#define E_SEEK 21 // Illegal Seek
#define E_MAX_OPEN 22 // Too Many Files are Open
#define E_EXISTS 23 // File/Directory Already Exists
#define E_NOTEMPTY 24 // Directory is Not Empty
/* the maximum allowed */
#define MAXERROR 24
#endif /* !__LIBS_ERROR_H__ */

@ -1,18 +0,0 @@
#include <stdlib.h>
/* 2^31 + 2^29 - 2^25 + 2^22 - 2^19 - 2^16 + 1 */
#define GOLDEN_RATIO_PRIME_32 0x9e370001UL
/* *
* hash32 - generate a hash value in the range [0, 2^@bits - 1]
* @val: the input value
* @bits: the number of bits in a return value
*
* High bits are more random, so we use them.
* */
uint32_t
hash32(uint32_t val, unsigned int bits) {
uint32_t hash = val * GOLDEN_RATIO_PRIME_32;
return (hash >> (32 - bits));
}

@ -1,163 +0,0 @@
#ifndef __LIBS_LIST_H__
#define __LIBS_LIST_H__
#ifndef __ASSEMBLER__
#include <defs.h>
/* *
* Simple doubly linked list implementation.
*
* Some of the internal functions ("__xxx") are useful when manipulating
* whole lists rather than single entries, as sometimes we already know
* the next/prev entries and we can generate better code by using them
* directly rather than using the generic single-entry routines.
* */
struct list_entry {
struct list_entry *prev, *next;
};
typedef struct list_entry list_entry_t;
static inline void list_init(list_entry_t *elm) __attribute__((always_inline));
static inline void list_add(list_entry_t *listelm, list_entry_t *elm) __attribute__((always_inline));
static inline void list_add_before(list_entry_t *listelm, list_entry_t *elm) __attribute__((always_inline));
static inline void list_add_after(list_entry_t *listelm, list_entry_t *elm) __attribute__((always_inline));
static inline void list_del(list_entry_t *listelm) __attribute__((always_inline));
static inline void list_del_init(list_entry_t *listelm) __attribute__((always_inline));
static inline bool list_empty(list_entry_t *list) __attribute__((always_inline));
static inline list_entry_t *list_next(list_entry_t *listelm) __attribute__((always_inline));
static inline list_entry_t *list_prev(list_entry_t *listelm) __attribute__((always_inline));
static inline void __list_add(list_entry_t *elm, list_entry_t *prev, list_entry_t *next) __attribute__((always_inline));
static inline void __list_del(list_entry_t *prev, list_entry_t *next) __attribute__((always_inline));
/* *
* list_init - initialize a new entry
* @elm: new entry to be initialized
* */
static inline void
list_init(list_entry_t *elm) {
elm->prev = elm->next = elm;
}
/* *
* list_add - add a new entry
* @listelm: list head to add after
* @elm: new entry to be added
*
* Insert the new element @elm *after* the element @listelm which
* is already in the list.
* */
static inline void
list_add(list_entry_t *listelm, list_entry_t *elm) {
list_add_after(listelm, elm);
}
/* *
* list_add_before - add a new entry
* @listelm: list head to add before
* @elm: new entry to be added
*
* Insert the new element @elm *before* the element @listelm which
* is already in the list.
* */
static inline void
list_add_before(list_entry_t *listelm, list_entry_t *elm) {
__list_add(elm, listelm->prev, listelm);
}
/* *
* list_add_after - add a new entry
* @listelm: list head to add after
* @elm: new entry to be added
*
* Insert the new element @elm *after* the element @listelm which
* is already in the list.
* */
static inline void
list_add_after(list_entry_t *listelm, list_entry_t *elm) {
__list_add(elm, listelm, listelm->next);
}
/* *
* list_del - deletes entry from list
* @listelm: the element to delete from the list
*
* Note: list_empty() on @listelm does not return true after this, the entry is
* in an undefined state.
* */
static inline void
list_del(list_entry_t *listelm) {
__list_del(listelm->prev, listelm->next);
}
/* *
* list_del_init - deletes entry from list and reinitialize it.
* @listelm: the element to delete from the list.
*
* Note: list_empty() on @listelm returns true after this.
* */
static inline void
list_del_init(list_entry_t *listelm) {
list_del(listelm);
list_init(listelm);
}
/* *
* list_empty - tests whether a list is empty
* @list: the list to test.
* */
static inline bool
list_empty(list_entry_t *list) {
return list->next == list;
}
/* *
* list_next - get the next entry
* @listelm: the list head
**/
static inline list_entry_t *
list_next(list_entry_t *listelm) {
return listelm->next;
}
/* *
* list_prev - get the previous entry
* @listelm: the list head
**/
static inline list_entry_t *
list_prev(list_entry_t *listelm) {
return listelm->prev;
}
/* *
* Insert a new entry between two known consecutive entries.
*
* This is only for internal list manipulation where we know
* the prev/next entries already!
* */
static inline void
__list_add(list_entry_t *elm, list_entry_t *prev, list_entry_t *next) {
prev->next = next->prev = elm;
elm->next = next;
elm->prev = prev;
}
/* *
* Delete a list entry by making the prev/next entries point to each other.
*
* This is only for internal list manipulation where we know
* the prev/next entries already!
* */
static inline void
__list_del(list_entry_t *prev, list_entry_t *next) {
prev->next = next;
next->prev = prev;
}
#endif /* !__ASSEMBLER__ */
#endif /* !__LIBS_LIST_H__ */

@ -1,359 +0,0 @@
#include <defs.h>
#include <x86.h>
#include <error.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
/* *
* Space or zero padding and a field width are supported for the numeric
* formats only.
*
* The special format %e takes an integer error code
* and prints a string describing the error.
* The integer may be positive or negative,
* so that -E_NO_MEM and E_NO_MEM are equivalent.
* */
static const char * const error_string[MAXERROR + 1] = {
[0] NULL,
[E_UNSPECIFIED] "unspecified error",
[E_BAD_PROC] "bad process",
[E_INVAL] "invalid parameter",
[E_NO_MEM] "out of memory",
[E_NO_FREE_PROC] "out of processes",
[E_FAULT] "segmentation fault",
[E_INVAL_ELF] "invalid elf file",
[E_KILLED] "process is killed",
[E_PANIC] "panic failure",
[E_NO_DEV] "no such device",
[E_NA_DEV] "device not available",
[E_BUSY] "device/file is busy",
[E_NOENT] "no such file or directory",
[E_ISDIR] "is a directory",
[E_NOTDIR] "not a directory",
[E_XDEV] "cross device link",
[E_UNIMP] "unimplemented feature",
[E_SEEK] "illegal seek",
[E_MAX_OPEN] "too many files are open",
[E_EXISTS] "file or directory already exists",
[E_NOTEMPTY] "directory is not empty",
};
/* *
* printnum - print a number (base <= 16) in reverse order
* @putch: specified putch function, print a single character
* @fd: file descriptor
* @putdat: used by @putch function
* @num: the number will be printed
* @base: base for print, must be in [1, 16]
* @width: maximum number of digits, if the actual width is less than @width, use @padc instead
* @padc: character that padded on the left if the actual width is less than @width
* */
static void
printnum(void (*putch)(int, void*, int), int fd, void *putdat,
unsigned long long num, unsigned base, int width, int padc) {
unsigned long long result = num;
unsigned mod = do_div(result, base);
// first recursively print all preceding (more significant) digits
if (num >= base) {
printnum(putch, fd, putdat, result, base, width - 1, padc);
} else {
// print any needed pad characters before first digit
while (-- width > 0)
putch(padc, putdat, fd);
}
// then print this (the least significant) digit
putch("0123456789abcdef"[mod], putdat, fd);
}
/* *
* getuint - get an unsigned int of various possible sizes from a varargs list
* @ap: a varargs list pointer
* @lflag: determines the size of the vararg that @ap points to
* */
static unsigned long long
getuint(va_list *ap, int lflag) {
if (lflag >= 2) {
return va_arg(*ap, unsigned long long);
}
else if (lflag) {
return va_arg(*ap, unsigned long);
}
else {
return va_arg(*ap, unsigned int);
}
}
/* *
* getint - same as getuint but signed, we can't use getuint because of sign extension
* @ap: a varargs list pointer
* @lflag: determines the size of the vararg that @ap points to
* */
static long long
getint(va_list *ap, int lflag) {
if (lflag >= 2) {
return va_arg(*ap, long long);
}
else if (lflag) {
return va_arg(*ap, long);
}
else {
return va_arg(*ap, int);
}
}
/* *
* printfmt - format a string and print it by using putch
* @putch: specified putch function, print a single character
* @fd: file descriptor
* @putdat: used by @putch function
* @fmt: the format string to use
* */
void
printfmt(void (*putch)(int, void*, int), int fd, void *putdat, const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
vprintfmt(putch, fd, putdat, fmt, ap);
va_end(ap);
}
/* *
* vprintfmt - format a string and print it by using putch, it's called with a va_list
* instead of a variable number of arguments
* @fd: file descriptor
* @putch: specified putch function, print a single character
* @putdat: used by @putch function
* @fmt: the format string to use
* @ap: arguments for the format string
*
* Call this function if you are already dealing with a va_list.
* Or you probably want printfmt() instead.
* */
void
vprintfmt(void (*putch)(int, void*, int), int fd, void *putdat, const char *fmt, va_list ap) {
register const char *p;
register int ch, err;
unsigned long long num;
int base, width, precision, lflag, altflag;
while (1) {
while ((ch = *(unsigned char *)fmt ++) != '%') {
if (ch == '\0') {
return;
}
putch(ch, putdat, fd);
}
// Process a %-escape sequence
char padc = ' ';
width = precision = -1;
lflag = altflag = 0;
reswitch:
switch (ch = *(unsigned char *)fmt ++) {
// flag to pad on the right
case '-':
padc = '-';
goto reswitch;
// flag to pad with 0's instead of spaces
case '0':
padc = '0';
goto reswitch;
// width field
case '1' ... '9':
for (precision = 0; ; ++ fmt) {
precision = precision * 10 + ch - '0';
ch = *fmt;
if (ch < '0' || ch > '9') {
break;
}
}
goto process_precision;
case '*':
precision = va_arg(ap, int);
goto process_precision;
case '.':
if (width < 0)
width = 0;
goto reswitch;
case '#':
altflag = 1;
goto reswitch;
process_precision:
if (width < 0)
width = precision, precision = -1;
goto reswitch;
// long flag (doubled for long long)
case 'l':
lflag ++;
goto reswitch;
// character
case 'c':
putch(va_arg(ap, int), putdat, fd);
break;
// error message
case 'e':
err = va_arg(ap, int);
if (err < 0) {
err = -err;
}
if (err > MAXERROR || (p = error_string[err]) == NULL) {
printfmt(putch, fd, putdat, "error %d", err);
}
else {
printfmt(putch, fd, putdat, "%s", p);
}
break;
// string
case 's':
if ((p = va_arg(ap, char *)) == NULL) {
p = "(null)";
}
if (width > 0 && padc != '-') {
for (width -= strnlen(p, precision); width > 0; width --) {
putch(padc, putdat, fd);
}
}
for (; (ch = *p ++) != '\0' && (precision < 0 || -- precision >= 0); width --) {
if (altflag && (ch < ' ' || ch > '~')) {
putch('?', putdat, fd);
}
else {
putch(ch, putdat, fd);
}
}
for (; width > 0; width --) {
putch(' ', putdat, fd);
}
break;
// (signed) decimal
case 'd':
num = getint(&ap, lflag);
if ((long long)num < 0) {
putch('-', putdat, fd);
num = -(long long)num;
}
base = 10;
goto number;
// unsigned decimal
case 'u':
num = getuint(&ap, lflag);
base = 10;
goto number;
// (unsigned) octal
case 'o':
num = getuint(&ap, lflag);
base = 8;
goto number;
// pointer
case 'p':
putch('0', putdat, fd);
putch('x', putdat, fd);
num = (unsigned long long)(uintptr_t)va_arg(ap, void *);
base = 16;
goto number;
// (unsigned) hexadecimal
case 'x':
num = getuint(&ap, lflag);
base = 16;
number:
printnum(putch, fd, putdat, num, base, width, padc);
break;
// escaped '%' character
case '%':
putch(ch, putdat, fd);
break;
// unrecognized escape sequence - just print it literally
default:
putch('%', putdat, fd);
for (fmt --; fmt[-1] != '%'; fmt --)
/* do nothing */;
break;
}
}
}
/* sprintbuf is used to save enough information of a buffer */
struct sprintbuf {
char *buf; // address pointer points to the first unused memory
char *ebuf; // points the end of the buffer
int cnt; // the number of characters that have been placed in this buffer
};
/* *
* sprintputch - 'print' a single character in a buffer
* @ch: the character will be printed
* @b: the buffer to place the character @ch
* */
static void
sprintputch(int ch, struct sprintbuf *b) {
b->cnt ++;
if (b->buf < b->ebuf) {
*b->buf ++ = ch;
}
}
/* *
* snprintf - format a string and place it in a buffer
* @str: the buffer to place the result into
* @size: the size of buffer, including the trailing null space
* @fmt: the format string to use
* */
int
snprintf(char *str, size_t size, const char *fmt, ...) {
va_list ap;
int cnt;
va_start(ap, fmt);
cnt = vsnprintf(str, size, fmt, ap);
va_end(ap);
return cnt;
}
/* *
* vsnprintf - format a string and place it in a buffer, it's called with a va_list
* instead of a variable number of arguments
* @str: the buffer to place the result into
* @size: the size of buffer, including the trailing null space
* @fmt: the format string to use
* @ap: arguments for the format string
*
* The return value is the number of characters which would be generated for the
* given input, excluding the trailing '\0'.
*
* Call this function if you are already dealing with a va_list.
* Or you probably want snprintf() instead.
* */
int
vsnprintf(char *str, size_t size, const char *fmt, va_list ap) {
struct sprintbuf b = {str, str + size - 1, 0};
if (str == NULL || b.buf > b.ebuf) {
return -E_INVAL;
}
// print the string to the buffer
vprintfmt((void*)sprintputch, NO_FD, &b, fmt, ap);
// null terminate the buffer
*b.buf = '\0';
return b.cnt;
}

@ -1,26 +0,0 @@
#include <x86.h>
#include <stdlib.h>
static unsigned long long next = 1;
/* *
* rand - returns a pseudo-random integer
*
* The rand() function return a value in the range [0, RAND_MAX].
* */
int
rand(void) {
next = (next * 0x5DEECE66DLL + 0xBLL) & ((1LL << 48) - 1);
unsigned long long result = (next >> 12);
return (int)do_div(result, RAND_MAX + 1);
}
/* *
* srand - seed the random number generator with the given number
* @seed: the required seed number
* */
void
srand(unsigned int seed) {
next = seed;
}

@ -1,87 +0,0 @@
#ifndef __LIBS_SKEW_HEAP_H__
#define __LIBS_SKEW_HEAP_H__
struct skew_heap_entry {
struct skew_heap_entry *parent, *left, *right;
};
typedef struct skew_heap_entry skew_heap_entry_t;
typedef int(*compare_f)(void *a, void *b);
static inline void skew_heap_init(skew_heap_entry_t *a) __attribute__((always_inline));
static inline skew_heap_entry_t *skew_heap_merge(
skew_heap_entry_t *a, skew_heap_entry_t *b,
compare_f comp);
static inline skew_heap_entry_t *skew_heap_insert(
skew_heap_entry_t *a, skew_heap_entry_t *b,
compare_f comp) __attribute__((always_inline));
static inline skew_heap_entry_t *skew_heap_remove(
skew_heap_entry_t *a, skew_heap_entry_t *b,
compare_f comp) __attribute__((always_inline));
static inline void
skew_heap_init(skew_heap_entry_t *a)
{
a->left = a->right = a->parent = NULL;
}
static inline skew_heap_entry_t *
skew_heap_merge(skew_heap_entry_t *a, skew_heap_entry_t *b,
compare_f comp)
{
if (a == NULL) return b;
else if (b == NULL) return a;
skew_heap_entry_t *l, *r;
if (comp(a, b) == -1)
{
r = a->left;
l = skew_heap_merge(a->right, b, comp);
a->left = l;
a->right = r;
if (l) l->parent = a;
return a;
}
else
{
r = b->left;
l = skew_heap_merge(a, b->right, comp);
b->left = l;
b->right = r;
if (l) l->parent = b;
return b;
}
}
static inline skew_heap_entry_t *
skew_heap_insert(skew_heap_entry_t *a, skew_heap_entry_t *b,
compare_f comp)
{
skew_heap_init(b);
return skew_heap_merge(a, b, comp);
}
static inline skew_heap_entry_t *
skew_heap_remove(skew_heap_entry_t *a, skew_heap_entry_t *b,
compare_f comp)
{
skew_heap_entry_t *p = b->parent;
skew_heap_entry_t *rep = skew_heap_merge(b->left, b->right, comp);
if (rep) rep->parent = p;
if (p)
{
if (p->left == b)
p->left = rep;
else p->right = rep;
return a;
}
else return rep;
}
#endif /* !__LIBS_SKEW_HEAP_H__ */

@ -1,27 +0,0 @@
#ifndef __LIBS_STAT_H__
#define __LIBS_STAT_H__
#include <defs.h>
struct stat {
uint32_t st_mode; // protection mode and file type
size_t st_nlinks; // number of hard links
size_t st_blocks; // number of blocks file is using
size_t st_size; // file size (bytes)
};
#define S_IFMT 070000 // mask for type of file
#define S_IFREG 010000 // ordinary regular file
#define S_IFDIR 020000 // directory
#define S_IFLNK 030000 // symbolic link
#define S_IFCHR 040000 // character device
#define S_IFBLK 050000 // block device
#define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) // regular file
#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) // directory
#define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK) // symlink
#define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR) // char device
#define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK) // block device
#endif /* !__LIBS_STAT_H__ */

@ -1,12 +0,0 @@
#ifndef __LIBS_STDARG_H__
#define __LIBS_STDARG_H__
/* compiler provides size of save area */
typedef __builtin_va_list va_list;
#define va_start(ap, last) (__builtin_va_start(ap, last))
#define va_arg(ap, type) (__builtin_va_arg(ap, type))
#define va_end(ap) /*nothing*/
#endif /* !__LIBS_STDARG_H__ */

@ -1,24 +0,0 @@
#ifndef __LIBS_STDIO_H__
#define __LIBS_STDIO_H__
#include <defs.h>
#include <stdarg.h>
/* kern/libs/stdio.c */
int cprintf(const char *fmt, ...);
int vcprintf(const char *fmt, va_list ap);
void cputchar(int c);
int cputs(const char *str);
int getchar(void);
/* kern/libs/readline.c */
char *readline(const char *prompt);
/* libs/printfmt.c */
void printfmt(void (*putch)(int, void *, int), int fd, void *putdat, const char *fmt, ...);
void vprintfmt(void (*putch)(int, void *, int), int fd, void *putdat, const char *fmt, va_list ap);
int snprintf(char *str, size_t size, const char *fmt, ...);
int vsnprintf(char *str, size_t size, const char *fmt, va_list ap);
#endif /* !__LIBS_STDIO_H__ */

@ -1,17 +0,0 @@
#ifndef __LIBS_STDLIB_H__
#define __LIBS_STDLIB_H__
#include <defs.h>
/* the largest number rand will return */
#define RAND_MAX 2147483647UL
/* libs/rand.c */
int rand(void);
void srand(unsigned int seed);
/* libs/hash.c */
uint32_t hash32(uint32_t val, unsigned int bits);
#endif /* !__LIBS_RAND_H__ */

@ -1,28 +0,0 @@
#ifndef __LIBS_STRING_H__
#define __LIBS_STRING_H__
#include <defs.h>
size_t strlen(const char *s);
size_t strnlen(const char *s, size_t len);
char *strcpy(char *dst, const char *src);
char *strncpy(char *dst, const char *src, size_t len);
char *strcat(char *dst, const char *src);
char *strdup(const char *src);
char *stradd(const char *src1, const char *src2);
int strcmp(const char *s1, const char *s2);
int strncmp(const char *s1, const char *s2, size_t n);
char *strchr(const char *s, char c);
char *strfind(const char *s, char c);
long strtol(const char *s, char **endptr, int base);
void *memset(void *s, char c, size_t n);
void *memmove(void *dst, const void *src, size_t n);
void *memcpy(void *dst, const void *src, size_t n);
int memcmp(const void *v1, const void *v2, size_t n);
#endif /* !__LIBS_STRING_H__ */

@ -1,68 +0,0 @@
#ifndef __LIBS_UNISTD_H__
#define __LIBS_UNISTD_H__
#define T_SYSCALL 0x80
/* syscall number */
#define SYS_exit 1
#define SYS_fork 2
#define SYS_wait 3
#define SYS_exec 4
#define SYS_clone 5
#define SYS_yield 10
#define SYS_sleep 11
#define SYS_kill 12
#define SYS_gettime 17
#define SYS_getpid 18
#define SYS_mmap 20
#define SYS_munmap 21
#define SYS_shmem 22
#define SYS_putc 30
#define SYS_pgdir 31
#define SYS_open 100
#define SYS_close 101
#define SYS_read 102
#define SYS_write 103
#define SYS_seek 104
#define SYS_fstat 110
#define SYS_fsync 111
#define SYS_getcwd 121
#define SYS_getdirentry 128
#define SYS_dup 130
/* OLNY FOR LAB6 */
#define SYS_lab6_set_priority 255
/* SYS_fork flags */
#define CLONE_VM 0x00000100 // set if VM shared between processes
#define CLONE_THREAD 0x00000200 // thread group
#define CLONE_FS 0x00000800 // set if shared between processes
/* VFS flags */
// flags for open: choose one of these
#define O_RDONLY 0 // open for reading only
#define O_WRONLY 1 // open for writing only
#define O_RDWR 2 // open for reading and writing
// then or in any of these:
#define O_CREAT 0x00000004 // create file if it does not exist
#define O_EXCL 0x00000008 // error if O_CREAT and the file exists
#define O_TRUNC 0x00000010 // truncate file upon open
#define O_APPEND 0x00000020 // append on each write
// additonal related definition
#define O_ACCMODE 3 // mask for O_RDONLY / O_WRONLY / O_RDWR
#define NO_FD -0x9527 // invalid fd
/* lseek codes */
#define LSEEK_SET 0 // seek relative to beginning of file
#define LSEEK_CUR 1 // seek relative to current position in file
#define LSEEK_END 2 // seek relative to end of file
#define FS_MAX_DNAME_LEN 31
#define FS_MAX_FNAME_LEN 255
#define FS_MAX_FPATH_LEN 4095
#define EXEC_MAX_ARG_NUM 32
#define EXEC_MAX_ARG_LEN 4095
#endif /* !__LIBS_UNISTD_H__ */

@ -1,310 +0,0 @@
#ifndef __LIBS_X86_H__
#define __LIBS_X86_H__
#include <defs.h>
#define do_div(n, base) ({ \
unsigned long __upper, __low, __high, __mod, __base; \
__base = (base); \
asm ("" : "=a" (__low), "=d" (__high) : "A" (n)); \
__upper = __high; \
if (__high != 0) { \
__upper = __high % __base; \
__high = __high / __base; \
} \
asm ("divl %2" : "=a" (__low), "=d" (__mod) \
: "rm" (__base), "0" (__low), "1" (__upper)); \
asm ("" : "=A" (n) : "a" (__low), "d" (__high)); \
__mod; \
})
#define barrier() __asm__ __volatile__ ("" ::: "memory")
static inline uint8_t inb(uint16_t port) __attribute__((always_inline));
static inline uint16_t inw(uint16_t port) __attribute__((always_inline));
static inline void insl(uint32_t port, void *addr, int cnt) __attribute__((always_inline));
static inline void outb(uint16_t port, uint8_t data) __attribute__((always_inline));
static inline void outw(uint16_t port, uint16_t data) __attribute__((always_inline));
static inline void outsl(uint32_t port, const void *addr, int cnt) __attribute__((always_inline));
static inline uint32_t read_ebp(void) __attribute__((always_inline));
static inline void breakpoint(void) __attribute__((always_inline));
static inline uint32_t read_dr(unsigned regnum) __attribute__((always_inline));
static inline void write_dr(unsigned regnum, uint32_t value) __attribute__((always_inline));
/* Pseudo-descriptors used for LGDT, LLDT(not used) and LIDT instructions. */
struct pseudodesc {
uint16_t pd_lim; // Limit
uintptr_t pd_base; // Base address
} __attribute__ ((packed));
static inline void lidt(struct pseudodesc *pd) __attribute__((always_inline));
static inline void sti(void) __attribute__((always_inline));
static inline void cli(void) __attribute__((always_inline));
static inline void ltr(uint16_t sel) __attribute__((always_inline));
static inline uint32_t read_eflags(void) __attribute__((always_inline));
static inline void write_eflags(uint32_t eflags) __attribute__((always_inline));
static inline void lcr0(uintptr_t cr0) __attribute__((always_inline));
static inline void lcr3(uintptr_t cr3) __attribute__((always_inline));
static inline uintptr_t rcr0(void) __attribute__((always_inline));
static inline uintptr_t rcr1(void) __attribute__((always_inline));
static inline uintptr_t rcr2(void) __attribute__((always_inline));
static inline uintptr_t rcr3(void) __attribute__((always_inline));
static inline void invlpg(void *addr) __attribute__((always_inline));
static inline uint8_t
inb(uint16_t port) {
uint8_t data;
asm volatile ("inb %1, %0" : "=a" (data) : "d" (port) : "memory");
return data;
}
static inline uint16_t
inw(uint16_t port) {
uint16_t data;
asm volatile ("inw %1, %0" : "=a" (data) : "d" (port));
return data;
}
static inline void
insl(uint32_t port, void *addr, int cnt) {
asm volatile (
"cld;"
"repne; insl;"
: "=D" (addr), "=c" (cnt)
: "d" (port), "0" (addr), "1" (cnt)
: "memory", "cc");
}
static inline void
outb(uint16_t port, uint8_t data) {
asm volatile ("outb %0, %1" :: "a" (data), "d" (port) : "memory");
}
static inline void
outw(uint16_t port, uint16_t data) {
asm volatile ("outw %0, %1" :: "a" (data), "d" (port) : "memory");
}
static inline void
outsl(uint32_t port, const void *addr, int cnt) {
asm volatile (
"cld;"
"repne; outsl;"
: "=S" (addr), "=c" (cnt)
: "d" (port), "0" (addr), "1" (cnt)
: "memory", "cc");
}
static inline uint32_t
read_ebp(void) {
uint32_t ebp;
asm volatile ("movl %%ebp, %0" : "=r" (ebp));
return ebp;
}
static inline void
breakpoint(void) {
asm volatile ("int $3");
}
static inline uint32_t
read_dr(unsigned regnum) {
uint32_t value = 0;
switch (regnum) {
case 0: asm volatile ("movl %%db0, %0" : "=r" (value)); break;
case 1: asm volatile ("movl %%db1, %0" : "=r" (value)); break;
case 2: asm volatile ("movl %%db2, %0" : "=r" (value)); break;
case 3: asm volatile ("movl %%db3, %0" : "=r" (value)); break;
case 6: asm volatile ("movl %%db6, %0" : "=r" (value)); break;
case 7: asm volatile ("movl %%db7, %0" : "=r" (value)); break;
}
return value;
}
static void
write_dr(unsigned regnum, uint32_t value) {
switch (regnum) {
case 0: asm volatile ("movl %0, %%db0" :: "r" (value)); break;
case 1: asm volatile ("movl %0, %%db1" :: "r" (value)); break;
case 2: asm volatile ("movl %0, %%db2" :: "r" (value)); break;
case 3: asm volatile ("movl %0, %%db3" :: "r" (value)); break;
case 6: asm volatile ("movl %0, %%db6" :: "r" (value)); break;
case 7: asm volatile ("movl %0, %%db7" :: "r" (value)); break;
}
}
static inline void
lidt(struct pseudodesc *pd) {
asm volatile ("lidt (%0)" :: "r" (pd) : "memory");
}
static inline void
sti(void) {
asm volatile ("sti");
}
static inline void
cli(void) {
asm volatile ("cli" ::: "memory");
}
static inline void
ltr(uint16_t sel) {
asm volatile ("ltr %0" :: "r" (sel) : "memory");
}
static inline uint32_t
read_eflags(void) {
uint32_t eflags;
asm volatile ("pushfl; popl %0" : "=r" (eflags));
return eflags;
}
static inline void
write_eflags(uint32_t eflags) {
asm volatile ("pushl %0; popfl" :: "r" (eflags));
}
static inline void
lcr0(uintptr_t cr0) {
asm volatile ("mov %0, %%cr0" :: "r" (cr0) : "memory");
}
static inline void
lcr3(uintptr_t cr3) {
asm volatile ("mov %0, %%cr3" :: "r" (cr3) : "memory");
}
static inline uintptr_t
rcr0(void) {
uintptr_t cr0;
asm volatile ("mov %%cr0, %0" : "=r" (cr0) :: "memory");
return cr0;
}
static inline uintptr_t
rcr1(void) {
uintptr_t cr1;
asm volatile ("mov %%cr1, %0" : "=r" (cr1) :: "memory");
return cr1;
}
static inline uintptr_t
rcr2(void) {
uintptr_t cr2;
asm volatile ("mov %%cr2, %0" : "=r" (cr2) :: "memory");
return cr2;
}
static inline uintptr_t
rcr3(void) {
uintptr_t cr3;
asm volatile ("mov %%cr3, %0" : "=r" (cr3) :: "memory");
return cr3;
}
static inline void
invlpg(void *addr) {
asm volatile ("invlpg (%0)" :: "r" (addr) : "memory");
}
static inline int __strcmp(const char *s1, const char *s2) __attribute__((always_inline));
static inline char *__strcpy(char *dst, const char *src) __attribute__((always_inline));
static inline void *__memset(void *s, char c, size_t n) __attribute__((always_inline));
static inline void *__memmove(void *dst, const void *src, size_t n) __attribute__((always_inline));
static inline void *__memcpy(void *dst, const void *src, size_t n) __attribute__((always_inline));
#ifndef __HAVE_ARCH_STRCMP
#define __HAVE_ARCH_STRCMP
static inline int
__strcmp(const char *s1, const char *s2) {
int d0, d1, ret;
asm volatile (
"1: lodsb;"
"scasb;"
"jne 2f;"
"testb %%al, %%al;"
"jne 1b;"
"xorl %%eax, %%eax;"
"jmp 3f;"
"2: sbbl %%eax, %%eax;"
"orb $1, %%al;"
"3:"
: "=a" (ret), "=&S" (d0), "=&D" (d1)
: "1" (s1), "2" (s2)
: "memory");
return ret;
}
#endif /* __HAVE_ARCH_STRCMP */
#ifndef __HAVE_ARCH_STRCPY
#define __HAVE_ARCH_STRCPY
static inline char *
__strcpy(char *dst, const char *src) {
int d0, d1, d2;
asm volatile (
"1: lodsb;"
"stosb;"
"testb %%al, %%al;"
"jne 1b;"
: "=&S" (d0), "=&D" (d1), "=&a" (d2)
: "0" (src), "1" (dst) : "memory");
return dst;
}
#endif /* __HAVE_ARCH_STRCPY */
#ifndef __HAVE_ARCH_MEMSET
#define __HAVE_ARCH_MEMSET
static inline void *
__memset(void *s, char c, size_t n) {
int d0, d1;
asm volatile (
"rep; stosb;"
: "=&c" (d0), "=&D" (d1)
: "0" (n), "a" (c), "1" (s)
: "memory");
return s;
}
#endif /* __HAVE_ARCH_MEMSET */
#ifndef __HAVE_ARCH_MEMMOVE
#define __HAVE_ARCH_MEMMOVE
static inline void *
__memmove(void *dst, const void *src, size_t n) {
if (dst < src) {
return __memcpy(dst, src, n);
}
int d0, d1, d2;
asm volatile (
"std;"
"rep; movsb;"
"cld;"
: "=&c" (d0), "=&S" (d1), "=&D" (d2)
: "0" (n), "1" (n - 1 + src), "2" (n - 1 + dst)
: "memory");
return dst;
}
#endif /* __HAVE_ARCH_MEMMOVE */
#ifndef __HAVE_ARCH_MEMCPY
#define __HAVE_ARCH_MEMCPY
static inline void *
__memcpy(void *dst, const void *src, size_t n) {
int d0, d1, d2;
asm volatile (
"rep; movsl;"
"movl %4, %%ecx;"
"andl $3, %%ecx;"
"jz 1f;"
"rep; movsb;"
"1:"
: "=&c" (d0), "=&D" (d1), "=&S" (d2)
: "0" (n / 4), "g" (n), "1" (dst), "2" (src)
: "memory");
return dst;
}
#endif /* __HAVE_ARCH_MEMCPY */
#endif /* !__LIBS_X86_H__ */

@ -1,46 +0,0 @@
#include <defs.h>
#include <string.h>
#include "syscall.h"
#include <stat.h>
#include <dirent.h>
#include "file.h"
#include "dir.h"
#include <error.h>
#include <unistd.h>
DIR dir, *dirp=&dir;
DIR *
opendir(const char *path) {
if ((dirp->fd = open(path, O_RDONLY)) < 0) {
goto failed;
}
struct stat __stat, *stat = &__stat;
if (fstat(dirp->fd, stat) != 0 || !S_ISDIR(stat->st_mode)) {
goto failed;
}
dirp->dirent.offset = 0;
return dirp;
failed:
return NULL;
}
struct dirent *
readdir(DIR *dirp) {
if (sys_getdirentry(dirp->fd, &(dirp->dirent)) == 0) {
return &(dirp->dirent);
}
return NULL;
}
void
closedir(DIR *dirp) {
close(dirp->fd);
}
int
getcwd(char *buffer, size_t len) {
return sys_getcwd(buffer, len);
}

@ -1,19 +0,0 @@
#ifndef __USER_LIBS_DIR_H__
#define __USER_LIBS_DIR_H__
#include <defs.h>
#include <dirent.h>
typedef struct {
int fd;
struct dirent dirent;
} DIR;
DIR *opendir(const char *path);
struct dirent *readdir(DIR *dirp);
void closedir(DIR *dirp);
int chdir(const char *path);
int getcwd(char *buffer, size_t len);
#endif /* !__USER_LIBS_DIR_H__ */

@ -1,68 +0,0 @@
#include <defs.h>
#include <string.h>
#include "syscall.h"
#include <stdio.h>
#include <stat.h>
#include <error.h>
#include <unistd.h>
int
open(const char *path, uint32_t open_flags) {
return sys_open(path, open_flags);
}
int
close(int fd) {
return sys_close(fd);
}
int
read(int fd, void *base, size_t len) {
return sys_read(fd, base, len);
}
int
write(int fd, void *base, size_t len) {
return sys_write(fd, base, len);
}
int
seek(int fd, off_t pos, int whence) {
return sys_seek(fd, pos, whence);
}
int
fstat(int fd, struct stat *stat) {
return sys_fstat(fd, stat);
}
int
fsync(int fd) {
return sys_fsync(fd);
}
int
dup2(int fd1, int fd2) {
return sys_dup(fd1, fd2);
}
static char
transmode(struct stat *stat) {
uint32_t mode = stat->st_mode;
if (S_ISREG(mode)) return 'r';
if (S_ISDIR(mode)) return 'd';
if (S_ISLNK(mode)) return 'l';
if (S_ISCHR(mode)) return 'c';
if (S_ISBLK(mode)) return 'b';
return '-';
}
void
print_stat(const char *name, int fd, struct stat *stat) {
cprintf("[%03d] %s\n", fd, name);
cprintf(" mode : %c\n", transmode(stat));
cprintf(" links : %lu\n", stat->st_nlinks);
cprintf(" blocks : %lu\n", stat->st_blocks);
cprintf(" size : %lu\n", stat->st_size);
}

@ -1,23 +0,0 @@
#ifndef __USER_LIBS_FILE_H__
#define __USER_LIBS_FILE_H__
#include <defs.h>
struct stat;
int open(const char *path, uint32_t open_flags);
int close(int fd);
int read(int fd, void *base, size_t len);
int write(int fd, void *base, size_t len);
int seek(int fd, off_t pos, int whence);
int fstat(int fd, struct stat *stat);
int fsync(int fd);
int dup(int fd);
int dup2(int fd1, int fd2);
int pipe(int *fd_store);
int mkfifo(const char *name, uint32_t open_flags);
void print_stat(const char *name, int fd, struct stat *stat);
#endif /* !__USER_LIBS_FILE_H__ */

@ -1,24 +0,0 @@
.text
.globl _start
_start:
# set ebp for backtrace
movl $0x0, %ebp
# load argc and argv
movl (%esp), %ebx
lea 0x4(%esp), %ecx
# move down the esp register
# since it may cause page fault in backtrace
subl $0x20, %esp
# save argc and argv on stack
pushl %ecx
pushl %ebx
# call user-program function
call umain
1: jmp 1b

@ -1,42 +0,0 @@
#ifndef __USER_LIBS_LOCK_H__
#define __USER_LIBS_LOCK_H__
#include <defs.h>
#include <atomic.h>
#include "ulib.h"
#define INIT_LOCK {0}
typedef volatile bool lock_t;
static inline void
lock_init(lock_t *l) {
*l = 0;
}
static inline bool
try_lock(lock_t *l) {
return test_and_set_bit(0, l);
}
static inline void
lock(lock_t *l) {
if (try_lock(l)) {
int step = 0;
do {
yield();
if (++ step == 100) {
step = 0;
sleep(10);
}
} while (try_lock(l));
}
}
static inline void
unlock(lock_t *l) {
test_and_clear_bit(0, l);
}
#endif /* !__USER_LIBS_LOCK_H__ */

@ -1,28 +0,0 @@
#include <defs.h>
#include <stdarg.h>
#include <stdio.h>
#include "ulib.h"
#include <error.h>
void
__panic(const char *file, int line, const char *fmt, ...) {
// print the 'message'
va_list ap;
va_start(ap, fmt);
cprintf("user panic at %s:%d:\n ", file, line);
vcprintf(fmt, ap);
cprintf("\n");
va_end(ap);
exit(-E_PANIC);
}
void
__warn(const char *file, int line, const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
cprintf("user warning at %s:%d:\n ", file, line);
vcprintf(fmt, ap);
cprintf("\n");
va_end(ap);
}

@ -1,89 +0,0 @@
#include <defs.h>
#include <stdio.h>
#include "syscall.h"
#include "file.h"
#include "ulib.h"
#include <unistd.h>
/* *
* cputch - writes a single character @c to stdout, and it will
* increace the value of counter pointed by @cnt.
* */
static void
cputch(int c, int *cnt) {
sys_putc(c);
(*cnt) ++;
}
/* *
* vcprintf - format a string and writes it to stdout
*
* The return value is the number of characters which would be
* written to stdout.
*
* Call this function if you are already dealing with a va_list.
* Or you probably want cprintf() instead.
* */
int
vcprintf(const char *fmt, va_list ap) {
int cnt = 0;
vprintfmt((void*)cputch, NO_FD, &cnt, fmt, ap);
return cnt;
}
/* *
* cprintf - formats a string and writes it to stdout
*
* The return value is the number of characters which would be
* written to stdout.
* */
int
cprintf(const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
int cnt = vcprintf(fmt, ap);
va_end(ap);
return cnt;
}
/* *
* cputs- writes the string pointed by @str to stdout and
* appends a newline character.
* */
int
cputs(const char *str) {
int cnt = 0;
char c;
while ((c = *str ++) != '\0') {
cputch(c, &cnt);
}
cputch('\n', &cnt);
return cnt;
}
static void
fputch(char c, int *cnt, int fd) {
write(fd, &c, sizeof(char));
(*cnt) ++;
}
int
vfprintf(int fd, const char *fmt, va_list ap) {
int cnt = 0;
vprintfmt((void*)fputch, fd, &cnt, fmt, ap);
return cnt;
}
int
fprintf(int fd, const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
int cnt = vfprintf(fd, fmt, ap);
va_end(ap);
return cnt;
}

@ -1,33 +0,0 @@
#ifndef __USER_LIBS_SYSCALL_H__
#define __USER_LIBS_SYSCALL_H__
int sys_exit(int error_code);
int sys_fork(void);
int sys_wait(int pid, int *store);
int sys_exec(const char *name, int argc, const char **argv);
int sys_yield(void);
int sys_kill(int pid);
int sys_getpid(void);
int sys_putc(int c);
int sys_pgdir(void);
int sys_sleep(unsigned int time);
size_t sys_gettime(void);
struct stat;
struct dirent;
int sys_open(const char *path, uint32_t open_flags);
int sys_close(int fd);
int sys_read(int fd, void *base, size_t len);
int sys_write(int fd, void *base, size_t len);
int sys_seek(int fd, off_t pos, int whence);
int sys_fstat(int fd, struct stat *stat);
int sys_fsync(int fd);
int sys_getcwd(char *buffer, size_t len);
int sys_getdirentry(int fd, struct dirent *dirent);
int sys_dup(int fd1, int fd2);
void sys_lab6_set_priority(uint32_t priority); //only for lab6
#endif /* !__USER_LIBS_SYSCALL_H__ */

@ -1,87 +0,0 @@
#include <defs.h>
#include "syscall.h"
#include <stdio.h>
#include "ulib.h"
#include <stat.h>
#include <string.h>
#include "lock.h"
static lock_t fork_lock = INIT_LOCK;
void
lock_fork(void) {
lock(&fork_lock);
}
void
unlock_fork(void) {
unlock(&fork_lock);
}
void
exit(int error_code) {
sys_exit(error_code);
cprintf("BUG: exit failed.\n");
while (1);
}
int
fork(void) {
return sys_fork();
}
int
wait(void) {
return sys_wait(0, NULL);
}
int
waitpid(int pid, int *store) {
return sys_wait(pid, store);
}
void
yield(void) {
sys_yield();
}
int
kill(int pid) {
return sys_kill(pid);
}
int
getpid(void) {
return sys_getpid();
}
//print_pgdir - print the PDT&PT
void
print_pgdir(void) {
sys_pgdir();
}
void
lab6_set_priority(uint32_t priority)
{
sys_lab6_set_priority(priority);
}
int
sleep(unsigned int time) {
return sys_sleep(time);
}
unsigned int
gettime_msec(void) {
return (unsigned int)sys_gettime();
}
int
__exec(const char *name, const char **argv) {
int argc = 0;
while (argv[argc] != NULL) {
argc ++;
}
return sys_exec(name, argc, argv);
}

@ -1,49 +0,0 @@
#ifndef __USER_LIBS_ULIB_H__
#define __USER_LIBS_ULIB_H__
#include <defs.h>
void __warn(const char *file, int line, const char *fmt, ...);
void __noreturn __panic(const char *file, int line, const char *fmt, ...);
#define warn(...) \
__warn(__FILE__, __LINE__, __VA_ARGS__)
#define panic(...) \
__panic(__FILE__, __LINE__, __VA_ARGS__)
#define assert(x) \
do { \
if (!(x)) { \
panic("assertion failed: %s", #x); \
} \
} while (0)
// static_assert(x) will generate a compile-time error if 'x' is false.
#define static_assert(x) \
switch (x) { case 0: case (x): ; }
int fprintf(int fd, const char *fmt, ...);
void __noreturn exit(int error_code);
int fork(void);
int wait(void);
int waitpid(int pid, int *store);
void yield(void);
int kill(int pid);
int getpid(void);
void print_pgdir(void);
int sleep(unsigned int time);
unsigned int gettime_msec(void);
int __exec(const char *name, const char **argv);
#define __exec0(name, path, ...) \
({ const char *argv[] = {path, ##__VA_ARGS__, NULL}; __exec(name, argv); })
#define exec(path, ...) __exec0(NULL, path, ##__VA_ARGS__)
#define nexec(name, path, ...) __exec0(name, path, ##__VA_ARGS__)
void lab6_set_priority(uint32_t priority); //only for lab6
#endif /* !__USER_LIBS_ULIB_H__ */

@ -1,34 +0,0 @@
#include "ulib.h"
#include <unistd.h>
#include "file.h"
#include <stat.h>
int main(int argc, char *argv[]);
static int
initfd(int fd2, const char *path, uint32_t open_flags) {
int fd1, ret;
if ((fd1 = open(path, open_flags)) < 0) {
return fd1;
}
if (fd1 != fd2) {
close(fd2);
ret = dup2(fd1, fd2);
close(fd1);
}
return ret;
}
void
umain(int argc, char *argv[]) {
int fd;
if ((fd = initfd(0, "stdin:", O_RDONLY)) < 0) {
warn("open <stdin> failed: %e.\n", fd);
}
if ((fd = initfd(1, "stdout:", O_WRONLY)) < 0) {
warn("open <stdout> failed: %e.\n", fd);
}
int ret = main(argc, argv);
exit(ret);
}

@ -1,5 +1,5 @@
#include <defs.h> #include <defs.h>
#include <x86.h> #include <arch.h>
#include <error.h> #include <error.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>

@ -1,4 +1,4 @@
#include <x86.h> #include <arch.h>
#include <stdlib.h> #include <stdlib.h>
static unsigned long long next = 1; static unsigned long long next = 1;

@ -1,5 +1,5 @@
#include <string.h> #include <string.h>
#include <x86.h> #include <arch.h>
/* * /* *
* strlen - calculate the length of the string @s, not including * strlen - calculate the length of the string @s, not including

@ -1,7 +1,7 @@
#include <defs.h> #include <defs.h>
#include <unistd.h> #include <unistd.h>
#include <stdarg.h> #include <stdarg.h>
#include "syscall.h" #include <syscall.h>
#include <stat.h> #include <stat.h>
#include <dirent.h> #include <dirent.h>
@ -19,6 +19,7 @@ syscall(int num, ...) {
} }
va_end(ap); va_end(ap);
#if defined(__i386__)
asm volatile ( asm volatile (
"int %1;" "int %1;"
: "=a" (ret) : "=a" (ret)
@ -30,6 +31,26 @@ syscall(int num, ...) {
"D" (a[3]), "D" (a[3]),
"S" (a[4]) "S" (a[4])
: "cc", "memory"); : "cc", "memory");
#elif defined(__riscv_xlen)
asm volatile (
"lw a0, %1\n"
"lw a1, %2\n"
"lw a2, %3\n"
"lw a3, %4\n"
"lw a4, %5\n"
"lw a5, %6\n"
"ecall\n"
"sw a0, %0"
: "=m" (ret)
: "m" (num),
"m" (a[0]),
"m" (a[1]),
"m" (a[2]),
"m" (a[3]),
"m" (a[4])
: "memory"
);
#endif
return ret; return ret;
} }
@ -84,7 +105,7 @@ sys_sleep(unsigned int time) {
return syscall(SYS_sleep, time); return syscall(SYS_sleep, time);
} }
size_t int
sys_gettime(void) { sys_gettime(void) {
return syscall(SYS_gettime); return syscall(SYS_gettime);
} }
Loading…
Cancel
Save