From 80fc25010907ad9010d0583d584a83eccf936c60 Mon Sep 17 00:00:00 2001 From: Yorick Barbanneau Date: Mon, 11 Oct 2021 22:41:17 +0200 Subject: [PATCH] Add Syscall: Exit, PutChar, GetCar, PutString, GetString --- code/Makefile.common | 2 +- code/Makefile.dep | 1 + code/test/getstring.c | 13 +++++ code/test/putchar.c | 17 +++++++ code/test/putstring.c | 15 ++++++ code/test/start.S | 37 ++++++++++++++ code/threads/main.cc | 15 +++++- code/threads/system.cc | 13 ++++- code/threads/system.h | 7 +++ code/userprog/consoledriver.cc | 66 ++++++++++++++++++++++++ code/userprog/consoledriver.h | 25 +++++++++ code/userprog/exception.cc | 92 ++++++++++++++++++++++++++++++++++ code/userprog/progtest.cc | 33 +++++++++++- code/userprog/progtest.h | 4 +- code/userprog/syscall.h | 36 ++++++++----- 15 files changed, 359 insertions(+), 17 deletions(-) create mode 100644 code/test/getstring.c create mode 100644 code/test/putchar.c create mode 100644 code/test/putstring.c create mode 100644 code/userprog/consoledriver.cc create mode 100644 code/userprog/consoledriver.h diff --git a/code/Makefile.common b/code/Makefile.common index edc397b..51711e6 100644 --- a/code/Makefile.common +++ b/code/Makefile.common @@ -31,7 +31,7 @@ THREAD_O := main.o list.o scheduler.o synch.o synchlist.o \ stats.o sysdep.o timer.o USERPROG_O := addrspace.o bitmap.o exception.o progtest.o console.o \ - machine.o mipssim.o translate.o + consoledriver.o machine.o mipssim.o translate.o VM_O := diff --git a/code/Makefile.dep b/code/Makefile.dep index 55deb72..e42a43b 100644 --- a/code/Makefile.dep +++ b/code/Makefile.dep @@ -40,6 +40,7 @@ HOST += -DLINUX CFLAGS += -fsanitize=undefined LDFLAGS += -fsanitize=undefined +# décommenté TD1 - partie V #CFLAGS += -fsanitize=address #LDFLAGS += -fsanitize=address -lpthread endif diff --git a/code/test/getstring.c b/code/test/getstring.c new file mode 100644 index 0000000..a90b50b --- /dev/null +++ b/code/test/getstring.c @@ -0,0 +1,13 @@ +#include "syscall.h" + +int main() +{ + //char s; + //s = GetChar(); + //PutChar(s); + char t[100]; + GetString(t, 100); + PutString(t); + PutChar('\n'); + PutString("Ceci est un test de grande ampleur"); +} diff --git a/code/test/putchar.c b/code/test/putchar.c new file mode 100644 index 0000000..6239668 --- /dev/null +++ b/code/test/putchar.c @@ -0,0 +1,17 @@ +#include "syscall.h" +void print(char c, int n) +{ + int i; +//#if 0 + for (i = 0; i < n; i++) { + PutChar(c + i); + } + PutChar('\n'); +//#endif +} +int +main() +{ + print('a',4); + Halt(); +} diff --git a/code/test/putstring.c b/code/test/putstring.c new file mode 100644 index 0000000..8e0da84 --- /dev/null +++ b/code/test/putstring.c @@ -0,0 +1,15 @@ +#include "syscall.h" + +int main() +{ + // PutString("Te\n"); + // PutString("Tes\n"); + // PutString("Tes t\n"); + // // les deux derniers ne fonctionnent pas car ila dépassent la taille du + // // buffer: MAX_STRING_SIZE + // // + // // Maitenant que j'ai fais une boucle dans PutString, tout fonctionne bien + PutString("BonjourTout\n"); + PutString("Bonjour tout le monde\n"); + Exit(4); +} diff --git a/code/test/start.S b/code/test/start.S index cd9817f..54d4d82 100644 --- a/code/test/start.S +++ b/code/test/start.S @@ -146,6 +146,43 @@ Yield: j $31 .end Yield +#ifdef CHANGED + .globl PutChar + .ent PutChar +PutChar: + addiu $2,$0,SC_PutChar + syscall + j $31 + .end PutChar + + + .globl PutString + .ent PutString +PutString: + addiu $2,$0,SC_PutString + syscall + j $31 + .end PutString + + .globl GetChar + .ent GetChar + +GetChar: + addiu $2,$0,SC_GetChar + syscall + j $31 + .end PutChar + + + .globl GetString + .ent GetString +GetString: + addiu $2,$0,SC_GetString + syscall + j $31 + .end GetString +#endif + /* dummy function to keep gcc happy */ .globl __main .ent __main diff --git a/code/threads/main.cc b/code/threads/main.cc index cad9249..c14167d 100644 --- a/code/threads/main.cc +++ b/code/threads/main.cc @@ -18,7 +18,6 @@ #include "utility.h" #include "system.h" - #ifdef USER_PROGRAM #include "progtest.h" #endif @@ -118,6 +117,7 @@ main (int argc, char **argv) if (!strcmp (*argv, "-x")) { // run a user program ASSERT (argc > 1); + consoledriver = new ConsoleDriver(NULL,NULL); StartProcess (*(argv + 1)); argCount = 2; } @@ -132,6 +132,19 @@ main (int argc, char **argv) argCount = 3; } } +#ifdef CHANGED + else if (!strcmp (*argv, "-sc")) + { // test the consoledriver + if (argc == 1) + ConsoleDriverTest (NULL, NULL); + else + { + ASSERT (argc > 2); + ConsoleDriverTest (*(argv + 1), *(argv + 2)); + argCount = 3; + } + } +#endif // CHANGE #endif // USER_PROGRAM #ifdef FILESYS if (!strcmp (*argv, "-cp")) diff --git a/code/threads/system.cc b/code/threads/system.cc index ef3da5f..cdf04fd 100644 --- a/code/threads/system.cc +++ b/code/threads/system.cc @@ -33,7 +33,12 @@ SynchDisk *synchDisk; #ifdef USER_PROGRAM // requires either FILESYS or FILESYS_STUB Machine *machine; // user program memory and registers -#endif + +#ifdef CHANGED // Define our consoledriver Object +ConsoleDriver *consoledriver; +#endif // CHANGED + +#endif // USER_PROGRAM #ifdef NETWORK PostOffice *postOffice; @@ -230,6 +235,12 @@ Cleanup () delete machine; machine = NULL; } +#ifdef CHANGED + if (consoledriver) { + delete consoledriver; + consoledriver = NULL; + } +#endif #endif #ifdef FILESYS_NEEDED diff --git a/code/threads/system.h b/code/threads/system.h index 3cb2097..763f5d3 100644 --- a/code/threads/system.h +++ b/code/threads/system.h @@ -32,6 +32,13 @@ extern Timer *timer; // the hardware alarm clock #ifdef USER_PROGRAM #include "machine.h" extern Machine *machine; // user program memory and registers + +#ifdef CHANGED +#define MAX_STRING_SIZE 8 +#include "consoledriver.h" +extern ConsoleDriver *consoledriver; // add console driver +#endif + #endif #ifdef FILESYS_NEEDED // FILESYS or FILESYS_STUB diff --git a/code/userprog/consoledriver.cc b/code/userprog/consoledriver.cc new file mode 100644 index 0000000..5386d0f --- /dev/null +++ b/code/userprog/consoledriver.cc @@ -0,0 +1,66 @@ +#ifdef CHANGED +#include "copyright.h" +#include "system.h" +#include "consoledriver.h" +#include "synch.h" + +#define STRINGBUFFER 8 + +static Semaphore *readAvail; +static Semaphore *writeDone; + +static void ReadAvailHandler(void *arg) { (void) arg; readAvail->V(); } +static void WriteDoneHandler(void *arg) { (void) arg; writeDone->V(); } + +ConsoleDriver::ConsoleDriver(const char *in, const char *out) +{ + readAvail = new Semaphore("read avail", 0); + writeDone = new Semaphore("write done", 0); + console = new Console (in, out, ReadAvailHandler, WriteDoneHandler, NULL); +} + +ConsoleDriver::~ConsoleDriver() +{ + delete console; + delete writeDone; + delete readAvail; +} + +void ConsoleDriver::PutChar( int ch) +{ + console->TX(ch); + writeDone->P(); +} + +int ConsoleDriver::GetChar() +{ + readAvail->P(); + int ch = console->RX(); + return ch; +} + +void ConsoleDriver::PutString(const char s[MAX_STRING_SIZE]) +{ + int i; + for (i = 0; i < MAX_STRING_SIZE; i++){ + if (*(s+i) =='\0'){ + return; + } + PutChar(*(s+i)); + } +} + +void ConsoleDriver::GetString(char * s, int n) +{ + int i; + for ( i = 0; i < n - 1; i++){ + char c = GetChar(); + if ( c == '\0' || c == '\n' || c == EOF) { + break; + } + *(s+i) = c; + } + *(s+i) = '\0'; +} + +#endif // CHANGED diff --git a/code/userprog/consoledriver.h b/code/userprog/consoledriver.h new file mode 100644 index 0000000..9f49ad5 --- /dev/null +++ b/code/userprog/consoledriver.h @@ -0,0 +1,25 @@ +#ifdef CHANGED +#ifndef CONSOLEDRIVER_H +#define CONSOLEDRIVER_H + +#include "copyright.h" +#include "utility.h" +#include "console.h" + +class ConsoleDriver:dontcopythis { + public: + // initialize the hardware console device + ConsoleDriver(const char *readFile, const char *writeFile); + + ~ConsoleDriver(); // clean up + + void PutChar(int ch); // Behaves like putchar(3S) + int GetChar(); // Behaves like getchar(3S) + + void PutString(const char *s); // Behaves like fputs(3S) + void GetString(char *s, int n); // Behaves like fgets(3S) + private: + Console *console; +}; +#endif // CONSOLEDRIVER_H +#endif // CHANGED diff --git a/code/userprog/exception.cc b/code/userprog/exception.cc index c2986db..e852696 100644 --- a/code/userprog/exception.cc +++ b/code/userprog/exception.cc @@ -63,6 +63,37 @@ UpdatePC () // "which" is the kind of exception. The list of possible exceptions // are in machine.h. //---------------------------------------------------------------------- +int copyStringFromMachine(int from, char *to, unsigned size) +{ + unsigned i = 0; + int res; + + // Need to read size-1 to put final /0 if needed + while((iReadMem(from+i,1,&res))){ + *(to+i) = (char)res; + if ((char)res == '\0'){ + return i; + } + i++; + } + *(to+i)='\0'; + return size; +} + +int copyStringToMachine(int to, char* from, unsigned size) +{ + unsigned i; + for (i=0; i < size - 1; i++) { + if (from[i] == '\0') { + break; + } + machine->WriteMem(to+i,1,(int)from[i]); + } + + // Write the last /0 + machine->WriteMem(to+i,1,'\0'); + return i; +} void ExceptionHandler (ExceptionType which) @@ -82,6 +113,67 @@ ExceptionHandler (ExceptionType which) interrupt->Powerdown (); break; } + #ifdef CHANGED + case SC_Exit: + { + int ret = machine->ReadRegister(4); + printf("Exit code %d\n", ret); + interrupt->Powerdown(); + break; + } + case SC_PutChar: + { + DEBUG ('s', "PutChar.\n"); + consoledriver->PutChar((char)machine->ReadRegister(4)); + break; + } + case SC_PutString: + { + + DEBUG ('s', "PutString.\n"); + int readsize; + int addr_start = machine->ReadRegister(4); + do { + char* read = new char[MAX_STRING_SIZE]; + readsize = copyStringFromMachine( addr_start, read, MAX_STRING_SIZE); + consoledriver->PutString(read); + // beware, the last element of our buffer was added by + // copyStringFromMachine(), we need to remove one memory case + // or the first char of our next read will be + // forgotten + addr_start += readsize - 1; + delete [] read; + } while(readsize == MAX_STRING_SIZE); + break; + } + case SC_GetChar: + { + DEBUG ('s', "GetChar.\n"); + // Get the char input an write it to the register n.2 + int c = consoledriver->GetChar(); + machine->WriteRegister((2), c); + break; + } + + case SC_GetString: + { + DEBUG ('s', "GetString.\n"); + int writesize = 0; + int addr = machine->ReadRegister(4); + int size = machine->ReadRegister(5); + DEBUG ('s', "size:%d\n", size); + do { + char* write = new char[MAX_STRING_SIZE]; + consoledriver->GetString(write, MAX_STRING_SIZE); + printf("write:%s:\n", write); + writesize = copyStringToMachine(addr, write, MAX_STRING_SIZE); + addr += writesize; + printf("Writed:%d\n", writesize); + delete [] write; + } while( writesize == MAX_STRING_SIZE - 1 ); + break; + } + #endif default: { printf("Unimplemented system call %d\n", type); diff --git a/code/userprog/progtest.cc b/code/userprog/progtest.cc index 5725dbd..90d0de3 100644 --- a/code/userprog/progtest.cc +++ b/code/userprog/progtest.cc @@ -10,6 +10,7 @@ #include "copyright.h" #include "system.h" +#include "consoledriver.h" #include "console.h" #include "addrspace.h" #include "synch.h" @@ -84,7 +85,7 @@ void ConsoleTest (const char *in, const char *out) { char ch; - + printf("test console\n<"); readAvail = new Semaphore ("read avail", 0); writeDone = new Semaphore ("write done", 0); console = new Console (in, out, ReadAvailHandler, WriteDoneHandler, NULL); @@ -93,14 +94,44 @@ ConsoleTest (const char *in, const char *out) { readAvail->P (); // wait for character to arrive ch = console->RX (); + #ifdef CHANGED + // My modifications... + // Check input before display it... + if (ch == 'q' || ch == -1 ) { + printf ("au revoir!\n"); + break; // if q, quit + } + + console->TX ('<'); + writeDone->P (); + console->TX (ch); // echo it! + writeDone->P (); // wait for write to finish + console->TX ('>'); + writeDone->P (); + #else console->TX (ch); // echo it! writeDone->P (); // wait for write to finish if (ch == 'q') { printf ("Nothing more, bye!\n"); break; // if q, quit } + #endif } delete console; delete readAvail; delete writeDone; } + +#ifdef CHANGED +void +ConsoleDriverTest (const char *in, const char *out) +{ + printf("test consoledriver\n"); + char ch; + ConsoleDriver *test_consoledriver = new ConsoleDriver(in, out); + while ((ch = test_consoledriver->GetChar()) != EOF) + test_consoledriver->PutChar(ch); + fprintf(stderr, "EOF detected in ConsoleDriver!\n"); + delete test_consoledriver; +} +#endif //CHANGED diff --git a/code/userprog/progtest.h b/code/userprog/progtest.h index af0a1f0..070625f 100644 --- a/code/userprog/progtest.h +++ b/code/userprog/progtest.h @@ -14,5 +14,7 @@ extern void StartProcess (char *filename); extern void ConsoleTest (const char *in, const char *out); - +#ifdef CHANGED +extern void ConsoleDriverTest (const char *in, const char *out); +#endif //CHANGED #endif // PROGTEST_H diff --git a/code/userprog/syscall.h b/code/userprog/syscall.h index 6c9e6e3..a072008 100644 --- a/code/userprog/syscall.h +++ b/code/userprog/syscall.h @@ -20,18 +20,23 @@ /* 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_Close 8 -#define SC_Fork 9 -#define SC_Yield 10 - +#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_Close 8 +#define SC_Fork 9 +#define SC_Yield 10 +#ifdef CHANGED +#define SC_PutChar 11 // My first SysCall :') +#define SC_PutString 12 +#define SC_GetChar 13 +#define SC_GetString 14 +#endif #ifdef IN_USER_MODE // LB: This part is read only on compiling the test/*.c files. @@ -130,6 +135,13 @@ void Fork (void (*func) ()); */ void Yield (); +#ifdef CHANGED +void PutChar (char c); +void PutString (char * s); +void GetChar(char c); +void GetString(char * s, int n ); +#endif // CHANGED + #endif // IN_USER_MODE #endif /* SYSCALL_H */