├── code ├── lec04 │ ├── baddata │ ├── data │ ├── mydata.csv │ ├── fork_demo.c │ ├── getline_simple.c │ ├── env_demo.c │ ├── scanf_demo.c │ ├── read_demo.c │ ├── fscanf_demo.c │ └── getline_demo.c ├── lec12 │ ├── .gitignore │ ├── README.txt │ ├── stacks.c │ ├── Makefile │ ├── sdl_test.c │ ├── matrix.c │ ├── mandelbrot-no-thread.c │ ├── mandelbrot-attempt1.c │ ├── mandelbrot-attempt2.c │ └── mandelbrot-task.c ├── lec02 │ ├── starting_code │ │ ├── print_args.c │ │ ├── malloc_address.c │ │ ├── macro_max.c │ │ ├── contains_at.c │ │ └── stack_address.c │ ├── unused_or_online_videos_only │ │ ├── starting_code │ │ │ ├── print_args.c │ │ │ ├── bad_strcmp.c │ │ │ └── addressof.c │ │ ├── addressof.c │ │ ├── bad_strcmp.c │ │ ├── stack_address.c │ │ └── print_args.c │ └── final_code │ │ ├── malloc_address.c │ │ ├── macro_max.c │ │ ├── stack_address.c │ │ ├── contains_at.c │ │ └── all.c ├── lec11 │ ├── threads.c │ ├── helloworld.c │ ├── hundred.c │ └── threaddemo.c ├── lec18 │ ├── semaphore_barrier_start.c │ ├── badbarrier.c │ ├── semaphore_barrier.c │ └── fireworks.c ├── lec17 │ ├── 17-barrier.c │ └── 17-binarygame.c ├── lec15 │ ├── cake-1.c │ ├── cake.c │ ├── block.c │ └── cake-colordemo.c ├── lec16 │ ├── producer_consumer.c │ ├── 16-cookie-start.c │ └── 16-cookie-solution.c └── lec13 │ ├── puzzle1.c │ ├── counter_start.c │ ├── counter.c │ ├── textmessage.c │ └── puzzle1_experiments.c ├── handouts ├── CS241-08-heap.docx ├── CS241-08-heap.pdf ├── CS241-01-Welcome.docx ├── CS241-01-Welcome.pdf ├── CS241-07-signals.docx ├── CS241-07-signals.pdf ├── CS241-11-Threads.docx ├── CS241-11-Threads.pdf ├── CS241-13-PThreads.pdf ├── CS241-02-SeeCCrash.docx ├── CS241-02-SeeCCrash.pdf ├── CS241-09-allocator.docx ├── CS241-09-allocator.pdf ├── CS241-13-PThreads.docx ├── CS241-04-ScanfGetline.docx ├── CS241-04-ScanfGetline.pdf ├── CS241-06-forkexecwait.docx ├── CS241-06-forkexecwait.pdf ├── CS241-10-allocatorII.docx ├── CS241-10-allocatorII.pdf ├── CS241-12-ThreadsMemory.pdf ├── CS241-15-CondVariables.pdf ├── CS241-03-ADayAtTheCside.docx ├── CS241-03-ADayAtTheCside.pdf ├── CS241-05-ExecForkEnviron.pdf ├── CS241-12-ThreadsMemory.docx ├── CS241-15-CondVariables.docx ├── CS241-05-ExecForkEnviron.docx ├── CS241-14-PThreadsAndLocks.docx ├── CS241-14-PThreadsAndLocks.pdf ├── CS241-16-CountingSemaphores.pdf ├── CS241-20-DiningPhilosophers.pdf ├── CS241-21-PageTablesAndIPC.docx ├── CS241-21-PageTablesAndIPC.pdf ├── CS241-16-CountingSemaphores.docx ├── CS241-18-ReaderWriterDeadlock.pdf ├── CS241-20-DiningPhilosophers.docx ├── CS241-18-ReaderWriterDeadlock.docx ├── CS241-20-DiningPhilosophersCode.docx ├── CS241-20-DiningPhilosophersCode.pdf ├── CS241-17-ProducerConsumerBarrierV2.pdf ├── CS241-17-ProducerConsumerBarrierV2.docx ├── CS241-19-ReaderWriterDeadlock-part2.docx └── CS241-19-ReaderWriterDeadlock-part2.pdf ├── welcome.txt └── HW0.md /code/lec04/baddata: -------------------------------------------------------------------------------- 1 | 70 -------------------------------------------------------------------------------- /code/lec04/data: -------------------------------------------------------------------------------- 1 | 77,88 2 | -------------------------------------------------------------------------------- /code/lec04/mydata.csv: -------------------------------------------------------------------------------- 1 | 10,23 2 | 20,25 3 | 30,37 4 | 40,44 5 | 50,58 6 | 60,64 7 | 70,75 8 | -------------------------------------------------------------------------------- /code/lec12/.gitignore: -------------------------------------------------------------------------------- 1 | mandel0 2 | mandel1 3 | mandel2 4 | mandel3 5 | matrix 6 | sdl_test 7 | stacks 8 | -------------------------------------------------------------------------------- /handouts/CS241-08-heap.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angrave/CS241-Lectures-SP20/HEAD/handouts/CS241-08-heap.docx -------------------------------------------------------------------------------- /handouts/CS241-08-heap.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angrave/CS241-Lectures-SP20/HEAD/handouts/CS241-08-heap.pdf -------------------------------------------------------------------------------- /handouts/CS241-01-Welcome.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angrave/CS241-Lectures-SP20/HEAD/handouts/CS241-01-Welcome.docx -------------------------------------------------------------------------------- /handouts/CS241-01-Welcome.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angrave/CS241-Lectures-SP20/HEAD/handouts/CS241-01-Welcome.pdf -------------------------------------------------------------------------------- /handouts/CS241-07-signals.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angrave/CS241-Lectures-SP20/HEAD/handouts/CS241-07-signals.docx -------------------------------------------------------------------------------- /handouts/CS241-07-signals.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angrave/CS241-Lectures-SP20/HEAD/handouts/CS241-07-signals.pdf -------------------------------------------------------------------------------- /handouts/CS241-11-Threads.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angrave/CS241-Lectures-SP20/HEAD/handouts/CS241-11-Threads.docx -------------------------------------------------------------------------------- /handouts/CS241-11-Threads.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angrave/CS241-Lectures-SP20/HEAD/handouts/CS241-11-Threads.pdf -------------------------------------------------------------------------------- /handouts/CS241-13-PThreads.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angrave/CS241-Lectures-SP20/HEAD/handouts/CS241-13-PThreads.pdf -------------------------------------------------------------------------------- /handouts/CS241-02-SeeCCrash.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angrave/CS241-Lectures-SP20/HEAD/handouts/CS241-02-SeeCCrash.docx -------------------------------------------------------------------------------- /handouts/CS241-02-SeeCCrash.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angrave/CS241-Lectures-SP20/HEAD/handouts/CS241-02-SeeCCrash.pdf -------------------------------------------------------------------------------- /handouts/CS241-09-allocator.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angrave/CS241-Lectures-SP20/HEAD/handouts/CS241-09-allocator.docx -------------------------------------------------------------------------------- /handouts/CS241-09-allocator.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angrave/CS241-Lectures-SP20/HEAD/handouts/CS241-09-allocator.pdf -------------------------------------------------------------------------------- /handouts/CS241-13-PThreads.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angrave/CS241-Lectures-SP20/HEAD/handouts/CS241-13-PThreads.docx -------------------------------------------------------------------------------- /handouts/CS241-04-ScanfGetline.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angrave/CS241-Lectures-SP20/HEAD/handouts/CS241-04-ScanfGetline.docx -------------------------------------------------------------------------------- /handouts/CS241-04-ScanfGetline.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angrave/CS241-Lectures-SP20/HEAD/handouts/CS241-04-ScanfGetline.pdf -------------------------------------------------------------------------------- /handouts/CS241-06-forkexecwait.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angrave/CS241-Lectures-SP20/HEAD/handouts/CS241-06-forkexecwait.docx -------------------------------------------------------------------------------- /handouts/CS241-06-forkexecwait.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angrave/CS241-Lectures-SP20/HEAD/handouts/CS241-06-forkexecwait.pdf -------------------------------------------------------------------------------- /handouts/CS241-10-allocatorII.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angrave/CS241-Lectures-SP20/HEAD/handouts/CS241-10-allocatorII.docx -------------------------------------------------------------------------------- /handouts/CS241-10-allocatorII.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angrave/CS241-Lectures-SP20/HEAD/handouts/CS241-10-allocatorII.pdf -------------------------------------------------------------------------------- /handouts/CS241-12-ThreadsMemory.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angrave/CS241-Lectures-SP20/HEAD/handouts/CS241-12-ThreadsMemory.pdf -------------------------------------------------------------------------------- /handouts/CS241-15-CondVariables.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angrave/CS241-Lectures-SP20/HEAD/handouts/CS241-15-CondVariables.pdf -------------------------------------------------------------------------------- /handouts/CS241-03-ADayAtTheCside.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angrave/CS241-Lectures-SP20/HEAD/handouts/CS241-03-ADayAtTheCside.docx -------------------------------------------------------------------------------- /handouts/CS241-03-ADayAtTheCside.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angrave/CS241-Lectures-SP20/HEAD/handouts/CS241-03-ADayAtTheCside.pdf -------------------------------------------------------------------------------- /handouts/CS241-05-ExecForkEnviron.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angrave/CS241-Lectures-SP20/HEAD/handouts/CS241-05-ExecForkEnviron.pdf -------------------------------------------------------------------------------- /handouts/CS241-12-ThreadsMemory.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angrave/CS241-Lectures-SP20/HEAD/handouts/CS241-12-ThreadsMemory.docx -------------------------------------------------------------------------------- /handouts/CS241-15-CondVariables.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angrave/CS241-Lectures-SP20/HEAD/handouts/CS241-15-CondVariables.docx -------------------------------------------------------------------------------- /code/lec02/starting_code/print_args.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, char** argv) { 4 | 5 | return 0; // Success 6 | } 7 | -------------------------------------------------------------------------------- /handouts/CS241-05-ExecForkEnviron.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angrave/CS241-Lectures-SP20/HEAD/handouts/CS241-05-ExecForkEnviron.docx -------------------------------------------------------------------------------- /handouts/CS241-14-PThreadsAndLocks.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angrave/CS241-Lectures-SP20/HEAD/handouts/CS241-14-PThreadsAndLocks.docx -------------------------------------------------------------------------------- /handouts/CS241-14-PThreadsAndLocks.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angrave/CS241-Lectures-SP20/HEAD/handouts/CS241-14-PThreadsAndLocks.pdf -------------------------------------------------------------------------------- /handouts/CS241-16-CountingSemaphores.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angrave/CS241-Lectures-SP20/HEAD/handouts/CS241-16-CountingSemaphores.pdf -------------------------------------------------------------------------------- /handouts/CS241-20-DiningPhilosophers.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angrave/CS241-Lectures-SP20/HEAD/handouts/CS241-20-DiningPhilosophers.pdf -------------------------------------------------------------------------------- /handouts/CS241-21-PageTablesAndIPC.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angrave/CS241-Lectures-SP20/HEAD/handouts/CS241-21-PageTablesAndIPC.docx -------------------------------------------------------------------------------- /handouts/CS241-21-PageTablesAndIPC.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angrave/CS241-Lectures-SP20/HEAD/handouts/CS241-21-PageTablesAndIPC.pdf -------------------------------------------------------------------------------- /handouts/CS241-16-CountingSemaphores.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angrave/CS241-Lectures-SP20/HEAD/handouts/CS241-16-CountingSemaphores.docx -------------------------------------------------------------------------------- /handouts/CS241-18-ReaderWriterDeadlock.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angrave/CS241-Lectures-SP20/HEAD/handouts/CS241-18-ReaderWriterDeadlock.pdf -------------------------------------------------------------------------------- /handouts/CS241-20-DiningPhilosophers.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angrave/CS241-Lectures-SP20/HEAD/handouts/CS241-20-DiningPhilosophers.docx -------------------------------------------------------------------------------- /handouts/CS241-18-ReaderWriterDeadlock.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angrave/CS241-Lectures-SP20/HEAD/handouts/CS241-18-ReaderWriterDeadlock.docx -------------------------------------------------------------------------------- /handouts/CS241-20-DiningPhilosophersCode.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angrave/CS241-Lectures-SP20/HEAD/handouts/CS241-20-DiningPhilosophersCode.docx -------------------------------------------------------------------------------- /handouts/CS241-20-DiningPhilosophersCode.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angrave/CS241-Lectures-SP20/HEAD/handouts/CS241-20-DiningPhilosophersCode.pdf -------------------------------------------------------------------------------- /handouts/CS241-17-ProducerConsumerBarrierV2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angrave/CS241-Lectures-SP20/HEAD/handouts/CS241-17-ProducerConsumerBarrierV2.pdf -------------------------------------------------------------------------------- /handouts/CS241-17-ProducerConsumerBarrierV2.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angrave/CS241-Lectures-SP20/HEAD/handouts/CS241-17-ProducerConsumerBarrierV2.docx -------------------------------------------------------------------------------- /handouts/CS241-19-ReaderWriterDeadlock-part2.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angrave/CS241-Lectures-SP20/HEAD/handouts/CS241-19-ReaderWriterDeadlock-part2.docx -------------------------------------------------------------------------------- /handouts/CS241-19-ReaderWriterDeadlock-part2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angrave/CS241-Lectures-SP20/HEAD/handouts/CS241-19-ReaderWriterDeadlock-part2.pdf -------------------------------------------------------------------------------- /code/lec02/unused_or_online_videos_only/starting_code/print_args.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, char** argv) { 4 | 5 | return 0; // Success 6 | } 7 | -------------------------------------------------------------------------------- /code/lec02/final_code/malloc_address.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(int argc, char** argv) { 5 | 6 | printf("%p %p\n", main, malloc); 7 | 8 | return 0; 9 | } 10 | -------------------------------------------------------------------------------- /code/lec02/starting_code/malloc_address.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(int argc, char** argv) { 5 | 6 | printf("%p %p\n", main, malloc); 7 | 8 | return 0; 9 | } 10 | -------------------------------------------------------------------------------- /code/lec11/threads.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int counter; 7 | 8 | 9 | 10 | int main() { 11 | return 0; // time to go away 12 | } 13 | -------------------------------------------------------------------------------- /code/lec02/starting_code/macro_max.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define max(a,b) a 2 | 3 | #define max(a,b) ((a)>(b) ? (a) : (b) ) 4 | 5 | int main(int argc, char**argv) { 6 | int result = max(10,5) + 1; 7 | //int result = 10>5 ? 10 : 5 +1; 8 | printf("Result:%d \n", result); 9 | } 10 | -------------------------------------------------------------------------------- /code/lec18/semaphore_barrier_start.c: -------------------------------------------------------------------------------- 1 | int remain =5; 2 | void barrier() { 3 | /* Rearrange the following */ 4 | sem_wait(&s); 5 | sem_post(&s); 6 | remain --; 7 | pthread_mutex_lock(&m); 8 | pthread_mutex_unlock(&m); 9 | if(remain) 10 | } 11 | -------------------------------------------------------------------------------- /code/lec04/fork_demo.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | int main() { 6 | int var = 10; 7 | 8 | 9 | fork(); 10 | fork(); 11 | fork(); 12 | 13 | printf("My variable is %d and it is stored at %p \n", var, &var); 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /code/lec18/badbarrier.c: -------------------------------------------------------------------------------- 1 | void badbarrier() { 2 | pthread_mutex_lock(&m) 3 | count ++ 4 | pthread_mutex_unlock(&m) 5 | 6 | // No memory fence - might never read a value of count that is updated by remote thread 7 | while(count != N) { 8 | pthread_yield(); 9 | } 10 | 11 | } -------------------------------------------------------------------------------- /code/lec02/unused_or_online_videos_only/starting_code/bad_strcmp.c: -------------------------------------------------------------------------------- 1 | 2 | int strcmp(const char *s1, const char *s2) { 3 | while(*s1 != 0 && *s2 != 0) { 4 | if(s1 != s2) return 1; // TODO FIX 5 | s1++; 6 | s2++; 7 | } 8 | 9 | return 1; // TODO FIX ME 10 | } 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /code/lec17/17-barrier.c: -------------------------------------------------------------------------------- 1 | 2 | int counter = 0; 3 | 4 | void barrier() { 5 | pthread_mutex_lock(&m); 6 | counter ++; 7 | if(counter == 8) { 8 | pthread_cond_broadcast(&cv); 9 | } 10 | 11 | while( counter < 8) { 12 | pthread_cond_wait(&cv,&m); 13 | } 14 | pthread_mutex_unlock(&m); 15 | } 16 | -------------------------------------------------------------------------------- /code/lec02/starting_code/contains_at.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int contains_at(char*); 4 | 5 | 6 | int main(int argc, char** argv) { 7 | int result = contains_at(NULL); 8 | if(result) printf("Contains an @"); 9 | else printf("No @ found"); 10 | return 0; 11 | } 12 | 13 | int contains_at(char* ptr) { 14 | 15 | return 0; 16 | } 17 | -------------------------------------------------------------------------------- /code/lec02/starting_code/stack_address.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int f1(int, int*); 4 | 5 | int abc = 5; 6 | 7 | int main() { f1( 10, &abc); return 0;} 8 | 9 | int f1(int v1, int* v2) { 10 | printf("&v1 is %p \n", &v1); 11 | 12 | printf("&v2 is %p \n", &v2); 13 | 14 | printf(" v2 is %p \n",v2); 15 | return 0; 16 | } 17 | 18 | -------------------------------------------------------------------------------- /code/lec02/final_code/stack_address.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int f1(int, int*); 4 | 5 | 6 | int abc = 5; 7 | 8 | int main() { f1( 10, &abc); return 0;} 9 | 10 | int f1(int v1, int* v2) { 11 | printf("&v1 is %p \n", &v1); 12 | 13 | printf("&v2 is %p \n", &v2); 14 | 15 | printf(" v2 is %p \n",v2); 16 | return 0; 17 | } 18 | 19 | -------------------------------------------------------------------------------- /code/lec02/unused_or_online_videos_only/addressof.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | void get_message(char**magic) { 6 | *magic = malloc(11); 7 | strcpy(*magic, "Amazing C!"); 8 | } 9 | 10 | int main() { 11 | char *ptr = NULL; 12 | get_message( &ptr ); 13 | puts( ptr ); // equiv printf("%s\n", ptr); 14 | } -------------------------------------------------------------------------------- /code/lec02/unused_or_online_videos_only/bad_strcmp.c: -------------------------------------------------------------------------------- 1 | 2 | int strcmp(const char *s1, const char *s2) { 3 | while(*s1 != 0 && *s2 != 0) { 4 | if(*s1 != *s2) return 1; // TODO FIX 5 | s1++; 6 | s2++; 7 | } 8 | if( *s1 == 0 && *s2 ==0) return 0; 9 | return 1; // TODO FIX ME 10 | } 11 | 12 | if( ! strcmp( s, "yes") ) 13 | 14 | -------------------------------------------------------------------------------- /code/lec02/unused_or_online_videos_only/stack_address.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int f1(int, int*); 4 | 5 | int abc = 5; 6 | 7 | int main() { f1( 10, &abc); return 0;} 8 | 9 | int f1(int v1, int* v2) { 10 | printf("&v1 is %p \n", &v1); 11 | 12 | printf("&v2 is %p \n", &v2); 13 | 14 | printf(" v2 is %p \n",v2); 15 | return 0; 16 | } 17 | 18 | -------------------------------------------------------------------------------- /code/lec02/unused_or_online_videos_only/starting_code/addressof.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | void get_message(char**magic) { 6 | *magic = malloc(11); 7 | strcpy(*magic, "Amazing C!"); 8 | } 9 | 10 | int main() { 11 | char *ptr = NULL; 12 | // get_message( ); 13 | puts( ptr ); // equiv printf("%s\n", ptr); 14 | } -------------------------------------------------------------------------------- /code/lec02/unused_or_online_videos_only/print_args.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, char** argv) { 4 | #if 0 5 | for(int i = 0 ; i < argc; i++ ) { 6 | printf( "%d : %p : %s \n", i , *(argv + i), argv[i] ); 7 | } 8 | #endif 9 | while( *argv ) { 10 | printf("%s\n", *argv); 11 | argv ++; 12 | } 13 | return 0; // Success 14 | } 15 | -------------------------------------------------------------------------------- /code/lec04/getline_simple.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main(int argc, char**argv) { 6 | 7 | char * buffer = NULL; 8 | size_t buf_capacity = 0; 9 | while(1) { 10 | ssize_t result = getline( &buffer, &buf_capacity, stdin); 11 | printf("result is %d at %p. Contents=%s", (int)result,buffer, buffer ); 12 | } 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /code/lec11/helloworld.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void* valentines(void* param) { 5 | printf("%s", param); 6 | fflush(stdout); 7 | return NULL; 8 | } 9 | 10 | int main() { 11 | pthread_t tids[2]; 12 | pthread_create( tids, NULL, valentines, "Hello "); 13 | pthread_create( tids +1, NULL, valentines, "World"); 14 | 15 | pthread_exit(NULL); 16 | 17 | } -------------------------------------------------------------------------------- /code/lec04/env_demo.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main() { 6 | char* user = getenv("USER"); 7 | char* secret = getenv("SECRET"); 8 | if( user == NULL || secret == NULL) { 9 | fprintf(stderr,"Please ensure USER and SECRET environment variables are set!\n"); 10 | exit(1); 11 | } 12 | puts(user); 13 | puts(secret); 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /code/lec02/final_code/contains_at.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int contains_at(char*); 4 | 5 | 6 | int main(int argc, char** argv) { 7 | int result = contains_at("Test"); 8 | 9 | if(result) puts("Contains an @"); 10 | else puts("No @ found"); 11 | return 0; 12 | } 13 | 14 | int contains_at(char* ptr) { 15 | char c; 16 | while( (c = *ptr) ) { 17 | 18 | if( c == '@' ) return 1; 19 | ptr ++; 20 | } 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /code/lec04/scanf_demo.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, char**argv) { 4 | int x = 10; 5 | int y = 20; 6 | puts("Enter your two secret numbers"); // adds newline for you 7 | 8 | int result = scanf("%d,%d", &x , &y); 9 | printf("x is now %d and y is now %d.\n", x, y); 10 | if( result != 2) { 11 | // handle the error 12 | puts("read the instructions!"); 13 | } else { 14 | puts("Thanks"); 15 | } 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /code/lec04/read_demo.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main( int argc, char** argv) { 5 | char buffer[4096]; 6 | 7 | ssize_t result = read( 0 , buffer, sizeof(buffer) -1 ); 8 | 9 | printf("result is %d", (int) result); 10 | if( result == -1 ) { 11 | fprintf(stderr,"Could not read from stdin!\n"); 12 | exit(1); 13 | } 14 | buffer[ result ] = '\0'; 15 | 16 | printf("and you gave me:%s\n", buffer ); 17 | puts(buffer); 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /code/lec15/cake-1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | pthread_mutex_t m = PTHREAD=MUTEX_INITIALIZER; 6 | pthread_cond_t cv = PTHREAD_COND_INITIALIZER; 7 | 8 | int cake = 0; 9 | 10 | // race conditions! 11 | // ... but a stepping stone to adding condition variables 12 | 13 | void decrement() { // Will block if zero 14 | 15 | while(cake == 0) { 16 | 17 | sleep(1) 18 | 19 | } 20 | cake --; 21 | 22 | } 23 | 24 | void increment() { 25 | cake ++; 26 | } 27 | -------------------------------------------------------------------------------- /code/lec18/semaphore_barrier.c: -------------------------------------------------------------------------------- 1 | int remain =5; 2 | .. sem_init(&s, 0, 0/*No Pizza slices!*/); 3 | 4 | void barrier() { 5 | /* Rearrange the following */ 6 | pthread_mutex_lock(&m); 7 | remain --; 8 | pthread_mutex_unlock(&m); 9 | 10 | if(remain) { 11 | sem_wait(&s); /* Will block */ 12 | } 13 | // sem_post is initially called by 5th thread, that let's one thread to continue 14 | 15 | // so one thread escapes sem_wait, but then calls sem_post, so like dominoes they escape! 16 | sem_post(&s); // allows anotherone to continue 17 | 18 | } 19 | -------------------------------------------------------------------------------- /code/lec11/hundred.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void* shout(void*arg) { 5 | printf("%p\n", arg); 6 | fflush(stdout); 7 | while(1) { } 8 | pthread_exit(NULL); 9 | } 10 | 11 | #define N (10000) 12 | pthread_t tids[N]; 13 | 14 | int main() { 15 | for(int i = 0; i < N;i++) { 16 | int result = pthread_create(tids+i, NULL, shout, tids+i); 17 | if(result!=0) perror("failed"); 18 | } 19 | 20 | for(int i = 0; i < N;i++) { 21 | void* retValue; 22 | pthread_join(tids[i], &retValue); 23 | } 24 | 25 | pthread_exit(NULL); // nver returns so exit() never happens! 26 | return 0; 27 | } -------------------------------------------------------------------------------- /code/lec16/producer_consumer.c: -------------------------------------------------------------------------------- 1 | 2 | task_t* buffer[16]; 3 | 4 | sem_t numspaces, numitems; 5 | 6 | init() { 7 | sem_init( &numspaces ,0/*pshared*/, 16); 8 | sem_init( &numspaces ,0/*pshared*/ , 0); 9 | } 10 | int in, out; 11 | 12 | void enqueue(value) { 13 | sem_wait( &numspaces); 14 | pthread_mutex_lock(&m); 15 | buffer[ (in++) & 0xf ] = value 16 | pthread_mutex_unlock(&m); 17 | sem_post( &numitems); 18 | } 19 | 20 | task_t dequeue() { 21 | sem_wait(&numitems); 22 | pthread_mutex_lock(&m2); 23 | result = buffer[ (out++) & 0xf ] 24 | pthread_mutex_unlock(&m2); 25 | sem_post(&numspaces); 26 | return result; 27 | } -------------------------------------------------------------------------------- /code/lec12/README.txt: -------------------------------------------------------------------------------- 1 | The graphic Mandelbrot demos use SDL2. 2 | 3 | run ../build_sdl2.sh 4 | 5 | to download and install SDL2 to ${HOME}/localinstall/ 6 | 7 | To test your installation this directory include sdl_test 8 | 9 | make sdl_test 10 | ./sdl_test 11 | 12 | On Linux, you will need to add the lib directory so the dynamic libraries can be loaded at runtime- 13 | export LD_LIBRARY_PATH=${HOME}/localinstall/lib/ 14 | 15 | If running on a remote Linux but with a local display, use the "-Y" option 16 | 17 | ssh -Y linux.ews.illinois.edu 18 | 19 | to connect using X Windows. You will also need to install an X server on your local machine e.g. Quartz for OSX 20 | -------------------------------------------------------------------------------- /code/lec13/puzzle1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | void* myfunc(void*ptr) { 7 | int myvalue = * (int*) ptr; 8 | pthread_t myid = pthread_self(); 9 | printf("My thread id is %p and I'm starting at %d\n",(void*) myid , myvalue); 10 | 11 | return NULL; 12 | } 13 | 14 | pthread_t tid[10]; 15 | 16 | int main() { 17 | // Each thread needs a different value of i 18 | 19 | for(int i =0; i < 10; i++) { 20 | 21 | pthread_create( &tid[i], NULL, myfunc, &i); 22 | } 23 | 24 | pthread_exit(NULL) ; // this is a one way trip, pthread_exit never returns !! 25 | return 0; 26 | } 27 | 28 | -------------------------------------------------------------------------------- /code/lec04/fscanf_demo.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define CAPACITY (100) 5 | 6 | int main(int argc,char**argv) { 7 | FILE* f = fopen( "mydata.csv", "r"); 8 | if( f == NULL) { 9 | fprintf(stderr, "Could not open data file!\n"); 10 | exit(1); 11 | } 12 | 13 | int data[CAPACITY]; 14 | int nread = 0; 15 | 16 | while(nread < CAPACITY ) { 17 | int result = fscanf(f , "%d,%d", data + nread *2 , data + nread*2 +1); 18 | if(result == 2) { nread += 2; continue; } 19 | if(result == 1) { fprintf(stderr,"Read only one value !?"); exit(2);} 20 | if(result < 1) break; 21 | } 22 | printf("Number of items read: %d\n", nread); 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /code/lec13/counter_start.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | pthread_mutex_t duck = PTHREAD_MUTEX_INITIALIZER; 5 | 6 | int sharedcounter=0; 7 | 8 | void* myfunc1(void*param) { 9 | int i=0; // stack variable 10 | 11 | for(; i < 1000000;i++) { 12 | sharedcounter++; 13 | } 14 | return NULL; 15 | } 16 | 17 | pthread_t tid1, tid2; 18 | 19 | int main() { 20 | pthread_create(&tid1, 0, myfunc1, NULL); 21 | pthread_create(&tid2, 0, myfunc1, NULL); 22 | 23 | pthread_join(tid1,NULL); // will block until thread finishes 24 | 25 | pthread_join(tid2,NULL); // will block until thread finishes 26 | 27 | printf("%d\n", sharedcounter ); 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /code/lec04/getline_demo.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main(int argc, char**argv) { 6 | 7 | char * buffer = NULL; 8 | size_t buf_capacity = 0; 9 | 10 | while( 1 ) { 11 | ssize_t result = getline( & buffer, & buf_capacity, stdin ); 12 | if( result == -1 ) break; 13 | 14 | printf("buffer is at %p, capacity is %d, result= %d\n", 15 | buffer, (int) buf_capacity, (int) result); 16 | 17 | // what if result is zero? 18 | // what if there is no newline 19 | if(result >0 && buffer[ result - 1] == '\n') { 20 | buffer [ result -1 ] = '\0'; 21 | } 22 | 23 | 24 | printf("Buffer contents: %s", buffer ); 25 | } 26 | free( buffer); 27 | buffer = NULL; 28 | 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /code/lec18/fireworks.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | pthread_cond_t cv = PTHREAD_COND_INITIALIZER; 5 | pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER; 6 | int fireworks=0; 7 | pthread_t tids[5]; 8 | void* firework(void*); // defined later in this file 9 | 10 | int main(int argc,char** argv) { 11 | for(int i=0;i<5;i++) pthread_create( tids+i , NULL, firework, NULL); 12 | fireworks = 1; 13 | pthread_cond_signal(&cv); 14 | pthread_exit(NULL); // wait for all threads to finish 15 | return 0; 16 | } 17 | void* firework(void*param) { 18 | pthread_mutex_lock(&m); 19 | while(fireworks ==0) {pthread_cond_wait(&cv, &m); } 20 | pthread_cond_broadcast(&cv); 21 | fireworks ++; 22 | printf("Oooh ahh %d\n", fireworks); 23 | fireworks --; 24 | pthread_mutex_unlock(&m); 25 | return NULL; 26 | } 27 | -------------------------------------------------------------------------------- /code/lec15/cake.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | 7 | pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER; 8 | pthread_cond_t cv = PTHREAD_COND_INITIALIZER; 9 | 10 | int cake = 0; // is only manipulated by the two functions below 11 | 12 | void decrement() { // Will block if zero 13 | pthread_mutex_lock(&m); 14 | 15 | while(cake == 0) { 16 | pthread_cond_wait(&cv, &m); // unlock mutex, SLEEP, later... lock mutex 17 | } 18 | 19 | cake --; 20 | 21 | pthread_mutex_unlock(&m); 22 | } 23 | 24 | void increment() { // never blocks 25 | pthread_mutex_lock(&m); 26 | 27 | cake ++; 28 | pthread_cond_broadcast(&cv); // You could wake up all hungry sleeping cake eaters 29 | // pthread_cond_signal(&cv); // You could wake up one hungry sleeping cake eater 30 | 31 | pthread_mutex_unlock(&m); 32 | 33 | } 34 | -------------------------------------------------------------------------------- /code/lec11/threaddemo.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | void* hello(void*arg) { 7 | sleep(1); 8 | char* mesg = arg; 9 | printf("My mesg is at %p\n", &mesg); 10 | printf("hello %s!\n", mesg); 11 | 12 | if( mesg[0] == 'T') { 13 | pthread_exit((void*) 0xdeadc0de); // nothing happens after this 14 | } 15 | 16 | return (void*) 0xdeadbeef; 17 | } 18 | 19 | int main(int argc, char**argv) { 20 | void *ptr = "Banana"; 21 | pthread_t tid1, tid2; 22 | printf("Address of tid1 is %p\n", & tid1); 23 | 24 | pthread_create( &tid1, NULL, hello, ptr ); 25 | pthread_create( &tid2, NULL, hello, "Tomato" ); 26 | void* retValue1; 27 | void* retValue2; 28 | pthread_join( tid1,& retValue1); 29 | pthread_join( tid2,& retValue2); 30 | 31 | printf("retValue1 is %p\n", retValue1) ; 32 | printf("retValue2 is %p\n", retValue2) ; 33 | 34 | return EXIT_SUCCESS; 35 | } -------------------------------------------------------------------------------- /code/lec12/stacks.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | // compile with -pthread 9 | 10 | void recurse(int param) { 11 | int calc= 10; 12 | calc ++; 13 | printf("calc=%d. &calc = %p\n",calc, & calc); 14 | if(param >1) recurse(param-1); 15 | } 16 | void* thread_starts_here(void* ptr) { 17 | recurse(3); 18 | return NULL; 19 | } 20 | 21 | // Number of threads: 22 | #define N (3) 23 | 24 | int main() { 25 | 26 | pthread_t tids[N]; 27 | for(int i=0;i/dev/null || true 33 | 34 | 35 | -------------------------------------------------------------------------------- /code/lec13/counter.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | pthread_mutex_t duck = PTHREAD_MUTEX_INITIALIZER; 5 | 6 | int counter; 7 | 8 | void* myfunc1(void*param) { 9 | int i=0; // stack variable 10 | for(; i < 1000000;i++) 11 | counter++; 12 | return NULL; 13 | } 14 | 15 | void* myfunc2(void*param) { 16 | int i=0; // stack variable 17 | pthread_mutex_lock(&duck); 18 | for(; i < 1000000;i++) 19 | counter++; 20 | pthread_mutex_unlock(&duck); 21 | return NULL; 22 | } 23 | 24 | void* myfunc3(void*param) { 25 | int i=0; // stack variable 26 | 27 | for(; i < 1000000;i++) { 28 | pthread_mutex_lock(&duck); 29 | counter++; 30 | pthread_mutex_unlock(&duck); 31 | } 32 | return NULL; 33 | } 34 | pthread_t tid1, tid2; 35 | 36 | int main() { 37 | pthread_create(&tid1, 0, myfunc3, NULL); 38 | pthread_create(&tid2, 0, myfunc3, NULL); 39 | 40 | pthread_join(tid2,NULL); // will block until thread 2 finishes 41 | pthread_join(tid1,NULL); // will block until thread 1 finishes 42 | 43 | printf("%d\n", counter ); 44 | return 0; 45 | } 46 | -------------------------------------------------------------------------------- /code/lec13/textmessage.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | static char message[200]; 8 | int pleaseStop; 9 | 10 | pthread_mutex_t duck = PTHREAD_MUTEX_INITIALIZER; 11 | 12 | char* toTextMessage(char*to, char* from, int val) { 13 | sprintf(message,"Text:%s From:%s You won %d million",to, from, val); 14 | return message; 15 | } 16 | 17 | void* runner2(void* ptr) { 18 | while(!pleaseStop) { 19 | // pthread_mutex_lock(&duck); 20 | char * unused = toTextMessage("JurassicPark","Dinosaur",999); 21 | // pthread_mutex_unlock(&duck); 22 | } 23 | return NULL; 24 | } 25 | 26 | void* runner1(void* ptr) { 27 | int count = 0; 28 | while(!pleaseStop) { 29 | // pthread_mutex_lock(&duck); 30 | 31 | char* mesg = toTextMessage("angrave","illinois",1); 32 | 33 | printf("%6d Sending %s\n", count ++, mesg); 34 | // pthread_mutex_unlock(&duck); 35 | } 36 | return NULL; 37 | } 38 | 39 | 40 | 41 | 42 | int main() { 43 | pthread_t tid1, tid2; 44 | pthread_create(&tid1, 0, runner1, NULL); 45 | sleep(2); 46 | pthread_create(&tid2, 0, runner2, NULL); 47 | sleep(5); 48 | pleaseStop = 1; 49 | pthread_join(tid1, NULL); 50 | pthread_join(tid2, NULL); 51 | } 52 | -------------------------------------------------------------------------------- /code/lec12/sdl_test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | // ../build_sdl2.sh to download and install SDL2 5 | // Linux - 6 | // export LD_LIBRARY_PATH=${HOME}/localinstall/lib/ 7 | // clang sdl_test.c -lSDL2 -I ${HOME}/localinstall/include/ -L ${HOME}/localinstall/lib && ./a.out 8 | 9 | #define width 1024 10 | #define height 1024 11 | 12 | SDL_Window* window; 13 | SDL_Renderer* renderer; 14 | 15 | 16 | int main() 17 | { 18 | SDL_CreateWindowAndRenderer(width, height, 0, &window, &renderer); 19 | // SDL_CreateWindowAndRenderer(0, 0, SDL_WINDOW_FULLSCREEN_DESKTOP, &window, &renderer); 20 | SDL_Texture* framebuffer = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGB888, SDL_TEXTUREACCESS_STREAMING, width, height); 21 | 22 | uint32_t myPixels[ width * height ]; 23 | 24 | for(int y=0; y < height; y++) { 25 | for(int x=0; x < width; x++) { 26 | myPixels[x + y * width] = - x * y; 27 | } 28 | } 29 | 30 | SDL_UpdateTexture(framebuffer, NULL, myPixels, width * sizeof(uint32_t) ); 31 | SDL_RenderCopy(renderer, framebuffer, NULL, NULL); 32 | SDL_RenderPresent(renderer); 33 | 34 | SDL_Event event; 35 | do SDL_WaitEvent(&event); while(event.type != SDL_KEYDOWN); 36 | 37 | SDL_DestroyWindow(window); 38 | SDL_Quit(); 39 | } 40 | -------------------------------------------------------------------------------- /code/lec13/puzzle1_experiments.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define N 5 7 | int starting_value[N]; 8 | pthread_t tid[N]; 9 | 10 | void* myfunc(void*ptr) { 11 | int myvalue = * (int*) ptr; 12 | printf("My thread id is %p and I'm starting at %d\n",pthread_self(), myvalue); 13 | 14 | return NULL; 15 | } 16 | int main() { 17 | puts("Experiment 1: pthread_create( &tid[i], 0, myfunc, & i )"); 18 | 19 | for(int i =0; i < N; i++) { 20 | pthread_create( &tid[i],NULL, myfunc, & i ); 21 | } 22 | 23 | for(int i =0; i < N; i++) { 24 | pthread_join(tid[i],NULL); 25 | } 26 | 27 | puts("Experiment 2: pthread_create(&tid[i],NULL, myfunc, & starting_value[i] );"); 28 | 29 | for(int i =0; i < N; i++) { 30 | starting_value[i] = 200 + i; 31 | pthread_create(&tid[i],NULL, myfunc, & starting_value[i] ); 32 | } 33 | for(int i =0; i < N; i++) { 34 | pthread_join(tid[i],NULL); 35 | } 36 | 37 | puts("Experiment 3: pthread_create & immediately pthread_create"); 38 | 39 | for(int i =0; i < N; i++) { 40 | starting_value[i] = 300 + i; 41 | pthread_create( &tid[i],NULL, myfunc, & starting_value[i] ); 42 | pthread_join(tid[i],NULL); 43 | } 44 | 45 | pthread_exit(NULL) ; // this is a one way trip - never returns !!!!!!!!! 46 | return 0; 47 | } 48 | 49 | -------------------------------------------------------------------------------- /code/lec16/16-cookie-start.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int game_running; 6 | int jar = 0; 7 | pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER; 8 | pthread_cond_t cv1 = PTHREAD_COND_INITIALIZER; 9 | 10 | void* cookie_eater(void*arg) { 11 | char*name = (char*) arg; 12 | while(game_running) { 13 | pthread_mutex_lock(&m); 14 | 15 | while(jar == 0 && game_running) { 16 | printf("%s: \"No cookies! Going for a nap...\"\n", name); 17 | pthread_cond_wait( &cv1, &m); 18 | printf("%s has woken up!\n", name); 19 | } 20 | if(!game_running) return NULL; 21 | jar --; 22 | pthread_mutex_unlock(&m); 23 | printf("%s eats! %d cookie(s) remain\n",name,jar); 24 | 25 | } //while game_running 26 | printf("%s finished\n",name); 27 | return NULL; 28 | } 29 | 30 | void add_cookie(int add) { 31 | pthread_mutex_lock(&m); 32 | jar += add; 33 | pthread_cond_broadcast(&cv1); 34 | pthread_mutex_unlock(&m); 35 | } 36 | 37 | int main() { 38 | game_running = 1; 39 | pthread_t tid1, tid2; 40 | pthread_create(&tid1, NULL, cookie_eater, "Angrave"); 41 | pthread_create(&tid2, NULL, cookie_eater, "Trevor"); 42 | puts("Number of cookies to add to the jar? (9=exit)"); 43 | 44 | int add = 0; 45 | while( scanf("%d", &add) == 1 && add != 9) add_cookie(add); 46 | 47 | puts("Finishing..."); 48 | game_running = 0; 49 | pthread_cond_broadcast(&cv1); 50 | 51 | pthread_join(tid1,NULL); 52 | pthread_join(tid2,NULL); 53 | puts("Finished!"); 54 | exit(0); 55 | } 56 | -------------------------------------------------------------------------------- /code/lec16/16-cookie-solution.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int game_running; 6 | int jar = 0; 7 | 8 | pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER; 9 | pthread_cond_t cv1 = PTHREAD_COND_INITIALIZER; 10 | // Demo : cookie value still goes negative when we quit 11 | 12 | void* cookie_eater(void*arg) { 13 | char*name = (char*) arg; 14 | while(game_running) { 15 | pthread_mutex_lock(&m); 16 | 17 | while(jar == 0 && game_running) { 18 | printf("%s: \"No cookies! Going for a nap...\"\n", name); 19 | pthread_cond_wait( &cv1, &m); 20 | printf("%s has woken up!\n", name); 21 | } 22 | if(!game_running) { 23 | break; 24 | } 25 | jar --; 26 | int currentJar = jar; 27 | pthread_mutex_unlock(&m); 28 | printf("%s eats! %d cookie(s) remain\n",name,currentJar); 29 | } //while game_running 30 | pthread_mutex_unlock(&m); 31 | printf("%s finished\n",name); 32 | return NULL; 33 | } 34 | 35 | void add_cookie(int add) { 36 | pthread_mutex_lock(&m); 37 | jar += add; 38 | pthread_cond_broadcast(&cv1); 39 | pthread_mutex_unlock(&m); 40 | } 41 | 42 | int main() { 43 | game_running = 1; 44 | pthread_t tid1, tid2; 45 | pthread_create(&tid1, NULL, cookie_eater, "Angrave"); 46 | pthread_create(&tid2, NULL, cookie_eater, "Smith"); 47 | puts("Number of cookies to add to the jar? (9=exit)"); 48 | 49 | int add = 0; 50 | while( scanf("%d", &add) == 1 && add != 9) add_cookie(add); 51 | 52 | puts("Finishing..."); 53 | pthread_mutex_lock(&m); // ensure memory fence --why you pay me the big $$ 54 | game_running = 0; 55 | pthread_cond_broadcast(&cv1); 56 | pthread_mutex_unlock(&m); 57 | pthread_join(tid1,NULL); 58 | pthread_join(tid2,NULL); 59 | 60 | puts("Finished!"); 61 | exit(0); 62 | } 63 | -------------------------------------------------------------------------------- /code/lec12/matrix.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | // compile with -pthread 9 | 10 | 11 | // Number of threads: 12 | #define N (10) 13 | 14 | pthread_t tid_runners[N]; 15 | pthread_t tid_display; 16 | int width; 17 | int height; 18 | 19 | void* display(void* ptr) { 20 | while(1) { 21 | for(int y=0; y < height;y++) { 22 | write( 1, ptr + y * width, width); 23 | write( 1, "\n", 1); 24 | } 25 | // Move back up by height lines then sleep for 10 milliseconds 26 | for(int y=0; y < height; y++) write(1,"\033[1A",5); 27 | usleep(10000); 28 | } 29 | return NULL; 30 | } 31 | 32 | void* run(void* ptr) { 33 | char* image = ptr; 34 | 35 | while(1) { 36 | int x= rand() % width; 37 | char*mesg = "CS241 Rocks!"; 38 | char c = mesg[ rand() % strlen(mesg) ]; 39 | for(int y = 0 ; y < height && (rand() & 15); y ++) { 40 | image[ x + y*width ] =c; //^= 0x6E; // flip some bits 41 | usleep(x * 500L); 42 | } 43 | 44 | } 45 | return NULL; 46 | } 47 | 48 | void getTerminalWidthHeight(int* width, int* height) { 49 | struct winsize w; 50 | ioctl(STDOUT_FILENO, TIOCGWINSZ, &w); 51 | *width = w.ws_col; 52 | *height = w.ws_row; 53 | } 54 | 55 | int main() { 56 | puts("\x1b[32m\x1b[2J"); // Green text and clear screen. use 'reset' to reset terminal 57 | getTerminalWidthHeight(&width, &height); 58 | 59 | void* image = malloc(height * width); 60 | memset(image, '.' , height * width); 61 | 62 | pthread_create(&tid_display,NULL,display, image); 63 | 64 | for(int i=0;i 2 | #include 3 | #include 4 | 5 | void get_message(char**magic) { 6 | *magic = malloc(11); 7 | strcpy(*magic, "Amazing C!"); 8 | } 9 | 10 | int main() { 11 | char *ptr = NULL; 12 | get_message( &ptr ); 13 | puts( ptr ); // equiv printf("%s\n", ptr); 14 | } 15 | int strcmp(const char *s1, const char *s2) { 16 | while(*s1 != 0 && *s2 != 0) { 17 | if(*s1 != *s2) return 1; // TODO FIX 18 | s1++; 19 | s2++; 20 | } 21 | if( *s1 == 0 && *s2 ==0) return 0; 22 | return 1; // TODO FIX ME 23 | } 24 | 25 | if( ! strcmp( s, "yes") ) 26 | 27 | #include 28 | 29 | int contains_at(char*); 30 | 31 | 32 | int main(int argc, char** argv) { 33 | int result = contains_at(NULL); 34 | if(result) printf("Contains an @"); 35 | else printf("No @ found"); 36 | return 0; 37 | } 38 | 39 | int contains_at(char* ptr) { 40 | while( * ptr ) { 41 | if( * ptr == '@' ) { return 1; } // SUCCESS 42 | ptr ++; 43 | } 44 | return 0; 45 | } 46 | #include 47 | 48 | #define max(a,b) ((a)>(b) ? (a) : (b) ) 49 | 50 | int main(int argc, char**argv) { 51 | int result = max(10,5) + 1; 52 | //int result = 10>5 ? 10 : 5 +1; 53 | printf("Result:%d \n", result); 54 | } 55 | #include 56 | #include 57 | 58 | int main(int argc, char** argv) { 59 | 60 | printf("%p %p\n", main, malloc); 61 | 62 | return 0; 63 | } 64 | #include 65 | 66 | int main(int argc, char** argv) { 67 | #if 0 68 | for(int i = 0 ; i < argc; i++ ) { 69 | printf( "%d : %p : %s \n", i , *(argv + i), argv[i] ); 70 | } 71 | #endif 72 | while( *argv ) { 73 | printf("%s\n", *argv); 74 | argv ++; 75 | } 76 | return 0; // Success 77 | } 78 | #include 79 | 80 | int f1(int, int*); 81 | 82 | 83 | int abc = 5; 84 | 85 | int main() { f1( 10, &abc); return 0;} 86 | 87 | int f1(int v1, int* v2) { 88 | printf("&v1 is %p \n", &v1); 89 | 90 | printf("&v2 is %p \n", &v2); 91 | 92 | printf(" v2 is %p \n",v2); 93 | return 0; 94 | } 95 | 96 | -------------------------------------------------------------------------------- /code/lec15/block.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER; 5 | pthread_cond_t cv = PTHREAD_COND_INITIALIZER; 6 | double array[10]; 7 | int n = 0; 8 | 9 | void push(double v) { // blocks while full (n ==10) 10 | 11 | pthread_mutex_lock( &m); 12 | while(n == 10) { 13 | pthread_cond_wait(&cv, &m); 14 | } 15 | 16 | array[n++] = v; 17 | // There can be no threads waiting if n = 5 for example so, 18 | pthread_cond_broadcast(&cv); // is simple but a little inefficient! 19 | 20 | if(n==1) pthread_cond_broadcast(&cv); 21 | pthread_mutex_unlock( &m); 22 | } 23 | 24 | 25 | double pop() { // blocks while empty (n == 0) 26 | pthread_mutex_lock( &m); 27 | while(n == 0) { 28 | pthread_cond_wait(&cv, &m); 29 | } 30 | double v = array[--n]; 31 | pthread_cond_broadcast(&cv); // safe but a little inefficient 32 | // Imagine if two threads are waiting to push, but we only wake up one of them. The 2nd thread might never wake up because pop could now keep 1 2 | #include 3 | #include 4 | #include 5 | #define CONSUMER 6 | 7 | pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER; 8 | pthread_cond_t cv = PTHREAD_COND_INITIALIZER; 9 | 10 | int cake = 0; 11 | volatile int please_stop = 0; 12 | 13 | void decrement() { // Will block if zero 14 | pthread_mutex_lock(&m); 15 | while(cake == 0) { 16 | printf(" cake_eater/decrement: cake is zero... calling pthread_cond_wait\n"); 17 | 18 | pthread_cond_wait(&cv, &m); // unlock mutex, SLEEP, later... lock mutex 19 | // SPURIOUS WAKEUP 20 | 21 | printf(" cake_eater/decrement: pthread_cond_wait returned (Is cake>0?)\n"); 22 | } 23 | printf(" cake_eater/decrement: -- "); 24 | 25 | cake --; 26 | pthread_mutex_unlock(&m); 27 | } 28 | 29 | void increment() { 30 | pthread_mutex_lock(&m); 31 | printf(" cake_maker/increment: ++ \n"); 32 | cake ++; 33 | 34 | printf(" cake_maker/increment: pthread_cond_broadcast\n"); 35 | pthread_cond_broadcast(&cv); // Wake up all hungry sleeping cake eaters 36 | 37 | //or pthread_cond_signal(&cv); // Wake up one hungry sleeping cake eater 38 | 39 | pthread_mutex_unlock(&m); 40 | 41 | } 42 | 43 | void* cake_eater(void*arg) { 44 | while(!please_stop) { 45 | sleep(1); 46 | decrement(); 47 | printf(" \e[102;30mConsumer: Thanks! Now %d pieces left\e[49;39m\n",cake); 48 | } 49 | return NULL; 50 | } 51 | void* cake_maker(void*arg) { 52 | while(!please_stop) { 53 | sleep(5); 54 | printf(" \e[103;30mProducer: Time for more cake\e[49;39m\n"); 55 | sleep(1); 56 | increment(); 57 | increment(); 58 | increment(); 59 | } 60 | return NULL; 61 | 62 | } 63 | void time_to_stop(int signal) { 64 | please_stop = 1; 65 | } 66 | 67 | int main() { 68 | signal(SIGINT, time_to_stop); 69 | pthread_t tid1, tid2; 70 | pthread_create(&tid1, NULL, cake_eater, NULL); 71 | pthread_create(&tid2, NULL, cake_maker, NULL); 72 | pthread_join(tid1,NULL); 73 | pthread_join(tid2,NULL); 74 | // reset display 75 | printf("\e[39;49m"); 76 | return EXIT_SUCCESS; 77 | } -------------------------------------------------------------------------------- /code/lec12/mandelbrot-no-thread.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | // Run ../build_sdl2.sh to download and install SDL2 to ${HOME}/localinstall/ 6 | // Linux - 7 | // export LD_LIBRARY_PATH=${HOME}/localinstall/lib/ 8 | // clang sdl_mandel.c -lSDL2 -I ${HOME}/localinstall/include/ -L ${HOME}/localinstall/lib && ./a.out 9 | 10 | // Global variables initialize to zero / NULL. 11 | int width; 12 | int height; 13 | int max_iterations; 14 | 15 | SDL_Window* window; 16 | SDL_Renderer* renderer; 17 | SDL_Texture* framebuffer; 18 | 19 | uint32_t* myPixels; 20 | 21 | /* The core of the Mandelbrot repeat z= z^2+c and see if z stays bounded (close to zero). 22 | We can stop iterating once |z| exceeds 2, because all values >2 diverge. 23 | */ 24 | int mandelbrot(int x, int y) { 25 | double realVal = 2.5 * x / width - 1.6; 26 | double imgVal = 2.5 * (height - y) / height - 1.25; 27 | 28 | double const complex c = realVal + I * imgVal; 29 | double complex z = 0; 30 | 31 | int iterations = 0; 32 | for( ; iterations < max_iterations && cabs(z)< 2 ; iterations++) { 33 | z = z * z + c; 34 | } 35 | // Convert the iteration count into the R G B bytes, using different multipliers 36 | return (cabs(z) < 2) ? 0xffffff : iterations * 0x81021; 37 | } 38 | 39 | void init_gui() { 40 | //SDL_CreateWindowAndRenderer(0, 0, SDL_WINDOW_FULLSCREEN_DESKTOP, &window, &renderer); 41 | SDL_CreateWindowAndRenderer(width, height, 0, &window, &renderer); 42 | framebuffer = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGB888, SDL_TEXTUREACCESS_STREAMING, width, height); 43 | SDL_RaiseWindow(window); 44 | SDL_PumpEvents(); 45 | } 46 | 47 | void close_gui_after_keypress() { 48 | SDL_Event event; 49 | while( SDL_WaitEvent(&event) && event.type != SDL_KEYDOWN && event.type != SDL_QUIT) {} 50 | 51 | SDL_DestroyWindow(window); 52 | SDL_DestroyRenderer(renderer); 53 | SDL_Quit(); 54 | } 55 | 56 | void update_gui() { 57 | SDL_UpdateTexture(framebuffer, NULL, myPixels, width * sizeof(uint32_t) ); 58 | SDL_RenderCopy(renderer, framebuffer, NULL, NULL); 59 | SDL_RenderPresent(renderer); 60 | } 61 | 62 | void parse_args(int argc, char**argv) { 63 | if(argc == 4) { 64 | sscanf(argv[1],"%d", & width); 65 | sscanf(argv[2],"%d", & height); 66 | sscanf(argv[3],"%d", & max_iterations); 67 | } 68 | if(width < 16|| height < 16 || max_iterations < 1 69 | || width >= 1<<15 || height >= 1<<15) { 70 | fprintf(stderr,"Usage: %s e.g. 512 512 1000\n", argv[0]); 71 | exit(1); 72 | } 73 | } 74 | 75 | int main(int argc, char**argv) { 76 | parse_args(argc, argv); 77 | init_gui(); 78 | 79 | myPixels = calloc(width * height, sizeof(uint32_t)); 80 | 81 | // Typical direct coupling between calculation and display tasks 82 | for(int y=0; y < height; y++) { 83 | for(int x=0; x < width; x++) { 84 | myPixels[x + y * width] = mandelbrot(x,y); 85 | } 86 | // update the window every 16 rows 87 | if((y & 0xf) == 0xf) update_gui(); 88 | } 89 | update_gui(); 90 | close_gui_after_keypress(); 91 | free(myPixels); 92 | return 0; 93 | } 94 | -------------------------------------------------------------------------------- /code/lec17/17-binarygame.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #define CLEARSCREEN "\033[2J" 9 | #define MOVETO "\033[%d;%d;H" 10 | #define BKCOLOR "\033[%dm" 11 | #define BKBLACK "\033[40m" 12 | 13 | #define N (8) 14 | 15 | pthread_t tids[N], display_tid; 16 | pthread_cond_t cvs[N]; 17 | pthread_mutex_t locks[N]; 18 | char* status[N]; 19 | int data[N]; 20 | int quit; 21 | int work[N]; 22 | 23 | void* display_runner(void*arg) { 24 | while(!quit) { // should be wrapped in mutex lock / unlock to ensure a memory fence 25 | printf(CLEARSCREEN MOVETO , 1, 1); // clear screen then move to top-left 26 | for(int i = 0; i < N; i++) { 27 | printf("%02i %5s %3i ", i, status[i], data[i]); 28 | printf( BKCOLOR,41+ (i%7)); 29 | for(int j=data[i]>64?64:data[i];j--;) putchar('*'); 30 | printf( BKBLACK "\n"); 31 | } 32 | printf( "Type 0 to %d and press Enter to add some beans or q and Enter to quit\n", N-1); 33 | usleep(1E5); 34 | } 35 | return NULL; 36 | } 37 | void init() { 38 | for(int i =0; i < N;i++) { 39 | pthread_cond_init(cvs + i, NULL); 40 | pthread_mutex_init(locks + i, NULL); 41 | status[i] = "---"; 42 | } 43 | pthread_create( &display_tid,NULL, display_runner, NULL); 44 | } 45 | 46 | void update_display(int row, char* mesg) { 47 | if(row>=0 && row 1, then half it and increments data[i+1] 53 | void* runner(void*arg) { 54 | int i = * (int*) arg; 55 | assert(i>=0 && i < N - 1); 56 | 57 | while(1) { 58 | update_display(i,"Lok"); 59 | pthread_mutex_lock(locks+i); 60 | 61 | while(!quit && data[i] < 2 ) { 62 | update_display(i,"Nap"); 63 | pthread_cond_wait(cvs + i,locks+i); 64 | } 65 | if(quit) break; 66 | 67 | data[i] -= 2; 68 | pthread_mutex_unlock(locks+i); 69 | 70 | update_display(i,"L+1"); 71 | pthread_mutex_lock(locks+i+1); 72 | data[i+1] ++; 73 | pthread_cond_signal( cvs+i+1); // wake up one thread 74 | pthread_mutex_unlock(locks+i+1); 75 | 76 | update_display(i,"Yum" ); 77 | usleep(2E5); 78 | } 79 | pthread_mutex_lock(locks+i+1); 80 | pthread_cond_signal(cvs + i + 1); // wake up the next thread 81 | pthread_mutex_unlock(locks+i+1); 82 | } 83 | 84 | void modify(int index, int amount) { 85 | if(index<0 || index>=N) return; 86 | pthread_mutex_lock(locks + index); 87 | data[index] += amount; 88 | pthread_cond_broadcast( cvs + index); 89 | pthread_mutex_unlock(locks + index); 90 | 91 | update_display(index,"Add"); 92 | } 93 | 94 | void start_threads() { 95 | for(int i=0; i < N-1;i++) { 96 | work[i] = i; 97 | pthread_create(tids+i, NULL, runner, work + i); 98 | } 99 | } 100 | 101 | int main() { 102 | init(); 103 | //data[0] = 1 << (N-1); 104 | start_threads(); 105 | while(1) { 106 | int c = getchar(); 107 | if(c=='q' || c == EOF) 108 | break; 109 | int index = c - '0'; 110 | if(index>=0 && index < N) 111 | modify(index, 8); 112 | } 113 | puts("Quitting"); 114 | quit = 1; 115 | pthread_cond_broadcast(cvs + 0); 116 | pthread_exit(NULL); 117 | // program will finish when last thread exits 118 | } 119 | -------------------------------------------------------------------------------- /code/lec12/mandelbrot-attempt1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | // ADD PTHREAD support (don't forget to compile with -pthread too) 6 | #include 7 | 8 | // Run ../build_sdl2.sh to download and install SDL2 to ${HOME}/localinstall/ 9 | // Linux - 10 | // export LD_LIBRARY_PATH=${HOME}/localinstall/lib/ 11 | // clang sdl_mande-thread-v1l.c -lSDL2 -I ${HOME}/localinstall/include/ -L ${HOME}/localinstall/lib -pthread && ./a.out 12 | 13 | // Global variables initialize to zero / NULL. 14 | int width; 15 | int height; 16 | int max_iterations; 17 | 18 | SDL_Window* window; 19 | SDL_Renderer* renderer; 20 | SDL_Texture* framebuffer; 21 | 22 | uint32_t* myPixels; 23 | 24 | /* The core of the Mandelbrot repeat z= z^2+c and see if z stays bounded (close to zero). 25 | We can stop iterating once |z| exceeds 2, because all values >2 diverge. 26 | */ 27 | int mandelbrot(int x, int y) { 28 | double realVal = 2.5 * x / width - 1.6; 29 | double imgVal = 2.5 * (height - y) / height - 1.25; 30 | 31 | double const complex c = realVal + I * imgVal; 32 | double complex z = 0; 33 | 34 | int iterations = 0; 35 | for( ; iterations < max_iterations && cabs(z)< 2 ; iterations++) { 36 | z = z * z + c; 37 | } 38 | // Convert the iteration count into the R G B bytes, using different multipliers 39 | return (cabs(z) < 2) ? 0xffffff : iterations * 0x81021; 40 | } 41 | 42 | void init_gui() { 43 | //SDL_CreateWindowAndRenderer(0, 0, SDL_WINDOW_FULLSCREEN_DESKTOP, &window, &renderer); 44 | SDL_CreateWindowAndRenderer(width, height, 0, &window, &renderer); 45 | framebuffer = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGB888, SDL_TEXTUREACCESS_STREAMING, width, height); 46 | SDL_RaiseWindow(window); 47 | SDL_PumpEvents(); 48 | } 49 | int check_for_keypress() { 50 | SDL_Event event; 51 | return (SDL_PollEvent(&event) && (event.type == SDL_KEYDOWN || event.type == SDL_QUIT)); 52 | } 53 | 54 | void wait_keypress() { 55 | SDL_Event event; 56 | while( SDL_WaitEvent(&event) && event.type != SDL_KEYDOWN && event.type != SDL_QUIT) {} 57 | } 58 | 59 | void close_gui() { 60 | SDL_DestroyWindow(window); 61 | SDL_DestroyRenderer(renderer); 62 | SDL_Quit(); 63 | } 64 | 65 | void update_gui() { 66 | SDL_UpdateTexture(framebuffer, NULL, myPixels, width * sizeof(uint32_t) ); 67 | SDL_RenderCopy(renderer, framebuffer, NULL, NULL); 68 | SDL_RenderPresent(renderer); 69 | } 70 | 71 | void parse_args(int argc, char**argv) { 72 | if(argc == 4) { 73 | sscanf(argv[1],"%d", & width); 74 | sscanf(argv[2],"%d", & height); 75 | sscanf(argv[3],"%d", & max_iterations); 76 | } 77 | if(width < 16|| height < 16 || max_iterations < 1 78 | || width >= 1<<15 || height >= 1<<15) { 79 | fprintf(stderr,"Usage: %s e.g. 512 512 1000\n", argv[0]); 80 | exit(1); 81 | } 82 | } 83 | void quit(char*mesg) { 84 | perror(mesg); 85 | exit(1); 86 | } 87 | 88 | /* 89 | Let's just create 1000 of threads! (one per row). hey it seems to work on my machine. Not so much on linux-a2 90 | */ 91 | 92 | void* calc_runner1(void*badhack1) { 93 | // Hey compiler treat this address as a plain integer 94 | 95 | int y = (int)badhack1; //We are NOT derefencing this pointer 96 | for(int x=0; x < width; x++) { 97 | myPixels[x + y * width] = mandelbrot(x,y); 98 | } 99 | return NULL; 100 | } 101 | 102 | 103 | int main(int argc, char**argv) { 104 | parse_args(argc, argv); 105 | init_gui(); 106 | 107 | myPixels = calloc(width * height, sizeof(uint32_t)); 108 | 109 | pthread_t* tids = calloc(height, sizeof(pthread_t)); 110 | 111 | for(int y = 0; y < height; y++) { 112 | void* badhack = (void*) y; // Hey compiler! Treat this integer as a memory address! 113 | 114 | int result = pthread_create( & tids[y] , NULL, calc_runner1, badhack); 115 | if(result) quit("pthread_create failed"); 116 | } 117 | 118 | while( ! check_for_keypress()) { 119 | update_gui(); 120 | SDL_Delay(10); 121 | } 122 | 123 | close_gui(); 124 | free(myPixels); 125 | return 0; 126 | } 127 | -------------------------------------------------------------------------------- /code/lec12/mandelbrot-attempt2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | // ADD PTHREAD support (don't forget to compile with -pthread too) 6 | #include 7 | 8 | // Run ../build_sdl2.sh to download and install SDL2 to ${HOME}/localinstall/ 9 | // Linux - 10 | // export LD_LIBRARY_PATH=${HOME}/localinstall/lib/ 11 | // clang sdl_mande-thread-v1l.c -lSDL2 -I ${HOME}/localinstall/include/ -L ${HOME}/localinstall/lib -pthread && ./a.out 12 | 13 | // Global variables initialize to zero / NULL. 14 | int width; 15 | int height; 16 | int max_iterations; 17 | 18 | SDL_Window* window; 19 | SDL_Renderer* renderer; 20 | SDL_Texture* framebuffer; 21 | 22 | uint32_t* myPixels; 23 | 24 | /* The core of the Mandelbrot repeat z= z^2+c and see if z stays bounded (close to zero). 25 | We can stop iterating once |z| exceeds 2, because all values >2 diverge. 26 | */ 27 | int mandelbrot(int x, int y) { 28 | double realVal = 2.5 * x / width - 1.6; 29 | double imgVal = 2.5 * (height - y) / height - 1.25; 30 | 31 | double const complex c = realVal + I * imgVal; 32 | double complex z = 0; 33 | 34 | int iterations = 0; 35 | for( ; iterations < max_iterations && cabs(z)< 2 ; iterations++) { 36 | z = z * z + c; 37 | } 38 | // Convert the iteration count into the R G B bytes, using different multipliers 39 | return (cabs(z) < 2) ? 0xffffff : iterations * 0x81021; 40 | } 41 | 42 | void init_gui() { 43 | //SDL_CreateWindowAndRenderer(0, 0, SDL_WINDOW_FULLSCREEN_DESKTOP, &window, &renderer); 44 | SDL_CreateWindowAndRenderer(width, height, 0, &window, &renderer); 45 | framebuffer = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGB888, SDL_TEXTUREACCESS_STREAMING, width, height); 46 | SDL_RaiseWindow(window); 47 | SDL_PumpEvents(); 48 | } 49 | int check_for_keypress() { 50 | SDL_Event event; 51 | return (SDL_PollEvent(&event) && (event.type == SDL_KEYDOWN || event.type == SDL_QUIT)); 52 | } 53 | 54 | void wait_keypress() { 55 | SDL_Event event; 56 | while( SDL_WaitEvent(&event) && event.type != SDL_KEYDOWN && event.type != SDL_QUIT) {} 57 | } 58 | 59 | void close_gui() { 60 | SDL_DestroyWindow(window); 61 | SDL_DestroyRenderer(renderer); 62 | SDL_Quit(); 63 | } 64 | 65 | void update_gui() { 66 | SDL_UpdateTexture(framebuffer, NULL, myPixels, width * sizeof(uint32_t) ); 67 | SDL_RenderCopy(renderer, framebuffer, NULL, NULL); 68 | SDL_RenderPresent(renderer); 69 | } 70 | 71 | void parse_args(int argc, char**argv) { 72 | if(argc == 4) { 73 | sscanf(argv[1],"%d", & width); 74 | sscanf(argv[2],"%d", & height); 75 | sscanf(argv[3],"%d", & max_iterations); 76 | } 77 | if(width < 16|| height < 16 || max_iterations < 1 78 | || width >= 1<<15 || height >= 1<<15) { 79 | fprintf(stderr,"Usage: %s e.g. 512 512 1000\n", argv[0]); 80 | exit(1); 81 | } 82 | } 83 | void quit(char*mesg) { 84 | perror(mesg); 85 | exit(1); 86 | } 87 | 88 | void* calc_runner1_NOTUSED(void*badhack1) { 89 | int y = (int)badhack1; //We are NOT derefencing this pointer 90 | for(int x=0; x < width; x++) { 91 | myPixels[x + y * width] = mandelbrot(x,y); 92 | } 93 | return NULL; 94 | } 95 | 96 | void* calc_runner2(void* better) { 97 | int* intptr = ((int*)better); 98 | int y = * intptr; 99 | for(int x=0; x < width; x++) { 100 | myPixels[x + y * width] = mandelbrot(x,y); 101 | } 102 | return NULL; 103 | } 104 | 105 | 106 | int main(int argc, char**argv) { 107 | parse_args(argc, argv); 108 | init_gui(); 109 | 110 | myPixels = calloc(width * height, sizeof(uint32_t)); 111 | 112 | pthread_t* tids = calloc(height, sizeof(pthread_t)); 113 | // awful 114 | for(int y = 0; y < height; y++) { 115 | //printf("Creating thread....%d\n",y); // Dont delete this line 116 | int result = pthread_create( & tids[y] , NULL, calc_runner2, &y); 117 | if(result) quit("pthread_create failed"); 118 | //SDL_Delay(5); // You might need a larger value to make it work on your machine 119 | } 120 | 121 | 122 | while( ! check_for_keypress()) { 123 | update_gui(); 124 | SDL_Delay(10); 125 | } 126 | 127 | close_gui(); 128 | free(myPixels); 129 | return 0; 130 | } 131 | -------------------------------------------------------------------------------- /welcome.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | Hi class! 4 | 5 | Welcome to CS241 System Programming! I'm Lawrence Angrave. I'm excited to be your instructor this semester and to meet you personally Wednesday in DCL1320 at 10AM or 11AM. The first lecture has real content - bring your A game. 6 | 7 | You've probably heard this is a challenging class! Yes, you'll need is time, tenacity and readiness to learn and use C. And the big picture - this course is a stepping stone - You're leaving behind CS225 land (where you write code that works with the course's provided code) and instead we're your launch pad you for the big leagues CS4xx at a tier-1 CS school. Take this course seriously and you will be a different and better person at the end of it. 8 | 9 | Prepare your neurons. 10 | 11 | C is one of the smallest, portable and simplest and "close-to-the-metal" languages that you'll ever use. Unlike C++ it is possible to actually nearly know all of the C specification in under 50 hours. Even if you program in the future with python/Go/Javascript ... you'll be linking and using cross-platform libraries written in ... C. And if you want your new self-aware-high-performance AI/Vision/networking/neural net/quantum computing/picture mod ibrary to be used everywhere i.e. useful directly from Matlab/R/C++/Java programs... or you want to exploit meltdown CPU attack... you'll first or second choice will be ...C 12 | 13 | C programs use a lot of memory pointers. This means your variables hold memory addresses (and the compiler uses the type of variable to infer how many bytes to read/write at that location). Everything is great providing your pointers point to the correct piece of memory and don't start reading or writing from incorrect pieces of memory. You can even indirectly cause "exciting things to happen" if you pass a bad pointer to a library or system call too. 14 | 15 | Pointers can be tricky to learn, but it helps to remember that 16 | 17 | 0) Asterisk in code "*" is either part of the type ("This is a pointer!") but in an expression it means follow the pointer and read the memory that it points to. 18 | 19 | 1) They just hold a memory address (which CAN be changed e.g " myptr = ... " ) 20 | 21 | 2) For a program to use ("dereference") a pointer, then the CPU will need to perform another memory access, 22 | 23 | 3) The variable type is a hint to the compiler as to how many bytes to read/write and is also useful to detect some programming errors at compile time. 24 | 25 | (I admit I simplified the last part about compilers but hey this is about using pointers with confidence, not about implementing a compiler OK?) 26 | 27 | Let's get started today, right now, with Homework Zero - my introductory mini-course. If you open the link below up on a powerful laptop or desktop using Chrome / Firefox you'll discover videos, man pages, and a complete virtual linux machine running inside your browser (yes it implements memory,disk and CPU in javascript and then boots up a linux machine with gcc and other standard tools - pretty cool! - it works best in Chrome). There's one #include issue with waitpid that I'll let you discover (and find a workaround) in the last lecture. 28 | 29 | http://tinyurl.com/vizzini2016 30 | 31 | The questions are here 32 | 33 | https://github.com/angrave/CS241-Lectures-SP20/blob/master/HW0.md 34 | 35 | We will put up a link to submit HW0 starting the first lab section, although it won't be due until the following week. 36 | 37 | You can also regular linux machines and other online environments of course. I suggest you work on HW0 a bit each day (it's much better for long term recall and innate skills acquisition if you exercise your CS241 neurons each day). 38 | 39 | With a bit of google magic and hunting you can also find: Piazza, secondly my *free* wikibook and Homework 0 (keep your answers to each question - we'll ask you to submit these as part of a lab) and of course the course website. However here are some starting points :-) 40 | 41 | https://piazza.com/illinois/spring2020/cs241 42 | 43 | Send all CS241 questions, comments, ideas, regrades, logistics, issues, grade requests,bananas-for-scale etc to Piazza - not to my email. Most issues can be solved with a public or private post on Piazza. If that's not appropriate, please contact cs241admin@illinois.edu :-) 44 | 45 | The course website (currently under construction) is here. You can find links to the coursebook and syllabus (including learning objectives) here - 46 | 47 | http://cs241.cs.illinois.edu/ 48 | 49 | 50 | Ready? Let's Go! 51 | 52 | - Captain Angrave 53 | 54 | p.s. Myself and the course staff love teaching this course. We're here help as many of you as possible to become the best programmers and computer scientists that you can be. Are you ready to stand up, put in the effort, and be recognized as an University of Illinois Computer Scientist? Then you're in the right place. Let's kick it into gear and get this show started. 55 | 56 | p.p.s. As we speak EngrIT + CS241 staff are also preparing a server-side multi-CPU-core virtual machine for each and everyone of you. More details next week. 57 | 58 | p.p.p.s Don't Panic, you'll be writing less code than Hamilton's Apollo team- 59 | 60 | https://en.wikipedia.org/wiki/Margaret_Hamilton_(scientist) 61 | https://en.wikipedia.org/wiki/Margaret_Hamilton_(software_engineer)#/media/File:Margaret_Hamilton_-_restoration.jpg 62 | ... but you will be thinking about concurrency, just like she had to for the Apollo code. 63 | 64 | -------------------------------------------------------------------------------- /code/lec12/mandelbrot-task.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | // ADD PTHREAD support (don't forget to compile with -pthread too) 8 | #include 9 | 10 | // Run ../build_sdl2.sh to download and install SDL2 to ${HOME}/localinstall/ 11 | // Linux - 12 | // export LD_LIBRARY_PATH=${HOME}/localinstall/lib/ 13 | // clang sdl_mande-thread-task.c -lSDL2 -I ${HOME}/localinstall/include/ -L ${HOME}/localinstall/lib -pthread && ./a.out 512 512 2000 14 | 15 | typedef struct _task_t { 16 | int start_x; 17 | int start_y; 18 | int end_x; 19 | int end_y; 20 | } task_t; 21 | 22 | 23 | // Global variables initialize to zero / NULL. 24 | int width; 25 | int height; 26 | int max_iterations; 27 | 28 | SDL_Window* window; 29 | SDL_Renderer* renderer; 30 | SDL_Texture* framebuffer; 31 | 32 | uint32_t* myPixels; 33 | 34 | int num_tasks; 35 | task_t* tasks; 36 | 37 | #define max_threads 2 38 | 39 | int thread_count; 40 | pthread_t thread_ids[max_threads]; 41 | 42 | /* The core of the Mandelbrot repeat z= z^2+c and see if z stays bounded (close to zero). 43 | We can stop iterating once |z| exceeds 2, because all values >2 diverge. 44 | */ 45 | int mandelbrot(int x, int y) { 46 | double realVal = 2.5 * x / width - 1.6; 47 | double imgVal = 2.5 * (height - y) / height - 1.25; 48 | 49 | double const complex c = realVal + I * imgVal; 50 | double complex z = 0; 51 | 52 | int iterations = 0; 53 | for( ; iterations < max_iterations && cabs(z)< 2 ; iterations++) { 54 | z = z * z + c; 55 | } 56 | // Convert the iteration count into the R G B bytes, using different multipliers 57 | return (cabs(z) < 2) ? 0xffffff : iterations * 0x81021; 58 | } 59 | 60 | void init_gui() { 61 | //SDL_CreateWindowAndRenderer(0, 0, SDL_WINDOW_FULLSCREEN_DESKTOP, &window, &renderer); 62 | SDL_CreateWindowAndRenderer(width, height, 0, &window, &renderer); 63 | framebuffer = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGB888, SDL_TEXTUREACCESS_STREAMING, width, height); 64 | SDL_RaiseWindow(window); 65 | SDL_PumpEvents(); 66 | } 67 | void close_gui_after_keypress() { 68 | SDL_Event event; 69 | while( SDL_WaitEvent(&event) && event.type != SDL_KEYDOWN && event.type != SDL_QUIT) {} 70 | 71 | SDL_DestroyWindow(window); 72 | SDL_DestroyRenderer(renderer); 73 | SDL_Quit(); 74 | } 75 | 76 | void update_gui() { 77 | SDL_PumpEvents(); 78 | SDL_UpdateTexture(framebuffer, NULL, myPixels, width * sizeof(uint32_t) ); 79 | SDL_RenderCopy(renderer, framebuffer, NULL, NULL); 80 | SDL_RenderPresent(renderer); 81 | } 82 | 83 | void parse_args(int argc, char**argv) { 84 | if(argc == 4) { 85 | sscanf(argv[1],"%d", & width); 86 | sscanf(argv[2],"%d", & height); 87 | sscanf(argv[3],"%d", & max_iterations); 88 | } 89 | if(width < 16|| height < 16 || max_iterations < 1 90 | || width >= 1<<15 || height >= 1<<15) { 91 | fprintf(stderr,"Usage: %s e.g. 512 512 1000\n", argv[0]); 92 | exit(1); 93 | } 94 | } 95 | 96 | void quit(char*mesg) { 97 | perror(mesg); 98 | exit(1); 99 | } 100 | 101 | int min(int a, int b) {return astart_x,task->end_x,task->start_y,task->end_y); 106 | 107 | for(int x = task->start_x; x < task->end_x; x++) { 108 | for(int y = task->start_y; y < task->end_y; y++) { 109 | myPixels[x + y * width] = mandelbrot(x,y); 110 | } 111 | } 112 | return NULL; 113 | } 114 | 115 | /* Randomly shuffle the order of the tasks */ 116 | void shuffle_tasks(task_t*tasks, int num_tasks) { 117 | task_t temp; 118 | for(int i=0;i< num_tasks-1; i++) { 119 | memcpy(&temp, &tasks[i],sizeof(task_t)); 120 | int j = i + (rand() % (num_tasks-i)); 121 | memcpy(&tasks[i], &tasks[j],sizeof(task_t)); 122 | memcpy(&tasks[j], &temp,sizeof(task_t)); 123 | } 124 | } 125 | 126 | void make_tile_tasks() { 127 | 128 | int size = 64; 129 | // round up (in case height or width is not divisible by size) 130 | num_tasks = ((height+size-1) / size) * ((width+size-1) / size); 131 | // For this problem we can calculate all of the concurrent tasks 132 | tasks = calloc(num_tasks , sizeof(task_t)); 133 | 134 | int i = 0; 135 | for(int y = 0; y < height; y+= size){ 136 | for(int x = 0; x < width; x+= size) { 137 | assert(i< num_tasks); 138 | tasks[i].start_x = x; 139 | tasks[i].start_y = y; 140 | tasks[i].end_x = min(x+size,width); 141 | tasks[i].end_y = min(y+size,height); 142 | i++; 143 | } 144 | } 145 | assert(i == num_tasks); 146 | shuffle_tasks(tasks, num_tasks); 147 | } 148 | 149 | void join_all_task_threads() { 150 | for(int i=0;i< thread_count;i++){ 151 | pthread_join(thread_ids[i], NULL); 152 | } 153 | thread_count = 0; 154 | } 155 | 156 | void run_all_tiles_and_wait() { 157 | for(int i= 0; i < num_tasks; i++) { 158 | int result = pthread_create( & thread_ids[thread_count++] , NULL, calc_runner3, tasks+i); 159 | if(result) quit("pthread_create failed"); 160 | 161 | // Max threads running, or we've reached the last task? 162 | // If so then join on all threads that we created earlier. 163 | // What are the limitations of this approach? Can we do better? 164 | if(thread_count == max_threads || i+1 == num_tasks) { 165 | join_all_task_threads(); 166 | update_gui(); 167 | } 168 | } 169 | } 170 | 171 | int main(int argc, char**argv) { 172 | parse_args(argc, argv); 173 | init_gui(); 174 | 175 | myPixels = calloc(width * height, sizeof(uint32_t)); 176 | 177 | make_tile_tasks(); 178 | 179 | run_all_tiles_and_wait(); 180 | 181 | close_gui_after_keypress(); 182 | 183 | free(myPixels); 184 | return 0; 185 | } 186 | -------------------------------------------------------------------------------- /HW0.md: -------------------------------------------------------------------------------- 1 | # Welcome to SP2020! 2 | ```C 3 | // First, can you guess which lyrics have been transformed into this C-like system code? 4 | char q[] = "Do you wanna build a C99 program?"; 5 | #define or "go debugging with gdb?" 6 | static unsigned int i = sizeof(or) != strlen(or); 7 | char* ptr = "lathe"; size_t come = fprintf(stdout,"%s door", ptr+2); 8 | int away = ! (int) * ""; 9 | 10 | int* shared = mmap(NULL, sizeof(int*), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0); 11 | munmap(shared,sizeof(int*)); 12 | 13 | if(!fork()) { execlp("man","man","-3","ftell", (char*)0); perror("failed"); } 14 | if(!fork()) { execlp("make","make", "snowman", (char*)0); execlp("make","make", (char*)0)); } 15 | 16 | exit(0); 17 | ``` 18 | 19 | ## So you want to master System Programming? And get a better grade than B? 20 | ```C 21 | int main(int argc, char** argv) { 22 | puts("Great! We have plenty of useful resources for you, but it's up to you to"); 23 | puts(" be an active learner and learn how to solve problems and debug code."); 24 | puts("Bring your near-completed answers the problems below"); 25 | puts(" to the first lab to show that you've been working on this."); 26 | printf("A few \"don't knows\" or \"unsure\" is fine for lab 1.\n"); 27 | puts("Warning: you and your peers will work hard in this class."); 28 | puts("This is not CS225; you will be pushed much harder to"); 29 | puts(" work things out on your own."); 30 | fprintf(stdout,"This homework is a stepping stone to all future assignments.\n"); 31 | char p[] = "So, you will want to clear up any confusions or misconceptions.\n"; 32 | write(1, p, strlen(p) ); 33 | char buffer[1024]; 34 | sprintf(buffer,"For grading purposes, this homework 0 will be graded as part of your lab %d work.\n", 1); 35 | write(1, buffer, strlen(buffer)); 36 | printf("Press Return to continue\n"); 37 | read(0, buffer, sizeof(buffer)); 38 | return 0; 39 | } 40 | ``` 41 | ## Watch the videos and write up your answers to the following questions 42 | 43 | **Important!** 44 | 45 | The virtual machine-in-your-browser and the videos you need for HW0 are here: 46 | 47 | http://cs-education.github.io/sys/ 48 | 49 | The coursebook: 50 | 51 | http://cs241.cs.illinois.edu/coursebook/index.html 52 | 53 | Questions? Comments? Use Piazza: 54 | https://piazza.com/illinois/spring2020/cs241 55 | 56 | The in-browser virtual machine runs entirely in Javascript and is fastest in Chrome. Note the VM and any code you write is reset when you reload the page, *so copy your code to a separate document.* The post-video challenges (e.g. Haiku poem) are not part of homework 0 but you learn the most by doing (rather than just passively watching) - so we suggest you have some fun with each end-of-video challenge. 57 | 58 | HW0 questions are below. Copy your answers into a text document because you'll need to submit them later in the course. More information will be in the first lab. 59 | 60 | ## Chapter 1 61 | 62 | In which our intrepid hero battles standard out, standard error, file descriptors and writing to files. 63 | 64 | ### Hello, World! (system call style) 65 | 1. Write a program that uses `write()` to print out "Hi! My name is ``". 66 | ### Hello, Standard Error Stream! 67 | 2. Write a function to print out a triangle of height `n` to standard error. 68 | - Your function should have the signature `void write_triangle(int n)` and should use `write()`. 69 | - The triangle should look like this, for n = 3: 70 | ```C 71 | * 72 | ** 73 | *** 74 | ``` 75 | ### Writing to files 76 | 3. Take your program from "Hello, World!" modify it write to a file called `hello_world.txt`. 77 | - Make sure to to use correct flags and a correct mode for `open()` (`man 2 open` is your friend). 78 | ### Not everything is a system call 79 | 4. Take your program from "Writing to files" and replace `write()` with `printf()`. 80 | - Make sure to print to the file instead of standard out! 81 | 5. What are some differences between `write()` and `printf()`? 82 | 83 | ## Chapter 2 84 | 85 | Sizing up C types and their limits, `int` and `char` arrays, and incrementing pointers 86 | 87 | ### Not all bytes are 8 bits? 88 | 1. How many bits are there in a byte? 89 | 2. How many bytes are there in a `char`? 90 | 3. How many bytes the following are on your machine? 91 | - `int`, `double`, `float`, `long`, and `long long` 92 | ### Follow the int pointer 93 | 4. On a machine with 8 byte integers: 94 | ```C 95 | int main(){ 96 | int data[8]; 97 | } 98 | ``` 99 | If the address of data is `0x7fbd9d40`, then what is the address of `data+2`? 100 | 101 | 5. What is `data[3]` equivalent to in C? 102 | - Hint: what does C convert `data[3]` to before dereferencing the address? 103 | 104 | ### `sizeof` character arrays, incrementing pointers 105 | 106 | Remember, the type of a string constant `"abc"` is an array. 107 | 108 | 6. Why does this segfault? 109 | ```C 110 | char *ptr = "hello"; 111 | *ptr = 'J'; 112 | ``` 113 | 7. What does `sizeof("Hello\0World")` return? 114 | 8. What does `strlen("Hello\0World")` return? 115 | 9. Give an example of X such that `sizeof(X)` is 3. 116 | 10. Give an example of Y such that `sizeof(Y)` might be 4 or 8 depending on the machine. 117 | 118 | ## Chapter 3 119 | 120 | Program arguments, environment variables, and working with character arrays (strings) 121 | 122 | ### Program arguments, `argc`, `argv` 123 | 1. What are two ways to find the length of `argv`? 124 | 2. What does `argv[0]` represent? 125 | ### Environment Variables 126 | 3. Where are the pointers to environment variables stored (on the stack, the heap, somewhere else)? 127 | ### String searching (strings are just char arrays) 128 | 4. On a machine where pointers are 8 bytes, and with the following code: 129 | ```C 130 | char *ptr = "Hello"; 131 | char array[] = "Hello"; 132 | ``` 133 | What are the values of `sizeof(ptr)` and `sizeof(array)`? Why? 134 | 135 | ### Lifetime of automatic variables 136 | 137 | 5. What data structure manages the lifetime of automatic variables? 138 | 139 | ## Chapter 4 140 | 141 | Heap and stack memory, and working with structs 142 | 143 | ### Memory allocation using `malloc`, the heap, and time 144 | 1. If I want to use data after the lifetime of the function it was created in ends, where should I put it? How do I put it there? 145 | 2. What are the differences between heap and stack memory? 146 | 3. Are there other kinds of memory in a process? 147 | 4. Fill in the blank: "In a good C program, for every malloc, there is a ___". 148 | ### Heap allocation gotchas 149 | 5. What is one reason `malloc` can fail? 150 | 6. What are some differences between `time()` and `ctime()`? 151 | 7. What is wrong with this code snippet? 152 | ```C 153 | free(ptr); 154 | free(ptr); 155 | ``` 156 | 8. What is wrong with this code snippet? 157 | ```C 158 | free(ptr); 159 | printf("%s\n", ptr); 160 | ``` 161 | 9. How can one avoid the previous two mistakes? 162 | ### `struct`, `typedef`s, and a linked list 163 | 10. Create a `struct` that represents a `Person`. Then make a `typedef`, so that `struct Person` can be replaced with a single word. A person should contain the following information: their name (a string), their age (an integer), and a list of their friends (stored as a pointer to an array of pointers to `Person`s). 164 | 11. Now, make two persons on the heap, "Agent Smith" and "Sonny Moore", who are 128 and 256 years old respectively and are friends with each other. 165 | ### Duplicating strings, memory allocation and deallocation of structures 166 | Create functions to create and destroy a Person (Person's and their names should live on the heap). 167 | 12. `create()` should take a name and age. The name should be copied onto the heap. Use malloc to reserve sufficient memory for everyone having up to ten friends. Be sure initialize all fields (why?). 168 | 13. `destroy()` should free up not only the memory of the person struct, but also free all of its attributes that are stored on the heap. Destroying one person should not destroy any others. 169 | 170 | ## Chapter 5 171 | 172 | Text input and output and parsing using `getchar`, `gets`, and `getline`. 173 | 174 | ### Reading characters, trouble with gets 175 | 1. What functions can be used for getting characters from `stdin` and writing them to `stdout`? 176 | 2. Name one issue with `gets()`. 177 | ### Introducing `sscanf` and friends 178 | 3. Write code that parses the string "Hello 5 World" and initializes 3 variables to "Hello", 5, and "World". 179 | ### `getline` is useful 180 | 4. What does one need to define before including `getline()`? 181 | 5. Write a C program to print out the content of a file line-by-line using `getline()`. 182 | 183 | ## C Development 184 | 185 | These are general tips for compiling and developing using a compiler and git. Some web searches will be useful here 186 | 187 | 1. What compiler flag is used to generate a debug build? 188 | 2. You modify the Makefile to generate debug builds and type `make` again. Explain why this is insufficient to generate a new build. 189 | 3. Are tabs or spaces used to indent the commands after the rule in a Makefile? 190 | 4. What does `git commit` do? What's a `sha` in the context of git? 191 | 5. What does `git log` show you? 192 | 6. What does `git status` tell you and how would the contents of `.gitignore` change its output? 193 | 7. What does `git push` do? Why is it not just sufficient to commit with `git commit -m 'fixed all bugs' `? 194 | 8. What does a non-fast-forward error `git push` reject mean? What is the most common way of dealing with this? 195 | 196 | ## Optional (Just for fun) 197 | - Convert your a song lyrics into System Programming and C code and share on Piazza. 198 | - Find, in your opinion, the best and worst C code on the web and post the link to Piazza. 199 | - Write a short C program with a deliberate subtle C bug and post it on Piazza to see if others can spot your bug. 200 | - Do you have any cool/disastrous system programming bugs you've heard about? Feel free to share with your peers and the course staff on piazza. --------------------------------------------------------------------------------