diff -r -u --new-file --exclude='*.patch--exclude=*.o' --exclude='Makefile*' --exclude=do_diff --exclude='*.patch' /home/bekone/nachos/machine/interrupt.cc /home/bekone/jikos/machine/interrupt.cc --- /home/bekone/nachos/machine/interrupt.cc Sun Nov 11 17:17:37 2001 +++ /home/bekone/jikos/machine/interrupt.cc Thu Dec 20 16:57:24 2001 @@ -41,7 +41,7 @@ // "kind" is the hardware device that generated the interrupt //---------------------------------------------------------------------- -PendingInterrupt::PendingInterrupt(VoidFunctionPtr func, int param, int time, +PendingInterrupt::PendingInterrupt(VoidFunctionPtr func, int param, tickT time, IntType kind) { handler = func; @@ -74,7 +74,7 @@ Interrupt::~Interrupt() { while (!pending->IsEmpty()) - delete pending->Remove(); + delete (PendingInterrupt *) pending->Remove(); delete pending; } @@ -162,6 +162,7 @@ } DEBUG('i', "\n== Tick %d ==\n", stats->totalTicks); +// fprintf(stderr, "\n== Tick %d ==\n", stats->totalTicks); // check any pending interrupts are now ready to fire ChangeLevel(IntOn, IntOff); // first, turn off interrupts // (interrupt handlers run with @@ -262,15 +263,32 @@ // "type" is the hardware device that generated the interrupt //---------------------------------------------------------------------- void -Interrupt::Schedule(VoidFunctionPtr handler, int arg, int fromNow, IntType type) +Interrupt::Schedule(VoidFunctionPtr handler, int arg, tickT fromNow, IntType type) { - int when = stats->totalTicks + fromNow; +// printf("%lld\n",stats->totalTicks); + ASSERT(stats->totalTicks >= 0); // jikos : neostra nerovnost - pri nahodnych Yieldech by spadlo, protoze by se zavolalo uplne na zacatku (0 tiku) + tickT when = stats->totalTicks + fromNow; PendingInterrupt *toOccur = new PendingInterrupt(handler, arg, when, type); - - DEBUG('i', "Scheduling interrupt handler the %s at time = %d\n", +/* + DEBUG('i', "Scheduling interrupt handler the %s at time = %ld\n", intTypeNames[type], when); - ASSERT(fromNow > 0); - +*/ +// printf("Scheduling interrupt handler the %s at time = %d\n", +// intTypeNames[type], when); + + if (!(fromNow > 0)) + { + printf("fromNow is WRONG!\n"); + printf("Sheduling interrupt - %lld / %lld\n", fromNow, when); + while (1) ; + + } + if (!(when > 0)) + { + printf("when is WRONG!\n"); + printf("Sheduling interrupt - %lld / %lld\n", fromNow, when); + while (1) ; + } pending->SortedInsert(toOccur, when); } @@ -291,7 +309,7 @@ Interrupt::CheckIfDue(bool advanceClock) { MachineStatus old = status; - int when; + tickT when; ASSERT(level == IntOff); // interrupts need to be disabled, // to invoke an interrupt handler @@ -346,7 +364,7 @@ { PendingInterrupt *pend = (PendingInterrupt *)arg; - printf("Interrupt handler %s, scheduled at %d\n", + printf("Interrupt handler %s, scheduled at %lld\n", intTypeNames[pend->type], pend->when); } @@ -359,7 +377,7 @@ void Interrupt::DumpState() { - printf("Time: %d, interrupts %s\n", stats->totalTicks, + printf("Time: %lld, interrupts %s\n", stats->totalTicks, intLevelNames[level]); printf("Pending interrupts:\n"); fflush(stdout); diff -r -u --new-file --exclude='*.patch--exclude=*.o' --exclude='Makefile*' --exclude=do_diff --exclude='*.patch' /home/bekone/nachos/machine/interrupt.h /home/bekone/jikos/machine/interrupt.h --- /home/bekone/nachos/machine/interrupt.h Sun Nov 21 09:44:08 1993 +++ /home/bekone/jikos/machine/interrupt.h Tue Dec 18 19:57:59 2001 @@ -58,14 +58,14 @@ class PendingInterrupt { public: - PendingInterrupt(VoidFunctionPtr func, int param, int time, IntType kind); + PendingInterrupt(VoidFunctionPtr func, int param, tickT time, IntType kind); // initialize an interrupt that will // occur in the future VoidFunctionPtr handler; // The function (in the hardware device // emulator) to call when the interrupt occurs int arg; // The argument to the function. - int when; // When the interrupt is supposed to fire + tickT when; // When the interrupt is supposed to fire IntType type; // for debugging }; @@ -107,7 +107,7 @@ // hardware device simulators. void Schedule(VoidFunctionPtr handler,// Schedule an interrupt to occur - int arg, int when, IntType type);// at time ``when''. This is called + int arg, tickT when, IntType type);// at time ``when''. This is called // by the hardware device simulators. void OneTick(); // Advance simulated time diff -r -u --new-file --exclude='*.patch--exclude=*.o' --exclude='Makefile*' --exclude=do_diff --exclude='*.patch' /home/bekone/nachos/machine/machine.cc /home/bekone/jikos/machine/machine.cc --- /home/bekone/nachos/machine/machine.cc Mon Oct 19 19:39:58 1998 +++ /home/bekone/jikos/machine/machine.cc Wed Dec 19 21:37:04 2001 @@ -9,6 +9,7 @@ #include "copyright.h" #include "machine.h" +#include "alloc.h" #include "system.h" #include @@ -64,12 +65,20 @@ mainMemory[i] = 0; #ifdef USE_TLB tlb = new TranslationEntry[TLBSize]; + printf("Created new TLB\n"); for (i = 0; i < TLBSize; i++) tlb[i].valid = FALSE; pageTable = NULL; #else // use linear page table tlb = NULL; pageTable = NULL; + +/* s_freePages *s_first = new s_freePages; // vytvorime spojovy seznam, ktery bude + s_first->begins=0; // udrzovat seznam bloku pameti (poc. a konc. stranka), + s_first->size=NumPhysPages; // kde se vyskytuji volne stranky + freePages = new List; // a na zacatku ho nainicalizujeme + freePages->Append((void *)s_first);// na celou pamet +*/ #endif singleStep = debug; @@ -83,6 +92,8 @@ Machine::~Machine() { +// delete freePages; // a zrusime spojak + delete [] mainMemory; if (tlb != NULL) delete [] tlb; diff -r -u --new-file --exclude='*.patch--exclude=*.o' --exclude='Makefile*' --exclude=do_diff --exclude='*.patch' /home/bekone/nachos/machine/machine.h /home/bekone/jikos/machine/machine.h --- /home/bekone/nachos/machine/machine.h Mon Nov 22 04:06:38 1993 +++ /home/bekone/jikos/machine/machine.h Sun Dec 23 10:28:58 2001 @@ -21,10 +21,15 @@ #ifndef MACHINE_H #define MACHINE_H + #include "copyright.h" +#include "types.h" #include "utility.h" #include "translate.h" #include "disk.h" +#include "alloc.h" +#include "list.h" +// nase prace s fyz. strankami // Definitions related to the size, and format of user memory @@ -32,7 +37,7 @@ // the disk sector size, for // simplicity -#define NumPhysPages 32 +#define NumPhysPages 1024 #define MemorySize (NumPhysPages * PageSize) #define TLBSize 4 // if there is a TLB, make it small @@ -131,6 +136,10 @@ // Read or write 1, 2, or 4 bytes of virtual // memory (at addr). Return FALSE if a // correct translation couldn't be found. + + int GetPhysPage(); // najde volnou fyzickou stranku v mainMemory + + void FreePhysPage(unsigned int num); // uvolni fyzickou stranku cislo num ExceptionType Translate(int virtAddr, int* physAddr, int size,bool writing); // Translate an address, and check for @@ -185,8 +194,10 @@ private: bool singleStep; // drop back into the debugger after each // simulated instruction - int runUntilTime; // drop back into the debugger when simulated + tickT runUntilTime; // drop back into the debugger when simulated // time reaches this value +// List *freePages; // globalni seznam volnych fyzickych stranek + }; extern void ExceptionHandler(ExceptionType which); diff -r -u --new-file --exclude='*.patch--exclude=*.o' --exclude='Makefile*' --exclude=do_diff --exclude='*.patch' /home/bekone/nachos/machine/mipssim.cc /home/bekone/jikos/machine/mipssim.cc --- /home/bekone/nachos/machine/mipssim.cc Sun Nov 21 12:34:06 1993 +++ /home/bekone/jikos/machine/mipssim.cc Sun Dec 23 10:29:50 2001 @@ -33,7 +33,7 @@ Instruction *instr = new Instruction; // storage for decoded instruction if(DebugIsEnabled('m')) - printf("Starting thread \"%s\" at time %d\n", + printf("Starting thread \"%s\" at time %lld\n", currentThread->getName(), stats->totalTicks); interrupt->setStatus(UserMode); for (;;) { @@ -108,7 +108,7 @@ struct OpString *str = &opStrings[instr->opCode]; ASSERT(instr->opCode <= MaxOpcode); - printf("At PC = 0x%x: ", registers[PCReg]); + printf("At PC = 0x%x: %d ", registers[PCReg], registers[29]); printf(str->string, TypeToReg(str->args[0], instr), TypeToReg(str->args[1], instr), TypeToReg(str->args[2], instr)); printf("\n"); diff -r -u --new-file --exclude='*.patch--exclude=*.o' --exclude='Makefile*' --exclude=do_diff --exclude='*.patch' /home/bekone/nachos/machine/stats.cc /home/bekone/jikos/machine/stats.cc --- /home/bekone/nachos/machine/stats.cc Sun Nov 21 12:01:07 1993 +++ /home/bekone/jikos/machine/stats.cc Tue Dec 18 19:55:36 2001 @@ -33,7 +33,7 @@ void Statistics::Print() { - printf("Ticks: total %d, idle %d, system %d, user %d\n", totalTicks, + printf("Ticks: total %lld, idle %lld, system %lld, user %lld\n", totalTicks, idleTicks, systemTicks, userTicks); printf("Disk I/O: reads %d, writes %d\n", numDiskReads, numDiskWrites); printf("Console I/O: reads %d, writes %d\n", numConsoleCharsRead, diff -r -u --new-file --exclude='*.patch--exclude=*.o' --exclude='Makefile*' --exclude=do_diff --exclude='*.patch' /home/bekone/nachos/machine/stats.h /home/bekone/jikos/machine/stats.h --- /home/bekone/nachos/machine/stats.h Sun Nov 21 10:02:47 1993 +++ /home/bekone/jikos/machine/stats.h Tue Dec 18 19:49:23 2001 @@ -12,6 +12,7 @@ #define STATS_H #include "copyright.h" +#include "sysdep.h" // The following class defines the statistics that are to be kept // about Nachos behavior -- how much time (ticks) elapsed, how @@ -21,10 +22,10 @@ class Statistics { public: - int totalTicks; // Total time running Nachos - int idleTicks; // Time spent idle (no threads to run) - int systemTicks; // Time spent executing system code - int userTicks; // Time spent executing user code + tickT totalTicks; // Total time running Nachos + tickT idleTicks; // Time spent idle (no threads to run) + tickT systemTicks; // Time spent executing system code + tickT userTicks; // Time spent executing user code // (this is also equal to # of // user instructions executed) diff -r -u --new-file --exclude='*.patch--exclude=*.o' --exclude='Makefile*' --exclude=do_diff --exclude='*.patch' /home/bekone/nachos/machine/sysdep.cc /home/bekone/jikos/machine/sysdep.cc --- /home/bekone/nachos/machine/sysdep.cc Tue Nov 24 11:45:37 1998 +++ /home/bekone/jikos/machine/sysdep.cc Sat Dec 15 01:26:00 2001 @@ -50,7 +50,7 @@ // int open(const char *name, int flags, ...); #else // int creat(const char *name, unsigned short mode); -int open(const char *name, int flags, ...); +//int open(const char *name, int flags, ...); // void signal(int sig, VoidFunctionPtr func); -- this may work now! #ifdef HOST_i386 int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, @@ -65,8 +65,8 @@ // int read(int filedes, char *buf, int numBytes); // int write(int filedes, char *buf, int numBytes); // int lseek(int filedes, int offset, int whence); -int tell(int filedes); -int close(int filedes); +//int tell(int filedes); +//int close(int filedes); // int unlink(char *name); // definition varies slightly from platform to platform, so don't @@ -75,11 +75,11 @@ // extern int sendto(int s, void *msg, int len, int flags, void *to, int tolen); -void srand(unsigned seed); -int rand(void); -unsigned sleep(unsigned); -void abort(); -void exit(); +//void srand(unsigned seed); +//int rand(void); +//unsigned sleep(unsigned); +//void abort(); +//void exit(); // int mprotect(char *addr, int len, int prot); int socket(int, int, int); diff -r -u --new-file --exclude='*.patch--exclude=*.o' --exclude='Makefile*' --exclude=do_diff --exclude='*.patch' /home/bekone/nachos/machine/sysdep.h /home/bekone/jikos/machine/sysdep.h --- /home/bekone/nachos/machine/sysdep.h Wed Jan 12 00:51:19 1994 +++ /home/bekone/jikos/machine/sysdep.h Tue Dec 18 19:50:03 2001 @@ -58,12 +58,13 @@ // Other C library routines that are used by Nachos. // These are assumed to be portable, so we don't include a wrapper. extern "C" { -int atoi(const char *str); -double atof(const char *str); -int abs(int i); +//int atoi(const char *str); +//double atof(const char *str); +//int abs(int i); #include // for printf, fprintf #include // for DEBUG, etc. +#include } #endif // SYSDEP_H diff -r -u --new-file --exclude='*.patch--exclude=*.o' --exclude='Makefile*' --exclude=do_diff --exclude='*.patch' /home/bekone/nachos/machine/timer.cc /home/bekone/jikos/machine/timer.cc --- /home/bekone/nachos/machine/timer.cc Sun Oct 3 23:08:35 1993 +++ /home/bekone/jikos/machine/timer.cc Thu Dec 20 16:53:47 2001 @@ -48,6 +48,7 @@ arg = callArg; // schedule the first interrupt from the timer device + printf("tni: %d\n",TimeOfNextInterrupt()); interrupt->Schedule(TimerHandler, (int) this, TimeOfNextInterrupt(), TimerInt); } diff -r -u --new-file --exclude='*.patch--exclude=*.o' --exclude='Makefile*' --exclude=do_diff --exclude='*.patch' /home/bekone/nachos/machine/translate.cc /home/bekone/jikos/machine/translate.cc --- /home/bekone/nachos/machine/translate.cc Thu Jan 20 19:22:30 1994 +++ /home/bekone/jikos/machine/translate.cc Wed Dec 19 21:42:43 2001 @@ -199,9 +199,17 @@ return AddressErrorException; } + if (tlb != NULL) + { + fprintf(stderr, "Someone has set up us the TLB\n"); + } + if (pageTable == NULL) + { + fprintf(stderr, "Someone has deleted (not created) our pageTable\n"); + } // we must have either a TLB or a page table, but not both! ASSERT(tlb == NULL || pageTable == NULL); - ASSERT(tlb != NULL || pageTable != NULL); + ASSERT(tlb != NULL || pageTable != NULL); // calculate the virtual page number, and offset within the page, // from the virtual address diff -r -u --new-file --exclude='*.patch--exclude=*.o' --exclude='Makefile*' --exclude=do_diff --exclude='*.patch' /home/bekone/nachos/machine/types.h /home/bekone/jikos/machine/types.h --- /home/bekone/nachos/machine/types.h Thu Jan 1 01:00:00 1970 +++ /home/bekone/jikos/machine/types.h Tue Dec 18 19:52:35 2001 @@ -0,0 +1,6 @@ +#ifndef TYPES_H +#define TYPES_H + +typedef unsigned long long int tickT; + +#endif diff -r -u --new-file --exclude='*.patch--exclude=*.o' --exclude='Makefile*' --exclude=do_diff --exclude='*.patch' /home/bekone/nachos/test/halt.c /home/bekone/jikos/test/halt.c --- /home/bekone/nachos/test/halt.c Thu Nov 29 15:00:01 2001 +++ /home/bekone/jikos/test/halt.c Sat Dec 15 01:26:07 2001 @@ -15,6 +15,6 @@ int main() { -// Halt(); + Halt(); /* not reached */ } diff -r -u --new-file --exclude='*.patch--exclude=*.o' --exclude='Makefile*' --exclude=do_diff --exclude='*.patch' /home/bekone/nachos/test/idle.c /home/bekone/jikos/test/idle.c --- /home/bekone/nachos/test/idle.c Thu Jan 1 01:00:00 1970 +++ /home/bekone/jikos/test/idle.c Thu Dec 20 13:28:39 2001 @@ -0,0 +1,11 @@ +#include "syscall.h" + +int +main() +{ + char b; + for( ; ; ){ + Read(&b, 1, input); + Yield(); + } +} diff -r -u --new-file --exclude='*.patch--exclude=*.o' --exclude='Makefile*' --exclude=do_diff --exclude='*.patch' /home/bekone/nachos/test/jikos_A.c /home/bekone/jikos/test/jikos_A.c --- /home/bekone/nachos/test/jikos_A.c Thu Jan 1 01:00:00 1970 +++ /home/bekone/jikos/test/jikos_A.c Sun Dec 16 00:42:03 2001 @@ -0,0 +1,13 @@ +#include "syscall.h" + +char text[255]="A"; + +int +main() +{ + int f1; + + for(f1=1;f1<10;f1++){ + Write(text,1,ConsoleOutput);Yield(); + } +} diff -r -u --new-file --exclude='*.patch--exclude=*.o' --exclude='Makefile*' --exclude=do_diff --exclude='*.patch' /home/bekone/nachos/test/jikos_B.c /home/bekone/jikos/test/jikos_B.c --- /home/bekone/nachos/test/jikos_B.c Thu Jan 1 01:00:00 1970 +++ /home/bekone/jikos/test/jikos_B.c Sun Dec 16 00:42:16 2001 @@ -0,0 +1,13 @@ +#include "syscall.h" + +char text[255]="B"; + +int +main() +{ + int f1; + + for(f1=1;f1<10;f1++){ + Write(text,1,ConsoleOutput);Yield(); + } +} diff -r -u --new-file --exclude='*.patch--exclude=*.o' --exclude='Makefile*' --exclude=do_diff --exclude='*.patch' /home/bekone/nachos/test/jikos_files.c /home/bekone/jikos/test/jikos_files.c --- /home/bekone/nachos/test/jikos_files.c Thu Jan 1 01:00:00 1970 +++ /home/bekone/jikos/test/jikos_files.c Sat Dec 15 23:18:50 2001 @@ -0,0 +1,23 @@ +#include "syscall.h" + +char file1[255]="/home/bekone/jikos/aa"; +char file2[255]="/home/bekone/jikos/bb"; +char text1[255]="prvni text"; +char text2[255]="druhy text"; + +int +main() +{ + int f1,f2; + + Yield(); + Create(file1); Yield(); + Create(file2); Yield(); + f1=Open(file1); Yield(); + f2=Open(file2); Yield(); + Write(text1,11,f1); Yield(); + Write(text2,11,f2); Yield(); + Close(f1); Yield(); + Close(f2); Yield(); + +} diff -r -u --new-file --exclude='*.patch--exclude=*.o' --exclude='Makefile*' --exclude=do_diff --exclude='*.patch' /home/bekone/nachos/test/jikos_fork.c /home/bekone/jikos/test/jikos_fork.c --- /home/bekone/nachos/test/jikos_fork.c Thu Jan 1 01:00:00 1970 +++ /home/bekone/jikos/test/jikos_fork.c Fri Dec 28 16:28:24 2001 @@ -0,0 +1,58 @@ +#include "syscall.h" + +/* Forkuje 4 * 2 procesy - jeden vypisuje A, druhy B + + * zamek - ilustrace userlandovych synch. primitiv + * zamyka si kazdy thread cely svuj beh - jsou + * videt neprerusene retezce delky nasobku deviti + * stejnych pismen + * + * Pokud je odkomentovat TJoin() - ten se beztak + * zablokuje, takze je jedno, jestli je program spusten + * s nahodnymi Yieldy - vzdy se stejne ceka az trhead + * skonci + */ + +char text1[255]="Forkuji"; +char text2[255]="A"; +char text3[255]="B"; +LockId lid=0; // kdyz se to naneinicializuje, tak nejde zkompilovat ;o + +void procedure (int a) +{ + int i; + + Lock_Acquire(lid); + for(i=1;i<10;i++) + Write(text2,255,ConsoleOutput); + Lock_Release(lid); +} + +void procedure2 (int a) +{ + int i; + + Lock_Acquire(lid); + for(i=1;i<10;i++) + Write(text3,255,ConsoleOutput); + Lock_Release(lid); +} + +int +main() +{ + int i; + int tid,tid2; + + lid = CreateLock(); + ps(); + for(i=1;i<5;i++){ + Write(text1,255,ConsoleOutput); + tid = Fork(procedure, 0); + tid2 = Fork(procedure2, 0); +// TJoin(tid); + } +// DeleteLock(lid); +// tady nemuzeme ten zamek jeste zrusit, thready ho pouzivaji +// pri zaniku address spacu se zrusi samy +} diff -r -u --new-file --exclude='*.patch--exclude=*.o' --exclude='Makefile*' --exclude=do_diff --exclude='*.patch' /home/bekone/nachos/test/jikos_spawner.c /home/bekone/jikos/test/jikos_spawner.c --- /home/bekone/nachos/test/jikos_spawner.c Thu Jan 1 01:00:00 1970 +++ /home/bekone/jikos/test/jikos_spawner.c Sat Dec 29 00:33:35 2001 @@ -0,0 +1,16 @@ +#include "syscall.h" + +//char a[255]="/home/bekone/jikos/test/jikos_A"; +//char b[255]="/home/bekone/jikos/test/jikos_B"; +//char c[255]="/home/bekone/jikos/test/jikos_files"; +char d[255]="/home/bekone/jikos/test/jikos_fork"; + +int +main() +{ + SpaceId p; +/* p = Exec(a); + p = Exec(b); + p = Exec(c);*/ + p = Exec(d); +} diff -r -u --new-file --exclude='*.patch--exclude=*.o' --exclude='Makefile*' --exclude=do_diff --exclude='*.patch' /home/bekone/nachos/test/kill.c /home/bekone/jikos/test/kill.c --- /home/bekone/nachos/test/kill.c Thu Jan 1 01:00:00 1970 +++ /home/bekone/jikos/test/kill.c Thu Dec 20 13:38:44 2001 @@ -0,0 +1,12 @@ +#include "syscall.h" + +char a[50]="/home/bekone/roger/test/idle"; + +int +main() +{ + SpaceId p; + p = Exec(a); + Yield(); + Kill(p); +} diff -r -u --new-file --exclude='*.patch--exclude=*.o' --exclude='Makefile*' --exclude=do_diff --exclude='*.patch' /home/bekone/nachos/test/roger1.c /home/bekone/jikos/test/roger1.c --- /home/bekone/nachos/test/roger1.c Thu Jan 1 01:00:00 1970 +++ /home/bekone/jikos/test/roger1.c Mon Dec 17 19:09:47 2001 @@ -0,0 +1,11 @@ +#include "syscall.h" + +char text[255]="/home/bekone/roger/test/roger2"; + +int +main() +{ + int pid; + pid=Exec(text); + Join(pid); +} diff -r -u --new-file --exclude='*.patch--exclude=*.o' --exclude='Makefile*' --exclude=do_diff --exclude='*.patch' /home/bekone/nachos/test/roger2.c /home/bekone/jikos/test/roger2.c --- /home/bekone/nachos/test/roger2.c Thu Jan 1 01:00:00 1970 +++ /home/bekone/jikos/test/roger2.c Mon Dec 17 19:16:11 2001 @@ -0,0 +1,8 @@ +#include "syscall.h" + +char text[255]="/home/bekone/roger/test/roger2"; + +int +main() +{ +} diff -r -u --new-file --exclude='*.patch--exclude=*.o' --exclude='Makefile*' --exclude=do_diff --exclude='*.patch' /home/bekone/nachos/test/shell.c /home/bekone/jikos/test/shell.c --- /home/bekone/nachos/test/shell.c Sun Nov 21 06:54:46 1993 +++ /home/bekone/jikos/test/shell.c Fri Dec 28 00:28:31 2001 @@ -11,6 +11,7 @@ prompt[0] = '-'; prompt[1] = '-'; + prompt[2] = '\0'; while( 1 ) { @@ -20,15 +21,23 @@ do { - Read(&buffer[i], 1, input); + Read(&buffer[i], 1, input); +// Write(&buffer[i], 1, output); } while( buffer[i++] != '\n' ); buffer[--i] = '\0'; if( i > 0 ) { + if (buffer[0]=='^') + { + ps(); + } + else + { newProc = Exec(buffer); Join(newProc); + } } } } diff -r -u --new-file --exclude='*.patch--exclude=*.o' --exclude='Makefile*' --exclude=do_diff --exclude='*.patch' /home/bekone/nachos/test/spawn.c /home/bekone/jikos/test/spawn.c --- /home/bekone/nachos/test/spawn.c Thu Jan 1 01:00:00 1970 +++ /home/bekone/jikos/test/spawn.c Tue Dec 18 13:46:51 2001 @@ -0,0 +1,22 @@ +#include "syscall.h" + +char a[255]="/home/bekone/jikos/test/jikos_A"; +char b[255]="/home/bekone/jikos/test/jikos_B"; +char c[255]="/home/bekone/jikos/test/jikos_files"; + +int +main() +{ + Exec(a); + Yield(); + Exec(b); + Yield(); + Exec(c); + Yield(); + Exec(a); + Yield(); + Exec(b); + Yield(); + Exec(c); + Yield(); +} diff -r -u --new-file --exclude='*.patch--exclude=*.o' --exclude='Makefile*' --exclude=do_diff --exclude='*.patch' /home/bekone/nachos/test/start.s /home/bekone/jikos/test/start.s --- /home/bekone/nachos/test/start.s Tue Jan 11 21:50:22 1994 +++ /home/bekone/jikos/test/start.s Fri Dec 28 16:10:01 2001 @@ -130,6 +130,143 @@ j $31 .end Yield + .globl Kill + .ent Kill +Kill: + addiu $2,$0,SC_Kill + syscall + j $31 + .end Kill + + .globl TJoin + .ent TJoin +TJoin: + addiu $2,$0,SC_TJoin + syscall + j $31 + .end TJoin + + .globl TKill + .ent TKill +TKill: + addiu $2,$0,SC_TKill + syscall + j $31 + .end TKill + + .globl ps + .ent ps +ps: + addiu $2,$0,SC_ps + syscall + j $31 + .end ps + +/* synchronizace */ + .globl CreateLock + .ent CreateLock +CreateLock: + addiu $2,$0,SC_CreateLock + syscall + j $31 + .end CreateLock + + .globl CreateSem + .ent CreateSem +CreateSem: + addiu $2,$0,SC_CreateSem + syscall + j $31 + .end CreateSem + + .globl CreateCond + .ent CreateCond +CreateCond: + addiu $2,$0,SC_CreateCond + syscall + j $31 + .end CreateCond + + .globl Lock_Acquire + .ent Lock_Acquire +Lock_Acquire: + addiu $2,$0,SC_Lock_Acquire + syscall + j $31 + .end Lock_Acquire + + .globl Lock_Release + .ent Lock_Release +Lock_Release: + addiu $2,$0,SC_Lock_Release + syscall + j $31 + .end Lock_Release + + .globl Sem_P + .ent Sem_P +Sem_P: + addiu $2,$0,SC_Sem_P + syscall + j $31 + .end Sem_P + + .globl Sem_V + .ent Sem_V +Sem_V: + addiu $2,$0,SC_Sem_V + syscall + j $31 + .end Sem_V + + .globl + .ent Cond_Wait +Cond_Wait: + addiu $2,$0,SC_Cond_Wait + syscall + j $31 + .end Cond_Wait + + .globl Cond_Signal + .ent Cond_Signal +Cond_Signal: + addiu $2,$0,SC_Cond_Signal + syscall + j $31 + .end Cond_Signal + + .globl Cond_Broadcast + .ent Cond_Broadcast +Cond_Broadcast: + addiu $2,$0,SC_Cond_Broadcast + syscall + j $31 + .end Cond_Broadcast + + .globl DeleteLock + .ent DeleteLock +DeleteLock: + addiu $2,$0,SC_DeleteLock + syscall + j $31 + .end DeleteLock + + .globl DeleteSem + .ent DeleteSem +DeleteSem: + addiu $2,$0,SC_DeleteSem + syscall + j $31 + .end DeleteSem + + .globl DeleteCond + .ent DeleteCond +DeleteCond: + addiu $2,$0,SC_DeleteCond + syscall + j $31 + .end DeleteCond + /* dummy function to keep gcc happy */ .globl __main .ent __main diff -r -u --new-file --exclude='*.patch--exclude=*.o' --exclude='Makefile*' --exclude=do_diff --exclude='*.patch' /home/bekone/nachos/threads/list.cc /home/bekone/jikos/threads/list.cc --- /home/bekone/nachos/threads/list.cc Sun Oct 3 23:08:46 1993 +++ /home/bekone/jikos/threads/list.cc Tue Dec 18 19:48:24 2001 @@ -27,7 +27,7 @@ // "sortKey" is the priority of the item, if any. //---------------------------------------------------------------------- -ListElement::ListElement(void *itemPtr, int sortKey) +ListElement::ListElement(void *itemPtr, tickT sortKey) { item = itemPtr; key = sortKey; @@ -176,7 +176,7 @@ //---------------------------------------------------------------------- void -List::SortedInsert(void *item, int sortKey) +List::SortedInsert(void *item, tickT sortKey) { ListElement *element = new ListElement(item, sortKey); ListElement *ptr; // keep track @@ -215,7 +215,7 @@ //---------------------------------------------------------------------- void * -List::SortedRemove(int *keyPtr) +List::SortedRemove(tickT *keyPtr) { ListElement *element = first; void *thing; @@ -235,4 +235,3 @@ delete element; return thing; } - diff -r -u --new-file --exclude='*.patch--exclude=*.o' --exclude='Makefile*' --exclude=do_diff --exclude='*.patch' /home/bekone/nachos/threads/list.h /home/bekone/jikos/threads/list.h --- /home/bekone/nachos/threads/list.h Sun Oct 3 23:08:48 1993 +++ /home/bekone/jikos/threads/list.h Tue Dec 18 19:53:34 2001 @@ -26,11 +26,11 @@ class ListElement { public: - ListElement(void *itemPtr, int sortKey); // initialize a list element + ListElement(void *itemPtr, tickT sortKey); // initialize a list element ListElement *next; // next element on list, // NULL if this is the last - int key; // priority, for a sorted list + tickT key; // priority, for a sorted list void *item; // pointer to item on the list }; @@ -55,8 +55,8 @@ // Routines to put/get items on/off list in order (sorted by key) - void SortedInsert(void *item, int sortKey); // Put item into list - void *SortedRemove(int *keyPtr); // Remove first item from list + void SortedInsert(void *item, tickT sortKey); // Put item into list + void *SortedRemove(tickT *keyPtr); // Remove first item from list private: ListElement *first; // Head of the list, NULL if list is empty diff -r -u --new-file --exclude='*.patch--exclude=*.o' --exclude='Makefile*' --exclude=do_diff --exclude='*.patch' /home/bekone/nachos/threads/main.cc /home/bekone/jikos/threads/main.cc --- /home/bekone/nachos/threads/main.cc Tue Sep 13 22:54:01 1994 +++ /home/bekone/jikos/threads/main.cc Fri Dec 28 14:54:46 2001 @@ -52,7 +52,24 @@ #include "utility.h" #include "system.h" +#include "synch.h" +#ifdef USER_PROGRAM +#include "alloc.h" +#include "process.h" +#include "console.h" +Alloc *alloc; +ProcList *PList; +DescriptorTable *descriptortable; +Console *console; +Semaphore *readAvail; +Semaphore *writeDone; + +void ReadAvail(int arg) { readAvail->V(); } +void WriteDone(int arg) { writeDone->V(); } + + +#endif // External functions used by this file @@ -61,6 +78,10 @@ extern void StartProcess(char *file), ConsoleTest(char *in, char *out); extern void MailTest(int networkID); +#define MAXTHREADS 20 + // maximalni pocet threadu +#define MAXFILESOPEN 20 + // maximalni pocet otevrenych souboru //---------------------------------------------------------------------- // main // Bootstrap the operating system kernel. @@ -81,29 +102,43 @@ int argCount; // the number of arguments // for a particular command - DEBUG('t', "Entering main"); (void) Initialize(argc, argv); #ifdef THREADS ThreadTest(); #endif +#ifdef USER_PROGRAM + alloc = new Alloc; + PList = new ProcList; + descriptortable = new DescriptorTable; + writeDone = new Semaphore("writesem",0); + readAvail = new Semaphore("readsem",0); + console = new Console((char *)NULL,(char *)NULL,ReadAvail,WriteDone,0); +#endif + for (argc--, argv++; argc > 0; argc -= argCount, argv += argCount) { argCount = 1; if (!strcmp(*argv, "-z")) // print copyright printf (copyright); #ifdef USER_PROGRAM +// je treba alokovat struktury pro udrzovani informaci o strankovacich tabulkach +// take o descriptorech +// nemelo by se dat do system.cc ? + if (!strcmp(*argv, "-x")) { // run a user program ASSERT(argc > 1); + printf("Running user program\n"); StartProcess(*(argv + 1)); argCount = 2; } else if (!strcmp(*argv, "-c")) { // test the console + printf("Testing console\n"); if (argc == 1) - ConsoleTest(NULL, NULL); + /*ConsoleTest(NULL, NULL)*/; else { ASSERT(argc > 2); - ConsoleTest(*(argv + 1), *(argv + 2)); - argCount = 3; +/* ConsoleTest(*(argv + 1), *(argv + 2)); + argCount = 3;*/ } interrupt->Halt(); // once we start the console, then // Nachos will loop forever waiting @@ -142,7 +177,7 @@ } #endif // NETWORK } - + printf("Finishing main thread\n"); currentThread->Finish(); // NOTE: if the procedure "main" // returns, then the program "nachos" // will exit (as any other normal program diff -r -u --new-file --exclude='*.patch--exclude=*.o' --exclude='Makefile*' --exclude=do_diff --exclude='*.patch' /home/bekone/nachos/threads/main.cc.my /home/bekone/jikos/threads/main.cc.my --- /home/bekone/nachos/threads/main.cc.my Thu Jan 1 01:00:00 1970 +++ /home/bekone/jikos/threads/main.cc.my Tue Dec 18 17:04:36 2001 @@ -0,0 +1,187 @@ +// main.cc +// Bootstrap code to initialize the operating system kernel. +// +// Allows direct calls into internal operating system functions, +// to simplify debugging and testing. In practice, the +// bootstrap code would just initialize data structures, +// and start a user program to print the login prompt. +// +// Most of this file is not needed until later assignments. +// +// Usage: nachos -d -rs +// -s -x -c +// -f -cp +// -p -r -l -D -t +// -n -m +// -o +// -z +// +// -d causes certain debugging messages to be printed (cf. utility.h) +// -rs causes Yield to occur at random (but repeatable) spots +// -z prints the copyright message +// +// USER_PROGRAM +// -s causes user programs to be executed in single-step mode +// -x runs a user program +// -c tests the console +// +// FILESYS +// -f causes the physical disk to be formatted +// -cp copies a file from UNIX to Nachos +// -p prints a Nachos file to stdout +// -r removes a Nachos file from the file system +// -l lists the contents of the Nachos directory +// -D prints the contents of the entire file system +// -t tests the performance of the Nachos file system +// +// NETWORK +// -n sets the network reliability +// -m sets this machine's host id (needed for the network) +// -o runs a simple test of the Nachos network software +// +// NOTE -- flags are ignored until the relevant assignment. +// Some of the flags are interpreted here; some in system.cc. +// +// Copyright (c) 1992-1993 The Regents of the University of California. +// All rights reserved. See copyright.h for copyright notice and limitation +// of liability and disclaimer of warranty provisions. + +#define MAIN +#include "copyright.h" +#undef MAIN + +#include "utility.h" +#include "system.h" +#include "synch.h" + +#ifdef USER_PROGRAM +#include "alloc.h" +#include "process.h" +#include "console.h" +Alloc *alloc; +ProcList *PList; +DescriptorTable *descriptortable; +Console *console; +Semaphore *readAvail; +Semaphore *writeDone; + +void ReadAvail(int arg) { readAvail->V(); } +void WriteDone(int arg) { writeDone->V(); } + + +#endif + +// External functions used by this file + +extern void ThreadTest(void), Copy(char *unixFile, char *nachosFile); +extern void Print(char *file), PerformanceTest(void); +extern void StartProcess(char *file), ConsoleTest(char *in, char *out); +extern void MailTest(int networkID); + +#define MAXTHREADS 20 // maximalni pocet threadu +#define MAXFILESOPEN 20 // maximalni pocet otevrenych souboru + +//---------------------------------------------------------------------- +// main +// Bootstrap the operating system kernel. +// +// Check command line arguments +// Initialize data structures +// (optionally) Call test procedure +// +// "argc" is the number of command line arguments (including the name +// of the command) -- ex: "nachos -d +" -> argc = 3 +// "argv" is an array of strings, one for each command line argument +// ex: "nachos -d +" -> argv = {"nachos", "-d", "+"} +//---------------------------------------------------------------------- + +int +main(int argc, char **argv) +{ + int argCount; // the number of arguments + // for a particular command + +// DEBUG('t', "Entering main"); + (void) Initialize(argc, argv); + +#ifdef THREADS + ThreadTest(); +#endif + + for (argc--, argv++; argc > 0; argc -= argCount, argv += argCount) { + argCount = 1; + if (!strcmp(*argv, "-z")) // print copyright + printf (copyright); +#ifdef USER_PROGRAM +// je treba alokovat struktury pro udrzovani informaci o strankovacich tabulkach +// take o descriptorech +// nemelo by se dat do system.cc ? + alloc = new Alloc; + PList = new ProcList; + descriptortable = new DescriptorTable; + writeDone = new Semaphore("writesem",0); + readAvail = new Semaphore("readsem",0); + console = new Console((char *)NULL,(char *)NULL,ReadAvail,WriteDone,0); + + if (!strcmp(*argv, "-x")) { // run a user program + ASSERT(argc > 1); + printf("Running user program\n"); + StartProcess(*(argv + 1)); + argCount = 2; + } else if (!strcmp(*argv, "-c")) { // test the console + printf("Testing console\n"); + if (argc == 1) + /*ConsoleTest(NULL, NULL)*/; + else { + ASSERT(argc > 2); +/* ConsoleTest(*(argv + 1), *(argv + 2)); + argCount = 3;*/ + } + interrupt->Halt(); // once we start the console, then + // Nachos will loop forever waiting + // for console input + } +#endif // USER_PROGRAM +#ifdef FILESYS + if (!strcmp(*argv, "-cp")) { // copy from UNIX to Nachos + ASSERT(argc > 2); + Copy(*(argv + 1), *(argv + 2)); + argCount = 3; + } else if (!strcmp(*argv, "-p")) { // print a Nachos file + ASSERT(argc > 1); + Print(*(argv + 1)); + argCount = 2; + } else if (!strcmp(*argv, "-r")) { // remove Nachos file + ASSERT(argc > 1); + fileSystem->Remove(*(argv + 1)); + argCount = 2; + } else if (!strcmp(*argv, "-l")) { // list Nachos directory + fileSystem->List(); + } else if (!strcmp(*argv, "-D")) { // print entire filesystem + fileSystem->Print(); + } else if (!strcmp(*argv, "-t")) { // performance test + PerformanceTest(); + } +#endif // FILESYS +#ifdef NETWORK + if (!strcmp(*argv, "-o")) { + ASSERT(argc > 1); + Delay(2); // delay for 2 seconds + // to give the user time to + // start up another nachos + MailTest(atoi(*(argv + 1))); + argCount = 2; + } +#endif // NETWORK + } + printf("Finishing main thread\n"); + currentThread->Finish(); // NOTE: if the procedure "main" + // returns, then the program "nachos" + // will exit (as any other normal program + // would). But there may be other + // threads on the ready list. We switch + // to those threads by saying that the + // "main" thread is finished, preventing + // it from returning. + return(0); // Not reached... +} diff -r -u --new-file --exclude='*.patch--exclude=*.o' --exclude='Makefile*' --exclude=do_diff --exclude='*.patch' /home/bekone/nachos/threads/scheduler.cc /home/bekone/jikos/threads/scheduler.cc --- /home/bekone/nachos/threads/scheduler.cc Sun Oct 3 23:08:49 1993 +++ /home/bekone/jikos/threads/scheduler.cc Fri Dec 28 17:05:33 2001 @@ -30,6 +30,7 @@ Scheduler::Scheduler() { readyList = new List; + exhaustedList = new List; } //---------------------------------------------------------------------- @@ -40,6 +41,7 @@ Scheduler::~Scheduler() { delete readyList; + delete exhaustedList; } //---------------------------------------------------------------------- @@ -50,13 +52,36 @@ // "thread" is the thread to be put on the ready list. //---------------------------------------------------------------------- +/* Do fronty se proces SortedInsertne podle priority, + * a poznamename si u nej, kolik jeste v tomto cyklu scheduleru + * ma bezet tiku + * pokud uz nema v tomto cyklu bezet, priradime do exhausted fronty + */ + void Scheduler::ReadyToRun (Thread *thread) { - DEBUG('t', "Putting thread %s on ready list.\n", thread->getName()); +/* DEBUG('t', "Putting thread %s on ready list.\n", thread->getName()); + thread->setStatus(READY); readyList->Append((void *)thread); +*/ + IntStatus old = interrupt->SetLevel(IntOff); // aby vic threadu najednou nerozvrtalo tyhle globalni fronty +// Print(); + if( (thread->toRun = ((stats->totalTicks - thread->tickStart>0) ? (stats->totalTicks - thread->tickStart) : 0)) ){ // TODO (?) penalizace threadu, ktery bezel dele nez mel urceno? v realnem svete by nemuselo nastat, kvuli prerusenim od casovace + // v tomto cyklu jeste nevycerpal svuj cas + DEBUG('t', "Putting thread %s on ready list.\n", thread->getName()); + thread->setStatus(READY); + readyList->SortedInsert((void *)thread,thread->priority); + } + else{ // uz vycerpal v tomto cyklu svuj cas + DEBUG('t', "Putting thread %s on exhausted list.\n", thread->getName()); + thread->setStatus(EXHAUSTED); + exhaustedList->Append((void *)thread); + } +// Print(); + interrupt->SetLevel(old); } //---------------------------------------------------------------------- @@ -67,10 +92,41 @@ // Thread is removed from the ready list. //---------------------------------------------------------------------- +/* exhausted fronta udrzuje procesy, ktere + * uz vycerpaly v tomto cyklu scheduleru svuj pridel casu + * pokud nebude zadny proces na ReadyListu, je treba vsechny + * procesy z teto nove fronty premistit do readyListu a znova + * spocitat kolik tiku maji v tomto cyklu bezet + * + * z readyListu se vybere prvni proces (jsou razeny podle priority, + * pocet tiku je asi jedno (?) + */ + Thread * Scheduler::FindNextToRun () { - return (Thread *)readyList->Remove(); +// return (Thread *)readyList->Remove(); + Thread *thread; + + +// Print(); + IntStatus old = interrupt->SetLevel(IntOff); // aby vic threadu najednou nerozvrtalo tyhle globalni fronty + if(readyList->IsEmpty()){ + // zacina dalsi cyklus scheduleru + while(!(exhaustedList->IsEmpty())){ + thread = (Thread *)exhaustedList->Remove(); + thread->toRun = 1000 - (thread->priority * 10); /* magie ;) - nizka cisla znamenaji kvuli SortedInsert() + * vysokou prioritu - takze procesum s nizkym cislem + * priradime, ze maji bezet hodne ticku + */ + thread->setStatus(READY); + readyList->SortedInsert((void *)thread,thread->priority); + } + } +// Print(); + return(Thread *)readyList->Remove(); // a jako driv, vratime proces s nejvyssi (=nejnizsim cislem ;) ) + interrupt->SetLevel(old); // prioritou, jako ze ten ma bezet + } //---------------------------------------------------------------------- @@ -93,6 +149,7 @@ Thread *oldThread = currentThread; #ifdef USER_PROGRAM // ignore until running user programs +#warning USER_PROGRAM if (currentThread->space != NULL) { // if this thread is a user program, currentThread->SaveUserState(); // save the user's CPU registers currentThread->space->SaveState(); @@ -104,6 +161,7 @@ currentThread = nextThread; // switch to the next thread currentThread->setStatus(RUNNING); // nextThread is now running + currentThread->tickStart = stats->totalTicks; DEBUG('t', "Switching from thread \"%s\" to thread \"%s\"\n", oldThread->getName(), nextThread->getName()); @@ -122,14 +180,22 @@ // before now (for example, in Thread::Finish()), because up to this // point, we were still running on the old thread's stack! if (threadToBeDestroyed != NULL) { + if (threadToBeDestroyed == currentThread) + printf("Znicil sis aktualni thread!!\n"); delete threadToBeDestroyed; threadToBeDestroyed = NULL; } #ifdef USER_PROGRAM if (currentThread->space != NULL) { // if there is an address space - currentThread->RestoreUserState(); // to restore, do it. - currentThread->space->RestoreState(); + /* prehozeno by jikos ;) + * nutne - je treba nejprve pred cimkoliv jinym + * nahrat spravny stack - jinak by proces v jednu + * chvili pracoval s cizim stackem + */ + currentThread->space->RestoreState(); + currentThread->RestoreUserState(); // to restore, do it. + } #endif } @@ -145,3 +211,39 @@ printf("Ready list contents:\n"); readyList->Mapcar((VoidFunctionPtr) ThreadPrint); } + +// Vyzaduje vypnute interupty, aby nas nekdo nerusil pri presypavani fronty +/* tahle funkce se pouziva pri zabijeni procesu/threadu + * muze se stat, ze proces/thread neni v readyListu, ale + * ve fronte tech, kterym uz casovy limit vyprsel + * takze je treba jeste projit tuto frontu + */ +void Scheduler::RemoveThread(Thread *which) +{ + List *newList = new List; + Thread *tmp; + int found=0; + + while (!readyList->IsEmpty()) + { + tmp = (Thread *)readyList->Remove(); + if (tmp != which) // pokud to neni on, tak ho tam vratime + newList->Append(tmp); + else found = 1; // poznamename si, ze uz neni treba hledat v + // exhausted fronte + } + delete readyList; + readyList = newList; // a nahradime novou, cistou frontou + + if(!found){ // v ready fronte nebyl, mel by tedy byt v exhausted + newList = new List; + while (!exhaustedList->IsEmpty()) + { + tmp = (Thread *)exhaustedList->Remove(); + if (tmp != which) // pokud to neni on, tak ho tam vratime + newList->Append(tmp); + } + delete exhaustedList; + exhaustedList = newList; // a nahradime novou, cistou frontou + } +} diff -r -u --new-file --exclude='*.patch--exclude=*.o' --exclude='Makefile*' --exclude=do_diff --exclude='*.patch' /home/bekone/nachos/threads/scheduler.h /home/bekone/jikos/threads/scheduler.h --- /home/bekone/nachos/threads/scheduler.h Sun Oct 3 23:08:50 1993 +++ /home/bekone/jikos/threads/scheduler.h Fri Dec 28 11:32:23 2001 @@ -28,9 +28,14 @@ void Run(Thread* nextThread); // Cause nextThread to start running void Print(); // Print contents of ready list + void RemoveThread(Thread *which); // odstrani z fronty thread + private: List *readyList; // queue of threads that are ready to run, // but not running + List *exhaustedList; // fronta procesu, ktere uz vycerpaly svuj casovy + // pridel, a ted jen cekaji, az zacne scheduler + // prepocitavat pridely casovych kvant }; #endif // SCHEDULER_H diff -r -u --new-file --exclude='*.patch--exclude=*.o' --exclude='Makefile*' --exclude=do_diff --exclude='*.patch' /home/bekone/nachos/threads/swtch.s /home/bekone/jikos/threads/swtch.s --- /home/bekone/nachos/threads/swtch.s Mon Nov 12 14:05:41 2001 +++ /home/bekone/jikos/threads/swtch.s Mon Dec 17 19:35:18 2001 @@ -1,213 +1,44 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - .text - .align 2 - - .globl ThreadRoot - - - - - - - - - + .align 2 + .globl ThreadRoot ThreadRoot: - pushl %ebp - movl %esp,%ebp - pushl %edx - call %ecx - call %esi - call %edi - - #NOT REACHED - movl %ebp,%esp - popl %ebp + pushl %ebp + movl %esp,%ebp + pushl %edx + call %ecx + call %esi + call %edi + # NOT REACHED + movl %ebp,%esp + popl %ebp ret - - - - - - - - - - - - - - - .comm _eax_save,4 - - .globl SWITCH + .comm _eax_save,4 + .globl SWITCH SWITCH: - movl %eax,_eax_save # save the value of eax - movl 4(%esp),%eax # move pointer to t1 into eax - movl %ebx,8 (%eax) # save registers - movl %ecx,12 (%eax) - movl %edx,16 (%eax) - movl %esi,24 (%eax) - movl %edi,28 (%eax) - movl %ebp,20 (%eax) - movl %esp,0 (%eax) # save stack pointer - movl _eax_save,%ebx # get the saved value of eax - movl %ebx,4 (%eax) # store it - movl 0(%esp),%ebx # get return address from stack into ebx - movl %ebx,32 (%eax) # save it into the pc storage - - movl 8(%esp),%eax # move pointer to t2 into eax - - movl 4 (%eax),%ebx # get new value for eax into ebx - movl %ebx,_eax_save # save it - movl 8 (%eax),%ebx # retore old registers - movl 12 (%eax),%ecx - movl 16 (%eax),%edx - movl 24 (%eax),%esi - movl 28 (%eax),%edi - movl 20 (%eax),%ebp - movl 0 (%eax),%esp # restore stack pointer - movl 32 (%eax),%eax # restore return address into eax - movl %eax,4(%esp) # copy over the ret address on the stack - movl _eax_save,%eax - + movl %eax,_eax_save # save the value of eax + movl 4(%esp),%eax # move pointer to t1 into eax + movl %ebx,8(%eax) # save registers + movl %ecx,12(%eax) + movl %edx,16(%eax) + movl %esi,24(%eax) + movl %edi,28(%eax) + movl %ebp,20(%eax) + movl %esp,0(%eax) # save stack pointer + movl _eax_save,%ebx # get the saved value of eax + movl %ebx,4(%eax) # store it + movl 0(%esp),%ebx # get return address from stack into ebx + movl %ebx,32(%eax) # save it into the pc storage + movl 8(%esp),%eax # move pointer to t2 into eax + movl 4(%eax),%ebx # get new value for eax into ebx + movl %ebx,_eax_save # save it + movl 8(%eax),%ebx # retore old registers + movl 12(%eax),%ecx + movl 16(%eax),%edx + movl 24(%eax),%esi + movl 28(%eax),%edi + movl 20(%eax),%ebp + movl 0(%eax),%esp # restore stack pointer + movl 32(%eax),%eax # restore return address into eax + movl %eax,4(%esp) # copy over the ret address on the stack + movl _eax_save,%eax ret diff -r -u --new-file --exclude='*.patch--exclude=*.o' --exclude='Makefile*' --exclude=do_diff --exclude='*.patch' /home/bekone/nachos/threads/synch.cc /home/bekone/jikos/threads/synch.cc --- /home/bekone/nachos/threads/synch.cc Tue Nov 13 18:21:41 2001 +++ /home/bekone/jikos/threads/synch.cc Fri Dec 28 16:01:05 2001 @@ -497,14 +497,6 @@ // CONDITION VARIABLES - implementace pomoci semaforu //---------------------------------------------------------------------- -//---------------------------------------------------------------------- -// SCondition::SCondition -// Konstruktor. Inicializuje frontu, do ktere se pro kazdy cekajici -// thread vytvori semafor, ne kterem dany thread bude cekat. -// -// "debugName" - jmeno semaforu. Urcene pro testovani. -//---------------------------------------------------------------------- - SCondition::SCondition(char *debugName) { name = debugName; diff -r -u --new-file --exclude='*.patch--exclude=*.o' --exclude='Makefile*' --exclude=do_diff --exclude='*.patch' /home/bekone/nachos/threads/synch.h /home/bekone/jikos/threads/synch.h --- /home/bekone/nachos/threads/synch.h Tue Nov 13 15:55:33 2001 +++ /home/bekone/jikos/threads/synch.h Mon Dec 17 18:14:46 2001 @@ -18,7 +18,8 @@ #define SYNCH_H #include "copyright.h" -#include "thread.h" +//#include "thread.h" +class Thread; #include "list.h" // The following class defines a "semaphore" whose value is a non-negative diff -r -u --new-file --exclude='*.patch--exclude=*.o' --exclude='Makefile*' --exclude=do_diff --exclude='*.patch' /home/bekone/nachos/threads/thread.cc /home/bekone/jikos/threads/thread.cc --- /home/bekone/nachos/threads/thread.cc Mon Oct 19 14:26:25 1998 +++ /home/bekone/jikos/threads/thread.cc Fri Dec 28 12:18:24 2001 @@ -40,6 +40,12 @@ status = JUST_CREATED; #ifdef USER_PROGRAM space = NULL; + proc = NULL; + TID = -1; + should_die = 0; + in_kernel = 1; + for(int i=0;iSetLevel(IntOff); + DEBUG('t', "Setting thread ready\n"); scheduler->ReadyToRun(this); // ReadyToRun assumes that interrupts // are disabled! (void) interrupt->SetLevel(oldLevel); + DEBUG('t', "Return from Thread->Fork()\n"); } //---------------------------------------------------------------------- @@ -141,15 +148,34 @@ // void -Thread::Finish () +Thread::Finish (int rv = -1) { - (void) interrupt->SetLevel(IntOff); + (void) interrupt->SetLevel(IntOff); ASSERT(this == currentThread); DEBUG('t', "Finishing thread \"%s\"\n", getName()); threadToBeDestroyed = currentThread; - Sleep(); // invokes SWITCH +#ifdef USER_PROGRAM + ret_val = rv; + + if (proc != NULL) + { + DEBUG('t',"Thread svuj proces zna\n"); + if (proc->ExitMe(ret_val, TID)) // pokud to byl posledni thread + { + DEBUG('t',"Byl to posledni thread procesu\n"); + ProcList *PL = proc->PL; + PL->RemoveProcess(proc->GetPID()); + } + } + // addrspace neni treba mazat, protoze se automaticky zrusi v ExitMe(), pokud to byl posledni thread + +#endif +// EOT(); // invokes SWITCH + DEBUG('t',"End-switching from thread \"%s\"\n", getName()); + + Sleep(); // not reached } @@ -219,12 +245,17 @@ DEBUG('t', "Sleeping thread \"%s\"\n", getName()); status = BLOCKED; + while ((nextThread = scheduler->FindNextToRun()) == NULL) interrupt->Idle(); // no one to run, wait for an interrupt - + + if (nextThread != NULL) + DEBUG('t', "Next running thread \"%s\"", nextThread->getName()); + scheduler->Run(nextThread); // returns when we've been signalled } + //---------------------------------------------------------------------- // ThreadFinish, InterruptEnable, ThreadPrint // Dummy functions because C++ does not allow a pointer to a member @@ -300,6 +331,11 @@ { for (int i = 0; i < NumTotalRegs; i++) userRegisters[i] = machine->ReadRegister(i); + for (int i=0;iReadMem((space->numPages)*PageSize - UserStackSize+i,4,&user_stack[(i/4)]); + } + } //---------------------------------------------------------------------- @@ -316,5 +352,33 @@ { for (int i = 0; i < NumTotalRegs; i++) machine->WriteRegister(i, userRegisters[i]); + for (int i=0;iWriteMem((space->numPages)*PageSize - UserStackSize+i,4,user_stack[(i/4)]); + } +} + +// ZAMYKAT!! +void Thread::Die() +{ + should_die = 1; +} + +void Thread::SetKernelMode() +{ + in_kernel = 1; + DEBUG('t', "Thread %s entered kernel\n", name); +} + +void Thread::SetUserMode() +{ + DEBUG('t', "Thread %s leaving kernel\n", name); + if (should_die) // behem syscallu nas nekdo zabil, takze ted umreme + { + DEBUG('t', "Someone killed us during syscall, finishing!\n"); + Finish(); + } + // NOT REACHED + in_kernel = 0; } #endif diff -r -u --new-file --exclude='*.patch--exclude=*.o' --exclude='Makefile*' --exclude=do_diff --exclude='*.patch' /home/bekone/nachos/threads/thread.h /home/bekone/jikos/threads/thread.h --- /home/bekone/nachos/threads/thread.h Fri Nov 19 08:18:38 1993 +++ /home/bekone/jikos/threads/thread.h Fri Dec 28 11:44:19 2001 @@ -43,6 +43,7 @@ #ifdef USER_PROGRAM #include "machine.h" #include "addrspace.h" +#include "process.h" #endif // CPU register state to be saved on context switch. @@ -53,11 +54,11 @@ // Size of the thread's private execution stack. // WATCH OUT IF THIS ISN'T BIG ENOUGH!!!!! -#define StackSize (4 * 1024) // in words +#define StackSize (40 * 1024) // in words // Thread state -enum ThreadStatus { JUST_CREATED, RUNNING, READY, BLOCKED }; +enum ThreadStatus { JUST_CREATED, RUNNING, READY, BLOCKED, EXHAUSTED }; // external function, dummy routine whose sole job is to call Thread::Print extern void ThreadPrint(int arg); @@ -94,7 +95,7 @@ // other thread is runnable void Sleep(); // Put the thread to sleep and // relinquish the processor - void Finish(); // The thread is done executing + void Finish(int rv=-1); // The thread is done executing void CheckOverflow(); // Check if thread has // overflowed its stack @@ -102,6 +103,15 @@ char* getName() { return (name); } void Print() { printf("%s, ", name); } + int priority; // priorita threadu + tickT tickStart; /* v Scheduler::Run() se nastavi na aktualni hodnotu + * tiku tesne pred tim, nez se thread pusti k procesoru + * pri volani Scheduler::ReadyToRun() se spocita, kolik tiku + * proces bezel, odecte se od hodnoty toRun, a pokud >0, tak + * se zaradi do readyListu, jinak do exhaustedListu + */ + tickT toRun; /* urcuje, kolik tiku ma thread bezet v jednom cyklu scheduleru */ + private: // some of the private data for this class is listed above @@ -119,14 +129,37 @@ // A thread running a user program actually has *two* sets of CPU registers -- // one for its state while executing user code, one for its state // while executing kernel code. - int userRegisters[NumTotalRegs]; // user-level CPU register state + + int TID; // cislo threadu v ramci procesu + + int ret_val; + + int in_kernel; // urcuje, zda je proces v kernelu + + int should_die; // pokusil se nekdo zabit thread v syscallu? + + int user_stack[UserStackSize]; // musime schovat zasobnik, kvuli uzivatelskym threadum + public: + Process *proc; // proces, do ktereho patri + void SaveUserState(); // save user-level register state void RestoreUserState(); // restore user-level register state AddrSpace *space; // User code this thread is running. + SpaceId GetPID() { if (proc != NULL) return proc->GetPID(); else return -2;} +// void SetPid(SpaceId i) { proc->SetPID = i;} + void SetTID(int i) { TID = i; } + int GetTID() { return TID; } + void Die(); + // rekne threadu, aby pri nejblizsi prilezitosti umrel + void SetUserMode(); + void SetKernelMode(); + int InKernel() { return in_kernel; } + int ShouldDie() { return should_die; } + #endif }; diff -r -u --new-file --exclude='*.patch--exclude=*.o' --exclude='Makefile*' --exclude=do_diff --exclude='*.patch' /home/bekone/nachos/threads/threadtest.cc /home/bekone/jikos/threads/threadtest.cc --- /home/bekone/nachos/threads/threadtest.cc Tue Nov 13 18:40:20 2001 +++ /home/bekone/jikos/threads/threadtest.cc Tue Dec 18 17:04:59 2001 @@ -530,7 +530,7 @@ ThreadTest() { - DEBUG('t', "Entering SimpleTest"); +// DEBUG('t', "Entering SimpleTest"); #ifndef DEMO Thread *t[5]; #endif diff -r -u --new-file --exclude='*.patch--exclude=*.o' --exclude='Makefile*' --exclude=do_diff --exclude='*.patch' /home/bekone/nachos/threads/utility.h /home/bekone/jikos/threads/utility.h --- /home/bekone/nachos/threads/utility.h Mon Oct 19 14:24:18 1998 +++ /home/bekone/jikos/threads/utility.h Tue Dec 18 19:52:58 2001 @@ -24,6 +24,7 @@ #define UTILITY_H #include "copyright.h" +#include "types.h" // Miscellaneous useful routines @@ -84,4 +85,4 @@ } -#endif UTILITY_H +#endif diff -r -u --new-file --exclude='*.patch--exclude=*.o' --exclude='Makefile*' --exclude=do_diff --exclude='*.patch' /home/bekone/nachos/userprog/addrspace.cc /home/bekone/jikos/userprog/addrspace.cc --- /home/bekone/nachos/userprog/addrspace.cc Mon Nov 22 08:25:32 1993 +++ /home/bekone/jikos/userprog/addrspace.cc Fri Dec 28 16:28:08 2001 @@ -19,6 +19,18 @@ #include "system.h" #include "addrspace.h" #include "noff.h" +#include "synch.h" +#include "interrupt.h" + +extern Alloc *alloc; + +/* + * zamek jsem dal sem - do addrspace.h se pridat neda, protoze + * pri includovani synch.h odtamtud dojde k cyklu addrspace -> synch -> + * thread -> addrspace + */ +Lock *PageTableLock = new Lock("PageTableLock"); // zamek na pristup k strankovaci tabulce +RWLock *MemAccessLock = new RWLock("MemAccessLock"); //---------------------------------------------------------------------- // SwapHeader @@ -61,6 +73,14 @@ { NoffHeader noffH; unsigned int i, size; + int phPage; + + /* vytvorim zamky, ktere se pouzivaji pro pristup k poli + * ktere udrzuje informace o uzivatelskych synch. prim. + */ + LockTableLock = new Lock("LockTableLock"); + SemTableLock = new Lock("SemTableLock"); + CondTableLock = new Lock("CondTableLock"); executable->ReadAt((char *)&noffH, sizeof(noffH), 0); if ((noffH.noffMagic != NOFFMAGIC) && @@ -83,10 +103,22 @@ DEBUG('a', "Initializing address space, num pages %d, size %d\n", numPages, size); // first, set up the translation + + DEBUG('a', "Creating pageTable\n"); pageTable = new TranslationEntry[numPages]; + ASSERT(pageTable != NULL); for (i = 0; i < numPages; i++) { pageTable[i].virtualPage = i; // for now, virtual page # = phys page # - pageTable[i].physicalPage = i; + // tady se musi najit volna stranka v mainMemory misto i + PageTableLock->Acquire(); + ASSERT((phPage = alloc->GetPhysPage()) != -1); // pokud uz nemame volne stranky, padni na hubu + PageTableLock->Release(); + DEBUG('a', "Requested new physical page - got %d\n", phPage); + + pageTable[i].physicalPage = phPage; // tady bude cislo stranky v machine->mainMemory + DEBUG('a', "Cleaning page %d/%d at %d\n", i, pageTable[i].physicalPage, machine->mainMemory+PageSize*pageTable[i].physicalPage); + bzero(machine->mainMemory+PageSize*pageTable[i].physicalPage,PageSize); // stranku vynulujeme + DEBUG('a', "Cleaned\n"); pageTable[i].valid = TRUE; pageTable[i].use = FALSE; pageTable[i].dirty = FALSE; @@ -94,23 +126,105 @@ // a separate page, we could set its // pages to be read-only } - // zero out the entire address space, to zero the unitialized data segment // and the stack segment - bzero(machine->mainMemory, size); +// bzero(machine->mainMemory, size); // tohle je DIVNE - mel by nulovat jenom svoje stranky // then, copy in the code and data segments into memory +// jikos: rekl bych, ze tady zamykani neni potreba, protoze do te pameti nikdo +// v danou chvili neleze: konstruktor jeste neskoncil, a stranky uz nejsou +// volne pro alokaci +// je to pravda, nebo ne? ;) if (noffH.code.size > 0) { DEBUG('a', "Initializing code segment, at 0x%x, size %d\n", noffH.code.virtualAddr, noffH.code.size); - executable->ReadAt(&(machine->mainMemory[noffH.code.virtualAddr]), + // Ted potrebujeme nakopirovat code do fyzicke pameti na misto podle mapovani + int offs = noffH.code.virtualAddr%PageSize; // offset ve VP + int initVP = noffH.code.virtualAddr/PageSize; // VP, od ktere zaciname kopirovat + int firstStep = PageSize - offs; // nejdriv precteme tolik, kolik se nam vejde do prvni stranky + int totalCopy = noffH.code.size-firstStep; // kolik zkopirovat zbytku + int filePos = noffH.code.inFileAddr; // pozice v souboru + int copied; // kolik jsme nakopirovali v poslednim kroku + + //printf("Copying first %d bytes to VA %d@%d (phys addr %d)\n", + // firstStep, noffH.code.virtualAddr, initVP, pageTable[initVP].physicalPage*PageSize+offs); + + // Nakopirujeme prvnich firstStep bytu - virtualAddr nemusi zacinat na zacatku stranky, takze timhle to zarovname na hranici stranky + // Tohle je vlastne simulate Translate + executable->ReadAt(&(machine->mainMemory[pageTable[initVP].physicalPage*PageSize+offs]), + firstStep, filePos); + // posuneme se v souboru + filePos += firstStep; + copied = 0; + // tady nakopirujeme zbytek + while (totalCopy>0) + { + initVP++; + // nakopirujeme bud celou stranku, nebo zbytek + if (totalCopy >=PageSize) + { + copied = PageSize; + } + else + { + copied = totalCopy; + } + //printf("Copying %d bytes from %d to VP %d (phys addr %d)\n", + // copied, filePos, initVP, pageTable[initVP].physicalPage*PageSize+offs); + executable->ReadAt(&(machine->mainMemory[pageTable[initVP].physicalPage*PageSize]), + copied, filePos); + // posuneme se v souboru o tolik, kolik jsme nakopirovali + filePos+=copied; + totalCopy -= copied; + } + + +/* + Tohle je SPATNE - kopiruje to primo do fyzicke pameti, kde muze byt uplne jiny proces - nepouziva mapovani + executable->ReadAt(&(machine->mainMemory[noffH.code.virtualAddr]), noffH.code.size, noffH.code.inFileAddr); +*/ + } if (noffH.initData.size > 0) { DEBUG('a', "Initializing data segment, at 0x%x, size %d\n", noffH.initData.virtualAddr, noffH.initData.size); + + int offs = noffH.initData.virtualAddr%PageSize; // offset ve VP + int initVP = noffH.initData.virtualAddr/PageSize; + int firstStep = PageSize - offs; // nejdriv precteme tolik, kolik se nam vejde do prvni stranky + int totalCopy = noffH.initData.size-firstStep; // kolik zkopirovat zbytku + int filePos = noffH.initData.inFileAddr; + int copied; + //printf("Copying first %d bytes to VA %d@%d (phys addr %d)\n", + // firstStep, noffH.initData.virtualAddr, initVP, pageTable[initVP].physicalPage*PageSize+offs); + executable->ReadAt(&(machine->mainMemory[pageTable[initVP].physicalPage*PageSize+offs]), + firstStep, filePos); + filePos += firstStep; + copied = 0; + while (totalCopy>0) + { + initVP++; + if (totalCopy >=PageSize) + { + copied = PageSize; + } + else + { + copied = totalCopy; + } + //printf("Copying %d bytes from %d to VP %d (phys addr %d)\n", + //copied, filePos, initVP, pageTable[initVP].physicalPage*PageSize+offs); + executable->ReadAt(&(machine->mainMemory[pageTable[initVP].physicalPage*PageSize]), + copied, filePos); + filePos+=copied; + totalCopy -= copied; + } + +/* executable->ReadAt(&(machine->mainMemory[noffH.initData.virtualAddr]), noffH.initData.size, noffH.initData.inFileAddr); +*/ } } @@ -122,7 +236,19 @@ AddrSpace::~AddrSpace() { + + PageTableLock->Acquire(); + for (unsigned int i = 0; i < numPages; i++) { +// printf("Deallocating page %d/%d\n", i, pageTable[i].physicalPage); + alloc->FreePhysPage(pageTable[i].physicalPage); //fixed by jikos + } + PageTableLock->Release(); + fprintf(stderr, "Deleting pageTable\n"); delete pageTable; + pageTable = NULL; + delete LockTableLock; + delete SemTableLock; + delete CondTableLock; } //---------------------------------------------------------------------- @@ -136,7 +262,7 @@ //---------------------------------------------------------------------- void -AddrSpace::InitRegisters() +AddrSpace::InitRegisters(int npc=0) { int i; @@ -144,11 +270,11 @@ machine->WriteRegister(i, 0); // Initial program counter -- must be location of "Start" - machine->WriteRegister(PCReg, 0); + machine->WriteRegister(PCReg, npc); // Need to also tell MIPS where next instruction is, because // of branch delay possibility - machine->WriteRegister(NextPCReg, 4); + machine->WriteRegister(NextPCReg, npc+4); // Set the stack register to the end of the address space, where we // allocated the stack; but subtract off a bit, to make sure we don't @@ -162,7 +288,7 @@ // On a context switch, save any machine state, specific // to this address space, that needs saving. // -// For now, nothing! +// For now, nothing! - pageTable se nemeni, stranky se nepridavaji, takze nemame co ukladat //---------------------------------------------------------------------- void AddrSpace::SaveState() @@ -178,6 +304,7 @@ void AddrSpace::RestoreState() { + DEBUG('a',"Restoring PT to %p\n", pageTable); machine->pageTable = pageTable; machine->pageTableSize = numPages; } diff -r -u --new-file --exclude='*.patch--exclude=*.o' --exclude='Makefile*' --exclude=do_diff --exclude='*.patch' /home/bekone/nachos/userprog/addrspace.h /home/bekone/jikos/userprog/addrspace.h --- /home/bekone/nachos/userprog/addrspace.h Mon Nov 22 04:07:25 1993 +++ /home/bekone/jikos/userprog/addrspace.h Fri Dec 28 16:33:23 2001 @@ -15,8 +15,12 @@ #include "copyright.h" #include "filesys.h" +#include "translate.h" +#include "syscall.h" +#include "synch.h" -#define UserStackSize 1024 // increase this as necessary! +#define UserStackSize 4096 // increase this as necessary! +#define MAXSYNCHPERTHREAD 20 class AddrSpace { public: @@ -25,17 +29,63 @@ // stored in the file "executable" ~AddrSpace(); // De-allocate an address space - void InitRegisters(); // Initialize user-level CPU registers, + void InitRegisters(int npc=0); // Initialize user-level CPU registers, // before jumping to user code void SaveState(); // Save/restore address space-specific void RestoreState(); // info on a context switch - private: TranslationEntry *pageTable; // Assume linear page table translation + +// private: // for now! unsigned int numPages; // Number of pages in the virtual // address space + + /* funkce na praci s uzivatelskymi synch. prim. v tomto addrspace + * !!! tyto funkce predpokladaji, ze je jim zvenku zajisteno zamkyani + * - nechceme, aby s polem pracovalo najednou vice threadu + * !!! + */ + + // zamkaji se tyhle zamky + Lock *LockTableLock; + Lock *SemTableLock; + Lock *CondTableLock; + + LockId AddLock(Lock *lock) { int i=0; + while((locks[i])&&(iMAXSYNCHPERTHREAD-1) return -1; //neni misto + locks[i]=lock;return i; + } + SemId AddSem(Semaphore *sem){ int i=0; + while((semaphores[i])&&(iMAXSYNCHPERTHREAD-1) return -1; //neni misto + semaphores[i]=sem;return i; + } + CondId AddCond(Condition *cond){ int i=0; + while((conditions[i])&&(iMAXSYNCHPERTHREAD-1) ;return -1; //neni misto + conditions[i]=cond;return i; + } + + + Lock *GetLock(LockId lockid) {if(lockid>MAXSYNCHPERTHREAD-1) return NULL; else return locks[lockid];} + Semaphore *GetSem(SemId semid) {if(semid>MAXSYNCHPERTHREAD-1) return NULL; else return semaphores[semid];} + Condition *GetCond(CondId condid) {if(condid>MAXSYNCHPERTHREAD-1) return NULL; else return conditions[condid];} + /* v techto funkcich neni treba vypinat interrupty, protoze jsou + * vypnute ve funcich na vytvoreni, takze si do toho nikdy nehrabnou + * vzajemne + */ + void DelLock(LockId lockid){if(!locks[lockid]) return; delete locks[lockid];locks[lockid]=NULL;} + void DelSem (SemId semid){if(!semaphores[semid]) return;delete semaphores[semid];semaphores[semid]=NULL;} + void DelCond (CondId condid){if(!conditions[condid]) return;delete conditions[condid];conditions[condid]=NULL;} + + /* ... a datove struktury na jejich udrzovani */ + private: + Lock *locks[MAXSYNCHPERTHREAD]; + Semaphore *semaphores[MAXSYNCHPERTHREAD]; + Condition *conditions[MAXSYNCHPERTHREAD]; }; #endif // ADDRSPACE_H diff -r -u --new-file --exclude='*.patch--exclude=*.o' --exclude='Makefile*' --exclude=do_diff --exclude='*.patch' /home/bekone/nachos/userprog/alloc.cc /home/bekone/jikos/userprog/alloc.cc --- /home/bekone/nachos/userprog/alloc.cc Thu Jan 1 01:00:00 1970 +++ /home/bekone/jikos/userprog/alloc.cc Thu Dec 20 13:19:04 2001 @@ -0,0 +1,94 @@ +#include "machine.h" +#include "alloc.h" +#include "syscall.h" + +Alloc::Alloc() +{ + s_freePages *s_first = new s_freePages; // vytvorime spojovy seznam, ktery bude + s_first->begins=0; // udrzovat seznam bloku pameti (poc. a konc. stranka), + s_first->size=NumPhysPages; // kde se vyskytuji volne stranky + freePages = new List; // a na zacatku ho nainicalizujeme + freePages->Append((void *)s_first);// na celou pamet +} + +Alloc::~Alloc() +{ + delete freePages; +} + +int Alloc::GetPhysPage() +{ + s_freePages *fp; + int rn; + if (freePages->IsEmpty()) + { + return -1; + } + fp=(s_freePages *)freePages->Remove(); + rn=fp->begins; + fp->size--; + fp->begins++; + if (fp->size) + { + freePages->Prepend((void *)fp); + } + return rn; +} + +void Alloc::FreePhysPage(int num) +{ + s_freePages *fp; + + if ((num>=NumPhysPages) || (num<0)) // snazi se uvolnit stranku, ktera je mimo rozsah + return; + + fp=(s_freePages *)freePages->Remove(); + if (num == fp->begins+fp->size) + { + fp->size++; + freePages->Prepend((void *)fp); + } + else + { + if (num == (fp->begins-1)) + { + fp->begins--; + fp->size++; + freePages->Prepend((void *)fp); + } + else + { + freePages->Prepend((void *)fp); + fp=new s_freePages; + fp->size=1; + fp->begins=num; + freePages->Prepend((void *)fp); + } + } +} + +DescriptorTable::DescriptorTable() +{ + int i=2; + +// descriptortable[0]=1; +// descriptortable[1]=1; // vstup a vystup se uz pouzivaji + + while(iAcquire(); + char *cptr = new char[MAXARG+1]; + int i=0; + machine->ReadMem(addr,1,(int*)(&cptr[i]));addr++; + while (cptr[i++]) { + machine->ReadMem(addr, 1, (int*)(&cptr[i])); + addr++; + } + ReadCharLock->Release(); + return cptr; +} + +/* zapise string buf na adresu addr + * obdoba linuxoveho copy_to_user + */ + +void WriteChar(int addr, char *buf) +{ + WriteCharLock->Acquire(); + int i=0; + while(buf[i]){ + machine->WriteMem(addr,1,(int)(buf[i])); + addr++; + i++; + } + addr++; + machine->WriteMem(addr,1,0); // koncova nula + WriteCharLock->Release(); +} + +// veci kolem konzole + +extern Console *console; +extern Semaphore *readAvail; +extern Semaphore *writeDone; + +Lock *ConsoleWriteLock = new Lock("ConsoleWriteLock"); //---------------------------------------------------------------------- // ExceptionHandler @@ -51,13 +114,402 @@ void ExceptionHandler(ExceptionType which) { + currentThread->SetKernelMode(); // poznamename si, ze je aktualni thread + // v kernelu - kvuli zabijeni procesu + int type = machine->ReadRegister(2); - if ((which == SyscallException) && (type == SC_Halt)) { - DEBUG('a', "Shutdown, initiated by user program.\n"); - interrupt->Halt(); - } else { + int addr,bytes,towrite,buflen; + char *filename, *buf; + OpenFile *openfile; + OpenFileId descriptor; + /* tyhle synch. prim. se pouzivaji, kdyz uzivatelsky thread vytvari + * nove synch. prim - o volani delete se neni treba starat, zavola + * ho AddrSpace::DelLock() + */ + Lock *tmplock; + Semaphore *tmpsem; + Condition *tmpcond; +// IntStatus oldlevel; + + + if (which == SyscallException){ + /* je potreba zvysit PC o 4 bajty (velikost instrukce), aby + * se volani syscallu neopakovalo v nekonecne smycce + */ + int pc = machine->ReadRegister(PCReg); + machine->WriteRegister(PrevPCReg, pc); + pc = machine->ReadRegister(NextPCReg); + machine->WriteRegister(PCReg, pc); + pc += 4; + machine->WriteRegister(NextPCReg, pc); + +// printf("Syscall by %d: ",currentThread->GetPID()); + switch(type){ + + /* syscally pro operace s address spacem */ + case SC_Halt:{ + interrupt->Halt(); + } + + case SC_Exit:{ + /* u threadu bude asi potreba si zapamatovat navratovou hodnotu, + * a pak v Thread->Finish() projit seznam vsech, kteri cekaji + * na Join() - seznam tech bude mit thread u sebe? + */ + int param1 = machine->ReadRegister(4); + +// printf("exit\n"); + currentThread->Finish(param1); + break; + } + + case SC_Exec:{ + addr = machine->ReadRegister(4); + filename = ReadChar(addr); + printf("Exec(%s)\n",filename); + /* otestujeme, jestli soubor existuje - jinak by nastal + * segfault celeho nachosu pri pokusu o nacteni do + * code segmentu + * TODO: nejak inteligentneji testovat existenci souboru, + * nez zrovna open()/close() ? + */ + OpenFile *executable; + if (!(executable = fileSystem->Open(filename))) + machine->WriteRegister(2,-1); + else{ + SpaceId i=PList->NewProcess(filename,currentThread->GetPID(),10); // posledni parametr je priorita + machine->WriteRegister(2, i); + } + delete executable; // zavreme soubor + break; + } + + case SC_Join:{ + int param1 = machine->ReadRegister(4); // spaceid je typedef int + DEBUG('t',"%d: join...%d\n", currentThread->GetPID(),param1); + int i = PList->WaitFor(param1, currentThread->GetPID()); + DEBUG('t',"%d: Joined %d (%d)\n", currentThread->GetPID(),param1, i); + machine->WriteRegister(2, i); + break; + } + + /* syscally tykajici se filesystemu. nachos ma jiz implementovany + * zaklady filesystemu, neni treba vyuzivat UNIXove API, jak jsme + * si mysleli + */ + + case SC_Create:{ + addr = machine->ReadRegister(4); // precteme adresu prvniho + filename = ReadChar(addr); +// printf("Create(%s)\n",filename); + if(!fileSystem->Create(filename,10)) + machine->WriteRegister(2,-1); + else + machine->WriteRegister(2,10); // desitka je defaultsize + break; + } + + case SC_Open:{ + addr = machine->ReadRegister(4); // precteme adresu prvniho + filename = ReadChar(addr); + + DescriptorTableLock->Acquire(); +// printf("Open(%s)\n",filename); + if (!(openfile = fileSystem->Open(filename))){ +// printf("napovedlo se otevrit soubor %s\n",filename); + machine->WriteRegister(2,-1); + } + else { + // je potreba najit volny descirptor, resp. OpenFileId, a to vratit + if(!(descriptor = descriptortable->GetFreeDescriptor())) // prilis mnoho otevrenych souboru + machine->WriteRegister(2,-1); + else{ + descriptortable->SetFileByDesc(openfile,descriptor); + currentThread->proc->AddDescr(descriptor); + machine->WriteRegister(2,descriptor); + } + + } + DescriptorTableLock->Release(); + + break; + } + + case SC_Write:{ + addr = machine->ReadRegister(4); + buf = ReadChar(addr); + buflen = strlen(buf); + bytes = machine->ReadRegister(5); + descriptor = machine->ReadRegister(6); + towrite = (buflen >= bytes)?bytes:buflen; + + if (descriptor == ConsoleOutput) { + for(int i=0;iAcquire(); + console->PutChar(buf[i]); + writeDone->P(); // pockame, az budeme moc zapisovat (semafor nastavuje emulace procesoru) + ConsoleWriteLock->Release(); + } + } + else + (descriptortable->GetFileByDesc(descriptor))->Write(buf,bytes); + + break; + } + + case SC_Read:{ + addr = machine->ReadRegister(4); // precteme adresu prvniho + bytes = machine->ReadRegister(5); + descriptor = machine->ReadRegister(6); + + buf = new char[bytes+1];buf[bytes]='\0'; + + if (descriptor == ConsoleInput) { + + for(int i=0;iP(); // pockame, az bude co cist (semafor nastavuje emulace procesoru) + buf[i] = console->GetChar(); + } + WriteChar(addr,buf); + machine->WriteRegister(2,bytes); + } + else + (descriptortable->GetFileByDesc(descriptor))->Read(buf,bytes); // nactu pozadovany pocet znaku ze souboru + + WriteChar(addr,buf); + machine->WriteRegister(2,bytes); + break; + } + + case SC_Close:{ +// printf("close\n"); + descriptor = machine->ReadRegister(4); + + if (descriptor == 0 || descriptor == 1) + machine->WriteRegister(2,-1); // zavirat konzoli nebudeme + else{ + DescriptorTableLock->Acquire(); + descriptortable->ReleaseDescriptor(descriptor); // uvolnime deskriptor + currentThread->proc->RemoveDescr(descriptor); // proces si rusi descriptor + DescriptorTableLock->Release(); + } + + break; + } + + /* syscally pro podporu threadu v user-landu. */ + + case SC_Fork: { + void ((*f)(int)) = (void (*)(int))machine->ReadRegister(4); // doufam, ze void * odpovida integeru ;) +// printf("fork(%d)\n",(int)f); + int par = machine->ReadRegister(5); // TODO parametr na predani + int cTID = currentThread->proc->AddThread(f); + machine->WriteRegister(2, cTID); + break; + } + case SC_Yield: { + currentThread->Yield(); + break; + } + + case SC_Kill: { + SpaceId kPID = machine->ReadRegister(4); + DEBUG('t', "Killing process %d\n", kPID); + PList->Kill(kPID); + machine->WriteRegister(2, 0); + break; + } + + case SC_TJoin: { + int kTID = machine->ReadRegister(4); + DEBUG('t', "Joining thread %d from process #%d\n", kTID, currentThread->GetPID()); + if (kTID == currentThread->GetTID()) + { + DEBUG('t', "Cannot join current thread!\n"); + machine->WriteRegister(2, -1); + } + else + { + currentThread->proc->WaitForThread(kTID); + machine->WriteRegister(2, 0); + } + break; + } + + case SC_TKill: { + int kTID = machine->ReadRegister(4); + DEBUG('t', "Killing thread %d from process #%d\n", kTID, currentThread->GetPID()); + if (kTID == currentThread->GetTID()) + { + DEBUG('t', "Cannot kill current thread!\n"); + machine->WriteRegister(2, -1); + } + else + { + currentThread->proc->KillThread(kTID); + machine->WriteRegister(2, 0); + } + break; + } + + case SC_ps: { + /* TODO: tohle je hodne dummy. Asi to bude chtit + * vyresit pres neco jako /proc soubory v linuxu. + * predavat struct ze syscallu je evidentni zhuverilost, + * ovsem stejne jako provadet z jadra printf() ;) + */ + PList->ps(); + break; + } + + /* syscally pro uzivatelskou praci se synch. primitivy */ + /* vytvareni */ + case SC_CreateLock: { + (currentThread->space)->LockTableLock->Acquire(); + tmplock = new Lock("user lock"); + LockId lockid = (currentThread->space)->AddLock(tmplock); + (currentThread->space)->LockTableLock->Release(); + machine->WriteRegister(2,lockid); + break; + } + case SC_CreateSem: { + (currentThread->space)->SemTableLock->Acquire(); + tmpsem = new Semaphore("user sem",1); + SemId semid = (currentThread->space)->AddSem(tmpsem); + (currentThread->space)->SemTableLock->Release(); + machine->WriteRegister(2,semid); + break; + } + case SC_CreateCond: { + (currentThread->space)->CondTableLock->Acquire(); + tmpcond = new Condition("user cond"); + CondId condid = (currentThread->space)->AddCond(tmpcond); + (currentThread->space)->CondTableLock->Release(); + machine->WriteRegister(2,condid); + break; + } + /* operace se zamky */ + case SC_Lock_Acquire: { + Lock *tlock=NULL; + LockId lockid = machine->ReadRegister(4); + if( (tlock = (currentThread->space)->GetLock(lockid))){ + tlock->Acquire(); + machine->WriteRegister(2,1); + } + else + machine->WriteRegister(2,-1); // zamek uz asi nekdo zrusil + break; + + } + case SC_Lock_Release: { + Lock *tlock=NULL; + LockId lockid = machine->ReadRegister(4); + if( (tlock = (currentThread->space)->GetLock(lockid))){ + tlock->Release(); + machine->WriteRegister(2,1); + } + else + machine->WriteRegister(2,-1); // zamek uz asi nekdo zrusil + break; + } + /* operace se semafory */ + case SC_Sem_P: { + Semaphore *tsem=NULL; + SemId semid = machine->ReadRegister(4); + if( (tsem = (currentThread->space)->GetSem(semid))){ + tsem->P(); + machine->WriteRegister(2,1); + } + else + machine->WriteRegister(2,-1); // semafor uz asi nekdo zrusil + break; + } + case SC_Sem_V: { + Semaphore *tsem=NULL; + SemId semid = machine->ReadRegister(4); + if( (tsem = (currentThread->space)->GetSem(semid))){ + tsem->V(); + machine->WriteRegister(2,1); + } + else + machine->WriteRegister(2,-1); // semafor uz asi nekdo zrusil + break; + } + /* operace s CV */ + case SC_Cond_Wait: { + Condition *tcond=NULL; + Lock *tclock=NULL; + CondId condid = machine->ReadRegister(4); + LockId clockid = machine->ReadRegister(5); + if( (tcond = (currentThread->space)->GetCond(condid))) + if( (tclock = (currentThread->space)->GetLock(clockid))){ + tcond->Wait(tclock); + machine->WriteRegister(2,1); + } + else + machine->WriteRegister(2,-1); // semafor uz asi nekdo zrusil + break; + } + case SC_Cond_Signal: { + Condition *tcond=NULL; + Lock *tclock=NULL; + CondId condid = machine->ReadRegister(4); + LockId clockid = machine->ReadRegister(5); + if( (tcond = (currentThread->space)->GetCond(condid))) + if( (tclock = (currentThread->space)->GetLock(clockid))){ + tcond->Signal(tclock); + machine->WriteRegister(2,1); + } + else + machine->WriteRegister(2,-1); // semafor uz asi nekdo zrusil + break; + } + case SC_Cond_Broadcast: { + Condition *tcond=NULL; + Lock *tclock=NULL; + CondId condid = machine->ReadRegister(4); + LockId clockid = machine->ReadRegister(5); + if( (tcond = (currentThread->space)->GetCond(condid))) + if( (tclock = (currentThread->space)->GetLock(clockid))){ + tcond->Broadcast(tclock); + machine->WriteRegister(2,1); + } + else + machine->WriteRegister(2,-1); // semafor uz asi nekdo zrusil + break; + } + /* ruseni */ + case SC_DeleteLock: { + LockId lockid = machine->ReadRegister(4); + (currentThread->space)->LockTableLock->Acquire(); + (currentThread->space)->DelLock(lockid); + (currentThread->space)->LockTableLock->Release(); + break; + } + case SC_DeleteSem: { + SemId semid = machine->ReadRegister(4); + (currentThread->space)->SemTableLock->Acquire(); + (currentThread->space)->DelSem(semid); + (currentThread->space)->SemTableLock->Release(); + break; + } + case SC_DeleteCond: { + CondId condid = machine->ReadRegister(4); + (currentThread->space)->CondTableLock->Acquire(); + (currentThread->space)->DelCond(condid); + (currentThread->space)->LockTableLock->Release(); + break; + } + + default:{ + printf("hm?\n"); + } + } + } + else { printf("Unexpected user mode exception %d %d\n", which, type); ASSERT(FALSE); } + currentThread->SetUserMode(); } diff -r -u --new-file --exclude='*.patch--exclude=*.o' --exclude='Makefile*' --exclude=do_diff --exclude='*.patch' /home/bekone/nachos/userprog/process.cc /home/bekone/jikos/userprog/process.cc --- /home/bekone/nachos/userprog/process.cc Thu Jan 1 01:00:00 1970 +++ /home/bekone/jikos/userprog/process.cc Fri Dec 28 01:07:18 2001 @@ -0,0 +1,569 @@ +#include "process.h" +#include "synch.h" +#include "thread.h" +#include "system.h" +//#include "filesys.h" + +extern DescriptorTable *descriptortable; +extern Lock *DescriptorTableLock; + +void Startup(int it) +{ + Thread *t; + + t=(Thread *)it; + + t->space->InitRegisters(); + t->space->RestoreState(); + machine->Run(); +} + +void Startup_user_thread(int f) +{ + Thread *t; + + t=currentThread; + + t->space->InitRegisters(f); + machine->WriteRegister(31,8); // kvuli tomu, aby ve start.s skocil na volani Exit() + t->space->RestoreState(); + machine->Run(); +} + + +// Pokud vrati 1, je treba ho zrusit +int Process::ExitMe(int rv, int TID) +{ + // ZAMKNOUT! + DEBUG('t',"Thread %d from process %d exiting!\n", TID, PID); + int rval=0; + int dll=0; // zamknuli jsme dielock? + zamek->Acquire(); + if (threads[TID]->InKernel()) // pokud se snazi umrit nejaky ex-kernelovy thread, tak ho prip. chvili zdrzime + { + dielock->Acquire(); + dll = 1; + } + if (rv>=0) + retval=rv; + if (threads[TID]) // thread nemazat, vola se pouze z Thread::Finish(), smaze ho sheduler nebo tak nekdo + { + num_thr--; + } + if ((num_thr == 0) && (space != NULL)) + { + DEBUG('t',"Deleting addrspace\n"); + delete space; + space = NULL; + threads[TID]->space=NULL; + rval = 1; + } + threads[TID] = NULL; + conds[TID]->Broadcast(zamek); // vzbudime ty, co na nas cekali + delete conds[TID]; + conds[TID]=NULL; + if (dll == 1) + dielock->Release(); + zamek->Release(); + return rval; +} + +Process::~Process() +{ + DEBUG('t',"Process %d destruktor!\n", PID); + zamek->Acquire(); + if (num_thr > 0) // TEORETICKY by tady nemel uz byt zadny thread + { + for (int i=0; iInKernel()) // thread je v kernelu, ted ho nemuzeme zabit + { + DEBUG('t', "Thread %d is in kernel, will die later\n", i); + threads[i]->proc=NULL; // aby se na nas neobracel + threads[i]->Die(); // tak mu rekneme, aby umrel, az se z nej vrati + // mame zamknuty dielock, takze prip. ExitMe neprobehnou pred nami + } + else + { + DEBUG('t', "Thread %d is in usermode, dies immediately\n", i); + IntStatus oldLevel = interrupt->SetLevel(IntOff); // disable interrupts + scheduler->RemoveThread(threads[i]); // je v usermode, muzeme ho klidne znicit + // a slehne se po nem zem + (void) interrupt->SetLevel(oldLevel); // obnovime prip. interrupty + delete threads[i]; // ani ExitMe() nezavola, proste zmizi + threads[i]=NULL; + num_thr--; // klidne si ho skrtneme + } + + } + } + } + if (space != NULL) + { + DEBUG('t',"Deleting addrspace\n"); + delete space; + } + + /* Tady bude prochazet descriptory a zavirat je */ + for (int i=2; iAcquire(); + descriptortable->ReleaseDescriptor(i); // uvolnime deskriptor + DescriptorTableLock->Release(); + } + } + zamek->Release(); + delete zamek; + delete dielock; + delete desclock; +} + + +/* Prida thread do procesu, tj. : + * vytvori ho + * nastavi mu TID + * zapamatuje si ten thread + * nastavi mu addrspace + * forkne ho + */ +int Process::AddThread(void (*f)(int)) +{ + Thread *thr = new Thread("user thread"); + zamek->Acquire(); + num_thr++; + thr->SetTID(++last_tid); + threads[last_tid] = thr; + conds[last_tid] = new Condition("thread cvar"); + thr->space = space; + thr->proc = this; +// thr->Fork(f,(int)thr); +// thr->Fork(f,0); +// FIXME: tady ROZHODNE nemuze byt adresa f, ale to co ji odpovida + thr->Fork(Startup_user_thread,(int)f); + zamek->Release(); + return last_tid; +} + + + +int Process::Die() +{ + int killed=1; // nechal po sobe nejake nezabite thready, ktere ho pozdeji zlikviduji + zamek->Acquire(); // nechceme, aby se nam sem pletl nejaky trapny thread z usermode + dielock->Acquire(); + for (int i=0; i<=last_tid; i++) + { + if (threads[i] != NULL) + { + if (threads[i]->InKernel()) // thread je v kernelu, ted ho nemuzeme zabit + { + killed = 0; // nejaky thread jsme nezabili a ten si nas zrusi sam + DEBUG('t', "Thread %d is in kernel, will die later\n", i); + threads[i]->Die(); // tak mu rekneme, aby umrel, az se z nej vrati + // mame zamknuty dielock, takze prip. ExitMe neprobehnou pred nami + } + else + { + DEBUG('t', "Thread %d is in usermode, dies immediately\n", i); + IntStatus oldLevel = interrupt->SetLevel(IntOff); // disable interrupts + scheduler->RemoveThread(threads[i]); // je v usermode, muzeme ho klidne znicit + // a slehne se po nem zem + (void) interrupt->SetLevel(oldLevel); // obnovime prip. interrupty + delete threads[i]; // ani ExitMe() nezavola, proste zmizi + conds[i]->Broadcast(zamek); + delete conds[i]; + conds[i]=NULL; + threads[i]=NULL; + num_thr--; // klidne si ho skrtneme + } + + } + } + dielock->Release(); + zamek->Release(); + return killed; // zabili jsme vsechny svoje thready? +} + + +/* Vytvori proces spustenim 'filename', s otcem 'otec' a prioritou 'pr' */ +Process::Process(char *filename, SpaceId my_pid, SpaceId otec, int pr) +{ + zamek = new Lock("process lock"); + dielock = new Lock("process die lock"); + OpenFile *executable = fileSystem->Open(filename); + space = new AddrSpace(executable); + delete executable; + + name=filename; + Thread *thread = new Thread(filename); + last_tid = 0; + threads[0] = thread; + conds[0] = new Condition("thread cvar"); + num_thr = 1; + thread->space = space; + thread->proc = this; + thread->SetTID(last_tid); + PID=my_pid; + + parent = otec; + priority = pr; + + desclock = new Lock("descriptor lock"); + openfiles[0] = 1; // stdin a stdout jsou otevreny + openfiles[1] = 1; + numfilesopen = 2; + + for (int i=2; iFork(Startup,(int)thread); + +} + +/* Vytvori proces "obalenim" threadu Main s pidem my_pid, otcem otec a prioritou pr */ +Process::Process(Thread *Main, SpaceId my_pid, SpaceId otec, int pr) +{ + zamek = new Lock("process lock"); + dielock = new Lock("process die lock"); + + name=Main->getName(); + + last_tid = 0; + threads[0] = Main; + conds[0] = new Condition("thread cvar"); + num_thr = 1; + Main->proc = this; + Main->SetTID(last_tid); + PID=my_pid; + + parent = otec; + priority = pr; + + desclock = new Lock("descriptor lock"); + openfiles[0] = 1; // stdin a stdout jsou otevreny + openfiles[1] = 1; + numfilesopen = 2; + + for (int i=2; iAcquire(); + for (int i=0; ipriority = newpr; + } + zamek->Release(); +} + +void Process::AddDescr(OpenFileId descr) +{ + desclock->Acquire(); + openfiles[descr]=1; + desclock->Release(); +} + + +void Process::RemoveDescr(OpenFileId descr) +{ + desclock->Acquire(); + openfiles[descr]=0; + desclock->Release(); +} + + +void Process::KillThread(int tid) +{ + zamek->Acquire(); // nechceme, aby se nam sem pletl nejaky trapny thread z usermode + if ((tid<0) || (tid>=MAXTHREADS)) + { + zamek->Release(); + return; + } + if (threads[tid] != NULL) + { + if (threads[tid]->InKernel()) // thread je v kernelu, ted ho nemuzeme zabit + { + DEBUG('t', "Thread %d is in kernel, will die later\n", tid); + threads[tid]->Die(); // tak mu rekneme, aby umrel, az se z nej vrati + // mame zamknuty dielock, takze prip. ExitMe neprobehnou pred nami + } + else + { + DEBUG('t', "Thread %d is in usermode, dies immediately\n", tid); + IntStatus oldLevel = interrupt->SetLevel(IntOff); // disable interrupts + scheduler->RemoveThread(threads[tid]); // je v usermode, muzeme ho klidne znicit + // a slehne se po nem zem + (void) interrupt->SetLevel(oldLevel); // obnovime prip. interrupty + delete threads[tid]; // ani ExitMe() nezavola, proste zmizi + threads[tid]=NULL; + num_thr--; // klidne si ho skrtneme + } + } + zamek->Release(); +} + + +int Process::WaitForThread(int tid) +{ + zamek->Acquire(); + if ((tid<0) || (tid>=MAXTHREADS)) // neplatne cislo threadu + { + zamek->Release(); + return -1; + } + + if (tid<=last_tid) // thread nekdy existoval + { + if (threads[tid]==NULL) // ale uz dobehl + { + zamek->Release(); + return 0; + } + else // jeste nedobehl, tak na nej pockame + { + conds[tid]->Wait(zamek); + } + } + zamek->Release(); + return 0; +} + + +/**************** + ** ProcList ** + ****************/ + +// Prida do seznamu novy proces, ktery vytvori na zaklade programu ve filename + +SpaceId ProcList::NewProcess(char* filename, SpaceId parent, int pr) +{ + CreateLock->Acquire(); + + SpaceId newId = GetFreePID(); + + DEBUG('t', "Creating new process from file '%s' with PID %d\n", filename, newId); + + if (newId == -1) + { + CreateLock->Release(); + return -1; + } + + if (parent<=last_PID) + { + procList[parent]->AddChild(newId); + waiting[newId] = new Condition(filename); + parents[newId] = parent; + } + + Process *proc = new Process(filename, newId, parent, pr); + + proc->PL = this; + procList[newId] = proc; + + CreateLock->Release(); + + return newId; +} + +// Prida do seznamu novy proces, ktery vytvori kolem threadu Main + +SpaceId ProcList::NewProcess(Thread *Main, SpaceId parent, int pr) +{ + CreateLock->Acquire(); + + SpaceId newId = GetFreePID(); + + DEBUG('t', "Creating new process from thread '%s'with PID %d\n", Main->getName(), newId); + + if (newId == -1) + { + CreateLock->Release(); + return -1; + } + + if (parent<=last_PID) + { + if (parent>=0) + procList[parent]->AddChild(newId); + + waiting[newId] = new Condition(Main->getName()); + parents[newId] = parent; + } + + Process *proc = new Process(Main, newId, parent, pr); + + proc->PL = this; + procList[newId] = proc; + + CreateLock->Release(); + + return newId; +} + +void ProcList::RemoveProcess(SpaceId PID) +{ + CreateLock->Acquire(); + if (PID<0) + { + CreateLock->Release(); + return; + } + if (procList[PID]!= NULL) + { + DEBUG('t', "Storing exit value\n"); + ret_vals[PID] = procList[PID]->RetVal(); // ulozime si posledni navratovou hodnotu + DEBUG('t', "Deleting process %d\n", PID); + delete procList[PID]; + procList[PID] = NULL; + waiting[PID]->Broadcast(CreateLock); // vzbudit vsechny, kteri cekaji na tenhle proces + } + CreateLock->Release(); +} + + +ProcList::ProcList() +{ + CreateLock = new Lock("CreateLock"); + + for (int i=0; iAcquire(); + for (int i=0; iBroadcast(CreateLock); // ma to tady vubec smysl? + delete waiting; + } + } + CreateLock->Release(); + delete CreateLock; +} + +int ProcList::WaitFor(SpaceId PID, SpaceId whoAmI) +{ + CreateLock->Acquire(); + // nejsem otec - bud opravdu, nebo ten proces nikdy nebezel a nema ho nastaveny + if (PID<0) + { + CreateLock->Release(); + return -1; + } + if (parents[PID] != whoAmI) + { + CreateLock->Release(); + return -1; + } + if (procList[PID]!=NULL) // jeste bezi, tak si na nej pockame + { + waiting[PID]->Wait(CreateLock); + } + CreateLock->Release(); + return ret_vals[PID]; +} + + +// Tohle snad +- funguje +int ProcList::ChangePriority(SpaceId PID, int newpr) +{ + // mozna by se melo zamykat -> promyslet + if (PID<0) + return -1; + if(procList[PID] == NULL) + return -1; + + procList[PID]->SetPriority(newpr); + return 0; +} + +// Hleda volne ID, pokud neni vrati -1 +// slo by to resit pomoci condition variable (pokud neni volne ID thread se +// uspi + +SpaceId ProcList::GetFreePID() +{ + if (last_PIDAcquire(); + for (int i=0; igetName()); + } + } + CreateLock->Release(); +} + + +void ProcList::Kill(SpaceId PID) +{ + if (PID<0) + return; + + if (procList[PID] != NULL) + { + procList[PID]->DieLock(); // nechceme, aby nam ho nekdo deletnul, pokud nezjistime, jestli to mame udelat my + if (procList[PID]->Die() == 1) // proces ZABIL vsechny svoje thready a muzeme ho zrusit + { + procList[PID]->DieUnlock(); // zadny ex-kernelovy thread nezbyl, muzeme ho klidne zrusit + RemoveProcess(PID); + } + else + procList[PID]->DieUnlock(); // a ted si ho ex-kernelove thready sezerou samy + } +} diff -r -u --new-file --exclude='*.patch--exclude=*.o' --exclude='Makefile*' --exclude=do_diff --exclude='*.patch' /home/bekone/nachos/userprog/process.h /home/bekone/jikos/userprog/process.h --- /home/bekone/nachos/userprog/process.h Thu Jan 1 01:00:00 1970 +++ /home/bekone/jikos/userprog/process.h Sat Dec 22 23:36:57 2001 @@ -0,0 +1,117 @@ +#ifndef THREADMAN_H +#define THREADMAN_H + +#include "syscall.h" +#include "synch.h" +#include "alloc.h" +#include "addrspace.h" + +class Thread; + +// maximalni pocet threadu v procesu +#define MAXTHREADS 10 +// maximalni pocet procesu v systemu +#define MAXPROCESS 30 + +typedef struct { + char* name; // jmeno threadu + Thread *thread; + int TID; +} s_threads; + +class ProcList; + +class Process +{ + SpaceId PID; // PID procesu + Thread *threads[MAXTHREADS]; // thready, ktere patri tomuto procesu + Condition *conds[MAXTHREADS]; // conditions na TJoin() + int num_thr; + int last_tid; + + SpaceId parent; // otcovsky proces + unsigned int num_chld; + + int priority; // priorita, s jakou bude thread bezet + OpenFileId openfiles[MAXFILESOPEN]; // binarni pole threadem otevrenych souboru + int numfilesopen; // pocet prave otevrenych souboru + int retval; // navratova hodnota z Exit() + int status; // status procesu - bezi, umrel - da se poznat z ProcList (snad) + int num_wait; // pocet cekajicich procesu + Lock *zamek; + AddrSpace *space; // addrspace + + Lock *dielock; // zamek, ktery zabrani preplanovanym ex-kernelovym threadum probehnout ExitMe() + // a tim zavolat destruktor driv, nez dobehne Process::Die() + + Lock *desclock; // zamek nad descriptory + + char *name; // jmeno procesu + +public: + int ExitMe(int rv, int TID); // ukonci tenhle proces s hodnotou rv (melo by se volat z Exit()) + // zrusi zaznam o volajicim threadu a snizi pocet deti + // pokud to byl posledni thread v procesu, zrusi addrspace + Process(char *filename, SpaceId my_pid, SpaceId otec, int pr); + // vytvori proces ze souboru filename a da mu pid PID, prioritu pr a otec je 'otec' + Process(Thread *Main, SpaceId my_pid, SpaceId otec, int pr); + // vytvori proces obalenim exitujiciho threadu + + ~Process(); + int AddThread(void (*func)(int)); // prida thread do procesu a !nastavi! jeho TID, forknou ho na zadanou funkci a vrati jeho TID + void AddChild(SpaceId child) { } // prida proces jako potomka + + SpaceId GetPID() { return PID; } // vrati PID procesu + int RetVal() { return retval; } // navratova hodnota procesu + char *getName() { return name; } // jmeno procesu + + void SetPriority(int newpr); // nastavi novou prioritu vsem threadum v procesu + + int WaitForThread(int tid); // pocka na thread tid, pri neuspechu vraci -1 + void KillThread(int tid); // zabije thread tid + + + void AddDescr(OpenFileId descr); // poznamena si descriptor + void RemoveDescr(OpenFileId descr); // zrusi si zaznam o descriptoru + + int Die(); + + void DieLock() { dielock->Acquire(); } // timhle zabranime, aby nam ten proces nekdo deletnul + void DieUnlock() { dielock->Release(); } // a timhle no nechame sezrat, pokud jsme si ho sami nezrusili a uz to vime + + ProcList *PL; // process list + +}; + + +class ProcList { + public: + ProcList(); + ~ProcList(); + SpaceId NewProcess(char* filename, SpaceId parent, int pr); + // vytvori proces ze souboru filename + // vrati PID + SpaceId NewProcess(Thread *Main, SpaceId parent, int pr); + // vytvori proces kolem threadu a zaradi si ho + void RemoveProcess(int rv); // Odstrani proces z fronty a pripadne ho zrusi + int WaitFor(SpaceId PID, SpaceId whoAmI); // Join() na PID, ceka whoAmI + int ChangePriority(SpaceId pid, int newpr); + // zmeni prioritu procesu + void Kill(SpaceId PID); + // zabije proces PID + + void ps(); // vypise seznam procesu + + private: + SpaceId GetFreePID(); // vrati prvni volne ID + SpaceId last_PID; + Lock *CreateLock; + // tohle asi dat do nejake struktury + Process *procList[MAXPROCESS]; // seznam procesu + int ret_vals[MAXPROCESS]; // navratove hodnoty procesu + SpaceId parents[MAXPROCESS]; // otcove, opravneni volat Join() + Condition *waiting[MAXPROCESS]; // conditiony na cekani na Join() +}; + + +#endif diff -r -u --new-file --exclude='*.patch--exclude=*.o' --exclude='Makefile*' --exclude=do_diff --exclude='*.patch' /home/bekone/nachos/userprog/progtest.cc /home/bekone/jikos/userprog/progtest.cc --- /home/bekone/nachos/userprog/progtest.cc Sun Nov 21 12:49:48 1993 +++ /home/bekone/jikos/userprog/progtest.cc Sat Dec 22 11:33:03 2001 @@ -13,7 +13,9 @@ #include "console.h" #include "addrspace.h" #include "synch.h" +#include "process.h" +extern ProcList *PList; //---------------------------------------------------------------------- // StartProcess // Run a user program. Open the executable, load it into @@ -23,6 +25,7 @@ void StartProcess(char *filename) { + OpenFile *executable = fileSystem->Open(filename); AddrSpace *space; @@ -30,15 +33,26 @@ printf("Unable to open file %s\n", filename); return; } + printf("Opened file %s\n", filename); + space = new AddrSpace(executable); currentThread->space = space; - delete executable; // close file + + PList->NewProcess(currentThread, -1, 10); // prida tenhle thread do procesu a jeden mu vytvori +// currentThread->proc = NULL; + +// int i = threadman->CreateThreadMan(filename,0,10); +// currentThread->SetPid(i); + + +// PList->NewProcess(filename,currentThread->GetPID(),10); space->InitRegisters(); // set the initial register values space->RestoreState(); // load page table register machine->Run(); // jump to the user progam + ASSERT(FALSE); // machine->Run never returns; // the address space exits // by doing the syscall "exit" diff -r -u --new-file --exclude='*.patch--exclude=*.o' --exclude='Makefile*' --exclude=do_diff --exclude='*.patch' /home/bekone/nachos/userprog/swtch.s /home/bekone/jikos/userprog/swtch.s --- /home/bekone/nachos/userprog/swtch.s Tue Oct 30 15:52:38 2001 +++ /home/bekone/jikos/userprog/swtch.s Sat Dec 29 00:29:40 2001 @@ -1,213 +1,44 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - .text - .align 2 - - .globl ThreadRoot - - - - - - - - - + .align 2 + .globl ThreadRoot ThreadRoot: - pushl %ebp - movl %esp,%ebp - pushl %edx - call %ecx - call %esi - call %edi - - #NOT REACHED - movl %ebp,%esp - popl %ebp + pushl %ebp + movl %esp,%ebp + pushl %edx + call %ecx + call %esi + call %edi + # NOT REACHED + movl %ebp,%esp + popl %ebp ret - - - - - - - - - - - - - - - .comm _eax_save,4 - - .globl SWITCH + .comm _eax_save,4 + .globl SWITCH SWITCH: - movl %eax,_eax_save # save the value of eax - movl 4(%esp),%eax # move pointer to t1 into eax - movl %ebx,8 (%eax) # save registers - movl %ecx,12 (%eax) - movl %edx,16 (%eax) - movl %esi,24 (%eax) - movl %edi,28 (%eax) - movl %ebp,20 (%eax) - movl %esp,0 (%eax) # save stack pointer - movl _eax_save,%ebx # get the saved value of eax - movl %ebx,4 (%eax) # store it - movl 0(%esp),%ebx # get return address from stack into ebx - movl %ebx,32 (%eax) # save it into the pc storage - - movl 8(%esp),%eax # move pointer to t2 into eax - - movl 4 (%eax),%ebx # get new value for eax into ebx - movl %ebx,_eax_save # save it - movl 8 (%eax),%ebx # retore old registers - movl 12 (%eax),%ecx - movl 16 (%eax),%edx - movl 24 (%eax),%esi - movl 28 (%eax),%edi - movl 20 (%eax),%ebp - movl 0 (%eax),%esp # restore stack pointer - movl 32 (%eax),%eax # restore return address into eax - movl %eax,4(%esp) # copy over the ret address on the stack - movl _eax_save,%eax - + movl %eax,_eax_save # save the value of eax + movl 4(%esp),%eax # move pointer to t1 into eax + movl %ebx,8(%eax) # save registers + movl %ecx,12(%eax) + movl %edx,16(%eax) + movl %esi,24(%eax) + movl %edi,28(%eax) + movl %ebp,20(%eax) + movl %esp,0(%eax) # save stack pointer + movl _eax_save,%ebx # get the saved value of eax + movl %ebx,4(%eax) # store it + movl 0(%esp),%ebx # get return address from stack into ebx + movl %ebx,32(%eax) # save it into the pc storage + movl 8(%esp),%eax # move pointer to t2 into eax + movl 4(%eax),%ebx # get new value for eax into ebx + movl %ebx,_eax_save # save it + movl 8(%eax),%ebx # retore old registers + movl 12(%eax),%ecx + movl 16(%eax),%edx + movl 24(%eax),%esi + movl 28(%eax),%edi + movl 20(%eax),%ebp + movl 0(%eax),%esp # restore stack pointer + movl 32(%eax),%eax # restore return address into eax + movl %eax,4(%esp) # copy over the ret address on the stack + movl _eax_save,%eax ret diff -r -u --new-file --exclude='*.patch--exclude=*.o' --exclude='Makefile*' --exclude=do_diff --exclude='*.patch' /home/bekone/nachos/userprog/syscall.h /home/bekone/jikos/userprog/syscall.h --- /home/bekone/nachos/userprog/syscall.h Thu Nov 29 15:08:56 2001 +++ /home/bekone/jikos/userprog/syscall.h Fri Dec 28 15:45:39 2001 @@ -29,10 +29,33 @@ #define SC_Close 8 #define SC_Fork 9 #define SC_Yield 10 +#define SC_Kill 20 +#define SC_TJoin 30 +// join na thread +#define SC_TKill 31 +// kill na thread +#define SC_ps 40 +// vypise procesy - testing purposes only!! + +/* synchronizace */ +#define SC_CreateLock 100 +#define SC_Lock_Acquire 101 +#define SC_Lock_Release 102 +#define SC_DeleteLock 199 + +#define SC_CreateSem 200 +#define SC_Sem_P 201 +#define SC_Sem_V 202 +#define SC_DeleteSem 299 + +#define SC_CreateCond 300 +#define SC_Cond_Wait 301 +#define SC_Cond_Signal 302 +#define SC_Cond_Broadcast 303 +#define SC_DeleteCond 399 -#ifndef IN_ASM -#warning WRN - BEZ HLAVICKY +#ifndef IN_ASM /* The system call interface. These are the operations the Nachos * kernel needs to support, to be able to run user programs. @@ -119,13 +142,54 @@ /* Fork a thread to run a procedure ("func") in the *same* address space * as the current thread. */ -void Fork(void (*func)()); +int Fork(void (*func)(int), int param); /* Yield the CPU to another runnable thread, whether in this address space * or not. */ void Yield(); +/* + * Nove syscally pro praci s thready a procesy + */ + +void Kill(SpaceId PID); + +void TJoin(int TID); + +void TKill(int TID); + +void ps(); + +/* + * Nove syscally pro praci s uzivatelskymi + * synchronizacnimi primitivy + */ + +typedef int LockId; +typedef int SemId; +typedef int CondId; + + +/* zamky */ +LockId CreateLock(); +int Lock_Acquire(LockId lockid); +int Lock_Release(LockId lockid); +int DeleteLock(LockId lockid); + +/* semafory */ +SemId CreateSem(); +int Sem_P(SemId semid); +int Sem_V(SemId semid); +int DeleteSem(SemId semid); + +/* cond. var */ +CondId CreateCond(); +int Cond_Wait(CondId condid, LockId lockid); +int Cond_Signal(CondId condid, LockId lockid); +int Cond_Broadcast(CondId condid, LockId lockid); +int DeleteCond(CondId condid); + #endif /* IN_ASM */ #endif /* SYSCALL_H */