diff options
| author | Virtual Student <Cisco_vX78@laptop4.(none)> | 2016-06-21 12:27:39 -0400 |
|---|---|---|
| committer | Virtual Student <Cisco_vX78@laptop4.(none)> | 2016-06-21 12:27:39 -0400 |
| commit | 5cfa2b1d9ed0ba4e35d051b1f5bd1ad8cae237fb (patch) | |
| tree | cd6ddfb1a5318212d8b208ce32e504eea5dccc6b | |
initial commit
43 files changed, 1723 insertions, 0 deletions
diff --git a/lab01/Makefile.debug0 b/lab01/Makefile.debug0 new file mode 100644 index 0000000..7ec22c3 --- /dev/null +++ b/lab01/Makefile.debug0 @@ -0,0 +1,8 @@ + +APP = debug0 + +############################################################################# + +include ../make/defaults.mk +include ../make/app-rules.mk + diff --git a/lab01/Makefile.debug1 b/lab01/Makefile.debug1 new file mode 100644 index 0000000..e110b8d --- /dev/null +++ b/lab01/Makefile.debug1 @@ -0,0 +1,8 @@ + +APP = debug1 + +############################################################################# + +include ../make/defaults.mk +include ../make/app-rules.mk + diff --git a/lab01/Makefile.hello b/lab01/Makefile.hello new file mode 100644 index 0000000..a0ed998 --- /dev/null +++ b/lab01/Makefile.hello @@ -0,0 +1,8 @@ + +APP = hello + +############################################################################# + +include ../make/defaults.mk +include ../make/app-rules.mk + diff --git a/lab01/debug0.c b/lab01/debug0.c new file mode 100644 index 0000000..61ada07 --- /dev/null +++ b/lab01/debug0.c @@ -0,0 +1,18 @@ +#include <stdio.h> +#include <string.h> +int *a; + +int main(int argc, char *argv[]) +{ + int x=5; + int y; + + sleep(4); + + y = atoi(argv[1]); + + printf("Hello World! x=%d, y=%d\n", x,y); + + return(0); +} + diff --git a/lab01/debug1.c b/lab01/debug1.c new file mode 100644 index 0000000..198cf96 --- /dev/null +++ b/lab01/debug1.c @@ -0,0 +1,25 @@ +#include <stdio.h> + +int *a; + +void a_badidea(void); + +int main(int argc, char *argv[]) +{ + int x=5; + + int y; + int z = 16; + + a_badidea(); + + printf("Hello World! x=%d, y=%d\n", x,y); + + return(0); +} + +void a_badidea (void) +{ + int z = 16; + *a = z; +} diff --git a/lab04/Makefile b/lab04/Makefile new file mode 100644 index 0000000..120f406 --- /dev/null +++ b/lab04/Makefile @@ -0,0 +1,8 @@ + +APP = mmu + +############################################################################# + +include ../make/defaults.mk +include ../make/app-rules.mk + diff --git a/lab04/mmu-solution.c b/lab04/mmu-solution.c new file mode 100644 index 0000000..6bb6768 --- /dev/null +++ b/lab04/mmu-solution.c @@ -0,0 +1,22 @@ +#include <unistd.h> +#include <stdlib.h> +#include <stdio.h> + +int bssvar; +int datavar = 99; + +int main() +{ + int stackvar; + char *mallocptr = malloc(100); + + printf("\n"); + printf("Address of bss section var = 0x%08x\n", (unsigned)&bssvar); + printf("Address of data section var = 0x%08x\n", (unsigned)&datavar); + printf("Address of stack var = 0x%08x\n", (unsigned)&stackvar); + printf("Address of malloc'd space = 0x%08x\n", (unsigned)mallocptr); + + while (1) { + sleep(10); + } +} diff --git a/lab04/mmu.c b/lab04/mmu.c new file mode 100644 index 0000000..d8dc198 --- /dev/null +++ b/lab04/mmu.c @@ -0,0 +1,20 @@ +#include <unistd.h> +#include <stdlib.h> +#include <stdio.h> + +int bssvar; +int datavar = 99; + +int main() +{ + int stackvar; + char *mallocptr = malloc(100); + + printf("\n"); + // print addresses of stack, BSS, data, heap segments + + // for extra credit, print the address of the code segment + while (1) { + sleep(10); + } +} diff --git a/lab05/Makefile b/lab05/Makefile new file mode 100644 index 0000000..67298b5 --- /dev/null +++ b/lab05/Makefile @@ -0,0 +1,20 @@ + +############################################################################# + +include ../make/defaults.mk + +clean: + rm -f procs threads $(DESTDIR)/procs $(DESTDIR)/threads + +procs: procs.c Makefile + $(CC) -o $@ $< + cp procs $(DESTDIR) + +threads: threads.c Makefile + $(CC) -o $@ $< -lpthread + cp threads $(DESTDIR) + +sched: sched.c Makefile + $(CC) -o $@ $< -lpthread + cp sched $(DESTDIR) + diff --git a/lab05/procs-solution.c b/lab05/procs-solution.c new file mode 100644 index 0000000..cf1a9ff --- /dev/null +++ b/lab05/procs-solution.c @@ -0,0 +1,18 @@ +#include <sys/types.h> +#include <unistd.h> +#include <stdio.h> + +int global; + +int main() +{ + if (fork()) { /* only the 1st parent enters here */ + fork(); /* ...to fork() a 2nd child... */ + } + + /* All 3 processes (parent and children) run the following */ + + global = getpid(); /* set to a process-specific value */ + sleep(1); + printf("PID is %d, global = %d\n", getpid(), global); +} diff --git a/lab05/procs.c b/lab05/procs.c new file mode 100644 index 0000000..9128b19 --- /dev/null +++ b/lab05/procs.c @@ -0,0 +1,22 @@ +#include <sys/types.h> +#include <unistd.h> +#include <stdio.h> + +int global; + +int main() +{ + /* + Have the parent fork() a child twice + Use the return value of fork() to make sure you're the + parent before forking a second child + */ + + /* Your code here */ + + /* All 3 processes (parent and children) run the following */ + + global = getpid(); /* set to a process-specific value */ + sleep(1); + printf("PID is %d, global = %d\n", getpid(), global); +} diff --git a/lab05/sched-solution.c b/lab05/sched-solution.c new file mode 100644 index 0000000..99b148b --- /dev/null +++ b/lab05/sched-solution.c @@ -0,0 +1,92 @@ +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <pthread.h> + +volatile pthread_t running; +volatile int thread_switches; +volatile int done = 0; + +void * thread(void *x) +{ + pthread_t self = pthread_self(); + long long self_count = 0; + long long avg = 0; + int avg_calculations = 0; + + /* let all threads start */ + sleep(1); + + while(1) { + if (running == self) { /* still this thread running */ + self_count++; + /* + * Safety net -- when running high priority we can prevent + * main() from running and stopping the program. + */ + if (self_count > 100000000) break; + } else { /* just switched to this thread */ + running = self; + thread_switches++; + + if(self_count) + { + /* Re-calculate average */ + avg *= avg_calculations; + avg += self_count; + avg_calculations++; + avg /= avg_calculations; + } + + /* + * Another safety net + */ + if (done || (thread_switches > 300)) break; + + self_count = 1; + } + } + printf("Thread %d exiting, average count between switches = %lld, self_count = %lld\n", + *(int *)x, avg, self_count); + pthread_exit((void*) 0); +} + +int main(void) +{ + void *status; + pthread_attr_t attr; + pthread_t t1, t2; + struct sched_param param; + int one=1; + int two=2; + + /* Add your scheduler setup logic here */ + pthread_attr_init(&attr); + pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED); + + /* Use this line for the first run only */ + pthread_attr_setschedpolicy(&attr, SCHED_OTHER); + /* End of first run only code */ + + /* Use these lines for the second run only */ +// pthread_attr_setschedpolicy(&attr, SCHED_RR); +// param.sched_priority = 10; +// pthread_attr_setschedparam(&attr, ¶m); + /* End of second run only code */ + + /* Use these lines for the third run only */ +// pthread_attr_setschedpolicy(&attr, SCHED_FIFO); +// param.sched_priority = 10; +// pthread_attr_setschedparam(&attr, ¶m); + /* End of third run only code */ + + if (pthread_create(&t1, &attr, thread, &one)) exit(1); + if (pthread_create(&t2, &attr, thread, &two)) exit(1); + + sleep(10); /* let program run 10 seconds */ + done = 1; + pthread_join(t1, &status); + pthread_join(t2, &status); + printf("Total thread switches: %d\n", thread_switches); + exit(0); +} diff --git a/lab05/sched.c b/lab05/sched.c new file mode 100644 index 0000000..ee0d1ac --- /dev/null +++ b/lab05/sched.c @@ -0,0 +1,74 @@ +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <pthread.h> + +volatile pthread_t running; +volatile int thread_switches; +volatile int done = 0; + +void * thread(void *x) +{ + pthread_t self = pthread_self(); + long long self_count = 0; + long long avg = 0; + int avg_calculations = 0; + + /* let all threads start */ + sleep(1); + + while(1) { + if (running == self) { /* still this thread running */ + self_count++; + /* + * Safety net -- when running high priority we can prevent + * main() from running and stopping the program. + */ + if (self_count > 100000000) break; + } else { /* just switched to this thread */ + running = self; + thread_switches++; + + if(self_count) + { + /* Re-calculate average */ + avg *= avg_calculations; + avg += self_count; + avg_calculations++; + avg /= avg_calculations; + } + + /* + * Another safety net + */ + if (done || (thread_switches > 300)) break; + + self_count = 1; + } + } + printf("Thread %d exiting, average count between switches = %lld, self_count = %lld\n", + *(int *)x, avg, self_count); + pthread_exit((void*) 0); +} + +int main(void) +{ + void *status; + pthread_attr_t attr; + pthread_t t1, t2; + struct sched_param param; + int one=1; + int two=2; + + /* Add your scheduler setup logic here */ + + if (pthread_create(&t1, &attr, thread, &one)) exit(1); + if (pthread_create(&t2, &attr, thread, &two)) exit(1); + + sleep(10); /* let program run 10 seconds */ + done = 1; + pthread_join(t1, &status); + pthread_join(t2, &status); + printf("Total thread switches: %d\n", thread_switches); + exit(0); +} diff --git a/lab05/threads-solution.c b/lab05/threads-solution.c new file mode 100644 index 0000000..7437c0f --- /dev/null +++ b/lab05/threads-solution.c @@ -0,0 +1,52 @@ +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <pthread.h> + +int global; + +void * thread(void *joiner) +{ + void *status; + + global = pthread_self(); + sleep(1); + printf("Parent PID is %d, TID is %d, global = %d\n", + getppid(), pthread_self(), global); + + if (joiner) { + if (pthread_join((pthread_t)joiner, &status)) { + exit(1); + } + } + + pthread_exit((void*) 0); +} + +int main(void) +{ + void *status; + int x; + pthread_attr_t attr; + pthread_t curr_thr_id; + pthread_t prev_thr_id; + + if (pthread_attr_init(&attr)) { + exit(1); + } + if (pthread_attr_setschedpolicy(&attr, SCHED_RR)) { + exit(1); + } + + /* Start 3 threads */ + prev_thr_id = 0; + for (x=0; x<3; x++) { + if (pthread_create(&curr_thr_id, &attr, thread, (void*)prev_thr_id)) { + exit(1); + } + prev_thr_id = curr_thr_id; + } + + /* Join last thread */ + pthread_join(curr_thr_id, &status); +} diff --git a/lab05/threads.c b/lab05/threads.c new file mode 100644 index 0000000..feee49c --- /dev/null +++ b/lab05/threads.c @@ -0,0 +1,59 @@ +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <pthread.h> + +int global; + +void * thread(void *joiner) +{ + void *status; + + global = pthread_self(); + sleep(1); + printf("Parent PID is %d, TID is %d, global = %d\n", + getppid(), pthread_self(), global); + + if (joiner) { + if (pthread_join((pthread_t)joiner, &status)) { + exit(1); + } + } + + pthread_exit((void*) 0); +} + +int main(void) +{ + void *status; + int x; + pthread_attr_t attr; + pthread_t curr_thr_id; + pthread_t prev_thr_id; + + if (pthread_attr_init(&attr)) { + exit(1); + } + if (pthread_attr_setschedpolicy(&attr, SCHED_OTHER)) { + exit(1); + } + + /* Start 3 threads */ + prev_thr_id = 0; + for (x=0; x<3; x++) { + /* + Fill in the code ala ... + if (pthread_create(¤tThreadID, &attribute, + thread, (void*)previousThreadID)) { + exit(1); + } + */ + + /* insert your code here */ + + prev_thr_id = curr_thr_id; + } + + /* Join last thread */ + pthread_join(curr_thr_id, &status); +} diff --git a/lab06/Makefile b/lab06/Makefile new file mode 100644 index 0000000..aaa4bdf --- /dev/null +++ b/lab06/Makefile @@ -0,0 +1,8 @@ + +APP = server + +############################################################################# + +include ../make/defaults.mk +include ../make/app-rules.mk + diff --git a/lab06/server-solution.c b/lab06/server-solution.c new file mode 100644 index 0000000..0a0cbed --- /dev/null +++ b/lab06/server-solution.c @@ -0,0 +1,59 @@ +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <stdlib.h> +#include <fcntl.h> +#include <signal.h> +#include <syslog.h> +#include <time.h> + +static void daemonize(void) +{ + int i; + + /* fork once to go into the background */ + switch(fork()) + { + case 0: break; /* child */ + case -1: exit(1); /* error */ + default: exit(0); /* parent */ + } + + /* get a new process group/session, no controlling terminal */ + if(setsid()<0) exit(1); + + /* change the file mode mask */ + umask(0); + + /* close all descriptors */ + for (i=sysconf(_SC_OPEN_MAX);i>=0;--i) close(i); + + /* run in a specific directory */ + chdir("/"); + + /* redirect stdio */ + open ("/dev/null",O_RDWR); + (void) dup(0); + (void) dup(0); + + /* we are now a daemon */ +} + +void hup_handler(int x) +{ + syslog(LOG_DAEMON | LOG_INFO, "Server received SIGHUP at %d\n", + time(0)); + signal(SIGHUP, hup_handler); +} + +int main() +{ + daemonize(); + if (signal(SIGHUP, hup_handler) == SIG_ERR) { + syslog(LOG_DAEMON | LOG_INFO, "Server failed to install signal handler\n"); + } + + while(1) { + sleep(1); + } +} diff --git a/lab06/server.c b/lab06/server.c new file mode 100644 index 0000000..978db64 --- /dev/null +++ b/lab06/server.c @@ -0,0 +1,58 @@ +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <stdlib.h> +#include <fcntl.h> +#include <signal.h> +#include <syslog.h> +#include <time.h> + +static void daemonize(void) +{ + int i; + + /* fork once to go into the background */ + switch(fork()) + { + case 0: break; /* child */ + case -1: exit(1); /* error */ + default: exit(0); /* parent */ + } + + /* get a new process group/session, no controlling terminal */ + if(setsid()<0) exit(1); + + /* change the file mode mask */ + umask(0); + + /* close all descriptors */ + for (i=sysconf(_SC_OPEN_MAX);i>=0;--i) close(i); + + /* run in a specific directory */ + chdir("/"); + + /* redirect stdio */ + open ("/dev/null",O_RDWR); + (void) dup(0); + (void) dup(0); + + /* we are now a daemon */ +} + +void hup_handler(int x) +{ + syslog(LOG_DAEMON | LOG_INFO, "Server received SIGHUP at %d\n", + time(0)); + signal(SIGHUP, hup_handler); +} + +int main() +{ + /* insert code to daemonize here */ + + /* install signal handler here */ + + while(1) { + sleep(1); + } +} diff --git a/lab07/Makefile b/lab07/Makefile new file mode 100644 index 0000000..9137600 --- /dev/null +++ b/lab07/Makefile @@ -0,0 +1,24 @@ +CC=/home/student/crosstools/arm-2010.09/bin/arm-none-linux-gnueabi-gcc + +all: install + +# link .o's together with correct soname and real name +libmy-utils.so.1.0 : test1.o test2.o test3.o + $(CC) + +test1.o : test1.c # compile test1 w/ correct flags and output test1.o + $(CC) + +test2.o : test2.c # compile test2 w/ correct flags and output test2.o + $(CC) + +test3.o : test3.c # compile test3 w/ correct flags and output test3.o + $(CC) + +clean: + rm -f *.o *.so.* + +install: libmy-utils.so.1.0 + cp $< /home/student/targetfs/usr/local/lib + + diff --git a/lab07/Makefile.libuser b/lab07/Makefile.libuser new file mode 100644 index 0000000..713cc94 --- /dev/null +++ b/lab07/Makefile.libuser @@ -0,0 +1,17 @@ +APP = libuser + +############################################################################# + +include ../make/defaults.mk + +all: install + +clean: + rm -f $(APP) $(DESTDIR)/$(APP) + +$(APP): $(APP).c Makefile + $(CC) -o $@ $< # add the lib search path and lib name + +install: $(APP) + cp $< $(DESTDIR) + diff --git a/lab07/solution/Makefile.libuser.solution b/lab07/solution/Makefile.libuser.solution new file mode 100644 index 0000000..3e9e891 --- /dev/null +++ b/lab07/solution/Makefile.libuser.solution @@ -0,0 +1,17 @@ +APP = libuser + +############################################################################# + +include ../make/defaults.mk + +all: install + +clean: + rm -f $(APP) $(DESTDIR)/$(APP) + +$(APP): $(APP).c Makefile + $(CC) -o $@ $< -L. -lmy-utils # add the lib search path and lib name + +install: $(APP) + cp $< $(DESTDIR) + diff --git a/lab07/solution/Makefile.solution b/lab07/solution/Makefile.solution new file mode 100644 index 0000000..63087a4 --- /dev/null +++ b/lab07/solution/Makefile.solution @@ -0,0 +1,24 @@ +CC=/home/student/crosstools/arm-2010.09/bin/arm-none-linux-gnueabi-gcc + +all: install + +# link .o's together with correct soname and real name +libmy-utils.so.1.0 : test1.o test2.o test3.o + $(CC) -o libmy-utils.so.1.0 test1.o test2.o test3.o -shared -Wl,-soname=libmy-utils.so.1 + +test1.o : test1.c # compile test1 w/ correct flags and output test1.o + $(CC) -o test1.o -fPIC -c test1.c + +test2.o : test2.c # compile test2 w/ correct flags and output test2.o + $(CC) -o test2.o -fPIC -c test2.c + +test3.o : test3.c # compile test3 w/ correct flags and output test3.o + $(CC) -o test3.o -fPIC -c test3.c + +clean: + rm -f *.o *.so.* + +install: libmy-utils.so.1.0 + cp $< /home/student/targetfs/usr/local/lib + + diff --git a/lab07/solution/libuser.c.solution b/lab07/solution/libuser.c.solution new file mode 100644 index 0000000..2fecec3 --- /dev/null +++ b/lab07/solution/libuser.c.solution @@ -0,0 +1,18 @@ +#include "stdio.h" +#include "stdlib.h" + +int main (int argc, char *argv[]) +{ + int i = atoi(argv[1]); + int result = 0; + + result = increment(i); + printf("%d\n", result); + result = decrement(i); + printf("%d\n", result); + result = mult2(i); + printf("%d\n", result); + + return(0); +} + diff --git a/lab07/test1.c b/lab07/test1.c new file mode 100644 index 0000000..ca5de68 --- /dev/null +++ b/lab07/test1.c @@ -0,0 +1,4 @@ +int increment (int x) +{ + return(x+1); +} diff --git a/lab07/test2.c b/lab07/test2.c new file mode 100644 index 0000000..48e542d --- /dev/null +++ b/lab07/test2.c @@ -0,0 +1,4 @@ +int mult2 (int x) +{ + return(x*4); +} diff --git a/lab07/test3.c b/lab07/test3.c new file mode 100644 index 0000000..bb4f10d --- /dev/null +++ b/lab07/test3.c @@ -0,0 +1,4 @@ +int decrement (int x) +{ + return(x-1); +} diff --git a/lab08/Makefile.mutex b/lab08/Makefile.mutex new file mode 100644 index 0000000..7632b5a --- /dev/null +++ b/lab08/Makefile.mutex @@ -0,0 +1,11 @@ + +APP = mutex + +############################################################################# + +include ../make/defaults.mk + +CC := $(CC) -lpthread + +include ../make/app-rules.mk + diff --git a/lab08/Makefile.rec b/lab08/Makefile.rec new file mode 100644 index 0000000..4ff8f41 --- /dev/null +++ b/lab08/Makefile.rec @@ -0,0 +1,11 @@ + +APP = rec + +############################################################################# + +include ../make/defaults.mk + +CC := $(CC) -lrt + +include ../make/app-rules.mk + diff --git a/lab08/Makefile.snd b/lab08/Makefile.snd new file mode 100644 index 0000000..df37639 --- /dev/null +++ b/lab08/Makefile.snd @@ -0,0 +1,11 @@ + +APP = snd + +############################################################################# + +include ../make/defaults.mk + +CC := $(CC) -lrt + +include ../make/app-rules.mk + diff --git a/lab08/mutex-solution.c b/lab08/mutex-solution.c new file mode 100644 index 0000000..9a67a32 --- /dev/null +++ b/lab08/mutex-solution.c @@ -0,0 +1,212 @@ +/* Example code to demonstrate behavior of multi-core, threaded application + * + * Written by: Mike Anderson + * The PTR Group, Inc. + * mike@theptrgroup.com + * + * License: GPLv2 + * + */ + +#include <ctype.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <pthread.h> +#include <signal.h> + +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif + + +pthread_mutex_t mutex_fix; /* protect the critical region */ + +pthread_t looperThId; +pthread_t conflictThId; + +volatile int value1; +volatile int value2; +volatile int counter = 0; +volatile int bTimeToExit = FALSE; + +int bUseMutex = FALSE; /* The "s" option */ + + +/* Conflict thread */ +void *conflictTh(void *arg) +{ + int same; + unsigned long loopCount = 0; + struct timespec sleep_time = { + .tv_sec = 0, + .tv_nsec = 7 * 1000 * 1000, + }; + + while (!bTimeToExit) { + if (bUseMutex) { + pthread_mutex_lock(&mutex_fix); + } + + same = (value1 == value2); + if (!same) + printf("\nHey! value1 = %d, value2 = %d\n", value1, + value2); + + loopCount++; + if ((loopCount % 1000) == 0) { + printf("\nConflict thread Counter = %lu \n", loopCount); + fflush(stdout); + counter = 0; + } + + if (bUseMutex) { + pthread_mutex_unlock(&mutex_fix); + } + + /* Sleep for 7ms */ + nanosleep(&sleep_time, NULL); + } + + return NULL; +} + +/* Main loop thread */ +void *looperTh(void *arg) +{ + int counterTemp; + struct timespec sleep_time = { + .tv_sec = 0, + .tv_nsec = 13 * 1000 * 1000, + }; + + + /* give the conflict thread a chance to start */ + sleep(1); + + while (!bTimeToExit) { + if (bUseMutex) { + pthread_mutex_lock(&mutex_fix); + } + + value1 = counter; + value2 = counter; + counterTemp = counter++; + + if (bUseMutex) { + pthread_mutex_unlock(&mutex_fix); + } + + if ((counterTemp % 1000000) == 0) { + printf("Main loop counter = %d \r", counterTemp); + fflush(stdout); + + /* Sleep for 13ms */ + nanosleep(&sleep_time, NULL); + } + } + + return NULL; +} + +/* Ctrl-C Signal Handler */ +void gotCtrlC(int sig) +{ + printf("\nGot Ctrl-C! Shutting down...\n"); + + bTimeToExit = TRUE; +} + +void print_usage(char *program) +{ + fprintf(stderr, "Usage: %s [options]\n%s", program, + "-h This help\n" + "-s (Use mutex to enforce synchronization)\n"); +} + +void parse_options(int argc, char *argv[]) +{ + int c; + + opterr = 0; /* get opt stuff */ + + while ((c = getopt(argc, argv, "hs")) != -1) { + switch (c) { + case 's': + bUseMutex = TRUE; + break; + case '?': + if (isprint(optopt)) + fprintf(stderr, "Unknown option '-%c'.\n", + optopt); + else + fprintf(stderr, + "Unknown option character '\\x%x'.\n", + optopt); + /*FALLTHRU*/ + case 'h': + default: + print_usage(argv[0]); + exit(EXIT_SUCCESS); + } + } + + printf("Options in effect:\n"); + if (bUseMutex) + printf(" Thread synchronization using mutexes is in effect \n"); + else + printf(" Mutex-based thread synchronization is off \n"); +} + +int main(int argc, char *argv[]) +{ + int res; + + /* Parse the command line arguments */ + parse_options(argc, argv); + + printf("\nUse ^C to exit application...\n"); + + /* Set up the ^C signal handler so we can shut down cleanly */ + (void)signal(SIGINT, gotCtrlC); + + /* Go ahead and initialize the mutex in case we need it */ + res = pthread_mutex_init(&mutex_fix, NULL); + if (res != 0) { + perror("Mutex initialization failed"); + exit(EXIT_FAILURE); + } + + /* Create the main loop thread */ + res = pthread_create(&looperThId, NULL, looperTh, NULL); + if (res != 0) { + perror("Main loop thread creation failed"); + exit(EXIT_FAILURE); + } + + + /* Create the conflict thread */ + res = pthread_create(&conflictThId, NULL, conflictTh, NULL); + if (res != 0) { + perror("Conflict thread creation failed"); + exit(EXIT_FAILURE); + } + + printf("\nMain is waiting for threads to finish...\n"); + res = pthread_join(conflictThId, NULL); + if (res != 0) { + perror("Thread join with conflictTh() failed"); + exit(EXIT_FAILURE); + } + res = pthread_join(looperThId, NULL); + if (res != 0) { + perror("Thread join with looperTh() failed"); + exit(EXIT_FAILURE); + } + + printf("Threads joined -- exiting main\n"); + pthread_mutex_destroy(&mutex_fix); + + return EXIT_SUCCESS; +} diff --git a/lab08/mutex.c b/lab08/mutex.c new file mode 100644 index 0000000..7015569 --- /dev/null +++ b/lab08/mutex.c @@ -0,0 +1,212 @@ +/* Example code to demonstrate behavior of multi-core, threaded application + * + * Written by: Mike Anderson + * The PTR Group, Inc. + * mike@theptrgroup.com + * + * License: GPLv2 + * + */ + +#include <ctype.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <pthread.h> +#include <signal.h> + +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif + + +pthread_mutex_t mutex_fix; /* protect the critical region */ + +pthread_t looperThId; +pthread_t conflictThId; + +volatile int value1; +volatile int value2; +volatile int counter = 0; +volatile int bTimeToExit = FALSE; + +int bUseMutex = FALSE; /* The "s" option */ + + +/* Conflict thread */ +void *conflictTh(void *arg) +{ + int same; + unsigned long loopCount = 0; + struct timespec sleep_time = { + .tv_sec = 0, + .tv_nsec = 7 * 1000 * 1000, + }; + + while (!bTimeToExit) { + if (bUseMutex) { + // Acquire mutex using pthread_mutex_lock(3p) + } + + same = (value1 == value2); + if (!same) + printf("\nHey! value1 = %d, value2 = %d\n", value1, + value2); + + loopCount++; + if ((loopCount % 1000) == 0) { + printf("\nConflict thread Counter = %lu \n", loopCount); + fflush(stdout); + counter = 0; + } + + if (bUseMutex) { + // Release mutex using pthread_mutex_unlock(3p); + } + + /* Sleep for 7ms */ + nanosleep(&sleep_time, NULL); + } + + return NULL; +} + +/* Main loop thread */ +void *looperTh(void *arg) +{ + int counterTemp; + struct timespec sleep_time = { + .tv_sec = 0, + .tv_nsec = 13 * 1000 * 1000, + }; + + + /* give the conflict thread a chance to start */ + sleep(1); + + while (!bTimeToExit) { + if (bUseMutex) { + // Acquire mutex using pthread_mutex_lock(3p) + } + + value1 = counter; + value2 = counter; + counterTemp = counter++; + + if (bUseMutex) { + // Release mutex using pthread_mutex_unlock(3p); + } + + if ((counterTemp % 1000000) == 0) { + printf("Main loop counter = %d \r", counterTemp); + fflush(stdout); + + /* Sleep for 13ms */ + nanosleep(&sleep_time, NULL); + } + } + + return NULL; +} + +/* Ctrl-C Signal Handler */ +void gotCtrlC(int sig) +{ + printf("\nGot Ctrl-C! Shutting down...\n"); + + bTimeToExit = TRUE; +} + +void print_usage(char *program) +{ + fprintf(stderr, "Usage: %s [options]\n%s", program, + "-h This help\n" + "-s (Use mutex to enforce synchronization)\n"); +} + +void parse_options(int argc, char *argv[]) +{ + int c; + + opterr = 0; /* get opt stuff */ + + while ((c = getopt(argc, argv, "hs")) != -1) { + switch (c) { + case 's': + bUseMutex = TRUE; + break; + case '?': + if (isprint(optopt)) + fprintf(stderr, "Unknown option '-%c'.\n", + optopt); + else + fprintf(stderr, + "Unknown option character '\\x%x'.\n", + optopt); + /*FALLTHRU*/ + case 'h': + default: + print_usage(argv[0]); + exit(EXIT_SUCCESS); + } + } + + printf("Options in effect:\n"); + if (bUseMutex) + printf(" Thread synchronization using mutexes is in effect \n"); + else + printf(" Mutex-based thread synchronization is off \n"); +} + +int main(int argc, char *argv[]) +{ + int res; + + /* Parse the command line arguments */ + parse_options(argc, argv); + + printf("\nUse ^C to exit application...\n"); + + /* Set up the ^C signal handler so we can shut down cleanly */ + (void)signal(SIGINT, gotCtrlC); + + /* Go ahead and initialize the mutex in case we need it */ + // Initialize the mutex using pthread_mutex_init(3p) + if (res != 0) { + perror("Mutex initialization failed"); + exit(EXIT_FAILURE); + } + + /* Create the main loop thread */ + res = pthread_create(&looperThId, NULL, looperTh, NULL); + if (res != 0) { + perror("Main loop thread creation failed"); + exit(EXIT_FAILURE); + } + + + /* Create the conflict thread */ + res = pthread_create(&conflictThId, NULL, conflictTh, NULL); + if (res != 0) { + perror("Conflict thread creation failed"); + exit(EXIT_FAILURE); + } + + printf("\nMain is waiting for threads to finish...\n"); + res = pthread_join(conflictThId, NULL); + if (res != 0) { + perror("Thread join with conflictTh() failed"); + exit(EXIT_FAILURE); + } + res = pthread_join(looperThId, NULL); + if (res != 0) { + perror("Thread join with looperTh() failed"); + exit(EXIT_FAILURE); + } + + printf("Threads joined -- exiting main\n"); + // Destroy the mutex using pthread_mutex_destroy(3p); + + return EXIT_SUCCESS; +} diff --git a/lab08/rec-solution.c b/lab08/rec-solution.c new file mode 100644 index 0000000..b07beb2 --- /dev/null +++ b/lab08/rec-solution.c @@ -0,0 +1,83 @@ +#include "stdio.h" +#include "stdlib.h" +#include "mqueue.h" +#include "sys/stat.h" +#include "string.h" +#include "signal.h" +#include "setjmp.h" + +int msg_analyze (char *); + +int main (void) +{ + int status = 0; + + mqd_t analyze_q; + struct mq_attr attr = + { + .mq_flags = 0, + .mq_maxmsg = 10, + .mq_msgsize = 100, + }; + + char recd_msg[100]; + + /* create message queue ptr_q */ + analyze_q = mq_open("/analyze_q",O_RDONLY|O_CREAT,S_IWUSR|S_IRUSR, &attr); + if (0 > analyze_q) + { + perror("mq_open"); + exit(1); + } + + while (1) + { + + status = mq_receive(analyze_q,(void *)&recd_msg[0],100,NULL); + + status = msg_analyze(recd_msg); + + } + + status = mq_close(analyze_q); + status = mq_unlink("/analyze_q"); + + return(0); +} + +int msg_analyze (char *msg) +{ + int status = 0; + int msg_len = 0; + int ndigit = 0; + int nlower = 0; + int nupper = 0; + int nother = 0; + + int i; + + status = msg_len = strlen(msg); + + for (i=0;i<msg_len;i++) + { + if ('0' <= msg[i] && '9' >= msg[i]) + ++ndigit; + else + if ('a' <= msg[i] && 'z' >= msg[i]) + ++nlower; + else + if ('A' <= msg[i] && 'Z' >= msg[i]) + ++nupper; + else + ++nother; + } + + printf("\n\nThe message:\n\n\"%s\"\n\nhas %d characters,\n", msg, msg_len); + printf("of which %d are digits,\n", ndigit); + printf("%d are lowercase characters,\n", nlower); + printf("%d are uppercase characters,\n", nupper); + printf("and %d are white space or punctuation.\n", nother); + + return(0); +} + diff --git a/lab08/rec.c b/lab08/rec.c new file mode 100644 index 0000000..11467a5 --- /dev/null +++ b/lab08/rec.c @@ -0,0 +1,72 @@ +#include "stdio.h" +#include "stdlib.h" +#include "mqueue.h" /* this header file is required */ +#include "sys/stat.h" +#include "string.h" +#include "signal.h" +#include "setjmp.h" + +int msg_analyze (char *); + +int main (void) +{ + int status = 0; + + /* create the message queue variable */ + + /* create and initialize the message queue attribute structure */ + /* don't forget the type for the structure */ + struct "type" attr = + { + }; + + char recd_msg[100]; + + /* create message queue analyze_q. check that the call succeeds */ + + /* make the message queue receive call here */ + + /* this call analyzes the string received from the queue */ + status = msg_analyze(recd_msg); + + /* use the close and unlink calls to make debugging easier */ + + return(0); +} + +int msg_analyze (char *msg) +{ + int status = 0; + int msg_len = 0; + int ndigit = 0; + int nlower = 0; + int nupper = 0; + int nother = 0; + + int i; + + status = msg_len = strlen(msg); + + for (i=0;i<msg_len;i++) + { + if ('0' <= msg[i] && '9' >= msg[i]) + ++ndigit; + else + if ('a' <= msg[i] && 'z' >= msg[i]) + ++nlower; + else + if ('A' <= msg[i] && 'Z' >= msg[i]) + ++nupper; + else + ++nother; + } + + printf("\n\nThe message:\n\n\"%s\"\n\nhas %d characters,\n", msg, msg_len); + printf("of which %d are digits,\n", ndigit); + printf("%d are lowercase characters,\n", nlower); + printf("%d are uppercase characters,\n", nupper); + printf("and %d are white space or punctuation.\n", nother); + + return(0); +} + diff --git a/lab08/snd-solution.c b/lab08/snd-solution.c new file mode 100644 index 0000000..76e0a76 --- /dev/null +++ b/lab08/snd-solution.c @@ -0,0 +1,60 @@ +#include "stdio.h" +#include "stdlib.h" +#include "mqueue.h" +#include "sys/stat.h" +#include "string.h" +#include "time.h" + +#define MAX_CHAR 127 +#define STR_SIZE 100 + +void give_string(char *); + +int main (void) +{ + int status = 0; + mqd_t analyze_q; + char *sent_msg; + struct mq_attr attr; + + analyze_q = mq_open("/analyze_q", O_WRONLY, S_IRUSR|S_IWUSR, NULL); + if (0 > analyze_q) + { + perror("mq_open"); + exit(1); + } + + sent_msg = (char *) malloc (100); + if (NULL == sent_msg) + { + perror("malloc"); + exit(1); + } + + give_string(sent_msg); + + status = mq_getattr(analyze_q,&attr); + status = mq_send(analyze_q,(void *)&sent_msg[0],attr.mq_msgsize,(unsigned)NULL); + + free(sent_msg); + + status = mq_close(analyze_q); + + return(0); +} + + +void give_string(char *result) +{ + int j = 0; + int i = 0; + + srand((unsigned)time(NULL)); + + for (i=0;i<100;i++) + { + result[i] = (char) (1 + (int) (MAX_CHAR * (rand() / (RAND_MAX + 1.0))) ); + } + +} + diff --git a/lab08/snd.c b/lab08/snd.c new file mode 100644 index 0000000..0b8fbd6 --- /dev/null +++ b/lab08/snd.c @@ -0,0 +1,58 @@ +#include "stdio.h" +#include "stdlib.h" +#include "mqueue.h" /* this header file is required */ +#include "sys/stat.h" +#include "string.h" +#include "time.h" + +#define MAX_CHAR 127 +#define STR_SIZE 100 + +void give_string(char *); + +int main (void) +{ + int status = 0; + /* declare a message queue variable */ + + char *sent_msg; + struct mq_attr attr; + + /* open the message queue for writing. don't forget to check the return value */ + + sent_msg = (char *) malloc (100); + if (NULL == sent_msg) + { + perror("malloc"); + exit(1); + } + + /* give_string(sent_msg); this function generates a random string */ + /* you can use this or just send your own string */ + + /* get the message queue attribute structure */ + + /* send a message */ + + free(sent_msg); + + status = mq_close(analyze_q); + + return(0); +} + + +void give_string(char *result) +{ + int j = 0; + int i = 0; + + srand((unsigned)time(NULL)); + + for (i=0;i<100;i++) + { + result[i] = (char) (1 + (int) (MAX_CHAR * (rand() / (RAND_MAX + 1.0))) ); + } + +} + diff --git a/lab09/Makefile b/lab09/Makefile new file mode 100644 index 0000000..0875293 --- /dev/null +++ b/lab09/Makefile @@ -0,0 +1,8 @@ + +APP = timer + +############################################################################# + +include ../make/defaults.mk +include ../make/app-rules.mk + diff --git a/lab09/timer-solution.c b/lab09/timer-solution.c new file mode 100644 index 0000000..467b3b4 --- /dev/null +++ b/lab09/timer-solution.c @@ -0,0 +1,35 @@ +#include <signal.h> +#include <sys/time.h> +#include <stdio.h> +#include <stdlib.h> + +#define RATE 5 /* 5 Hz */ + +int count = 0; + +void alarm_handler(int x) { + count++; + if ((count > 0) && ((count % 10) == 0)) { + printf("Number of timer callbacks: %d\n", count); + } + signal(SIGALRM, alarm_handler); +} + +int main() +{ + struct timeval initial = {0, 1000000/RATE}; + struct timeval interval = {0, 1000000/RATE}; + struct itimerval t; + + t.it_value = initial; + t.it_interval = interval; + if (signal(SIGALRM, alarm_handler) != SIG_ERR) { + if (!setitimer(ITIMER_REAL, &t, 0)) { + /* Perform other tasks waiting for our SIGALRMs */ + while(count <= 50) { + ; + } + } + } + exit(0); +} diff --git a/lab09/timer.c b/lab09/timer.c new file mode 100644 index 0000000..6c609f5 --- /dev/null +++ b/lab09/timer.c @@ -0,0 +1,33 @@ +#include <signal.h> +#include <sys/time.h> +#include <stdio.h> +#include <stdlib.h> + +#define RATE 5 /* 5 Hz */ + +int count = 0; + +void alarm_handler(int x) { + count++; + if ((count > 0) && ((count % 10) == 0)) { + printf("Number of timer callbacks: %d\n", count); + } + signal(SIGALRM, alarm_handler); +} + +int main() +{ + /* define the initial and interval to run at 5 hz */ + struct timeval initial = {0, ???/RATE}; + struct timeval interval = {0, ???/RATE}; + struct itimerval t; + + t.it_value = initial; + t.it_interval = interval; + + /* install a signal handler for SIGALRM and start timer ticking */ + + /* use the count variable to terminate after 10 seconds */ + + exit(0); +} diff --git a/lab10/Makefile b/lab10/Makefile new file mode 100644 index 0000000..bfa648f --- /dev/null +++ b/lab10/Makefile @@ -0,0 +1,8 @@ + +APP = net + +############################################################################# + +include ../make/defaults.mk +include ../make/app-rules.mk + diff --git a/lab10/net-solution.c b/lab10/net-solution.c new file mode 100644 index 0000000..bc811a0 --- /dev/null +++ b/lab10/net-solution.c @@ -0,0 +1,103 @@ +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> + +#define SOCKET_PATHNAME "/root/unixsock" +#define BUFSIZE 200 + +void consumer() +{ + struct sockaddr_un peer_addr; + int len; + int size; + char buf[BUFSIZE]; + + /* Attach to server socket */ + int sock = socket(AF_UNIX, SOCK_STREAM, 0); + if (sock < 0) { + printf("consumer: error opening socket\n"); + exit(1); + } + + printf("consumer connecting to producer\n"); + + peer_addr.sun_family = AF_UNIX; + strcpy(peer_addr.sun_path, SOCKET_PATHNAME); + len = strlen(SOCKET_PATHNAME) + sizeof(peer_addr.sun_family); + if (connect(sock, (struct sockaddr*)&peer_addr, len) < 0) { + printf("consumer: error in connect\n"); + exit(1); + } + + printf("consumer connected to producer\n"); + + size = recv(sock, &buf[0], BUFSIZE, 0); + if (size < 0) { + printf("consumer: error in recv\n"); + exit(1); + } + + printf("consumer received message: %s\n", &buf[0]); +} + +void producer() +{ + struct sockaddr_un my_addr; + struct sockaddr_un peer_addr; + int status; + int connsock; + int len; + socklen_t peeraddrlen; + char *msg = "this is a message from producer to consumer"; + + /* Create server socket, UNIX domain */ + int sock = socket(AF_UNIX, SOCK_STREAM, 0); + if (sock < 0) { + printf("producer: error opening socket\n"); + exit(1); + } + + /* Await connections */ + my_addr.sun_family = AF_UNIX; + strcpy(my_addr.sun_path, SOCKET_PATHNAME); + len = strlen(SOCKET_PATHNAME) + sizeof(my_addr.sun_family); + unlink(SOCKET_PATHNAME); + status = bind(sock, (struct sockaddr*)&my_addr, len); + if (status < 0) { + printf("producer failed to bind\n"); + exit(1); + } + if (listen(sock, 5) < 0) { + printf("producer failed to listen\n"); + exit(1); + } + connsock = accept(sock, (struct sockaddr*)&peer_addr, &peeraddrlen); + if (connsock < 0) { + printf("producer failed to accept\n"); + exit(1); + } + + /* Send out message on socket */ + status = send(connsock, &msg[0], strlen(msg)+1, 0); + if (status < 0) { + printf("producer failed to send\n"); + exit(1); + } +} + +int main() +{ + if (fork() == 0) { + /* start the producer/server first */ + producer(); + exit(0); + } + /* parent process proceeds here */ + sleep(1); + consumer(); + exit(0); +} diff --git a/lab10/net.c b/lab10/net.c new file mode 100644 index 0000000..7f52e20 --- /dev/null +++ b/lab10/net.c @@ -0,0 +1,100 @@ +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> + +#define SOCKET_PATHNAME "/root/unixsock" +#define BUFSIZE 200 + +void consumer() +{ + struct sockaddr_un peer_addr; + int len; + int size; + char buf[BUFSIZE]; + + /* Attach to server socket */ + int sock = socket(AF_UNIX, SOCK_STREAM, 0); + if (sock < 0) { + printf("consumer: error opening socket\n"); + exit(1); + } + + printf("consumer connecting to producer\n"); + + peer_addr.sun_family = AF_UNIX; + strcpy(peer_addr.sun_path, SOCKET_PATHNAME); + len = strlen(SOCKET_PATHNAME) + sizeof(peer_addr.sun_family); + if (connect(sock, (struct sockaddr*)&peer_addr, len) < 0) { + printf("consumer: error in connect\n"); + exit(1); + } + + printf("consumer connected to producer\n"); + + size = recv(sock, &buf[0], BUFSIZE, 0); + if (size < 0) { + printf("consumer: error in recv\n"); + exit(1); + } + + printf("consumer received message: %s\n", &buf[0]); +} + +void producer() +{ + struct sockaddr_un my_addr; + struct sockaddr_un peer_addr; + int status; + int connsock; + int len; + socklen_t peeraddrlen; + char *msg = "this is a message from producer to consumer"; + + /* Create server socket, UNIX domain */ + int sock = socket(AF_UNIX, SOCK_STREAM, 0); + if (sock < 0) { + printf("producer: error opening socket\n"); + exit(1); + } + + /* Await connections */ + my_addr.sun_family = AF_UNIX; + strcpy(my_addr.sun_path, SOCKET_PATHNAME); + len = strlen(SOCKET_PATHNAME) + sizeof(my_addr.sun_family); + unlink(SOCKET_PATHNAME); + status = bind(sock, (struct sockaddr*)&my_addr, len); + if (status < 0) { + printf("producer failed to bind\n"); + exit(1); + } + if (listen(sock, 5) < 0) { + printf("producer failed to listen\n"); + exit(1); + } + connsock = accept(sock, (struct sockaddr*)&peer_addr, &peeraddrlen); + if (connsock < 0) { + printf("producer failed to accept\n"); + exit(1); + } + + /* Send out message on socket */ + status = send(connsock, &msg[0], strlen(msg)+1, 0); + if (status < 0) { + printf("producer failed to send\n"); + exit(1); + } +} + +int main() +{ + /* fork a child, if I'm the child, call producer and exit */ + + /* if I'm the parent, sleep for 1 second and call the consumer */ + + /* parent process proceeds here */ + exit(0); +} diff --git a/make/app-rules.mk b/make/app-rules.mk new file mode 100644 index 0000000..c66eca4 --- /dev/null +++ b/make/app-rules.mk @@ -0,0 +1,12 @@ + +all: install + +clean: + rm -f $(APP) $(DESTDIR)/$(APP) + +$(APP): $(APP).c + $(CC) -g3 -o $@ $< + +install: $(APP) + cp $< $(DESTDIR) + diff --git a/make/defaults.mk b/make/defaults.mk new file mode 100644 index 0000000..bec7ca0 --- /dev/null +++ b/make/defaults.mk @@ -0,0 +1,3 @@ +DESTDIR = /home/student/targetfs/root +CC = $(CROSS_COMPILE)gcc + |
