Tyler Gaynair Lab 6 Score is out of 20 1.) Try the pthreads.cpp and sdlthreads_demo.cpp programs presented in Introduction. Modify the programs so that they run 3 threads ( instead of two ) and each thread runs a different function, displaying a different message. Copy-and-paste the source code as well as the outputs into your report. *Pthread Modified for 3 threads instead of 2 #include <pthread.h> #include <stdio.h> using namespace std; //The thread void *runner ( void *data ) char *tname = ( char * )data; printf("i am %s\n", tname ); pthread_exit ( 0 ); void *walker (void *data ) char *tname = (char * )data; printf("hows it %s\n", tname ); pthread_exit (0); void *jogger (void *data ) char *tname = (char * )data; printf("what is %s\n", tname ); pthread_exit (0); int main () pthread_t id1, id2, id3; //thread identifiers pthread_attr_t attr1, attr2, attr3; //set of thread attributes char *tnames[3] = "Thread 1", "going", "up" ; //names of threads //get the default attributes pthread_attr_init ( &attr1 ); pthread_attr_init ( &attr2 ); pthread_attr_init ( &attr3 ); //create the threads pthread_create ( &id1, &attr1, runner, tnames[0] ); pthread_create ( &id2, &attr2, walker, tnames[1] ); pthread_create ( &id3, &attr3, jogger, tnames[2] );
//wait for the threads to exit pthread_join ( id1, NULL ); pthread_join ( id2, NULL ); pthread_join ( id3, NULL ); *Pthread modified executed [005283235@csusb.edu@jbh3-1 Lab6]$ vi sdlthread_demomod.cpp [005283235@csusb.edu@jbh3-1 Lab6]$./pthreads_demomod I am Thread 1 Hows it going What is up [005283235@csusb.edu@jbh3-1 Lab6]$ *Sdl thread modified for 3 threads instead of 2. #include <SDL/SDL.h> #include <SDL/SDL_thread.h> #include <stdio.h> using namespace std; //The thread int runner ( void *data ) char *tname = ( char * )data; printf("i am %s\n", tname ); int walker ( void *data ) char *tname = ( char * )data; printf("howdy %s\n", tname ); int jogger (void *data ) char *tname = (char * )data; printf("my name is %s\n", tname ); int main () SDL_Thread *id1, *id2, *id3; //thread identifiers char *tnames[3] = "Thread 1", "Partner", "Tyler" ; //names of threads //create the threads id1 = SDL_CreateThread ( runner, tnames[0] ); id2 = SDL_CreateThread ( walker, tnames[1] );
id3 = SDL_CreateThread ( jogger, tnames[2] ); //wait for the threads to exit SDL_WaitThread ( id1, NULL ); SDL_WaitThread ( id2, NULL ); SDL_WaitThread ( id3, NULL ); *SDL modified thread running [005283235@csusb.edu@jb358-3 Lab6]$./sdlthread_demomod I am Thread 1 Howdy Partner My name is Tyler [005283235@csusb.edu@jb358-3 Lab6]$ The following example, sema1.cpp demonstrates the use of semaphores; it prints an "E" when entering and an "L" when leaving a critical section if the program is invoked with one or more parameters, otherwise it prints an "e" and an "l" respectively. In the program, SEM_DOWN() changes the semaphore sem_op to -1 ( waiting ), which decrements the semaphore value, and SEM_UP() changes it to 1, which increments the semaphore value so that the semaphore becomes available. Note that this sample program allows only a single binary semaphore per program, although we could extend it to pass the semaphore variable if we need more semaphores. The function set_semvalue( value ) initializes the semaphore value; if we set it to 0 and the first process executes a SEM_DOWN() then it has to wait until another process would execute a SEM_UP() to unlock the semaphore. Of course, here we only deal with one process; there's no need to use any semaphore. So the code is mainly to demonstrate the coding of semaphores. Sema1.cpp //sema1.cpp #include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h> #include <iostream> #include <stdio.h> using namespace std; static int sem_id; //semaphore id #if defined( GNU_LIBRARY ) &&!defined(_sem_semun_undefined) /* union semun is defined by including <sys/sem.h> */ #else /* according to X/OPEN we have to define it ourselves */ union semun
int val; /* value for SETVAL */ struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */ unsigned short *array; /* array for GETALL, SETALL */ /* Linux specific part: */ struct seminfo * buf; /* buffer for IPC_INFO */ ; #endif //initializes semaphore using SETVAL static int set_semvalue ( int val ) union semun sem_union;// sem_union; sem_union.val = val; if ( semctl ( sem_id, 0, SETVAL, sem_union ) == -1 ) return ( 0 ); return 1; //delete semaphore static int del_semvalue () union semun sem_union;// sem_union; sem_union.val = 1; if ( semctl ( sem_id, 0, IPC_RMID, sem_union ) == -1 ) return ( 0 ); return 1; static int SEM_DOWN () struct sembuf b; b.sem_num = 0; b.sem_op = -1; //P(), i.e. down() b.sem_flg = SEM_UNDO; if ( semop ( sem_id, &b, 1 ) == -1 ) cout << "Semaphore DOWN() failed!" << endl; return 1; static int SEM_UP() struct sembuf b; b.sem_num = 0; b.sem_op = 1; //V(), i.e. UP() b.sem_flg = SEM_UNDO; if ( semop ( sem_id, &b, 1 ) == -1 ) cout << "Semaphore UP() failed!" << endl; return 1; int main ( int argc, char *argv[] ) int i, pause_time;
char ce = 'e', cl = 'l'; srand ( ( unsigned int ) getpid() ); //seed RNG with process id sem_id = semget ( (key_t) 1234, 1, 0666 IPC_CREAT ); if ( argc > 0 ) if (!set_semvalue( 1 ) ) //process can enter CS cout << "Semaphore initialized failed!" << endl; exit ( EXIT_FAILURE ); if ( argc > 1 ) ce = 'E'; cl = 'L'; sleep ( 1 ); else if (!set_semvalue( 0 ) ) cout << "Semaphore initialized failed!" << endl; exit ( EXIT_FAILURE ); sleep ( 1 ); //process will be blocked initially //enter and leave critical section 10 times for ( i = 0; i < 10; i++ ) if (!SEM_DOWN () ) exit ( EXIT_FAILURE ); cout << ce; fflush ( stdout ); //entering critical section pause_time = rand() % 3; //simulate critical section sleep ( pause_time ); cout << cl; fflush ( stdout ); //leaving critical section if (!SEM_UP() ) exit ( EXIT_FAILURE ); pause_time = rand() % 2; sleep ( pause_time ); cout << endl << getpid() << " finished!" << endl; if ( argc > 0 ) sleep ( 2 ); del_semvalue (); exit ( EXIT_SUCCESS ); //signal other waiting process *Execute with./sema1 & [005283235@csusb.edu@jb358-2 Lab6]$./sema1 & [1] 9969 [005283235@csusb.edu@jb358-2 Lab6]$ elelelelelelelelelel 9969 finished! *Execute with./sema1 a [005283235@csusb.edu@jb358-2 Lab6]$./sema1 a ELELELELELELELELELEL 10056 finished! [005283235@csusb.edu@jb358-2 Lab6]$
sema1mod.cpp modified programs #include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h> #include <iostream> #include <stdio.h> using namespace std; static int sem_id; //semaphore id #if defined( GNU_LIBRARY ) &&!defined(_sem_semun_undefined) /* union semun is defined by including <sys/sem.h> */ #else /* according to X/OPEN we have to define it ourselves */ union semun int val; /* value for SETVAL */ struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */ unsigned short *array; /* array for GETALL, SETALL */ /* Linux specific part: */ struct seminfo * buf; /* buffer for IPC_INFO */ ; #endif //initializes semaphore using SETVAL static int set_semvalue ( int val ) union semun sem_union;// sem_union; sem_union.val = val; if ( semctl ( sem_id, 0, SETVAL, sem_union ) == -1 ) return ( 0 ); return 1; //delete semaphore static int del_semvalue () union semun sem_union;// sem_union; sem_union.val = 1; if ( semctl ( sem_id, 0, IPC_RMID, sem_union ) == -1 ) return ( 0 ); return 1; static int SEM_DOWN ()
struct sembuf b; b.sem_num = 0; b.sem_op = -1; //P(), i.e. down() b.sem_flg = SEM_UNDO; if ( semop ( sem_id, &b, 1 ) == -1 ) cout << "Semaphore DOWN() failed!" << endl; return 1; static int SEM_UP() struct sembuf b; b.sem_num = 0; b.sem_op = 1; //V(), i.e. UP() b.sem_flg = SEM_UNDO; if ( semop ( sem_id, &b, 1 ) == -1 ) cout << "Semaphore UP() failed!" << endl; return 1; int main ( int argc, char *argv[] ) int i, pause_time; char ce = 'e', cl = 'l'; srand ( ( unsigned int ) getpid() ); //seed RNG with process id sem_id = semget ( (key_t) 1234, 1, 0666 IPC_CREAT ); if ( argc > 1 ) argc = atoi(argv[1]); //if 1, proceed if (argc ==1) if (!set_semvalue( 1 ) ) //process can enter CS cout << "Semaphore initialized failed!" << endl; exit ( EXIT_FAILURE ); ce = 'E';
cl = 'L'; sleep ( 1 ); else if (!set_semvalue( 0 ) ) //process will be blocked initially cout << "Semaphore initialized failed!" << endl; exit ( EXIT_FAILURE ); sleep ( 1 ); //enter and leave critical section 10 times for ( i = 0; i < 10; i++ ) if (!SEM_DOWN () ) exit ( EXIT_FAILURE ); cout << ce; fflush ( stdout ); //entering critical section pause_time = rand() % 3; //simulate critical section sleep ( pause_time ); cout << cl; fflush ( stdout ); //leaving critical section if (!SEM_UP() ) exit ( EXIT_FAILURE ); //signal other waiting process pause_time = rand() % 2; sleep ( pause_time ); cout << endl << getpid() << " finished!" << endl; if ( argc > 0 ) sleep ( 2 ); del_semvalue (); exit ( EXIT_SUCCESS ); *Executed./sema1mod 0 then./sema1mod 1./sema1mod 0 ^C [1]+ Done./sema1 [005283235@csusb.edu@jb358-2 Lab6]$./sema1mod 1 ELELELELELELELELELEL 11366 finished! [005283235@csusb.edu@jb358-2 Lab6]$ XV6 Scheduling Proc.c modified printf cprintf("process %s with pid %d running\n", p->name, p->pid);
[005283235@csusb.edu@jb359-1 Lab3]$ vi proc.c [005283235@csusb.edu@jb359-1 Lab3]$ make qemu-nox gcc -fno-pic -static -fno-builtin -fno-strict-aliasing -O2 -Wall-Werror -fno-omitframe-pointer -fno-stack-protector -c -o pro proc.c: In function scheduler : proc.c:347:7: error: expected ; before swtch swtch(&(c->scheduler), p->context); ^~~~~ make: *** [<builtin>: proc.o] Error 1 [005283235@csusb.edu@jb359-1 Lab3]$ vi proc.c [005283235@csusb.edu@jb359-1 Lab3]$ make qemu-nox gcc -fno-pic -static -fno-builtin -fno-strict-aliasing -O2 -Wall-Werror -fno-omitframe-pointer -fno-stack-protector -c -o pro ld -m elf_i386 -T kernel.ld -o kernel entry.o bio.o console.os.o ide.o ioapic.o kalloc.o kbd.o lapic.o log.o main.o mp.o pici.o sleeplock.o spinlock.o string.o swtch.o syscall.o sysfile.o s.o trap.o uart.o vectors.o vm.o -b binary initcode entryother objdump -S kernel > kernel.asm objdump -t kernel sed '1,/SYMBOL TABLE/d; s/.* / /; /^$/d' > dd if=/dev/zero of=xv6.img count=10000 10000+0 records in 10000+0 records out 5120000 bytes (5.1 MB, 4.9 MiB) copied, 0.257629 s, 19.9 MB/s dd if=bootblock of=xv6.img conv=notrunc 1+0 records in 1+0 records out 512 bytes copied, 0.00143718 s, 356 kb/s dd if=kernel of=xv6.img seek=1 conv=notrunc 350+1 records in 350+1 records out 179212 bytes (179 kb, 175 KiB) copied, 0.00471889 s, 38.0 MB/s which: no qemu in (/usr/local/matlab/r2018a/bin:/share/bin:/usr/:/opt/xilinx/14.7/ise_ds/ise/bin/ lin64:/opt/xilinx/14.7/ise_ds/c/opt/xilinx/docnav:/opt/xilinx/vivado/2017.2/bin:/ opt/xilinx/vivin:/opt/xilinx/vivado/2017.2/bin:/opt/xilinx/vivado_hls/2017.2/ bstudio/bin:/opt/android-sdk-linux/tools:/opt/android-sdk-linux/psr/java/latest/ bin:/usr/local/matlab/r2018a/bin:/share/bin:/usr/:/opt/xilinx/14.7/ise_ds/ise/bin/ lin64:/opt/xilinx/14.7/ise_ds/c/opt/xilinx/docnav:/opt/xilinx/vivado/2017.2/bin:/ opt/xilinx/vivin:/opt/xilinx/vivado/2017.2/bin:/opt/xilinx/vivado_hls/2017.2/ bstudio/bin:/opt/android-sdk-linux/tools:/opt/android-sdk-linux/psr/java/latest/ bin:/usr/lib64/qt-3.3/bin:/usr/lib64/ccache:/usr/in:/usr/local/sbin:/usr/sbin:/ home/csusb.edu/005283235/bin) qemu-system-i386 -nographic -drive file=fs.img,index=1,media=disive file=xv6.img,index=0,media=disk,format=raw -smp 2 -m 512 xv6... cpu1: starting 1 cpu0: starting 0 sb: size 1000 nblocks 941 ninodes 200 nlog 30 logstart 2 inodestt 58 Process initcode with pid 1 running
Process init with pid 1 running Process init with pid 1 running Process init with pid 1 running init: starting sh Process init with pid 1 running
$ ls Process sh with pid 2 running P ailedcess sh with pid 5 running Process sh with pid 2 running $ ec: fail with pid 3 running exec ss sh with pid 3 running. 1 1 512.. Process ls with pid 3 running 1 1 512 Process ls with pid 3 running Process ls with pid 3 running Process ls with pid 3 running README 2 2 2290 cat 2 3 13692 Process ls with pid 3 running echo 2 4 12700 forktest 2 5 8132 grep 2 6 15568 init 2 7 13284 kill 2 8 12752 ln 2 9 12652 Process ls with pid 3 running ls 2 10 14840
mkdir 2 11 12832 rm 2 12 12812 sh 2 13 23300 stressfs 2 14 13480 usertests 2 15 56Process ls with pid 3 running 416 wc 2 16 14228 cp 2 17 13448 zombie 2 18 12476 console 3 19 0 myfile 2 20 2290 Process sh with pid 2 running Process sh with pid 2 running Now we write a dummy program named foo.c that creates some child processes and consumes some computing time: #include "types.h" #include "stat.h" #include "user.h" #include "fcntl.h" int main(int argc, char *argv[]) int k, n, id; double x = 0, z; if(argc < 2 ) n = 1; //default value else n = atoi ( argv[1] ); //from command line if ( n < 0 n > 20 ) n = 2; x = 0; id = 0; for ( k = 0; k < n; k++ ) id = fork (); if ( id < 0 ) printf(1, "%d failed in fork!\n", getpid() ); else if ( id > 0 ) //parent printf(1, "Parent %d creating child %d\n", getpid(), id ); // wait (); else // child printf(1, "Child %d created\n",getpid() ); break; for ( z = 0; z < 300000.0; z += 0.1 ) x = x + 3.14 * 89.64; // useless calculations to consume CPU time exit(); After Makefile is updated. [005283235@csusb.edu@jb359-1 Lab3]$ vim Makefile
[005283235@csusb.edu@jb359-1 Lab3]$ make ld -m elf_i386 -T kernel.ld -o kernel entry.o bio.o console.o exec.o file.o fs.o ide.o ioapic.o kalloc.o kbd.o lapic.o log.o main.o mp.o picirq.o pipe.o proc.o sleeplock.o spinlock.o string.o swtch.o syscall.o sysfile.o sysproc.o trapasm.o trap.o uart.o vectors.o vm.o -b binary initcode entryother objdump -S kernel > kernel.asm objdump -t kernel sed '1,/SYMBOL TABLE/d; s/.* / /; /^$/d' > kernel.sym gcc -fno-pic -static -fno-builtin -fno-strict-aliasing -O2 -Wall -MD -ggdb -m32 - Werror -fno-omit-frame-pointer -fno-stack-protector -c -o foo.o foo.c ld -m elf_i386 -N -e main -Ttext 0 -o _foo foo.o ulib.o usys.o printf.o umalloc.o objdump -S _foo > foo.asm objdump -t _foo sed '1,/SYMBOL TABLE/d; s/.* / /; /^$/d' > foo.sym./mkfs fs.img README _cat _echo _forktest _grep _init _kill _ln _ls _mkdir _rm _sh _stressfs _usertests _wc _cp _foo _zombie nmeta 59 (boot, super, log blocks 30 inode blocks 26, bitmap blocks 1) blocks 941 total 1000 balloc: first 629 blocks have been allocated balloc: write bitmap block at sector 58 dd if=/dev/zero of=xv6.img count=10000 10000+0 records in 10000+0 records out 5120000 bytes (5.1 MB, 4.9 MiB) copied, 0.24472 s, 20.9 MB/s dd if=bootblock of=xv6.img conv=notrunc 1+0 records in 1+0 records out 512 bytes copied, 0.0022678 s, 226 kb/s dd if=kernel of=xv6.img seek=1 conv=notrunc 350+1 records in 350+1 records out 179212 bytes (179 kb, 175 KiB) copied, 0.00566428 s, 31.6 MB/s After running foo 4 in qemu-nox $ foo 4 Process sh with pid 2 running Process sh with pid 2 running
Process foo with pid 3 running Parent 3 creating child 4 Parent 3 creating child 5 Parent 3 creating child 6 Process foo with pid 5 running Process foo with pid 6 running Child 6 created Process foo with pid 5 running Process foo with pid 3 running Process foo with pid 5 running Process foo with pid 6 running Process foo with pid 5 running Process foo with pid 3 running Parent 3 creating chilprocess foo with pid 7 running Process foo with pid 5 running Process foo with pid 6 running Process foo with pid 7 running Process foo with pid 3 running d 7 Process foo with pid 7 running Process foo with pid 5 running Child 5 created Process foo with pid 6 running Process foo with pid 7 running Child 7 created Process foo with pid 6 running Process foo with pid 3 running Child 4 created Process foo with pid 3 running Process foo with pid 5 running
Process foo with pid 6 running Process foo with pid 5 running Process foo with pid 7 running Process foo with pid 3 running Process foo with pid 7 running Process foo with pid 5 running Process foo with pid 6 running Add in the file proc.h the struct proc> the timestamps and the priority: struct proc uint sz; // Size of process memory (bytes) pde_t* pgdir; // Page table char *kstack; // Bottom of kernel stack for this process enum procstate state; // Process state int pid; // Process ID struct proc *parent; // Parent process struct trapframe *tf; // Trap frame for current syscall struct context *context; // swtch() here to run process void *chan; // If non-zero, sleeping on chan int killed; // If non-zero, have been killed struct file *ofile[nofile]; // Open files struct inode *cwd; // Current directory char name[16]; // Process name (debugging) //add timestamps and others uint createtime; //process creation time int sleeptime; //process sleeping time int readytime; //process ready (RUNNABLE) time int runtime; //process running time int priority; //process priority int tickcounter; char dum[8]; Add to the function allocproc() in proc.c the timestamp statements (highlighted in blue): static struct proc* allocproc(void) struct proc *p; char *sp; acquire(&ptable.lock);
for(p = ptable.proc; p < &ptable.proc[nproc]; p++) if(p->state == UNUSED) goto found; release(&ptable.lock); found: p->state = EMBRYO; p->pid = nextpid++; p->createtime = ticks; p->readytime = 0; p->runtime = 0; p->sleeptime = 0; release(&ptable.lock); Running foo after updating the printf in proc.c cprintf("process %s with pid %d running with createtime %d\n", p->name, p->pid, p->createtime); $ foo 4 Process sh with pid 2 running with creattime 22 with creattime 997 with creattime 997 with creattime 997 with creattime 997 with creattime 997 with creattime 997 with creattime 997 with creattime 997 with creattime 997 with creattime 997 with creattime 997 with creattime 997 with creattime 997 with creattime 997 with creattime 997 with creattime 997 with creattime 997 Parent 3 creating child 4 Parent 3 creating child 5 Child 4 created Child 5 created
Parent 3 creating child 6 Parent 3 creating child 7 Process foo with pid 7 running with creattime 1008 Process foo with pid 7 running with creattime 1008 Child 7 created Child 6 created Process foo with pid 7 running with creattime 1008 Process foo with pid 7 running with creattime 1008 Process foo with pid 7 running with creattime 1008 Process foo with pid 7 running with creattime 1008 Process foo with pid 7 running with creattime 1008 Process foo with pid 7 running with creattime 1008 Process foo with pid 7 running with creattime 1008
Process Creation time looks consistent with process ids. Evaluation: I feel like I deserve a 20/20 on this project because I did every part fully and put a lot of effort into it. I learned how to further manipulate a makefile and read creationtimes on process ids. Score: 20/20