Lesson 2 Laboratory work in TDDI04 Assignment 2 » Lesson purposes n n n n »Viacheslav Izosimov »2009-02-16 »viaiz@ida.liu.se Threads Pintos Organization User programs » Smallest execution unit » Own stack » User-thread run in a process address User memory User stack Threads Kernel stack Scheduler Short repetition of Processes and Threads System call details in PINTOS Details of system calls to implement Synchronization problems, questions, solutions User-exception handler space (user-mode) » Kernel-thread run OS-code in physical Synchronization primitives address space (kernel-mode) Memory management Interrupt handler » Share memory with all threads in same File system Timer Threads address space Threads A system contains several threads running in parallel Thread is a “basic unit of CPU utilization” §Thread ID §A program counter §A register set §A stack Thread 1 void SimpleThread(void * which) { int num; for (num = 0; num < 5; num++) { printf("*** thread %d looped %d times\n", (int)which, num); thread_yield(); Entering SimpleTest } *** thread 0 looped 0 times } void SimpleThreadTest(void) { char *t_name = "forked thread"; printf("Entering SimpleTest"); *** thread 1 looped 0 times *** thread 0 looped 1 times *** thread 1 looped 1 times … Thread 2 thread_create(t_name, PRI_MIN, SimpleThread, (void *)1); Thread execution sequence SimpleThread((void *)0); } 1 Process and thread relations / Signal up sema_ waiting until completion of start_process Kernel pr ex oces ec s ut ion e: pr oc ge ess_ ne ex ra ec te u t r t_ pr oc es s( SP SP :l ) oa din g SP ini : st tia ac liz k at ion e User Program (Process) sta d pi Wait / wn do sema_ Ke ex rne ec l ut ion » Program in execution » Own stack » Define own independent address space » Powered by kernel thread(s) » Can contain several user threads » Run in user mode Processes Ke ex rne ec l ut ion pr oc es s_ ex ec ut Processes process_execute(task); // starts the user program (process) Process and thread relations Process memory, Logic address space » Cooperate to step by step draw an illustrating picture over the process and thread relation on the board. » Discuss and correct the picture. User thread Process User thread User thread User Mode Process Process Process System call interface Kernel thread Kernel thread Kernel thread Kernel thread Kernel Mode Physical memory address space Process questions » If a kernel thread exit, will the process survive? » If a user thread exit, will the process survive? » How to stop a process? » How to read from keyboard? » How to write to screen? System call » Process run in user mode » Process need access to shared resources controlled by kernel » A ”system call” is the request for this service, and handling thereof 2 Systems Calls At High Level » System calls: n n n communication between the user program and the kernel functions, called from the user program and performed by the kernel computers often use interrupts to accomplish that switch from user code to system code Useful Files » Have a look at: pintos/src/lib/user/syscall[.h|.c] – the wrapper… userprog/syscall[.h|.c] – Your implementation of system calls!!! n threads/interrupt.[h|c] – important structures!!! n lib/syscall-nr.h – system call constants n filesys/filesys.[h|c] – Pintos file system implementation… n examples/lab2test.c – the “official” test program for this lab n filesys/file.[h|c] – useful functions for operations with files. Things which you don’t find in “filesys”, you find here n userprog/process.c – implementation of process functions n n Where is it done in PINTOS? System calls to implement » You will need to implement: create - creates a file. open - opens a file. n close - closes a file. n read - reads from a file or the console (the keyboard). n write - writes to a file or the console (the monitor). n halt - halts the processor. n exit - Terminates a program and deallocates resources occupied by the program, for example, closes all files opened by the program. n n System call step by step 1. Store operation to do and parameters on the stack 2. Trigger a switch to kernel thread by means of software interrupt 3. Read and verify the parameters in kernel mode 4. Perform the requested operation 5. Save the result for the process 6. Return from the interrupt to the process Systems Calls At High Level user_program.c » Step 1-2 Done by ”wrapper” in lib/user/syscall.c » Step 3-5 For YOU to implement in userprog/syscall.c » Step 6 Automatically done after syscall_handler returns bool flag; Calling flag = create(“file.txt”, 1000); corresponding Return result back function in to the user program the wrapper System call wrapper pintos/src/lib/user/syscall.c bool create (const char *file, unsigned initial_size) { return syscall2 (SYS_CREATE, file, initial_size); } Calling corresponding exception in Pintos kernel pintos/src/userprog/syscall.c the kernel Return result back to the wrapper User exception handler // Your code here! 3 System call questions System call details » Which steps are done in kernel mode? » Which are done in user mode? » Are interrupts on or off during a system call? » What security risks exist? » At which step(s)? System call stacks User stack … size name SYSCALL » Assume a process is about to execute the system call: bool create_file(char* name, int size) » Cooperate to push the (most important) contents of the user and kernel stack. » Discuss where to find and store important data. System call stacks Kernel stack cs flags error gs ESP ss frame fs es ds EIP int-no edx ecx EAX ebp dummy ebx F edi esi kernel esp Stack layouts when the kernel code for create_file(char* name, int size) is ready to execute (after the interrupt). hy W Important data in uppercase letters ”? “4 Important stack data System call stacks f->esp + 4 f->esp + 8 f->esp f->esp + 12 … » F is points to a structure representing the stack content (”interrupt-frame”) It become parameter to syscall_handler(struct frame* f) See threads/interrupt.h » SYSCALL is a number identifying the requested service. See lib/syscall-nr.h » ESP is the process stack pointer » EAX is the register where the process will look for any return values 4 System call halt » void halt (void) NO_RETURN; » Shut down the computer. See threads/init.h Shutdown Example » » » » » » halt.c #include <syscall.h> #include "userprog/syscall.h“ int #include <stdio.h> #include <syscall-nr.h> main (void){ #include "threads/interrupt.h“ halt (); #include "threads/thread.h“ static void syscall_handler (struct intr_frame *); } userprog/syscall.c Shutdown Example » » » » » » halt.c #include "userprog/syscall.h“ #include <syscall.h> #include <stdio.h> #include <syscall-nr.h> int #include "threads/interrupt.h“ main (void){ #include "threads/thread.h“ static void syscall_handler (struct intr_frame *); halt (); voidsyscall_init (void) { } intr_register_int (0x30, 3, INTR_ON, syscall_handler, "syscall"); } static void syscall_handler (struct intr_frame *f) { // DEMO CODE userprog/syscall.c thread_exit (); } get a name of the system call ! SYS_HALT from the stack f->esp – stack pointer voidsyscall_init (void) { intr_register_int (0x30, 3, INTR_ON, syscall_handler, "syscall"); } static void syscall_handler (struct intr_frame *f) { // DEMO CODE thread_exit (); } Useful Files » You have to have a look at: pintos/src/lib/user/syscall[.h|.c] – the wrapper… userprog/syscall[.h|.c] – Your implementation of system calls!!! n threads/interrupt.[h|c] – important structures!!! n lib/syscall-nr.h – system call constants n filesys/filesys.[h|c] – Pintos file system implementation… n examples/lab2test.c – the “official” test program for this lab n filesys/file.[h|c] – useful functions for operations with files. Things which you don’t find in “filesys”, you find here n userprog/process.c – implementation of process functions n n use power_off() System call exit » void exit (int status) NO_RETURN; » Exit process. See threads/thread.h » Be aware of the different responsibilities of thread_ and process_ exit. » process_exit only free process resources and is called by thread_exit. » Status is associated with the process for later retrieval by parent process (lab 4) System call create » bool create (const char *name, unsigned initial_size); » Create a file with given “name” and “size”. See filesys/filesys.h 5 Create Example » bool create (const char *file, unsigned initial_size) » Example: create(“file.txt”, 1000); How to get them? f->esp Answer: f->esp Hint: … note that, in order to get How to return a value? a string, you will need get a void pointer Answer: f->eax from esp and then get a char pointer to which points that void pointer. The char pointer will point to the first element of the string … System call open Create Example » To implement the system calls, which operate with files, look at “filesys/filesys.[h|c]” and “filesys/file.[h|c]”. » Everything is already done there for you! Just call the functions… » int open (const char *file); » Open the named “file”. See filesys/filesys.h » The process must keep track of all files it opens, and assign an “fd” to it that subsequent system-calls may use. The “fd” is returned. System call read System call read » int read (int fd, void *buffer, unsigned length); » Read “length” from file identified by “f”d. “fd” must be open or » Returns the number of bytes actually read (0 at end of file), or -1 if the file could not be read (due to a condition other than end of file) STDIN_FILENO. » Store read data in “buffer”. Use input_getc for keyboard. See filesys/file.h, devices/input.h 6 System call write » int write (int fd, const void *buffer, unsigned length); System call write » Returns the number of bytes actually written or -1 if the file could not be written » Write “length” from file identified by “fd”. “fd” must be open or FILENO_STDOUT. » Find data to write in “buffer”. Use putpuf for screen. Check lib/kernel/stdio.h and lib/kernel/console.c Console The reading from the console should be done in the following convenient way: » You should implement echo » The typing should be permitted until Enter is pressed (ASCII code 13) » Do not use the graphical qemu terminal for keyboard » The expected behavior is to write as many bytes as possible up to end-of-file and return the actual number written or -1 if no bytes could be written at all System call close » void close (int fd); » Close the open file associated with “fd”. input (it behaves strangely), instead use the terminal from which you start pintos » Only the requested number of characters passed in a read system call should be stored (for example, 10), the rest should be ignored » Do not forget to add NULL character at the end of the string that you have read. System calls saved for later » pid_t exec (const char *file); » int wait (pid_t); Synchronization » Previously presented problems n n n n » int filesize (int fd); » void seek (int fd, unsigned position); » unsigned tell (int fd); » bool remove (const char *file); Bounded buffer – two solutions Stack – two solutions One-time communication – two solutions Seat-reservation » New problems n n Provide a number of reasons to open/close the file versus direct access to the file with read/write. Create a data structure (or a set of structures) to store open files pointers. Each thread should be able to open 128 files. w How will this structure look like (dynamic vs. static, global vs. local, array vs. list)? w Where will you declare/init/de-init this structure? w How will you synchronize access to this structure? 7 Synchronization Exit(SUCCESS); » Solve problems step by step » Discuss each sub-problem » Discuss different solutions » Answer questions 8