Merge remote-tracking branch 'origin/decode_print' into decode_print
This commit is contained in:
commit
ddc86f6f0a
2
test_programs/.gitignore
vendored
2
test_programs/.gitignore
vendored
@ -1,4 +1,4 @@
|
||||
# Ignoring dump files
|
||||
*.dump
|
||||
*.o
|
||||
./target
|
||||
target
|
@ -6,8 +6,16 @@ include $(TOPDIR)/Makefile.config
|
||||
#
|
||||
dumps:
|
||||
$(MAKE) dumps -C riscv_instructions/
|
||||
mkdir -p ${TOPDIR}/target
|
||||
find . -name '*.dump' -exec mv {} ${TOPDIR}/target \;
|
||||
mkdir -p ${TOPDIR}/target/dumps/
|
||||
find . -name '*.dump' -exec mv {} ${TOPDIR}/target/dumps/ \;
|
||||
|
||||
user_lib:
|
||||
$(MAKE) -C userlib/
|
||||
|
||||
tests: user_lib
|
||||
$(MAKE) tests -C riscv_instructions/
|
||||
mkdir -p ${TOPDIR}/target/guac/
|
||||
find . -name '*.guac' -exec mv {} ${TOPDIR}/target/guac/ \;
|
||||
|
||||
clean:
|
||||
rm -rf $(TOPDIR)/target
|
38
test_programs/Makefile.tests
Normal file
38
test_programs/Makefile.tests
Normal file
@ -0,0 +1,38 @@
|
||||
include $(TOPDIR)/Makefile.config
|
||||
USERLIB = $(TOPDIR)/userlib
|
||||
INCPATH += -I$(TOPDIR) -I$(USERLIB)
|
||||
LDFLAGS = $(RISCV_LDFLAGS) -T $(USERLIB)/ldscript.lds
|
||||
ASFLAGS = $(RISCV_ASFLAGS) $(INCPATH)
|
||||
CFLAGS = $(RISCV_CFLAGS) $(INCPATH)
|
||||
|
||||
# Rules
|
||||
%.o: %.s
|
||||
$(RISCV_AS) $(ASFLAGS) -c $<
|
||||
|
||||
%.o: %.c
|
||||
$(RISCV_GCC) $(CFLAGS) -c $<
|
||||
|
||||
%.dump: %.o
|
||||
$(RISCV_OBJCOPY) -j .text -O $(DUMP_FORMAT) $< $@
|
||||
|
||||
%.guac: %.o
|
||||
$(RISCV_LD) $(LDFLAGS) $+ -o $@
|
||||
|
||||
# Dependencies
|
||||
.%.d: %.s
|
||||
@echo Generating dependencies for $<
|
||||
@$(SHELL) -ec '$(GCC) -x assembler-with-cpp -M $(ASFLAGS) $< \
|
||||
| sed '\''s/\($*\)\.o[ :]*/\1.o $@ : /g'\'' > $@; \
|
||||
[ -s $@ ] || rm -f $@'
|
||||
|
||||
.%.d: %.c
|
||||
@echo Generating dependencies for $<
|
||||
@$(SHELL) -ec '$(GCC) -M $(CFLAGS) $< \
|
||||
| sed '\''s/\($*\)\.o[ :]*/\1.o $@ : /g'\'' > $@; \
|
||||
[ -s $@ ] || rm -f $@'
|
||||
|
||||
# Targets
|
||||
#clean:
|
||||
# rm -rf *.o 2> /dev/null
|
||||
# rm -rf *.dump 2> /dev/null
|
||||
# rm -rf *.guac 2> /dev/null
|
@ -2,3 +2,8 @@ dumps:
|
||||
make dumps -C boolean_logic/
|
||||
make dumps -C jump_instructions/
|
||||
make dumps -C simple_arithmetics/
|
||||
|
||||
tests:
|
||||
make tests -C boolean_logic/
|
||||
make tests -C jump_instructions/
|
||||
make tests -C simple_arithmetics/
|
@ -1,4 +1,9 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Makefile.dumps
|
||||
include $(TOPDIR)/Makefile.tests
|
||||
|
||||
dumps: comparisons.dump if.dump switch.dump
|
||||
|
||||
tests: comparisons.guac if.guac switch.guac
|
||||
|
||||
# Dependances
|
||||
$(PROGRAMS): % : $(USERLIB)/sys.o $(USERLIB)/libnachos.o %.o
|
@ -1,4 +1,6 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Makefile.dumps
|
||||
include $(TOPDIR)/Makefile.tests
|
||||
|
||||
dumps: jump.dump ret.dump
|
||||
|
||||
tests: jump.guac ret.guac
|
@ -1,4 +1,6 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Makefile.dumps
|
||||
include $(TOPDIR)/Makefile.tests
|
||||
|
||||
dumps: unsigned_addition.dump unsigned_division.dump unsigned_multiplication.dump unsigned_substraction.dump
|
||||
|
||||
tests: unsigned_addition.guac unsigned_division.guac unsigned_multiplication.guac unsigned_substraction.guac
|
@ -1,3 +1,6 @@
|
||||
#include "userlib/syscall.h"
|
||||
#include "userlib/libnachos.h"
|
||||
|
||||
// EXPECTS TWO VARIABLES WITH A VALUE OF UNSIGNED 1
|
||||
int main() {
|
||||
unsigned int x = 0;
|
||||
|
4
test_programs/userlib/Makefile
Normal file
4
test_programs/userlib/Makefile
Normal file
@ -0,0 +1,4 @@
|
||||
TOPDIR = ../
|
||||
include $(TOPDIR)/Makefile.tests
|
||||
|
||||
default: sys.o libnachos.o
|
61
test_programs/userlib/ldscript.lds
Normal file
61
test_programs/userlib/ldscript.lds
Normal file
@ -0,0 +1,61 @@
|
||||
/*
|
||||
ldscript for running user programs under Nachos
|
||||
|
||||
Sections should be aligned on page boundaries. Here an alignement of
|
||||
at least 0x2000 is selected, thus supporting pages up to 8KB
|
||||
large. See addrspace.cc for details.
|
||||
*/
|
||||
|
||||
ENTRY(__start)
|
||||
SECTIONS
|
||||
{
|
||||
|
||||
/* Skip an area of about 8k, so that NULL pointer dereferences can
|
||||
be detected */
|
||||
. += 0x2000;
|
||||
|
||||
.sys ALIGN(0x4000) : {
|
||||
*(.init)
|
||||
*(.sys)
|
||||
}
|
||||
|
||||
/* Code is aligned on a 16k boundary
|
||||
Due to the size of the .sys section, the code start address will
|
||||
presumably be at address 0x4000 */
|
||||
.text ALIGN(0x400000) : {
|
||||
_ftext = .;
|
||||
eprol = .;
|
||||
*(.text)
|
||||
*(.fini)
|
||||
}
|
||||
etext = .;
|
||||
_etext = .;
|
||||
|
||||
/* Initialized data is aligned on a 16k boundary */
|
||||
.data ALIGN(0x4000) : {
|
||||
_fdata = .;
|
||||
*(.data)
|
||||
*(.sdata)
|
||||
}
|
||||
.rodata ALIGN(0x4000) :
|
||||
{
|
||||
*(.rdata)
|
||||
*(.srodata)
|
||||
*(.rodata)
|
||||
}
|
||||
edata = .;
|
||||
_edata = .;
|
||||
|
||||
/* Non-initialized data is aligned on a 16k boundary */
|
||||
/* Bss = Block Started by Symbol */
|
||||
.bss ALIGN(0x4000) : {
|
||||
*(.bss)
|
||||
*(.sbss)
|
||||
*(.scommon)
|
||||
*(COMMON)
|
||||
}
|
||||
|
||||
end = .;
|
||||
_end = .;
|
||||
|
||||
}
|
630
test_programs/userlib/libnachos.c
Normal file
630
test_programs/userlib/libnachos.c
Normal file
@ -0,0 +1,630 @@
|
||||
/*! \file libnachos.c
|
||||
* \brief Functions of our library, for user programs.
|
||||
*
|
||||
* This library only provides some usefull functions for
|
||||
* programming.
|
||||
*
|
||||
* -----------------------------------------------------
|
||||
* This file is part of the Nachos-RiscV distribution
|
||||
* Copyright (c) 2022 University of Rennes 1.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details
|
||||
* (see see <http://www.gnu.org/licenses/>).
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "libnachos.h"
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// threadStart()
|
||||
/*! Makes a thread execute a function or program. This function
|
||||
// is static, it is called internally by library function threadCreate
|
||||
// and should not be called directly by user programs. The interest
|
||||
// of this function is to be able to terminate threads correctly,
|
||||
// even when the thread to be terminated does not explicitly call
|
||||
// Exit. threadStart provides the mechanism by which Exit
|
||||
// is called automatically
|
||||
//
|
||||
// \param func is the identificator of the function to execute.
|
||||
*/
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
static void threadStart(uint64_t func)
|
||||
{
|
||||
VoidNoArgFunctionPtr func2;
|
||||
func2=(VoidNoArgFunctionPtr)func;
|
||||
// Call the function that actually contains the thread code
|
||||
(*func2)();
|
||||
// Call exit, such that there is no return using an empty stack
|
||||
Exit(0);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// threadCreate()
|
||||
/*! Creates a thread and makes it execute a function.
|
||||
//
|
||||
// NB : instead of directly executing the required function,
|
||||
// function threadStart is called so as to ensure
|
||||
// that the thread will properly exit
|
||||
// This function must be called instead of calling directly
|
||||
// the system call newThread
|
||||
//
|
||||
// \param name the name of the thread (for debugging purpose)
|
||||
// \param func is the address of the function to execute.
|
||||
*/
|
||||
//----------------------------------------------------------------------
|
||||
ThreadId threadCreate(char *debug_name, VoidNoArgFunctionPtr func)
|
||||
{
|
||||
return newThread(debug_name, (uint64_t)threadStart,(uint64_t)func);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// n_strcmp()
|
||||
/*! String comparison
|
||||
//
|
||||
// \param s1 is the first string,
|
||||
// \param s2 is the second one.
|
||||
// \return an integer greater than, equal to, or less than 0,
|
||||
// if the first string is greater than, equal to, or less than
|
||||
// the the second string.
|
||||
*/
|
||||
//----------------------------------------------------------------------
|
||||
int n_strcmp(const char *s1, const char *s2)
|
||||
{
|
||||
int comparaison;
|
||||
int fini=0;
|
||||
int i=0;
|
||||
while(!fini) {
|
||||
if ((s1[i]==0)&&(s2[i]==0)) {
|
||||
fini=1;
|
||||
comparaison=0;
|
||||
}
|
||||
if (s1[i]<s2[i]) {
|
||||
fini=1;
|
||||
comparaison=-1;
|
||||
}
|
||||
if(s1[i]>s2[i]) {
|
||||
fini=1;
|
||||
comparaison=1;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return comparaison;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// n_strcpy()
|
||||
/*! String copy
|
||||
//
|
||||
// \param dst is where the string is to be copied,
|
||||
// \param src is where the string to copy is.
|
||||
// \return dst, if the copy successes, 0 otherwise
|
||||
*/
|
||||
//----------------------------------------------------------------------
|
||||
char *n_strcpy(char *dst, const char *src)
|
||||
{
|
||||
int i=0;
|
||||
int fini=0;
|
||||
if ((dst!=0)&&(src!=0)) {
|
||||
while(fini==0) {
|
||||
if(src[i]=='\0') fini=1;
|
||||
dst[i]=src[i];
|
||||
i++;
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
else return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// n_strlen()
|
||||
/*! Gives the number of bytes in a string, not including the
|
||||
// terminating null character.
|
||||
//
|
||||
// \param c is a pointer onto a string.
|
||||
// \return the length of the string.
|
||||
*/
|
||||
//----------------------------------------------------------------------
|
||||
size_t n_strlen(const char *s)
|
||||
{
|
||||
size_t i=0;
|
||||
while (s[i] != 0) i++;
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// n_strcat()
|
||||
/*! Appends a copy of a string, including null character, to the end
|
||||
// of another string. Enough memory has to be available in the
|
||||
// destination string.
|
||||
//
|
||||
// \param dst is a pointer onto the string where the other string
|
||||
// will be appended.
|
||||
// \param src is the string to append.
|
||||
// \return the pointer string dst.
|
||||
*/
|
||||
//----------------------------------------------------------------------
|
||||
char *n_strcat(char *dst, const char *src)
|
||||
{
|
||||
int i,j,k;
|
||||
i=(int)n_strlen(dst);
|
||||
j=(int)n_strlen(src);
|
||||
for(k=i;k<=j+i;k++) {
|
||||
dst[k]=src[k-i];
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// n_toupper()
|
||||
/*! Gives the upper-case letter corresponding to the lower-case
|
||||
// letter passed as parameter.
|
||||
//
|
||||
// \param c is the ASCII code of the letter to transform.
|
||||
// \return the corresponding upper-case letter
|
||||
*/
|
||||
//----------------------------------------------------------------------
|
||||
int n_toupper(int c)
|
||||
{
|
||||
if((c>='a')&&(c<='z'))
|
||||
return c+('A'-'a');
|
||||
else return c;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// n_tolower()
|
||||
/*! Gives the lower-case letter corresponding to the upper-case
|
||||
// letter passed as parameter
|
||||
//
|
||||
// \param c is the ASCII code of the letter to transform.
|
||||
// \return the corresponding lower-case letter
|
||||
*/
|
||||
//----------------------------------------------------------------------
|
||||
int n_tolower(int c)
|
||||
{
|
||||
if((c<='Z')&&(c>='A'))
|
||||
return c+('a'-'A');
|
||||
else return c;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// n_atoi()
|
||||
/*! String to integer conversion.
|
||||
//
|
||||
// \param c is a pointer onto a string.
|
||||
// \return the corresponding value
|
||||
*/
|
||||
//----------------------------------------------------------------------
|
||||
int n_atoi(const char *str)
|
||||
{
|
||||
int i=0;
|
||||
int fini=0;
|
||||
int val=0;
|
||||
int negative = 0;
|
||||
if (str[i] == '-') {
|
||||
negative = 1; i=1;
|
||||
}
|
||||
while(!fini)
|
||||
{
|
||||
if(str[i]==0 || str[i]<'0' || str[i]>'9')
|
||||
fini=1;
|
||||
else
|
||||
{
|
||||
val*=10;
|
||||
val+=str[i]-'0';
|
||||
i++;
|
||||
}
|
||||
}
|
||||
if (negative) return(-val); else return val;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// n_memcmp()
|
||||
/*! Memory comparison.
|
||||
//
|
||||
// \param s1 is the first memory area,
|
||||
// \param s2 is the second memory area.
|
||||
// \param n size in bytes of the area to be compared.
|
||||
// \return an integer less than, equal to, or greater than 0,
|
||||
// according as s1 is lexicographically less than, equal to,
|
||||
// or greater than s2 when taken to be unsigned characters.
|
||||
//
|
||||
*/
|
||||
//----------------------------------------------------------------------
|
||||
int n_memcmp(const void *s1, const void *s2, size_t n)
|
||||
{
|
||||
unsigned char* c1=(unsigned char*)s1;
|
||||
unsigned char* c2=(unsigned char*)s2;
|
||||
|
||||
int comparaison=0;
|
||||
int fini=0;
|
||||
int i=0;
|
||||
while ((!fini)&&(i<n)) {
|
||||
if (c1[i]<c2[i]) {
|
||||
fini=1;
|
||||
comparaison=-1;
|
||||
}
|
||||
if (c1[i]>c2[i]) {
|
||||
fini=1;
|
||||
comparaison=1;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return comparaison;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// n_memcpy()
|
||||
/*! Memory copy.
|
||||
//
|
||||
// \param s1 is where the elements are to be copied,
|
||||
// \param s2 is the memory area to copy.
|
||||
// \param n size in bytes of the area to be copied.
|
||||
// \return the memory area where the copy has been done.
|
||||
*/
|
||||
//----------------------------------------------------------------------
|
||||
void *n_memcpy(void *s1, const void *s2, size_t n)
|
||||
{
|
||||
|
||||
unsigned char* c1=(unsigned char*)s1;
|
||||
unsigned char* c2=(unsigned char*)s2;
|
||||
|
||||
int i=0;
|
||||
if ((c1!=0)&&(c2!=0)) {
|
||||
while(i<n) {
|
||||
c1[i]=c2[i];
|
||||
i++;
|
||||
}
|
||||
return (void *)c1;
|
||||
}
|
||||
else return 0;
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// n_memset()
|
||||
/*! Sets the first n bytes of a memory area to a value (converted to
|
||||
// an unsigned char).
|
||||
//
|
||||
// \param s is the memory area to transform,
|
||||
// \param c is the value wanted,
|
||||
// \param n is the number of bytes to put at c.
|
||||
// \return s.
|
||||
*/
|
||||
//----------------------------------------------------------------------
|
||||
void *n_memset(void *s, int c, size_t n)
|
||||
{
|
||||
unsigned char* c1=(unsigned char*)s;
|
||||
int i;
|
||||
for (i=0;i<n;i++) {
|
||||
c1[i]=c;
|
||||
}
|
||||
return (void *)c1;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// n_dumpmem()
|
||||
/*! Dumps on the string the n first bytes of a memory area
|
||||
// (used for debugging)
|
||||
//
|
||||
// \param addr address of the memory area
|
||||
// \param len number of bytes to be dumped
|
||||
*/
|
||||
//----------------------------------------------------------------------
|
||||
void n_dumpmem(char *addr, int len)
|
||||
{
|
||||
#define TOHEX(x) \
|
||||
({ char __x = (x); if(__x < 10) __x+='0'; else __x='a'+(__x-10) ; __x; })
|
||||
|
||||
int i;
|
||||
for (i = 0 ; i < len ; i++) {
|
||||
char s[3];
|
||||
if ((i%16) == 0)
|
||||
n_printf("%x\t", (unsigned long)&addr[i]);
|
||||
else if ((i%8) == 0)
|
||||
n_printf(" ");
|
||||
s[0] = TOHEX((addr[i] >> 4) & 0xf);
|
||||
s[1] = TOHEX(addr[i] & 0xf);
|
||||
s[2] = '\0';
|
||||
n_printf("%s ", s);
|
||||
if ((((i+1)%16) == 0) || (i == len-1))
|
||||
n_printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
#define PUTCHAR(carac) \
|
||||
do { \
|
||||
if (result < len-1) *buff++ = carac;\
|
||||
result++; \
|
||||
} while (0)
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// n_vsnprintf()
|
||||
/*! Build a string according to a specified format (internal function)
|
||||
//
|
||||
// Nachos vsnprintf accepts:
|
||||
// %c to print a character,
|
||||
// %s, to print a string,
|
||||
// %d, to print an integer,
|
||||
// %x, to print an integer in hexa
|
||||
// %lx %ld same for 64-bit values
|
||||
// %f, to print a floating point value
|
||||
//
|
||||
// \param buff the destination buffer to generate the string to
|
||||
// \param len the size of buff, determines the number max of
|
||||
// characters copied to buff (taking the final \0 into account)
|
||||
// \param format the string to parse
|
||||
// \param ap parameters to print
|
||||
//
|
||||
// \return the number of characters formatted (NOT including \0),
|
||||
// that is, the number of characters that would have been written
|
||||
// to the buffer if it were large enough. -1 on error.
|
||||
*/
|
||||
//----------------------------------------------------------------------
|
||||
static int n_vsnprintf(char *buff, int len, const char *format, va_list ap)
|
||||
{
|
||||
int i, result;
|
||||
|
||||
if (!buff || !format || (len < 0)) {
|
||||
return -1;
|
||||
}
|
||||
result = 0;
|
||||
|
||||
for (i=0 ; format[i] != '\0' ; i++) {
|
||||
switch (format[i]) {
|
||||
case '%':
|
||||
i++;
|
||||
switch(format[i]) {
|
||||
case '%': {
|
||||
PUTCHAR('%');
|
||||
break;
|
||||
}
|
||||
case 'i':
|
||||
case'd': {
|
||||
int integer = (int) va_arg(ap,int);
|
||||
int cpt2 = 0;
|
||||
char buff_int[11];
|
||||
if (integer<0) {PUTCHAR('-');
|
||||
}
|
||||
do {
|
||||
int m10 = integer%10;
|
||||
m10 = (m10 < 0)? -m10:m10;
|
||||
buff_int[cpt2++]=(char)('0'+ m10);
|
||||
integer=integer/10;
|
||||
} while(integer!=0);
|
||||
for (cpt2 = cpt2 - 1 ; cpt2 >= 0 ; cpt2--) {
|
||||
PUTCHAR(buff_int[cpt2]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'l': {
|
||||
i++;
|
||||
switch(format[i]) {
|
||||
case 'd': {
|
||||
long longer = va_arg(ap,long);
|
||||
int cpt2 = 0;
|
||||
char buff_long[20];
|
||||
if (longer<0) {
|
||||
PUTCHAR('-');
|
||||
}
|
||||
do {
|
||||
int m10 = longer%10;
|
||||
m10 = (m10 < 0)? -m10:m10;
|
||||
buff_long[cpt2++]=(char)('0'+ m10);
|
||||
longer=longer/10;
|
||||
} while(longer!=0);
|
||||
for (cpt2 = cpt2 - 1 ; cpt2 >= 0 ; cpt2--) {
|
||||
PUTCHAR(buff_long[cpt2]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'x': {
|
||||
uint64_t hexa = va_arg(ap,long);
|
||||
uint64_t nb;
|
||||
uint32_t i, had_nonzero = 0;
|
||||
for (i=0 ; i < 16 ; i++) {
|
||||
nb = (hexa << (i*4));
|
||||
nb = (nb >> 60);
|
||||
nb = nb & 0x000000000000000f;
|
||||
// Skip the leading zeros
|
||||
if (nb == 0) {
|
||||
if (had_nonzero) {
|
||||
PUTCHAR((uint8_t)'0');
|
||||
}
|
||||
}
|
||||
else {
|
||||
had_nonzero = 1;
|
||||
if (nb < 10)
|
||||
PUTCHAR((uint8_t)'0'+(uint8_t)nb);
|
||||
else
|
||||
PUTCHAR((uint8_t)'a'+(uint8_t)(nb-10));
|
||||
}
|
||||
}
|
||||
if (! had_nonzero)
|
||||
PUTCHAR((uint8_t)'0');
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
PUTCHAR('%');
|
||||
PUTCHAR('l');
|
||||
PUTCHAR(format[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case 'c': {
|
||||
int value = va_arg(ap,int);
|
||||
PUTCHAR((char)value);
|
||||
break;
|
||||
}
|
||||
case 's': {
|
||||
char *string = va_arg(ap,char *);
|
||||
if (! string)
|
||||
string = "(null)";
|
||||
for( ; *string != '\0' ; string++)
|
||||
PUTCHAR(*string);
|
||||
break;
|
||||
}
|
||||
case 'x': {
|
||||
uint32_t hexa = va_arg(ap,int);
|
||||
uint32_t nb;
|
||||
uint32_t i, had_nonzero = 0;
|
||||
for (i=0 ; i < 8 ; i++) {
|
||||
nb = (hexa << (i*4));
|
||||
nb = (nb >> 28);
|
||||
nb = nb & 0x0000000f;
|
||||
// Skip the leading zeros
|
||||
if (nb == 0) {
|
||||
if (had_nonzero)
|
||||
PUTCHAR((uint8_t)'0');
|
||||
}
|
||||
else {
|
||||
had_nonzero = 1;
|
||||
if (nb < 10)
|
||||
PUTCHAR((uint8_t)'0'+(uint8_t)nb);
|
||||
else
|
||||
PUTCHAR((uint8_t)'a'+(uint8_t)(nb-10));
|
||||
}
|
||||
}
|
||||
if (! had_nonzero)
|
||||
PUTCHAR((uint8_t)'0');
|
||||
break;
|
||||
}
|
||||
/*case 'f': {
|
||||
// Very simple routine to print floats as xxxx.yyyyy
|
||||
// Not very good (unable to print large numbers)
|
||||
// If anyone wants to re-write it, feel free ...
|
||||
double f = (double) va_arg(ap,double);
|
||||
int cpt2, j;
|
||||
char buff_float[200];
|
||||
long ient,idec;
|
||||
if (f<0) {
|
||||
PUTCHAR('-');
|
||||
f = -f;
|
||||
}
|
||||
ient = (int)f;
|
||||
// 100000 = print 5 digits max
|
||||
idec = (int)((f - ((double)ient))*100000);
|
||||
// Round up
|
||||
if ( f - ((double)ient) - ((double)idec)/100000.0 >= 0.5E-5)
|
||||
idec ++;
|
||||
cpt2 = 0;
|
||||
// Print digits after the '.'
|
||||
for (j=0 ; j<5 ; j++) {
|
||||
buff_float[cpt2++]=(char)('0'+(idec%10));
|
||||
idec=idec/10;
|
||||
}
|
||||
buff_float[cpt2++] = '.';
|
||||
// Print digits before the '.'
|
||||
do {
|
||||
buff_float[cpt2++]=(char)('0'+ (ient%10));
|
||||
ient=ient/10;
|
||||
} while (ient!=0);
|
||||
for(j = cpt2 - 1 ; j >= 0 ; j--)
|
||||
PUTCHAR(buff_float[j]);
|
||||
break;
|
||||
}
|
||||
*/
|
||||
default:
|
||||
PUTCHAR('%');
|
||||
PUTCHAR(format[i]);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
PUTCHAR(format[i]);
|
||||
}
|
||||
}
|
||||
*buff = '\0';
|
||||
return result;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// n_snprintf()
|
||||
/*! Build a string according to a specified format
|
||||
//
|
||||
// Nachos snprintf accepts:
|
||||
// %c to print a character,
|
||||
// %s, to print a string,
|
||||
// %d, to print an integer,
|
||||
// %x, to print a string in hexa
|
||||
// %f, to print a floating point value
|
||||
//
|
||||
// \param buff the destination buffer to generate the string to
|
||||
// \param len the size of buff, determines the number max of
|
||||
// characters copied to buff (taking the final \0 into account)
|
||||
// \param format the string to parse
|
||||
// \param ... the (variable number of) arguments
|
||||
//
|
||||
// \return the number of characters formatted (NOT including \0),
|
||||
// that is, the number of characters that would have been written
|
||||
// to the buffer if it were large enough. -1 on error.
|
||||
*/
|
||||
//----------------------------------------------------------------------
|
||||
int n_snprintf(char * buff, int len, const char *format, ...){
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
len = n_vsnprintf(buff, len, format, ap);
|
||||
va_end(ap);
|
||||
return len;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// n_printf()
|
||||
/*! Print to the standard output parameters.
|
||||
//
|
||||
// Nachos printf accepts:
|
||||
// %c to print a character,
|
||||
// %s, to print a string,
|
||||
// %d, to print an integer,
|
||||
// %x, to print a string in hexa
|
||||
// %ld, %lx, same for 64-bit values
|
||||
// %f, to print a floating point value
|
||||
//
|
||||
// \param parameters to print,
|
||||
// \param type of print.
|
||||
*/
|
||||
//----------------------------------------------------------------------
|
||||
void n_printf(const char *format, ...){
|
||||
|
||||
va_list ap;
|
||||
char buff[200];
|
||||
int len;
|
||||
|
||||
va_start(ap, format);
|
||||
len = n_vsnprintf(buff, sizeof(buff), format, ap);
|
||||
va_end(ap);
|
||||
|
||||
if (len >= sizeof(buff)) {
|
||||
len = sizeof(buff) - 1;
|
||||
}
|
||||
if (len > 0) {
|
||||
Write(buff,len,CONSOLE_OUTPUT);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// n_read_int()
|
||||
/*!
|
||||
// Very basic minimalist read integer function, no error
|
||||
// checking...
|
||||
*/
|
||||
//----------------------------------------------------------------------
|
||||
int n_read_int(void) {
|
||||
char buff[200];
|
||||
Read(buff,200,CONSOLE_INPUT);
|
||||
return n_atoi(buff);
|
||||
}
|
87
test_programs/userlib/libnachos.h
Normal file
87
test_programs/userlib/libnachos.h
Normal file
@ -0,0 +1,87 @@
|
||||
/*! \file libnachos.h
|
||||
\brief Function structures for programs
|
||||
|
||||
Libnachos proposes several 'libc-like' functions
|
||||
for:
|
||||
Input-Output operations,
|
||||
String operations,
|
||||
Memory operations,
|
||||
System calls are defined in kernel/syscalls.h
|
||||
|
||||
Nachos-libc functions are prefixed by 'n' to avoid
|
||||
any confusion with standard libc functions.
|
||||
|
||||
* -----------------------------------------------------
|
||||
* This file is part of the Nachos-RiscV distribution
|
||||
* Copyright (c) 2022 University of Rennes 1.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details
|
||||
* (see see <http://www.gnu.org/licenses/>).
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "userlib/syscall.h"
|
||||
|
||||
typedef void (*VoidNoArgFunctionPtr)();
|
||||
typedef unsigned int size_t;
|
||||
|
||||
// Thread management
|
||||
// ----------------------------
|
||||
ThreadId threadCreate(char * debug_name, VoidNoArgFunctionPtr func);
|
||||
|
||||
// Input/Output operations :
|
||||
// ------------------------------------
|
||||
|
||||
// Print on the standard output specified parameters.
|
||||
void n_printf(const char *format, ...);
|
||||
|
||||
// Format <buff> (of max length <len>) according to the format <format>
|
||||
int n_snprintf(char * buff, int len, const char *format, ...);
|
||||
|
||||
// Read an integer on the standard input
|
||||
int n_read_int(void);
|
||||
|
||||
// String operations :
|
||||
// -------------------
|
||||
|
||||
// Compare two strings byte by byte.
|
||||
int n_strcmp(const char *s1, const char *s2);
|
||||
|
||||
// Copy a string.
|
||||
char* n_strcpy(char *dst, const char *src);
|
||||
|
||||
// Return the number of bytes in a string.
|
||||
size_t n_strlen(const char *s);
|
||||
|
||||
// appends a copy of a string, to the end of another string.
|
||||
char* n_strcat(char *dst, const char *src);
|
||||
|
||||
// Return a upper-case letter,
|
||||
// equivalent to the lower-case letter given.
|
||||
int n_toupper(int c);
|
||||
|
||||
// Return a lower-case letter,
|
||||
// equivalent to the upper-case letter given.
|
||||
int n_tolower(int c);
|
||||
|
||||
// Convert a string in integer.
|
||||
int n_atoi(const char *str);
|
||||
|
||||
// Concerning memory area operations :
|
||||
// -----------------------------------
|
||||
|
||||
// Compare two memory area, looking at the first n bytes .
|
||||
int n_memcmp(const void *s1, const void *s2, size_t n);
|
||||
|
||||
// Copy n byte from an memory area to another.
|
||||
void* n_memcpy(void *s1, const void *s2, size_t n);
|
||||
|
||||
// Set the first n bytes in a memory area to a specified value.
|
||||
void* n_memset(void *s, int c, size_t n);
|
343
test_programs/userlib/sys.s
Normal file
343
test_programs/userlib/sys.s
Normal file
@ -0,0 +1,343 @@
|
||||
/* Start.s
|
||||
* Assembly language assist for user programs running on top of Nachos.
|
||||
*
|
||||
* Since we don't want to pull in the entire C library, we define
|
||||
* what we need for a user program here, namely Start and the system
|
||||
* calls.
|
||||
*
|
||||
* -----------------------------------------------------
|
||||
* This file is part of the BurritOS distribution
|
||||
* Copyright (c) 2022 University of Rennes 1.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details
|
||||
* (see see <http://www.gnu.org/licenses/>).
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
|
||||
#define IN_ASM
|
||||
#include "userlib/syscall.h"
|
||||
|
||||
// Equivalent to ".text", but with a different name, in order
|
||||
// to be correctly handled by the ldscript
|
||||
.section .sys,"ax",@progbits
|
||||
|
||||
.align 2
|
||||
|
||||
/* -------------------------------------------------------------
|
||||
* __start
|
||||
* Initialize running a C program, by calling "main".
|
||||
*
|
||||
* NOTE: This has to be first, so that it gets loaded at location 0.
|
||||
* The Nachos kernel always starts a program by jumping to location 0.
|
||||
* -------------------------------------------------------------
|
||||
*/
|
||||
|
||||
.globl __start
|
||||
.type __start, @function
|
||||
__start:
|
||||
|
||||
/* Call the program entry point */
|
||||
call main
|
||||
li a0, 0
|
||||
call Exit
|
||||
jr ra /* if we return from main, exit(0) */
|
||||
|
||||
|
||||
/* -------------------------------------------------------------
|
||||
* System call stubs:
|
||||
* Assembly language assist to make system calls to the Nachos kernel.
|
||||
* There is one stub per system call, that places the code for the
|
||||
* system call into register r10, and leaves the arguments to the
|
||||
* system call alone (in other words, arg1 is in r12, arg2 is
|
||||
* in r13, arg3 is in r14, arg4 is in r15)
|
||||
*
|
||||
* The return value is in r10. This follows the standard C calling
|
||||
* convention on the RISC-V.
|
||||
* -------------------------------------------------------------
|
||||
*/
|
||||
|
||||
.globl Halt
|
||||
.type __Halt, @function
|
||||
Halt:
|
||||
addi a7,zero,SC_HALT
|
||||
ecall
|
||||
jr ra
|
||||
|
||||
|
||||
.globl Exit
|
||||
.type __Exit, @function
|
||||
Exit:
|
||||
addi a7,zero,SC_EXIT
|
||||
ecall
|
||||
jr ra
|
||||
|
||||
|
||||
.globl Exec
|
||||
.type __Exec, @function
|
||||
Exec:
|
||||
addi a7,zero,SC_EXEC
|
||||
ecall
|
||||
jr ra
|
||||
|
||||
|
||||
.globl Join
|
||||
.type __Join, @function
|
||||
Join:
|
||||
addi a7,zero,SC_JOIN
|
||||
ecall
|
||||
jr ra
|
||||
|
||||
|
||||
.globl Create
|
||||
.type __Create, @function
|
||||
Create:
|
||||
addi a7,zero,SC_CREATE
|
||||
ecall
|
||||
jr ra
|
||||
|
||||
|
||||
.globl Open
|
||||
.type __Open, @function
|
||||
Open:
|
||||
addi a7,zero,SC_OPEN
|
||||
ecall
|
||||
jr ra
|
||||
|
||||
|
||||
.globl Read
|
||||
.type __Read, @function
|
||||
Read:
|
||||
addi a7,zero,SC_READ
|
||||
ecall
|
||||
jr ra
|
||||
|
||||
|
||||
|
||||
.globl Write
|
||||
.type __Write, @function
|
||||
Write:
|
||||
addi a7,zero,SC_WRITE
|
||||
ecall
|
||||
jr ra
|
||||
|
||||
|
||||
.globl Seek
|
||||
.type __Seek, @function
|
||||
Seek:
|
||||
addi a7,zero,SC_SEEK
|
||||
ecall
|
||||
jr ra
|
||||
|
||||
|
||||
.globl Close
|
||||
.type __Close, @function
|
||||
Close:
|
||||
addi a7,zero,SC_CLOSE
|
||||
ecall
|
||||
jr ra
|
||||
|
||||
|
||||
.globl FSList
|
||||
.type __FSList, @function
|
||||
FSList:
|
||||
addi a7,zero,SC_FSLIST
|
||||
ecall
|
||||
jr ra
|
||||
|
||||
|
||||
.globl newThread
|
||||
.type __newThread, @function
|
||||
newThread:
|
||||
addi a7,zero,SC_NEW_THREAD
|
||||
ecall
|
||||
jr ra
|
||||
|
||||
|
||||
.globl Remove
|
||||
.type __Remove, @function
|
||||
Remove:
|
||||
addi a7,zero,SC_REMOVE
|
||||
ecall
|
||||
jr ra
|
||||
|
||||
|
||||
.globl Yield
|
||||
.type __Yield, @function
|
||||
Yield:
|
||||
addi a7,zero,SC_YIELD
|
||||
ecall
|
||||
jr ra
|
||||
|
||||
|
||||
.globl PError
|
||||
.type __PError, @function
|
||||
PError:
|
||||
addi a7,zero,SC_PERROR
|
||||
ecall
|
||||
jr ra
|
||||
|
||||
|
||||
.globl P
|
||||
.type __P, @function
|
||||
P:
|
||||
addi a7,zero,SC_P
|
||||
ecall
|
||||
jr ra
|
||||
|
||||
|
||||
.globl V
|
||||
.type __V, @function
|
||||
V:
|
||||
addi a7,zero,SC_V
|
||||
ecall
|
||||
jr ra
|
||||
|
||||
.globl SemCreate
|
||||
.type __SemCreate, @function
|
||||
SemCreate:
|
||||
addi a7,zero,SC_SEM_CREATE
|
||||
ecall
|
||||
jr ra
|
||||
|
||||
|
||||
.globl SemDestroy
|
||||
.type __SemDestroy, @function
|
||||
SemDestroy:
|
||||
addi a7,zero,SC_SEM_DESTROY
|
||||
ecall
|
||||
jr ra
|
||||
|
||||
|
||||
.globl SysTime
|
||||
.type __SysTime, @function
|
||||
SysTime:
|
||||
addi a7,zero,SC_SYS_TIME
|
||||
ecall
|
||||
jr ra
|
||||
|
||||
|
||||
.globl LockCreate
|
||||
.type __LockCreate, @function
|
||||
LockCreate:
|
||||
addi a7,zero,SC_LOCK_CREATE
|
||||
ecall
|
||||
jr ra
|
||||
|
||||
.globl LockDestroy
|
||||
.type __LockDestroy, @function
|
||||
LockDestroy:
|
||||
addi a7,zero,SC_LOCK_DESTROY
|
||||
ecall
|
||||
jr ra
|
||||
|
||||
|
||||
.globl LockAcquire
|
||||
.type __LockAquire, @function
|
||||
LockAcquire:
|
||||
addi a7,zero,SC_LOCK_ACQUIRE
|
||||
ecall
|
||||
jr ra
|
||||
|
||||
|
||||
.globl LockRelease
|
||||
.type __LockRelease, @function
|
||||
LockRelease:
|
||||
addi a7,zero,SC_LOCK_RELEASE
|
||||
ecall
|
||||
jr ra
|
||||
|
||||
|
||||
.globl CondCreate
|
||||
.type __CondCreate, @function
|
||||
CondCreate:
|
||||
addi a7,zero,SC_COND_CREATE
|
||||
ecall
|
||||
jr ra
|
||||
|
||||
|
||||
.globl CondDestroy
|
||||
.type __CondDestroy, @function
|
||||
CondDestroy:
|
||||
addi a7,zero,SC_COND_DESTROY
|
||||
ecall
|
||||
jr ra
|
||||
|
||||
|
||||
.globl CondWait
|
||||
.type __CondWait, @function
|
||||
CondWait:
|
||||
addi a7,zero,SC_COND_WAIT
|
||||
ecall
|
||||
jr ra
|
||||
|
||||
|
||||
.globl CondSignal
|
||||
.type __CondSignal, @function
|
||||
CondSignal:
|
||||
addi a7,zero,SC_COND_SIGNAL
|
||||
ecall
|
||||
jr ra
|
||||
|
||||
|
||||
.globl CondBroadcast
|
||||
.type __CondBroadcast, @function
|
||||
CondBroadcast:
|
||||
addi a7,zero,SC_COND_BROADCAST
|
||||
ecall
|
||||
jr ra
|
||||
|
||||
|
||||
.globl TtySend
|
||||
.type __TtySend, @function
|
||||
TtySend:
|
||||
addi a7,zero,SC_TTY_SEND
|
||||
ecall
|
||||
jr ra
|
||||
|
||||
|
||||
.globl TtyReceive
|
||||
.type __TtyReceive, @function
|
||||
TtyReceive:
|
||||
addi a7,zero,SC_TTY_RECEIVE
|
||||
ecall
|
||||
jr ra
|
||||
|
||||
|
||||
.globl Mkdir
|
||||
.type __Mkdir, @function
|
||||
Mkdir:
|
||||
addi a7,zero,SC_MKDIR
|
||||
ecall
|
||||
jr ra
|
||||
|
||||
|
||||
.globl Rmdir
|
||||
.type __Rmdir, @function
|
||||
Rmdir:
|
||||
addi a7,zero,SC_RMDIR
|
||||
ecall
|
||||
jr ra
|
||||
|
||||
|
||||
.globl Mmap
|
||||
.type __Mmap, @function
|
||||
Mmap:
|
||||
addi a7,zero,SC_MMAP
|
||||
ecall
|
||||
jr ra
|
||||
|
||||
.globl Debug
|
||||
.type __Debug, @function
|
||||
Debug:
|
||||
addi a7,zero,SC_DEBUG
|
||||
ecall
|
||||
jr ra
|
||||
|
||||
|
287
test_programs/userlib/syscall.h
Normal file
287
test_programs/userlib/syscall.h
Normal file
@ -0,0 +1,287 @@
|
||||
/*! \file syscall.h
|
||||
\brief Nachos system call interface.
|
||||
|
||||
These are Nachos kernel operations
|
||||
that can be invoked from user programs, by trapping to the kernel
|
||||
via the "syscall" instruction.
|
||||
|
||||
This file is included by user programs and by the Nachos kernel.
|
||||
|
||||
Each of these is invoked by a user program by simply calling the
|
||||
procedure; an assembly language stub stuffs the system call code
|
||||
into a register, and traps to the kernel. The kernel procedures
|
||||
are then invoked in the Nachos kernel, after appropriate error checking,
|
||||
from the system call entry point in exception.cc.
|
||||
|
||||
* -----------------------------------------------------
|
||||
* This file is part of the Nachos-RiscV distribution
|
||||
* Copyright (c) 2022 University of Rennes 1.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details
|
||||
* (see see <http://www.gnu.org/licenses/>).
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
#ifndef SYSCALLS_H
|
||||
#define SYSCALLS_H
|
||||
|
||||
//#include "kernel/copyright.h"
|
||||
|
||||
/* system call codes -- used by the stubs to tell the kernel which system call
|
||||
* is being asked for
|
||||
*/
|
||||
#define SC_HALT 0
|
||||
#define SC_EXIT 1
|
||||
#define SC_EXEC 2
|
||||
#define SC_JOIN 3
|
||||
#define SC_CREATE 4
|
||||
#define SC_OPEN 5
|
||||
#define SC_READ 6
|
||||
#define SC_WRITE 7
|
||||
#define SC_SEEK 8
|
||||
#define SC_CLOSE 9
|
||||
#define SC_NEW_THREAD 10
|
||||
#define SC_YIELD 11
|
||||
#define SC_PERROR 12
|
||||
#define SC_P 13
|
||||
#define SC_V 14
|
||||
#define SC_SEM_CREATE 15
|
||||
#define SC_SEM_DESTROY 16
|
||||
#define SC_LOCK_CREATE 17
|
||||
#define SC_LOCK_DESTROY 18
|
||||
#define SC_LOCK_ACQUIRE 19
|
||||
#define SC_LOCK_RELEASE 20
|
||||
#define SC_COND_CREATE 21
|
||||
#define SC_COND_DESTROY 22
|
||||
#define SC_COND_WAIT 23
|
||||
#define SC_COND_SIGNAL 24
|
||||
#define SC_COND_BROADCAST 25
|
||||
#define SC_TTY_SEND 26
|
||||
#define SC_TTY_RECEIVE 27
|
||||
#define SC_MKDIR 28
|
||||
#define SC_RMDIR 29
|
||||
#define SC_REMOVE 30
|
||||
#define SC_FSLIST 31
|
||||
#define SC_SYS_TIME 32
|
||||
#define SC_MMAP 33
|
||||
#define SC_DEBUG 34
|
||||
|
||||
#ifndef IN_ASM
|
||||
|
||||
/* The system call interface. These are the operations the Nachos
|
||||
* kernel needs to support, to be able to run user programs.
|
||||
*
|
||||
*/
|
||||
|
||||
typedef int t_error;
|
||||
|
||||
/* Stop Nachos, and print out performance stats */
|
||||
void Halt();
|
||||
|
||||
|
||||
/* Return the time spent running Nachos */
|
||||
|
||||
/*! \brief Defines the Nachos basic time unit */
|
||||
typedef struct {
|
||||
long seconds;
|
||||
long nanos;
|
||||
} Nachos_Time;
|
||||
void SysTime(Nachos_Time *t);
|
||||
|
||||
/* Address space control operations: Exit, Exec, and Join */
|
||||
|
||||
/* This user program is done (status = 0 means exited normally). */
|
||||
void Exit(int status);
|
||||
|
||||
/* A unique identifier for a thread executed within a user program */
|
||||
typedef unsigned long ThreadId;
|
||||
|
||||
/* Run the executable, stored in the Nachos file "name", and return the
|
||||
* master thread identifier
|
||||
*/
|
||||
ThreadId Exec(char *name);
|
||||
|
||||
/* Create a new thread in the current process
|
||||
* Return thread identifier
|
||||
*/
|
||||
ThreadId newThread(char * debug_name, int func, int arg);
|
||||
|
||||
/* Only return once the the thread "id" has finished.
|
||||
*/
|
||||
t_error Join(ThreadId id);
|
||||
|
||||
/* Yield the CPU to another runnable thread, whether in this address space
|
||||
* or not.
|
||||
*/
|
||||
void Yield();
|
||||
|
||||
/*! Print the last error message with the personalized one "mess" */
|
||||
void PError(char *mess);
|
||||
|
||||
/* File system operations: Create, Open, Read, Write, Seek, Close
|
||||
* These functions are patterned after UNIX -- files represent
|
||||
* both files *and* hardware I/O devices.
|
||||
*
|
||||
* If this assignment is done before doing the file system assignment,
|
||||
* note that the Nachos file system has a stub implementation, which
|
||||
* will work for the purposes of testing out these routines.
|
||||
*/
|
||||
|
||||
/* A unique identifier for an open Nachos file. */
|
||||
typedef unsigned long OpenFileId;
|
||||
|
||||
/* when an address space starts up, it has two open files, representing
|
||||
* keyboard input and display output (in UNIX terms, stdin and stdout).
|
||||
* Read and Write can be used directly on these, without first opening
|
||||
* the console device.
|
||||
*/
|
||||
#define CONSOLE_INPUT 0
|
||||
#define CONSOLE_OUTPUT 1
|
||||
|
||||
/* Create a Nachos file, with "name" */
|
||||
t_error Create(char *name,int size);
|
||||
|
||||
/* Open the Nachos file "name", and return an "OpenFileId" that can
|
||||
* be used to read and write to the file.
|
||||
*/
|
||||
OpenFileId Open(char *name);
|
||||
|
||||
/* Write "size" bytes from "buffer" to the open file. */
|
||||
t_error Write(char *buffer, int size, OpenFileId id);
|
||||
|
||||
/* Read "size" bytes from the open file into "buffer".
|
||||
* Return the number of bytes actually read -- if the open file isn't
|
||||
* long enough, or if it is an I/O device, and there aren't enough
|
||||
* characters to read, return whatever is available (for I/O devices,
|
||||
* you should always wait until you can return at least one character).
|
||||
*/
|
||||
t_error Read(char *buffer, int size, OpenFileId id);
|
||||
|
||||
/* Seek to a specified offset into an opened file */
|
||||
t_error Seek(int offset, OpenFileId id);
|
||||
|
||||
#ifndef SYSDEP_H
|
||||
/* Close the file, we're done reading and writing to it. */
|
||||
t_error Close(OpenFileId id);
|
||||
#endif // SYSDEP_H
|
||||
|
||||
/* Remove the file */
|
||||
t_error Remove(char* name);
|
||||
|
||||
/******************************************************************/
|
||||
/* system calls concerning directory management */
|
||||
|
||||
/* Create a new repertory
|
||||
Return a negative number if an error ocurred.
|
||||
*/
|
||||
t_error Mkdir(char* name);
|
||||
|
||||
/* Destroy a repertory, which must be empty.
|
||||
Return a negative number if an error ocurred.
|
||||
*/
|
||||
t_error Rmdir(char* name);
|
||||
|
||||
/* List the content of NachOS FileSystem */
|
||||
t_error FSList();
|
||||
|
||||
/******************************************************************/
|
||||
/* User-level synchronization operations : */
|
||||
|
||||
/* System calls concerning semaphores management */
|
||||
|
||||
typedef unsigned long SemId;
|
||||
|
||||
/* Create a semaphore, initialising it at count.
|
||||
Return a Semid, which will enable to do operations on this
|
||||
semaphore */
|
||||
SemId SemCreate(char * debug_name, int count);
|
||||
|
||||
/* Destroy a semaphore identified by sema.
|
||||
Return a negative number if an error occured during the destruction */
|
||||
t_error SemDestroy(SemId sema);
|
||||
|
||||
/* Do the operation P() on the semaphore sema */
|
||||
t_error P(SemId sema);
|
||||
|
||||
/* Do the operation V() on the semaphore sema */
|
||||
t_error V(SemId sema);
|
||||
|
||||
/* System calls concerning locks management */
|
||||
typedef unsigned long LockId;
|
||||
|
||||
/* Create a lock.
|
||||
Return an identifier */
|
||||
LockId LockCreate(char * debug_name);
|
||||
|
||||
/* Destroy a lock.
|
||||
Return a negative number if an error ocurred
|
||||
during the destruction. */
|
||||
t_error LockDestroy(LockId id);
|
||||
|
||||
/* Do the operation Acquire on the lock id.
|
||||
Return a negative number if an error ocurred. */
|
||||
t_error LockAcquire(LockId id);
|
||||
|
||||
/* Do the operation Release on the lock id.
|
||||
Return a negative number if an error ocurred.
|
||||
*/
|
||||
t_error LockRelease(LockId id);
|
||||
|
||||
/* System calls concerning conditions variables. */
|
||||
typedef unsigned long CondId;
|
||||
|
||||
/* Create a new condition variable */
|
||||
CondId CondCreate(char * debug_name);
|
||||
|
||||
/* Destroy a condition variable.
|
||||
Return a negative number if an error ocurred.
|
||||
*/
|
||||
t_error CondDestroy(CondId id);
|
||||
|
||||
/* Do the operation Wait on a condition variable.
|
||||
Returns a negative number if an error ocurred.
|
||||
*/
|
||||
t_error CondWait(CondId cond);
|
||||
|
||||
/* Do the operation Signal on a condition variable (wake up only one thread).
|
||||
Return a negative number if an error ocurred.
|
||||
*/
|
||||
t_error CondSignal(CondId cond);
|
||||
|
||||
/* Do the operation Signal on a condition variable (wake up all threads).
|
||||
Return a negative number if an error ocurred.
|
||||
*/
|
||||
t_error CondBroadcast(CondId cond);
|
||||
|
||||
/******************************************************************/
|
||||
/* System calls concerning serial port and console */
|
||||
|
||||
/* Send the message on the serial communication link.
|
||||
Returns the number of bytes successfully sent.
|
||||
*/
|
||||
int TtySend(char *mess);
|
||||
|
||||
/* Wait for a message comming from the serial communication link.
|
||||
The length of the buffer where the bytes will be copied is given as a parameter.
|
||||
Returns the number of characters actually received.
|
||||
*/
|
||||
int TtyReceive(char *mess,int length);
|
||||
|
||||
/* Map an opened file in memory. Size is the size to be mapped in bytes.
|
||||
*/
|
||||
void *Mmap(OpenFileId f, int size);
|
||||
|
||||
/* For debug purpose
|
||||
*/
|
||||
void Debug(int param);
|
||||
|
||||
#endif // IN_ASM
|
||||
#endif // SYSCALL_H
|
Loading…
Reference in New Issue
Block a user