├── a-Note-on-Testing.md ├── assignments ├── A0 │ ├── CompSys20-A0-polyglot.pdf │ ├── CompSys20-A0.pdf │ └── src.zip ├── A1 │ ├── CompSys20-A1-polyglot.pdf │ ├── CompSys20-A1.pdf │ └── src.zip ├── A2 │ ├── CompSys20-A2-polyglot.pdf │ ├── CompSys20-A2.pdf │ ├── a2_help.md │ └── src.zip ├── A3 │ ├── CompSys20-A3-polyglot.pdf │ ├── CompSys20-A3.pdf │ └── src.zip ├── A4 │ ├── CompSys20-A4.pdf │ └── src.zip ├── A5 │ ├── CompSys20-A5.pdf │ └── src.zip ├── A6 │ ├── CompSys20-A6.pdf │ └── src.zip ├── A7 │ ├── CompSys20-A7.pdf │ └── src.zip └── commented_report_example.pdf ├── collect-slides-in-folder.sh ├── coursedescription.md ├── lectureplan.md ├── material ├── .gitignore ├── 200831_introduction-plus-c │ ├── 01-c-intro.pdf │ ├── 01-intro.pdf │ ├── 01-overview.pdf │ ├── code │ │ ├── 0_one_or_three │ │ ├── 0_one_or_three.c │ │ ├── 10_safe_reading.c │ │ ├── 11_echo_int.c │ │ ├── 12_int_arg.c │ │ ├── 13_arg_play.c │ │ ├── 1_one_or_three_switch.c │ │ ├── 2_one_or_three_switch2.c │ │ ├── 3_print_args_while │ │ ├── 3_print_args_while.c │ │ ├── 4_print_args_for.c │ │ ├── 5_some_assignments.c │ │ ├── 6_sideeffects │ │ ├── 6_sideeffects.c │ │ ├── 7_sideeffects │ │ ├── 7_sideeffects2.c │ │ ├── 8_array_inc │ │ ├── 8_array_inc.c │ │ ├── 9_echo │ │ ├── 9_echo.c │ │ └── Makefile │ ├── code_more │ │ ├── Makefile │ │ ├── args.c │ │ ├── error.c │ │ ├── helloworld.c │ │ ├── roll.c │ │ └── sum.c │ └── exercises.md ├── 200902_bits-bytes-words │ ├── code │ │ ├── io.c │ │ └── puzzels.c │ ├── exercises.md │ └── slides.pdf ├── 200907_arithmetic │ ├── exercises.md │ ├── slides.pdf │ └── ternary │ │ ├── Makefile │ │ ├── ternary.c │ │ ├── ternary.h │ │ └── test.c ├── 200909_pointers-and-memory │ ├── exercise_code │ │ ├── array.c │ │ ├── capitalize.c │ │ ├── hello.c │ │ └── table.c │ ├── exercises.md │ ├── gdb │ │ ├── Makefile │ │ ├── foo.txt │ │ ├── lastchar.c │ │ ├── macro.c │ │ └── segfault.c │ ├── gdb_even_quicker_reference.md │ ├── gdb_pointers.pdf │ ├── gdb_reference.pdf │ ├── lecture_code │ │ ├── Makefile │ │ ├── funpointers.c │ │ ├── pointers.c │ │ ├── pointers_old.c │ │ └── strings.c │ └── pointers_and_memory.pdf ├── 200914_basic_instructions │ ├── code │ │ ├── Makefile │ │ ├── arith.c │ │ ├── sum.c │ │ └── swap.c │ ├── exercises.md │ ├── exercises_code │ │ ├── Makefile │ │ ├── a_sum.c │ │ ├── a_sum.prime │ │ └── decode1.s │ └── slides.pdf ├── 200916_control_instructions │ ├── code │ │ ├── p.c │ │ ├── p.prime │ │ ├── p.s │ │ ├── recap.c │ │ └── recap.s │ ├── exercises.md │ ├── exercises_solution.md │ └── slides.pdf ├── 200921_simple_computer │ ├── exercises.md │ ├── readingMaterial.md │ ├── slides.pdf │ └── tools.md ├── 200923_processor_realization │ ├── exercises.md │ ├── mark-bohr-2014-reduced.pdf │ └── slides.pdf ├── 200928_simple_uarch │ ├── exercise_solutions.md │ ├── exercises.md │ └── slides.pdf ├── 200930_memory_hierachy │ ├── exercise_code │ │ ├── Makefile │ │ ├── sum-array-cols.c │ │ └── sum-array-rows.c │ ├── exercises.md │ └── slides.pdf ├── 201005_caching │ ├── exercises.md │ ├── matmult │ │ ├── Makefile │ │ ├── README.txt │ │ ├── bmm.c │ │ ├── clock.c │ │ ├── clock.h │ │ ├── fcycbmm.c │ │ ├── fcycbmm.h │ │ ├── fcycmm.c │ │ ├── fcycmm.h │ │ ├── mm-corei7h.txt │ │ ├── mm.c │ │ └── mm.h │ ├── mountain │ │ ├── Makefile │ │ ├── README.txt │ │ ├── clock.c │ │ ├── clock.h │ │ ├── fcyc2.c │ │ ├── fcyc2.h │ │ ├── mountain.c │ │ └── mountain4x4-corei7h.txt │ └── slides.pdf ├── 201007_advanced_uarch │ ├── exercises.md │ └── slides.pdf ├── 201019_exceptional_control_flow │ ├── exceptional-control-flow.odp │ ├── exceptional-control-flow.pdf │ ├── exec0.c │ ├── exec1.c │ ├── exercises.md │ ├── fork0.c │ ├── fork1.c │ ├── fork2.c │ ├── forkbomb.c │ └── pipe0.c ├── 201021_dynamic_memory │ ├── calc │ │ ├── Makefile │ │ ├── calc.c │ │ ├── stack.c │ │ └── stack.h │ ├── calc_solution │ │ ├── Makefile │ │ ├── calc.c │ │ ├── stack.c │ │ └── stack.h │ ├── exercises.md │ ├── fib │ │ ├── Makefile │ │ ├── fib.c │ │ ├── fib.h │ │ └── test.c │ └── list │ │ ├── Makefile │ │ ├── doubly_linked │ │ ├── Makefile │ │ ├── list.c │ │ ├── list.h │ │ └── test_list.c │ │ ├── flat_array │ │ ├── Makefile │ │ ├── list.c │ │ ├── list.h │ │ └── test_list.c │ │ ├── list.c │ │ ├── list.h │ │ └── test_list.c ├── 201026_signals │ ├── csapp.c │ ├── csapp.h │ ├── exercises.md │ ├── forks │ ├── forks.c │ ├── lecture │ │ └── fork.c │ ├── pipes.c │ ├── primes.c │ ├── shellex.c │ ├── sigint │ ├── sigint.c │ ├── signals.c │ ├── signals.odp │ ├── signals.pdf │ └── solutions │ │ ├── homework_problem_8.24 │ │ ├── Makefile │ │ └── illegal_activity_in_child_process.c │ │ └── homework_problem_8.25 │ │ ├── Makefile │ │ ├── tfgets │ │ └── tfgets.c ├── 201028_virtual_memory_i │ ├── .gitignore │ ├── exercises.md │ ├── mem0.c │ ├── mem1.c │ ├── memfork.c │ ├── virtual_memory_i.odp │ └── virtual_memory_i.pdf ├── 201102_virtual_memory_ii │ ├── compsys_malloc.c │ ├── compsys_malloc.h │ ├── exercises.md │ ├── mallocs.c │ ├── mmap_fork.c │ ├── small_mallocs.c │ ├── virtual_memory_ii.odp │ └── virtual_memory_ii.pdf ├── 201106_concurrent_programming │ ├── .gitignore │ ├── badcnt.c │ ├── concurrent_programming.odp │ ├── concurrent_programming.pdf │ ├── csapp.c │ ├── exercises.md │ ├── goodcnt.c │ ├── hello.c │ ├── parcat.c │ ├── sharing.c │ └── sumbytes.c ├── 201116_advanced_concurrency │ ├── .gitignore │ ├── Makefile │ ├── README.md │ ├── advanced_concurrency.md │ ├── exercises.md │ ├── fibs-futures.c │ ├── fibs-huge.input │ ├── fibs-medium.input │ ├── fibs-mt.c │ ├── fibs-threadpool-spin.c │ ├── fibs-threadpool.c │ ├── fibs-verytiny.input │ ├── fibs.c │ ├── futures.h │ ├── main-common.c │ ├── main-header.h │ ├── main-one-cv-while.c │ ├── main-two-cvs-if.c │ ├── main-two-cvs-while-extra-unlock.c │ ├── main-two-cvs-while.c │ ├── mythreads.h │ └── pc-header.h ├── 201118_system_io │ ├── copy-buffered-byte.c │ ├── copy-buffered.c │ ├── copy-chunks.c │ ├── copy-mmap.c │ ├── copy-unbuffered.c │ ├── csapp.c │ ├── csapp.h │ ├── exercise_code │ │ ├── Makefile │ │ ├── cpfile.c │ │ ├── csapp.c │ │ ├── csapp.h │ │ ├── fstatcheck.c │ │ └── solutions │ │ │ ├── Makefile │ │ │ ├── cpfile.c │ │ │ ├── cpfile_infile.c │ │ │ ├── csapp.c │ │ │ ├── csapp.h │ │ │ └── fstatcheck.c │ ├── exercises.md │ └── system_io.odp ├── 201123_os_summary │ ├── exercises.md │ └── os_summary.odp ├── 201125_introduction_to_computer_network │ ├── exercises.md │ └── slides.pdf ├── 201130_application_layer_http │ ├── exercises.md │ └── slides.pdf ├── 201202_network_programming │ ├── code │ │ ├── Makefile │ │ ├── csapp.c │ │ ├── csapp.h │ │ ├── hostinfo.c │ │ └── netpfragments.c │ ├── code_echo │ │ ├── Makefile │ │ ├── csapp.c │ │ ├── csapp.h │ │ ├── echo.c │ │ ├── echoclient.c │ │ ├── echoserveri.c │ │ ├── echoserverp.c │ │ └── echoservert.c │ ├── code_iVar │ │ ├── Makefile │ │ ├── csapp.c │ │ ├── csapp.h │ │ ├── get.c │ │ ├── iVar-server.c │ │ ├── put.c │ │ └── test.sh │ ├── exercises.md │ └── slides.pdf ├── 201207_dns_bittorrent_udp │ ├── exercises.md │ ├── slides-dns.pdf │ ├── slides-p2p.pdf │ └── slides-udp.pdf ├── 201209_tcp │ ├── exercises.md │ └── slides.pdf ├── 201214_network_layer_forwarding_ip │ ├── exercises.md │ └── slides.pdf ├── 201216_network_layer_dhcp_nat_routing │ ├── exercises.md │ └── slides.pdf ├── 210104_link_layer_ethernet │ ├── exercises.md │ └── slides.pdf ├── 210106_encryption_security │ ├── exercises.md │ └── slides.pdf ├── 210111_network_security │ ├── exercises.md │ └── slides.pdf ├── 210113_cloud computers_datacenters │ ├── recap-decompilation │ │ ├── answer.c │ │ └── decompilation.prime │ └── slides.pdf └── 210115_recap │ ├── LocalityCache_slides.pdf │ ├── concurrency-protection-recap-slides.pdf │ ├── recap-network-layer.odp │ └── tcp-slides.pdf ├── relevant-material ├── README.md └── uldp17-2018-08-16.pdf ├── tools ├── README.md ├── linux.md ├── macos.md ├── vm │ ├── README.md │ ├── login.sh │ ├── mount.sh │ ├── rev_mount.sh │ ├── setup_rev_mount.sh │ └── startup.sh └── windows.md └── x86prime_tools ├── gcc-online.py ├── gdb-online.py ├── install.sh ├── prasm.py ├── prerf.py ├── primify.py ├── prun.py └── uninstall.sh /assignments/A0/CompSys20-A0-polyglot.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diku-compSys/compSys-e2020-pub/2117354114df749a5327584885c88a0b3ad5f9d9/assignments/A0/CompSys20-A0-polyglot.pdf -------------------------------------------------------------------------------- /assignments/A0/CompSys20-A0.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diku-compSys/compSys-e2020-pub/2117354114df749a5327584885c88a0b3ad5f9d9/assignments/A0/CompSys20-A0.pdf -------------------------------------------------------------------------------- /assignments/A0/src.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diku-compSys/compSys-e2020-pub/2117354114df749a5327584885c88a0b3ad5f9d9/assignments/A0/src.zip -------------------------------------------------------------------------------- /assignments/A1/CompSys20-A1-polyglot.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diku-compSys/compSys-e2020-pub/2117354114df749a5327584885c88a0b3ad5f9d9/assignments/A1/CompSys20-A1-polyglot.pdf -------------------------------------------------------------------------------- /assignments/A1/CompSys20-A1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diku-compSys/compSys-e2020-pub/2117354114df749a5327584885c88a0b3ad5f9d9/assignments/A1/CompSys20-A1.pdf -------------------------------------------------------------------------------- /assignments/A1/src.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diku-compSys/compSys-e2020-pub/2117354114df749a5327584885c88a0b3ad5f9d9/assignments/A1/src.zip -------------------------------------------------------------------------------- /assignments/A2/CompSys20-A2-polyglot.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diku-compSys/compSys-e2020-pub/2117354114df749a5327584885c88a0b3ad5f9d9/assignments/A2/CompSys20-A2-polyglot.pdf -------------------------------------------------------------------------------- /assignments/A2/CompSys20-A2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diku-compSys/compSys-e2020-pub/2117354114df749a5327584885c88a0b3ad5f9d9/assignments/A2/CompSys20-A2.pdf -------------------------------------------------------------------------------- /assignments/A2/src.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diku-compSys/compSys-e2020-pub/2117354114df749a5327584885c88a0b3ad5f9d9/assignments/A2/src.zip -------------------------------------------------------------------------------- /assignments/A3/CompSys20-A3-polyglot.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diku-compSys/compSys-e2020-pub/2117354114df749a5327584885c88a0b3ad5f9d9/assignments/A3/CompSys20-A3-polyglot.pdf -------------------------------------------------------------------------------- /assignments/A3/CompSys20-A3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diku-compSys/compSys-e2020-pub/2117354114df749a5327584885c88a0b3ad5f9d9/assignments/A3/CompSys20-A3.pdf -------------------------------------------------------------------------------- /assignments/A3/src.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diku-compSys/compSys-e2020-pub/2117354114df749a5327584885c88a0b3ad5f9d9/assignments/A3/src.zip -------------------------------------------------------------------------------- /assignments/A4/CompSys20-A4.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diku-compSys/compSys-e2020-pub/2117354114df749a5327584885c88a0b3ad5f9d9/assignments/A4/CompSys20-A4.pdf -------------------------------------------------------------------------------- /assignments/A4/src.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diku-compSys/compSys-e2020-pub/2117354114df749a5327584885c88a0b3ad5f9d9/assignments/A4/src.zip -------------------------------------------------------------------------------- /assignments/A5/CompSys20-A5.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diku-compSys/compSys-e2020-pub/2117354114df749a5327584885c88a0b3ad5f9d9/assignments/A5/CompSys20-A5.pdf -------------------------------------------------------------------------------- /assignments/A5/src.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diku-compSys/compSys-e2020-pub/2117354114df749a5327584885c88a0b3ad5f9d9/assignments/A5/src.zip -------------------------------------------------------------------------------- /assignments/A6/CompSys20-A6.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diku-compSys/compSys-e2020-pub/2117354114df749a5327584885c88a0b3ad5f9d9/assignments/A6/CompSys20-A6.pdf -------------------------------------------------------------------------------- /assignments/A6/src.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diku-compSys/compSys-e2020-pub/2117354114df749a5327584885c88a0b3ad5f9d9/assignments/A6/src.zip -------------------------------------------------------------------------------- /assignments/A7/CompSys20-A7.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diku-compSys/compSys-e2020-pub/2117354114df749a5327584885c88a0b3ad5f9d9/assignments/A7/CompSys20-A7.pdf -------------------------------------------------------------------------------- /assignments/A7/src.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diku-compSys/compSys-e2020-pub/2117354114df749a5327584885c88a0b3ad5f9d9/assignments/A7/src.zip -------------------------------------------------------------------------------- /assignments/commented_report_example.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diku-compSys/compSys-e2020-pub/2117354114df749a5327584885c88a0b3ad5f9d9/assignments/commented_report_example.pdf -------------------------------------------------------------------------------- /collect-slides-in-folder.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # The following script can be used to generate a single folder with only the slides. 4 | # You need to rerun this script every time you pull new slides from the repo. 5 | 6 | # Exit immediately if any command below fails. 7 | set -e 8 | 9 | echo "Collecting slides in slides/" 10 | 11 | mkdir -p slides 12 | rm -f slides/* 13 | 14 | cd material 15 | for f in *; do 16 | cd $f 17 | for s in *.pdf; do 18 | if [[ $s != "*.pdf" ]]; then 19 | if [[ $s == "slides.pdf" ]]; then 20 | ln $s ../../slides/${f}.pdf 21 | else 22 | ln $s ../../slides/${f}-${s} 23 | fi 24 | fi 25 | done 26 | cd .. 27 | done 28 | cd .. 29 | -------------------------------------------------------------------------------- /material/.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore LibreOffice lock files. 2 | .~lock* -------------------------------------------------------------------------------- /material/200831_introduction-plus-c/01-c-intro.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diku-compSys/compSys-e2020-pub/2117354114df749a5327584885c88a0b3ad5f9d9/material/200831_introduction-plus-c/01-c-intro.pdf -------------------------------------------------------------------------------- /material/200831_introduction-plus-c/01-intro.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diku-compSys/compSys-e2020-pub/2117354114df749a5327584885c88a0b3ad5f9d9/material/200831_introduction-plus-c/01-intro.pdf -------------------------------------------------------------------------------- /material/200831_introduction-plus-c/01-overview.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diku-compSys/compSys-e2020-pub/2117354114df749a5327584885c88a0b3ad5f9d9/material/200831_introduction-plus-c/01-overview.pdf -------------------------------------------------------------------------------- /material/200831_introduction-plus-c/code/0_one_or_three: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diku-compSys/compSys-e2020-pub/2117354114df749a5327584885c88a0b3ad5f9d9/material/200831_introduction-plus-c/code/0_one_or_three -------------------------------------------------------------------------------- /material/200831_introduction-plus-c/code/0_one_or_three.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(int argc, char* argv[]) { 5 | if (argc == 2) { // 1 argument 6 | printf("One arguments: %s\n", argv[0]); 7 | return EXIT_SUCCESS; 8 | } 9 | else if (argc == 4) { // 3 arguments 10 | printf("Three arguments: %s\n", argv[0]); 11 | return EXIT_SUCCESS; 12 | } 13 | else { 14 | return EXIT_FAILURE; 15 | } 16 | } -------------------------------------------------------------------------------- /material/200831_introduction-plus-c/code/10_safe_reading.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | int main() { 6 | char input[20]; 7 | printf ("Give me a string\n"); 8 | fgets(input, sizeof(input), stdin); 9 | printf ("You wrote: %s\n", input); 10 | 11 | return EXIT_SUCCESS; 12 | } 13 | -------------------------------------------------------------------------------- /material/200831_introduction-plus-c/code/11_echo_int.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | int main() { 6 | int input; 7 | printf ("Give me a integer\n"); 8 | scanf("%d", input); 9 | printf ("You wrote: %d\n", input); 10 | 11 | return EXIT_SUCCESS; 12 | } 13 | -------------------------------------------------------------------------------- /material/200831_introduction-plus-c/code/12_int_arg.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #define BAD_INPUT 0 6 | 7 | int main(int argc, char *argv[]) { 8 | int input; 9 | 10 | if(argc == 2) { // 1st argument is the name of the program 11 | int res; 12 | res = sscanf(argv[1],"%d", &input); 13 | if (res == BAD_INPUT) { 14 | printf("Bad value\n"); 15 | } 16 | else { 17 | printf("Input was: %d\n", input); 18 | } 19 | } 20 | else { 21 | printf("Not one argument\n"); 22 | } 23 | 24 | return EXIT_SUCCESS; 25 | } 26 | -------------------------------------------------------------------------------- /material/200831_introduction-plus-c/code/13_arg_play.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #define BAD_INPUT 0 6 | 7 | int main(int argc, char *argv[]) { 8 | int input; 9 | int input2; 10 | int result; 11 | 12 | if(argc == 2) { // 1st argument is the name of the program 13 | int res; 14 | res = sscanf(argv[1],"%d and %d",&input, &input2); 15 | if (res == BAD_INPUT) { 16 | printf("Bad value\n"); 17 | } 18 | else { 19 | printf("Input: %d\n", input); 20 | result = input + input2; 21 | printf("Result: %d \n", result); 22 | } 23 | } 24 | else { 25 | printf("Not one argument\n"); 26 | } 27 | 28 | return EXIT_SUCCESS; 29 | } 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /material/200831_introduction-plus-c/code/1_one_or_three_switch.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, char* argv[]) { 4 | (void) argv; // Don't do this at home 5 | switch (argc) { 6 | case 2: 7 | return EXIT_SUCCESS; 8 | break; 9 | case 4: 10 | return EXIT_SUCCESS; 11 | break; 12 | default: 13 | return EXIT_FAILURE; 14 | break; 15 | } 16 | } -------------------------------------------------------------------------------- /material/200831_introduction-plus-c/code/2_one_or_three_switch2.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, char* argv[]) { 4 | (void) argv; // Don't do this at home 5 | switch (argc) { 6 | case 2: 7 | case 4: 8 | return EXIT_SUCCESS; 9 | break; 10 | default: 11 | return EXIT_FAILURE; 12 | break; 13 | } 14 | } -------------------------------------------------------------------------------- /material/200831_introduction-plus-c/code/3_print_args_while: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diku-compSys/compSys-e2020-pub/2117354114df749a5327584885c88a0b3ad5f9d9/material/200831_introduction-plus-c/code/3_print_args_while -------------------------------------------------------------------------------- /material/200831_introduction-plus-c/code/3_print_args_while.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(int argc, char* argv[]) { 5 | int i = 1; 6 | while (i < argc) { 7 | printf("Argument number %d: %s\n", i, argv[i]); 8 | i = i + 1; 9 | } 10 | // Implicit return EXIT_SUCCESS; -- But it is better to keep 11 | } 12 | -------------------------------------------------------------------------------- /material/200831_introduction-plus-c/code/4_print_args_for.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(int argc, char* argv[]) { 5 | for (int i = 1; i < argc; i++) { 6 | printf("Argument number %d: %s\n", i, argv[i]); 7 | } 8 | return EXIT_SUCCESS; 9 | } 10 | 11 | -------------------------------------------------------------------------------- /material/200831_introduction-plus-c/code/5_some_assignments.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | int a = 1; 6 | int b = 2 + a; 7 | a += b; // a = a + b 8 | a *= 2; 9 | a++; // a = a + 1 10 | a--; 11 | ++a; // a = a + 1 12 | printf("a is %d and b is %d\n", a, b); 13 | 14 | return EXIT_SUCCESS; 15 | } 16 | -------------------------------------------------------------------------------- /material/200831_introduction-plus-c/code/6_sideeffects: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diku-compSys/compSys-e2020-pub/2117354114df749a5327584885c88a0b3ad5f9d9/material/200831_introduction-plus-c/code/6_sideeffects -------------------------------------------------------------------------------- /material/200831_introduction-plus-c/code/6_sideeffects.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | int a = 3; 6 | int b = 5; 7 | int c = a++ + ++b; 8 | printf("a = %d\n", a); 9 | printf("b = %d\n", b); 10 | printf("c = %d\n", c); 11 | 12 | return EXIT_SUCCESS; 13 | } -------------------------------------------------------------------------------- /material/200831_introduction-plus-c/code/7_sideeffects: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diku-compSys/compSys-e2020-pub/2117354114df749a5327584885c88a0b3ad5f9d9/material/200831_introduction-plus-c/code/7_sideeffects -------------------------------------------------------------------------------- /material/200831_introduction-plus-c/code/7_sideeffects2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | int a = 3; 6 | int b = 5; 7 | int c = -2; 8 | a += (c = a++ - (b += --c) + ++b); 9 | printf("a = %d\n", a); 10 | printf("b = %d\n", b); 11 | printf("c = %d\n", c); 12 | 13 | return EXIT_SUCCESS; 14 | } -------------------------------------------------------------------------------- /material/200831_introduction-plus-c/code/8_array_inc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diku-compSys/compSys-e2020-pub/2117354114df749a5327584885c88a0b3ad5f9d9/material/200831_introduction-plus-c/code/8_array_inc -------------------------------------------------------------------------------- /material/200831_introduction-plus-c/code/8_array_inc.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | int a[16]; 6 | int b = 2; 7 | a[0] = 1; 8 | for (int i = 1; i <= 18; i++) { 9 | a[i] = a[i-1] + 1; 10 | } 11 | printf("final = %d\n", a[15]); 12 | printf("final b = %d\n", b); 13 | 14 | return EXIT_SUCCESS; 15 | } 16 | -------------------------------------------------------------------------------- /material/200831_introduction-plus-c/code/9_echo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diku-compSys/compSys-e2020-pub/2117354114df749a5327584885c88a0b3ad5f9d9/material/200831_introduction-plus-c/code/9_echo -------------------------------------------------------------------------------- /material/200831_introduction-plus-c/code/9_echo.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | char input[8]; 6 | printf ("Give me a string\n"); 7 | scanf("%s", input); 8 | printf ("You wrote: %s\n", input); 9 | 10 | return EXIT_SUCCESS; 11 | } 12 | -------------------------------------------------------------------------------- /material/200831_introduction-plus-c/code/Makefile: -------------------------------------------------------------------------------- 1 | # For usage run: 2 | # make [programname] 3 | # You should not include the ".c" part of the file name. 4 | # Result would that make would say "Nothing to do" 5 | # Run your run your program by: 6 | # ./programname 7 | 8 | # OS X users should use additionally gcc-X, gcc will invoke the Clang compiler 9 | CC=gcc-9 10 | CFLAGS=-std=c11 -Wall -Werror -Wextra -pedantic 11 | 12 | .PHONY: clean all 13 | 14 | %.o: %.c 15 | $(CC) $(CFLAGS) -o $@ -c $< 16 | 17 | # No cleaning up!!! Be aware of this... 18 | -------------------------------------------------------------------------------- /material/200831_introduction-plus-c/code_more/Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS=-Wall -Wextra -pedantic -std=c11 2 | 3 | helloworld: helloworld.c 4 | gcc helloworld.c -o helloworld $(CFLAGS) 5 | 6 | error: error.c 7 | gcc error.c -o error $(CFLAGS) 8 | 9 | args: args.c 10 | gcc args.c -o args $(CFLAGS) 11 | 12 | sum: sum.c 13 | gcc sum.c -o sum $(CFLAGS) 14 | 15 | roll: roll.c 16 | gcc roll.c -o roll $(CFLAGS) 17 | -------------------------------------------------------------------------------- /material/200831_introduction-plus-c/code_more/args.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, char* argv[]) { 4 | printf("argc: %d\n", argc); 5 | for (int i = 0; i < argc; i++) { 6 | char* arg = argv[i]; 7 | printf("%s", arg); 8 | printf("\n"); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /material/200831_introduction-plus-c/code_more/error.c: -------------------------------------------------------------------------------- 1 | int main() { 2 | return 1; 3 | } 4 | -------------------------------------------------------------------------------- /material/200831_introduction-plus-c/code_more/helloworld.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | printf("Hello, world!\n"); 5 | } 6 | -------------------------------------------------------------------------------- /material/200831_introduction-plus-c/code_more/roll.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main(int argc, char* argv[]) { 6 | srand(time(NULL)); 7 | 8 | // NdM 3d6 2d8 9 | 10 | int dice_dices[argc-1]; 11 | int dice_sides[argc-1]; 12 | 13 | for (int i = 1; i < argc; i++) { 14 | int num_dice; 15 | int num_sides; 16 | if (sscanf(argv[i], "%dd%d", &num_dice, &num_sides) == 2) { 17 | dice_dices[i-1] = num_dice; 18 | dice_sides[i-1] = num_sides; 19 | } else { 20 | printf("Not a dice roll: %s\n", argv[i]); 21 | return 1; 22 | } 23 | } 24 | 25 | for (int i = 0; i < argc-1; i++) { 26 | int sum = 0; 27 | for (int j = 0; j < dice_dices[i]; j++) { 28 | int x = rand() % dice_sides[i] + 1; 29 | sum = sum + x; 30 | } 31 | printf("Rolled %d %d-sided dice; sum: %d\n", 32 | dice_dices[i], dice_sides[i], sum); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /material/200831_introduction-plus-c/code_more/sum.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(int argc, char* argv[]) { 5 | int sum = 0; 6 | for (int i = 1; i < argc; i++) { 7 | int x; 8 | if (sscanf(argv[i], "%d", &x) == 1) { 9 | sum = sum + x; 10 | } else { 11 | printf("Not an integer: %s\n", argv[i]); 12 | return 1; 13 | } 14 | } 15 | printf("%d\n", sum); 16 | } 17 | -------------------------------------------------------------------------------- /material/200831_introduction-plus-c/exercises.md: -------------------------------------------------------------------------------- 1 | # Exercises for 2020-08-31 2 | 3 | These exercises are intended to give your a first quick feeling of C 4 | and prepare you for what comes in A0. Use the exercise classes to get 5 | help. This is not part of the assignment. 6 | 7 | For all of the below, you should use `make` to build your programs. To 8 | parametrize `make` to build with all the necessary compiler flags, start by 9 | writing down a `Makefile` containing the following: 10 | 11 | ``` 12 | CC=gcc 13 | CFLAGS=-std=c11 -Wall -Werror -Wextra -pedantic -g 14 | ``` 15 | 16 | Then when you add a program `foo`, add a rule to `Makefile` as 17 | follows: 18 | 19 | ``` 20 | foo: foo.c 21 | $(CC) -o foo foo.c $(CFLAGS) 22 | ``` 23 | 24 | **Beware**: the leading whitespace *must* be a single tab character. 25 | Now, to compile `foo`, just run `make foo`. For example: 26 | 27 | ``` 28 | $ make mynameis 29 | ``` 30 | 31 | There are ways to automate parts of this, but we recommend being 32 | explicit until you get a firm grasp on what `make` does. 33 | 34 | In the following, we colloquially use "print" as slang for writing to 35 | standard output. 36 | 37 | ## Printing in C 38 | 39 | Write a C program `mynameis` that prints your name. 40 | 41 | ## Input arguments in C 42 | 43 | Write a C program `repeatme` that given a string as argument, prints 44 | the string twice on separate lines. 45 | 46 | If the program gets a number of arguments that is different from 1 it 47 | should print "`Wrong number of arguments`". 48 | 49 | ## Input argument validation 50 | 51 | Write a C program that `noAs` that given a string as argument, does 52 | either of the following. 53 | 54 | * If the first character of the string is an the `char` `A` it 55 | prints "`No beginning A's are allowed`", 56 | 57 | * otherwise it prints the given string. 58 | 59 | Reminder: Consider how strings are formatted in C. 60 | 61 | Note: reuse your argument validation from before. You can just as well 62 | learn it from the beginning. _Always sanitise your input._ 63 | 64 | ## Multiple input formats 65 | 66 | Modify the `dice` program developed at lecture to support `dN` as 67 | alternative notation for `1dN`. Hint: if one `sscanf()` fails, try 68 | another. 69 | 70 | ## Guessing game 71 | 72 | Write a C program that on startup generates a random number with 73 | `rand()`, and then asks the user to guess it, answering either "too 74 | low" or "too high" when the user guesses wrong. Take care to handle 75 | non-numeric user input in a sensible way. _Always sanitise your 76 | input._ 77 | -------------------------------------------------------------------------------- /material/200902_bits-bytes-words/code/io.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void bits(FILE* f, char b) { 5 | for (int i = 7; i >= 0; i--) { 6 | if ((b>>i) & 1) { 7 | fprintf(f, "1"); 8 | } else { 9 | fprintf(f, "0"); 10 | } 11 | } 12 | } 13 | 14 | int main(int argc, char* argv[]) { 15 | assert(argc == 3); 16 | 17 | char* input_filename = argv[1]; 18 | char* output_filename = argv[2]; 19 | 20 | FILE* f_in = fopen(input_filename, "r"); 21 | FILE* f_out = fopen(output_filename, "w"); 22 | 23 | assert(f_in != NULL); 24 | assert(f_out != NULL); 25 | 26 | int i = 0; 27 | while (1) { 28 | char b; 29 | int read = fread(&b, 1, 1, f_in); 30 | 31 | if (read == 0) { 32 | break; 33 | } 34 | 35 | fprintf(f_out, "Byte #%d: ", i); 36 | bits(f_out, b); 37 | fprintf(f_out, "\n"); 38 | i++; 39 | } 40 | 41 | fwrite(&i, sizeof(i), 1, f_out); 42 | 43 | fclose(f_in); 44 | fclose(f_out); 45 | } 46 | -------------------------------------------------------------------------------- /material/200902_bits-bytes-words/exercises.md: -------------------------------------------------------------------------------- 1 | # Exercises for 2020-09-02 2 | 3 | You can find an example of a C program using I/O under code. 4 | 5 | ## Integer representation 6 | Play with integer representation. Try to get `0xA` correct on the different "levels". 7 | 8 | http://topps.diku.dk/compsys/integers.html 9 | 10 | ## File check 11 | 12 | Write a C program `fileexist` that given a filename checks if it can 13 | read the file and prints a reasonable status message. 14 | 15 | ## File printing 16 | 17 | Write a C program `fileecho` that given a filename opens the file in 18 | read-only mode, reads its content and prints it. 19 | 20 | ## File content validation 21 | 22 | Write a C program `noAshere` that given a filename (formatted as a 23 | string) opens the file in read-only mode, reads its content and 24 | checks if it contains any character `A`. If it contains an `A` print 25 | "`No A's are allowed`" otherwise print "`Ok`". 26 | 27 | ## File copying 28 | 29 | Write a C program `filecopy` that given two filenames copies the 30 | contents of the former to the latter. The program should fail if the 31 | target file already exists. Note that this differs from what `cp` 32 | does. 33 | 34 | ## Simple Caesar Cipher (bonus) 35 | 36 | Write a C program `caesar` that is given a string as argument (we will 37 | treat this as a plain text) prints the string where all characters are 38 | replaced with the character with one higher `char` value. 39 | 40 | The standard Caesar cipher (also called shift cipher), used for 41 | communicating secret messages in ancient times, shifts all letters _n_ 42 | places in the alphabet, where _n_ then is the secret key. For 43 | simplicity we have here fixed _n_ to 1 and do not use consider the 44 | alphabet a finite field. 45 | 46 | If you are interested, you can read more at 47 | [https://learncryptography.com/classical-encryption/caesar-cipher](https://learncryptography.com/classical-encryption/caesar-cipher) 48 | 49 | ### Extras 50 | 51 | You are welcome to extend this with 52 | 53 | * an extra argument that is read to an integer, such you can 54 | implement the full Caesar cipher, 55 | 56 | * a flag (e.g. argument "-enc" and "-dec"), such that you program 57 | can perform encryption and decryption, 58 | 59 | * reading plain text from a filename and writing it to a different 60 | filename, 61 | 62 | * ensure that you only use the letters of the ASCII table; ensure 63 | that the case of each letter is preserved. 64 | -------------------------------------------------------------------------------- /material/200902_bits-bytes-words/slides.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diku-compSys/compSys-e2020-pub/2117354114df749a5327584885c88a0b3ad5f9d9/material/200902_bits-bytes-words/slides.pdf -------------------------------------------------------------------------------- /material/200907_arithmetic/slides.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diku-compSys/compSys-e2020-pub/2117354114df749a5327584885c88a0b3ad5f9d9/material/200907_arithmetic/slides.pdf -------------------------------------------------------------------------------- /material/200907_arithmetic/ternary/Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | CFLAGS =-Wall -Wextra -pedantic -std=gnu11 3 | 4 | all : ternary.o 5 | 6 | rebuild : clean all 7 | 8 | ternary.o : bcd.c bcd.h 9 | $(CC) $(CFLAGS) -c $< -o $@ 10 | 11 | clean : 12 | rm -rf *.o 13 | -------------------------------------------------------------------------------- /material/200907_arithmetic/ternary/ternary.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "ternary.h" 4 | 5 | ternary toTernary(unsigned long input) { 6 | // UPDATE WITH YOUR CODE 7 | ternary b; 8 | return b; 9 | } 10 | 11 | unsigned long fromTernary(ternary b) { 12 | // UPDATE WITH YOUR CODE 13 | return 0; 14 | } 15 | 16 | ternary addTernary(ternary a, ternary b) { 17 | // UPDATE WITH YOUR CODE 18 | ternary res; 19 | return res; 20 | } 21 | -------------------------------------------------------------------------------- /material/200907_arithmetic/ternary/ternary.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | typedef struct ternary { 4 | unsigned long val; 5 | } ternary; 6 | 7 | /** 8 | * Converts a two-complement unsigned long to a BCD number 9 | **/ 10 | ternary toTernary(unsigned long i); 11 | 12 | /** 13 | * Converts a 14 | **/ 15 | unsigned long fromTernary(ternary b); 16 | 17 | 18 | /** 19 | * Adds two values of bcd representation a and b, and returns the result. 20 | **/ 21 | ternary addTernary(ternary a, ternary b); 22 | -------------------------------------------------------------------------------- /material/200907_arithmetic/ternary/test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "ternary.h" 3 | 4 | #define ARGNUM 1 5 | 6 | int main(int argc, char**argv) { 7 | if (argc != ARGNUM + 1) { 8 | printf("Usage:"); 9 | printf(" %s [filename]\n", (argv[0]+2)); 10 | printf(" Filename: a file containing a stream of line separated hex-addresses"); 11 | return(0); 12 | } 13 | 14 | //TODO: Make some test 15 | 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /material/200909_pointers-and-memory/exercise_code/array.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int update (int *arr, int size); 5 | 6 | #define SIZE 10 7 | 8 | int main() { 9 | int x[SIZE]; 10 | 11 | // Initialize array 12 | for (int c = 0 ; c < SIZE ; c++) { 13 | x[c] = c * 2; 14 | } 15 | 16 | // Do some random updates to an array 17 | update((int*) &x, SIZE); 18 | 19 | // Print the elements 20 | for (int c = 0 ; c < SIZE ; c++) { 21 | printf("%d\n", x[c]); 22 | } 23 | 24 | return EXIT_SUCCESS; 25 | } 26 | 27 | int update (int *arr, int size) { 28 | for (int i = 0 ; i < size ; i++) { 29 | arr[i] += i; 30 | update(arr+i, size-1); 31 | } 32 | return 1; 33 | } 34 | -------------------------------------------------------------------------------- /material/200909_pointers-and-memory/exercise_code/capitalize.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // Inline capitalisation of an input text. 5 | 6 | int main(int argc, char *argv[]) { 7 | if (argc != 2) { 8 | fprintf(stderr, "Usage: %s argument\n", argv[0]); 9 | return EXIT_FAILURE; 10 | } 11 | 12 | char *str = argv[1]; 13 | 14 | printf("Input string: %s\n", str); 15 | 16 | while (*str != 0) { 17 | if (97 <= *str && *str <= 122) { 18 | str -= 32; 19 | } 20 | str++; 21 | } 22 | printf("Capitalised string: %s\n", argv[1]); 23 | return EXIT_SUCCESS; 24 | 25 | } 26 | -------------------------------------------------------------------------------- /material/200909_pointers-and-memory/exercise_code/hello.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(int argc, char *argv[]) { 5 | if (argc != 2) { 6 | fprintf(stderr, "Usage: %s argument\n", argv[0]); 7 | return EXIT_FAILURE; 8 | } 9 | 10 | char *hello = "hello"; 11 | *hello = 'H'; 12 | 13 | fprintf(stdout, "%s, %s!\n", hello, argv[1]); 14 | 15 | return EXIT_SUCCESS; 16 | } 17 | -------------------------------------------------------------------------------- /material/200909_pointers-and-memory/exercise_code/table.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define HEIGHT 1000 5 | #define WIDTH 10 6 | 7 | int updateElement (int* table, int row, int col, int value); 8 | 9 | int main() { 10 | int table[HEIGHT][WIDTH]; 11 | 12 | for (int h = 0 ; h < HEIGHT ; h++) { 13 | for (int w = 0 ; w < WIDTH ; w++) { 14 | table[w*h][h] = w*h; 15 | } 16 | } 17 | 18 | // print table[5][5] 19 | printf("Element 5,5: %d\n", table[5][5]); 20 | return EXIT_SUCCESS; 21 | } 22 | -------------------------------------------------------------------------------- /material/200909_pointers-and-memory/exercises.md: -------------------------------------------------------------------------------- 1 | # Exercises for 2020-09-09 2 | 3 | Author: Michael Kirkedal Thomsen 4 | 5 | These exercises will to give you some experience with using GDB. 6 | 7 | --- 8 | 9 | ## Play with GDB 10 | 11 | Take some of the programs from last weeks exercises or perhaps even 12 | the assignment and play around with GDB. Recreate a bug that you had 13 | in your program and try finding it with GDB. Test most of the 14 | commands on the [GDB QUICK REFERENCE 15 | sheet](https://sourceware.org/gdb/current/onlinedocs/refcard.pdf.gz) 16 | (which can also be found in today's exercise folder). 17 | 18 | ## Debug some programs 19 | 20 | [Attached](exercise_code/) there is a list of programs containing some 21 | different bugs. Some of them very obvious. Use GDB to identify and 22 | profile the bugs. Record your approach in a GDB script. 23 | 24 | We recommend to investigate in the following order: 25 | 26 | * `hello.c` 27 | * `table.c` 28 | * `capitalize.c` 29 | * `array.c` 30 | 31 | ## Play with floating points 32 | 33 | Integers are by now way too easy. Don't miss the [Floating point 34 | game](http://topps.diku.dk/compsys/floating-point.html). 35 | -------------------------------------------------------------------------------- /material/200909_pointers-and-memory/gdb/Makefile: -------------------------------------------------------------------------------- 1 | # OS X users should use additionally gcc-6, gcc will invoke the Clang compiler 2 | CC=gcc-10 3 | CFLAGS=-std=c11 -Wall -Werror -Wextra -pedantic 4 | PROGRAMS=macro lastchar segfault 5 | # LIBS=myio.c 6 | 7 | .PHONY: clean all 8 | 9 | all: 10 | make $(PROGRAMS) 11 | 12 | macro: macro.c 13 | $(CC) $(CFLAGS) -g -o $@ $< 14 | 15 | lastchar: lastchar.c 16 | $(CC) $(CFLAGS) -g -o $@ $< 17 | 18 | segfault: segfault.c 19 | $(CC) $(CFLAGS) -g -o $@ $< 20 | 21 | clean: 22 | rm -f $(PROGRAMS) 23 | # Needed to clean OS X debug information} 24 | rm -fr $(foreach prg,$(PROGRAMS),$(prg).dSYM) 25 | -------------------------------------------------------------------------------- /material/200909_pointers-and-memory/gdb/foo.txt: -------------------------------------------------------------------------------- 1 | CompSys -------------------------------------------------------------------------------- /material/200909_pointers-and-memory/gdb/lastchar.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | 6 | int main(int argc, char *argv[]) { 7 | if (argc != 2) { // 1 argument 8 | printf("Usage %s filename\n", argv[0]); 9 | return EXIT_SUCCESS; 10 | } 11 | 12 | FILE* fp; 13 | fp = fopen(argv[1], "r"); 14 | 15 | if (errno == 0) { 16 | printf("File: %s was found, status: %d\n", argv[1], errno); 17 | 18 | char last; 19 | char cur; 20 | cur = fgetc(fp); 21 | while (!feof(fp)) { 22 | last = cur; 23 | cur = fgetc(fp); 24 | } 25 | printf("The last char was: %c\n", last); 26 | 27 | fclose(fp); 28 | } 29 | else { 30 | printf("Reading %s resulted in error %d\n", argv[1], errno); 31 | } 32 | 33 | return EXIT_SUCCESS; 34 | } -------------------------------------------------------------------------------- /material/200909_pointers-and-memory/gdb/macro.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define square(x) ((x)*(x)) 4 | 5 | int main() { 6 | int a = square(3+5); 7 | int b = a*2; 8 | int c = b/4; 9 | printf("%d\n", c); 10 | return 0; 11 | } 12 | 13 | int fadd(int a, int b) { 14 | return a + b; 15 | } 16 | -------------------------------------------------------------------------------- /material/200909_pointers-and-memory/gdb/segfault.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int tester(int* c, int k); 5 | int update(int* c, int k, int v); 6 | 7 | int main() { 8 | int i, k; 9 | int x[1000]; 10 | 11 | for(i = 0; i < 1000; ++i){ 12 | update(x, i, i); 13 | } 14 | 15 | printf("Enter integer in 0..9999: "); 16 | scanf("%d", &k); 17 | 18 | tester(x, k); 19 | } 20 | 21 | int tester(int* c, int k) { 22 | printf("x[%d] = %d\n", k, c[k]); 23 | return 1; 24 | } 25 | 26 | // Update of array c in index i with v 27 | int update(int* c, int k, int v) { 28 | int val = v*v; 29 | // By accidence, I swap the index and the value 30 | // c[val] = k; 31 | c[k] = val; 32 | return 1; 33 | } -------------------------------------------------------------------------------- /material/200909_pointers-and-memory/gdb_pointers.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diku-compSys/compSys-e2020-pub/2117354114df749a5327584885c88a0b3ad5f9d9/material/200909_pointers-and-memory/gdb_pointers.pdf -------------------------------------------------------------------------------- /material/200909_pointers-and-memory/gdb_reference.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diku-compSys/compSys-e2020-pub/2117354114df749a5327584885c88a0b3ad5f9d9/material/200909_pointers-and-memory/gdb_reference.pdf -------------------------------------------------------------------------------- /material/200909_pointers-and-memory/lecture_code/Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS=-Wall -Wextra -pedantic -g 2 | CC=gcc 3 | 4 | pointers: pointers.c 5 | $(CC) pointers.c -o pointers $(CFLAGS) 6 | 7 | strings: strings.c 8 | $(CC) strings.c -o strings $(CFLAGS) 9 | 10 | copyinput: funpointers.c 11 | $(CC) funpointers.c -o funpointers $(CFLAGS) 12 | -------------------------------------------------------------------------------- /material/200909_pointers-and-memory/lecture_code/funpointers.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | void print_int_arr(int* numbers, int n) { 7 | for (int i = 0; i < n; i++) { 8 | printf("%d\n", numbers[i]); 9 | } 10 | } 11 | 12 | void print_float_arr(float* numbers, int n) { 13 | for (int i = 0; i < n; i++) { 14 | printf("%f\n", numbers[i]); 15 | } 16 | } 17 | 18 | typedef void (*printer)(void*); 19 | 20 | void print_arr(void* arr, int n, int elem_size, 21 | printer f) { 22 | char* arr_c = (char*) arr; 23 | for (int i = 0; i < n; i++) { 24 | (*f)((void*)(arr_c + i * elem_size)); 25 | } 26 | } 27 | 28 | void float_printer(void* p) { 29 | float* px = (float*) p; 30 | float x = *px; 31 | printf("%f\n", x); 32 | } 33 | 34 | int cmp_float(const void* px, const void* py) { 35 | float x = *(float*)px; 36 | float y = *(float*)py; 37 | if (x < y) { 38 | return -1; 39 | } else if (x > y) { 40 | return 1; 41 | } else { 42 | return 0; 43 | } 44 | } 45 | 46 | int main() { 47 | int numbers[10]; 48 | for (int i = 0; i < 10; i++) { 49 | numbers[i] = rand(); 50 | } 51 | 52 | print_int_arr(numbers, 10); 53 | 54 | float floats[10]; 55 | for (int i = 0; i < 10; i++) { 56 | floats[i] = rand(); 57 | } 58 | 59 | print_float_arr(floats, 10); 60 | 61 | printf("\nunsorted:\n"); 62 | print_arr(floats, 10, sizeof(float), 63 | &float_printer); 64 | 65 | printf("\nsorted:\n"); 66 | qsort(floats, 10, sizeof(float), 67 | cmp_float); 68 | print_arr(floats, 10, sizeof(float), 69 | &float_printer); 70 | 71 | printf("&float_printer: %p\n", (void*)&float_printer); 72 | } 73 | -------------------------------------------------------------------------------- /material/200909_pointers-and-memory/lecture_code/pointers.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | 5 | int main() { 6 | char* c = "test"; 7 | 8 | while (*c != 0) { 9 | printf("%s\n", c); 10 | c++; 11 | } 12 | 13 | 14 | int y = 0; 15 | int x = 2; 16 | int *yptr = &y; 17 | int *xptr = &x; 18 | *xptr += 5; 19 | printf("x = %i\n", x); 20 | y = 5 + (*xptr); 21 | 22 | printf("y = %i\n", y); 23 | printf("xptr = %p\n", (void *) xptr); 24 | printf("yadder = %p\n", (void *) &y); 25 | 26 | 27 | printf("yptr = %p\n", (void *) yptr); 28 | yptr--; 29 | *yptr -=3; 30 | printf("yptr++ = %p\n", (void *) yptr); 31 | 32 | printf("x = %i\n", x); 33 | 34 | int *cptr = (int *) &c; 35 | printf("c1 %i\n", *cptr); 36 | 37 | 38 | } 39 | -------------------------------------------------------------------------------- /material/200909_pointers-and-memory/lecture_code/pointers_old.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void recurse(int i) { 5 | int x; 6 | printf("&x: %p\n", (void*)&x); 7 | if (i > 0) { 8 | recurse(i-1); 9 | } 10 | } 11 | 12 | void fun_arr(char bytes[]) { 13 | printf("sizeof(bytes) = %d\n", (int)sizeof(bytes)); 14 | } 15 | 16 | int main() { 17 | int x = 22; 18 | int* px = &x; 19 | 20 | printf("x: %d\n", x); 21 | printf("px: %p\n", (void*)px); 22 | printf("*px: %d\n", *px); 23 | 24 | recurse(10); 25 | 26 | char bytes[sizeof(int)]; 27 | memcpy(bytes, &x, sizeof(int)); 28 | 29 | for (unsigned int i = 0; i < sizeof(int); i++) { 30 | printf("%d\n", bytes[i]); 31 | } 32 | 33 | printf("sizeof(bytes) = %d\n", (int)sizeof(bytes)); 34 | fun_arr(bytes); 35 | 36 | printf("&bytes = %p\n", (void*)&bytes); 37 | printf("&bytes[0] = %p\n", (void*)&bytes[0]); 38 | printf("&bytes[1] = %p\n", (void*)&bytes[1]); 39 | } 40 | -------------------------------------------------------------------------------- /material/200909_pointers-and-memory/lecture_code/strings.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int stringlength(char* s) { 5 | int count = 0; 6 | while (s[count] != 0) { 7 | count++; 8 | } 9 | return count; 10 | } 11 | 12 | int main(int argc, char** argv) { 13 | int sum = 0; 14 | for (int i = 1; i < argc; i++) { 15 | sum += stringlength(argv[i]); 16 | } 17 | 18 | char res[sum+1]; 19 | res[sum] = '\0'; 20 | int x = 0; 21 | 22 | for (int i = 1; i < argc; i++) { 23 | int n = stringlength(argv[i]); 24 | for (int j = 0; j < n; j++) { 25 | res[x] = argv[i][j]; 26 | x++; 27 | } 28 | } 29 | 30 | printf("%s\n", res); 31 | } 32 | -------------------------------------------------------------------------------- /material/200909_pointers-and-memory/pointers_and_memory.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diku-compSys/compSys-e2020-pub/2117354114df749a5327584885c88a0b3ad5f9d9/material/200909_pointers-and-memory/pointers_and_memory.pdf -------------------------------------------------------------------------------- /material/200914_basic_instructions/code/Makefile: -------------------------------------------------------------------------------- 1 | 2 | CC = gcc 3 | OFLAGS = -Og 4 | CFLAGS = $(OFLAGS) -Wall -g 5 | CINC = 6 | 7 | .SUFFIXES: .c .s .o .d 8 | 9 | # Compile a C program to assembler. ".s" is the common file extension. 10 | %.s:%.c 11 | $(CC) $(OFLAGS) $(CINC) -S $(F64) $*.c -o $*.s 12 | 13 | # Generate a hex-dump from a C program 14 | %.d:%.c 15 | $(CC) $(CFLAGS) $(CINC) $(F64) $*.c -o $* 16 | objdump -d $* > $*.d 17 | rm -f $* 18 | 19 | # Compile the sum program 20 | sum: sum.c 21 | $(CC) $(CFLAGS) $(CINC) $(F64) sum.c -o sum 22 | 23 | # Clean up after yourself 24 | clean: 25 | rm -f *~ *.s *.d sum *.hex *.prime *.sym 26 | -------------------------------------------------------------------------------- /material/200914_basic_instructions/code/arith.c: -------------------------------------------------------------------------------- 1 | long plus(long x, long y) { 2 | return x+y; 3 | } 4 | 5 | long arith (long x, long y, long z) { 6 | long t1 = x+y; 7 | long t2 = z+t1; 8 | long t3 = x+4; 9 | long t4 = y * 48; 10 | long t5 = t3 + t4; 11 | long rval = t2 * t5; 12 | return rval; 13 | } 14 | 15 | long m12(long x) { 16 | return 12*x; 17 | } 18 | 19 | long scale(long x, long y, long z) { 20 | return x + 8*y + 4; 21 | } 22 | -------------------------------------------------------------------------------- /material/200914_basic_instructions/code/sum.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | long plus(long x, long y) { 5 | return x + y; 6 | } 7 | 8 | void sumstore(long x, long y, long *dest) 9 | { 10 | long t = plus(x, y); 11 | *dest = t; 12 | } 13 | 14 | int main(int argc, char *argv[]) { 15 | long x = atoi(argv[1]); 16 | long y = atoi(argv[2]); 17 | long z; 18 | sumstore(x, y, &z); 19 | printf("%ld + %ld --> %ld\n", x, y, z); 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /material/200914_basic_instructions/code/swap.c: -------------------------------------------------------------------------------- 1 | void swap(long *xp, long *yp) 2 | { 3 | long t0 = *xp; 4 | long t1 = *yp; 5 | *xp = t1; 6 | *yp = t0; 7 | } 8 | 9 | -------------------------------------------------------------------------------- /material/200914_basic_instructions/exercises.md: -------------------------------------------------------------------------------- 1 | # Exercises for 14/9-2019 2 | 3 | Author: Michael Kirkedal Thomsen 4 | 5 | These exercises will: 6 | * Recap basic instructions 7 | * Translation of C to assembler and x86prime 8 | * Work with assembler in C 9 | 10 | ## Memory calculation and operation on register file 11 | * BOH 3.1 (page 218) 12 | * BOH 3.2 (page 221) 13 | * BOH 3.3 (page 222) 14 | * BOH 3.8 (page 230) 15 | 16 | ## Understanding translations 17 | * BOH 3.5 (page 225) 18 | * BOH 3.10 (page 232) 19 | * BOH 3.11 (page 233) 20 | 21 | ### More compilation quirks 22 | `a_sum.c` is a simple function calculating five times the sum of a `0` terminated list of `long`s using pointer arithmetic. Using `x86prime`, this is translated into x86prime assembly code in `a_sum.prime`. 23 | * Locate the non-control statements of `a_sum.c` (lines 4, 5, 7, 8 and 9) in `a_sum.prime`. For each, what differs from the expected translation and try to consider why? 24 | 25 | Remember that: 26 | - function parameter registers are `%rdi`, `%rsi`, and so on (BOH p. 216). 27 | - return value register is `%rax` (BOH p. 216). 28 | - in x86prime, %r11 is the return address register. 29 | 30 | Note: for now, please ignore lines 3-4 and 15-16 of `a_sum.prime`, as these instructions relate to the stack pointer, which we will save for later. 31 | -------------------------------------------------------------------------------- /material/200914_basic_instructions/exercises_code/Makefile: -------------------------------------------------------------------------------- 1 | # replace prime_dir with path to your own installation of x86prime 2 | prime_dir = ~/x86prime 3 | 4 | primify = $(prime_dir)/primify 5 | prasm = $(prime_dir)/prasm 6 | prun = $(prime_dir)/prun 7 | 8 | GCC = gcc -S -O3 -fno-optimize-sibling-calls 9 | 10 | 11 | all: a_sum.hex 12 | 13 | 14 | a_sum.s: a_sum.c 15 | $(GCC) a_sum.c 16 | 17 | 18 | a_sum.prime: a_sum.s 19 | $(primify) a_sum.s && rm -f a_sum.s 20 | 21 | 22 | a_sum.hex: a_sum.prime 23 | $(prasm) a_sum.prime 24 | 25 | 26 | run_a_sum: a_sum.hex 27 | $(prun) a_sum.hex plus -show 28 | 29 | 30 | 31 | clean: 32 | rm -f *.s *.prime *.hex *.sym 33 | -------------------------------------------------------------------------------- /material/200914_basic_instructions/exercises_code/a_sum.c: -------------------------------------------------------------------------------- 1 | // Calculated five times the sum of a `0` terminated list of `long`s using pointer arithmetic 2 | 3 | long plus(long *a) { 4 | long sum = 0; 5 | long tmp = *a; 6 | while (tmp != 0) { 7 | sum += 5*tmp; 8 | a++; 9 | tmp = *a; 10 | } 11 | return sum; 12 | } 13 | -------------------------------------------------------------------------------- /material/200914_basic_instructions/exercises_code/a_sum.prime: -------------------------------------------------------------------------------- 1 | plus: 2 | .LFB0: 3 | subq $8, %rsp 4 | movq %r11, (%rsp) 5 | movq (%rdi), %rax 6 | xorq %r8d, %r8d 7 | cbe $0,%rax,.L1 8 | .L3: 9 | leaq (%rax, %rax, 4), %rax 10 | addq $8, %rdi 11 | addq %rax, %r8 12 | movq (%rdi), %rax 13 | cbne $0,%rax,.L3 14 | .L1: 15 | movq %r8, %rax 16 | movq (%rsp), %r11 17 | addq $8, %rsp 18 | ret %r11 19 | .LFE0: 20 | -------------------------------------------------------------------------------- /material/200914_basic_instructions/exercises_code/decode1.s: -------------------------------------------------------------------------------- 1 | .type decode1, @function 2 | .cfi_startproc 3 | decode1: 4 | movq (%rdi), %r8 5 | movq (%rsi), %rcx 6 | movq (%rdx), %rax 7 | movq %r8, (%rsi) 8 | movq %rcx, (%rdx) 9 | movq %rax, (%rdi) 10 | ret 11 | .cfi_endproc 12 | -------------------------------------------------------------------------------- /material/200914_basic_instructions/slides.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diku-compSys/compSys-e2020-pub/2117354114df749a5327584885c88a0b3ad5f9d9/material/200914_basic_instructions/slides.pdf -------------------------------------------------------------------------------- /material/200916_control_instructions/code/p.c: -------------------------------------------------------------------------------- 1 | long power(long n, long p) { 2 | long res; 3 | if (p == 1) { 4 | res = 1; 5 | } 6 | else { 7 | res = power(n, p-1); 8 | } 9 | res = res * n; 10 | return res; 11 | } 12 | -------------------------------------------------------------------------------- /material/200916_control_instructions/code/p.prime: -------------------------------------------------------------------------------- 1 | power: 2 | subq $16, %rsp 3 | movq %r11, 8(%rsp) 4 | movq %rbx, (%rsp) 5 | movq %rdi, %rbx 6 | movq %rsi, %rax 7 | cbe $1, %rsi, .L2 8 | leaq -1(%rsi), %rsi 9 | call power, %r11 10 | .L2: 11 | imulq %rbx, %rax 12 | movq (%rsp), %rbx 13 | movq 8(%rsp), %r11 14 | addq $16, %rsp 15 | ret %r11 16 | -------------------------------------------------------------------------------- /material/200916_control_instructions/code/p.s: -------------------------------------------------------------------------------- 1 | .file "pow.c" 2 | .text 3 | .globl power 4 | .type power, @function 5 | power: 6 | .LFB0: 7 | .cfi_startproc 8 | pushq %rbx 9 | .cfi_def_cfa_offset 16 10 | .cfi_offset 3, -16 11 | movq %rdi, %rbx 12 | movq %rsi, %rax 13 | cmpq $1, %rsi 14 | je .L2 15 | leaq -1(%rsi), %rsi 16 | call power 17 | .L2: 18 | imulq %rbx, %rax 19 | popq %rbx 20 | .cfi_def_cfa_offset 8 21 | ret 22 | .cfi_endproc 23 | .LFE0: 24 | .size power, .-power 25 | .ident "GCC: (Debian 6.3.0-18+deb9u1) 6.3.0 20170516" 26 | .section .note.GNU-stack,"",@progbits 27 | -------------------------------------------------------------------------------- /material/200916_control_instructions/code/recap.c: -------------------------------------------------------------------------------- 1 | 2 | 3 | // x is an array of long 4 | // i is an index into the array 5 | 6 | long weightedSumOfTwo (long *x, unsigned i) { 7 | long rval = (*x) * 7; 8 | x += i; 9 | rval += (*x)*5; 10 | return rval; 11 | } 12 | -------------------------------------------------------------------------------- /material/200916_control_instructions/code/recap.s: -------------------------------------------------------------------------------- 1 | .file "0b93edeca53a44db475acf9640f99c10.c" 2 | .text 3 | .globl weightedSumOfTwo 4 | .type weightedSumOfTwo, @function 5 | weightedSumOfTwo: 6 | .LFB0: 7 | .cfi_startproc 8 | movq (%rdi), %rdx 9 | leaq 0(,%rdx,8), %rax 10 | subq %rdx, %rax 11 | movl %esi, %esi 12 | movq (%rdi,%rsi,8), %rdx 13 | leaq (%rdx,%rdx,4), %rdx 14 | addq %rdx, %rax 15 | ret 16 | .cfi_endproc 17 | .LFE0: 18 | .size weightedSumOfTwo, .-weightedSumOfTwo 19 | .ident "GCC: (Ubuntu 5.4.0-6ubuntu1~16.04.12) 5.4.0 20160609" 20 | .section .note.GNU-stack,"",@progbits 21 | -------------------------------------------------------------------------------- /material/200916_control_instructions/exercises.md: -------------------------------------------------------------------------------- 1 | # Exercises for 16/9-2020 2 | 3 | Author: Michael Kirkedal Thomsen 4 | 5 | ## Understanding translations 6 | * 3.18 (BOH p 249) 7 | * Furthermore, rewrite the control flow to x86prime (use cbX instructions) 8 | * We assume that idivq exists 9 | * 3.23 (BOH p 258) 10 | * Furthermore, rewrite the control flow to x86prime (use cbX instructions) 11 | 12 | ## Decompilation 13 | Rewrite the following program to C 14 | 15 | ``` 16 | p: 17 | subq $8, %rsp 18 | movq %r11, (%rsp) 19 | movq %rdi, %rax 20 | jmp .L2 21 | .L3: 22 | addq %rsi, %rdx 23 | movq %rdx, (%rax) 24 | addq $8, %rax 25 | .L2: 26 | movq (%rax), %rdx 27 | cbl $0, %rdx, .L3 28 | subq %rdi, %rax 29 | sarq $3, %rax 30 | movq (%rsp), %r11 31 | addq $8, %rsp 32 | ret %r11 33 | ``` 34 | -------------------------------------------------------------------------------- /material/200916_control_instructions/slides.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diku-compSys/compSys-e2020-pub/2117354114df749a5327584885c88a0b3ad5f9d9/material/200916_control_instructions/slides.pdf -------------------------------------------------------------------------------- /material/200921_simple_computer/exercises.md: -------------------------------------------------------------------------------- 1 | # Opgaver til 21/9-2019 2 | 3 | Se også [Reading Material](readingMaterial.md). 4 | 5 | De øvelser der ikke nås 21/9, vil nok indgå 23/9 6 | 7 | ## Opgave 1 8 | 9 | Få installeret x86prime. Hvis du kører Windows eller Mac skal du formodentlig have 10 | fat i en virtuel maskine med Linux. 11 | 12 | Alternativt: få installeret scripts til at kalde de samme programmer på DIKUs remote 13 | server. Tjek at det virker. 14 | 15 | Se følgende anbefalinger [Tool setup](tools.md). 16 | 17 | ## Opgave 2 18 | 19 | Oversæt nedenstående C program til x86prime: 20 | ~~~ 21 | long fib(long n) { 22 | if (n < 2) return 1; 23 | return fib(n-1) + fib(n-2); 24 | } 25 | ~~~ 26 | 27 | Spg 1: Prøv først at lave oversættelsen i hånden. 28 | 29 | Spg 2: Brug dernæst gcc til at lave et x86-assembler program, 30 | og oversæt så dette program manuelt til x86prime. 31 | 32 | Spg 3: Brug x86prime til få oversat fra x86 assembler. 33 | Svarer resultatet til din manuelle oversættelse? Hvis ikke, 34 | hvad er forskellen? 35 | 36 | 37 | ## Opgave 3 38 | 39 | Byg den udleverede simulator til A2. Lav et ganske lille program 40 | der kun bruger de aritmetisk/logiske instruktioner samt STOP. 41 | Oversæt programmet med "prasm". Kør den resulterende hex file 42 | (det oversatte program) med den udleverede simulator. Ser 43 | udførelsen korrekt ud? 44 | 45 | 46 | ## Opgave 4 47 | 48 | Udfør programmet fra forrige opgave med "prun" (også kaldet 49 | reference-simulatoren). Få "prun" til at generere en sporingsfil 50 | (også kaldet en trace-file). Gentag derefter kørslen af hex filen 51 | på simulatoren til A2 og brug sporingsfilen til at tjekke om kørslen 52 | er korrekt. 53 | 54 | 55 | ## Opgave 5 56 | 57 | Indfør en brug af CALL, RET eller JMP i dit prime program. 58 | Oversæt til en hex fil, kør den med simulatoren til A2. 59 | Hvad går der galt? Eller virker det? 60 | 61 | 62 | ## Opgave 6 63 | 64 | Lav en sporingsfil (som i opgave 4) og brug den til at detektere 65 | afvigelser mellem simulatoren til A2 og reference-simulatoren. 66 | 67 | 68 | ## Opgave 7 69 | 70 | Betragt koden i kroppen af løkken i main() funktionen i main.c. 71 | Prøv at beskrive hvad de forskellige dele af koden gør. 72 | Tegningen af mikroarkitekturen (se forelæsnings slides) er ret 73 | overordnet. Man signaler er udeladt. 74 | 75 | Lav en mere detaljeret tegning af mikroarkitekturen, hvor de 76 | signaler/forbindelser der indgår i den udleverede kode er medtaget. 77 | 78 | ## Opgave 8 79 | 80 | Besøg "nandgame.com" og brug en times tid på at bygge kredsløb. 81 | Stop og vær meget stolt af dig selv, hvis du når til opbygning 82 | af aritmetisk-logiske kredsløb. 83 | 84 | 85 | -------------------------------------------------------------------------------- /material/200921_simple_computer/readingMaterial.md: -------------------------------------------------------------------------------- 1 | # Baggrundsstof 21/9 + 23/9 2 | 3 | Læs introduktion til digitallogik her: 4 | 5 | * intro: https://da.wikipedia.org/wiki/Digital_elektronik, skip fra "Større digitale kredsløb" 6 | 7 | Og følgende sider for underemner her: 8 | 9 | * https://da.wikipedia.org/wiki/Gate_(digital_elektronik), til og med "Digitale gates i praksis" 10 | * https://da.wikipedia.org/wiki/Inverter_(digital_elektronik) 11 | * https://da.wikipedia.org/wiki/Additionskredsl%C3%B8b_(digital_elektronik) 12 | * https://da.wikipedia.org/wiki/Multiplekser_(digital_elektronik) 13 | * https://da.wikipedia.org/wiki/Demultiplekser_(digital_elektronik) 14 | * https://da.wikipedia.org/wiki/Flip-flop_(digital_elektronik), skip J/K flipflop og T-flipflop. 15 | 16 | BOH omhandler også emnet i afsnit 4.2, men det er vævet sammen med bogens særlige 17 | hardvare beskrivelses-sprog, som vi ikke anvender. Det er nemmere at få lidt intro 18 | fra Wikipedias artikler ovenfor. 19 | 20 | Slides fra forelæsningerne bliver gjort tilgængelige ved selve forelæsningen 21 | eller lige efter. 22 | 23 | Læs igen: https://github.com/kirkedal/compSys-e2020-pub/blob/master/x86prime.md 24 | 25 | Læs oversigten over indkodningen af x86prime instruktioner her: https://github.com/finnschiermer/x86prime/blob/master/encoding.txt 26 | 27 | Besøg http://nandgame.com/ og brug tid på at løse opgaver der. Det er fantastisk til 28 | at få en intuition for digitallogik. "Levels" til og med "ALU" er relevante, derefter 29 | bliver det mere specifikt for lige den processor som nandgame fører frem til, og den 30 | er anderledes end x86prime. 31 | 32 | -------------------------------------------------------------------------------- /material/200921_simple_computer/slides.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diku-compSys/compSys-e2020-pub/2117354114df749a5327584885c88a0b3ad5f9d9/material/200921_simple_computer/slides.pdf -------------------------------------------------------------------------------- /material/200921_simple_computer/tools.md: -------------------------------------------------------------------------------- 1 | 2 | # Tools 3 | 4 | ## GCC 5 | Der er vigtigt at benytte de rigtige tools. For at cross-compileringen til x86prime fungerer korrekt er du nødt til at benytte `gcc` på en Linux maskine; husk at oversættelse på forskellige arkitekturer og OS's kan være meget forskelligt. Der er tre måder at gøre dette på. Du kan: 6 | 7 | * Benytte vores python-script til at oversætte koden via på en af vores servere. [gcc-online.py](https://github.com/kirkedal/compSys-e2020-pub/blob/master/x86prime_tools/gcc-online.py) -- Vi kan ikke garanterer stabiliteten af denne. 8 | * Have en maskine med Linux eller Windows subsystem for Linux. ([Detaljer](https://github.com/kirkedal/compSys-e2020-pub/tree/master/tools)) 9 | * Have en maskine med macOS eller andet og benytte en virtuel Linux maskine. ([Detaljer](https://github.com/kirkedal/compSys-e2020-pub/tree/master/tools/vm)) 10 | 11 | ## x86prime Tools 12 | 13 | Som beskrevet nedenfor (og I A2 opgaveteksten) vil der de næste uger være nødvendigt at benytte et speciel udviklet værktøj. Dette er skrevet i OCaml. Det kan installeres eller køres på følgende måde: 14 | 15 | * Have en maskine med Linux eller Windows subsystem for Linux og installerer det. ([Detaljer](https://github.com/finnschiermer/x86prime/blob/master/README.md)) 16 | * Have en hvilken som helst maskine og benytte en virtuel Linux maskine med værktøjet præinstalleret. ([Detaljer](https://github.com/kirkedal/compSys-e2020-pub/tree/master/tools/vm)) 17 | * (Den midlertidige) Benytte vores python-script til at benytte x86prime via en af vores servere. [gcc-online.py](https://github.com/kirkedal/compSys-e2020-pub/blob/master/x86prime_tools/) -- Vi kan ikke garanterer stabiliteten af denne. 18 | 19 | -------------------------------------------------------------------------------- /material/200923_processor_realization/exercises.md: -------------------------------------------------------------------------------- 1 | # Øvelsesopgaver for 23/9-2019 2 | 3 | 4 | ## Opgave 1 5 | 6 | Følg signalerne compute.is_valid og load_store.is_valid i den udleverede 7 | kode til A2, og opstil en liste over alt, hvad de to signaler har indflydelse 8 | på, direkte eller indirekte. 9 | 10 | ## Iøvrigt 11 | 12 | Opgaver fra 21/9 såfremt I ikke allerede har løst dem. 13 | -------------------------------------------------------------------------------- /material/200923_processor_realization/mark-bohr-2014-reduced.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diku-compSys/compSys-e2020-pub/2117354114df749a5327584885c88a0b3ad5f9d9/material/200923_processor_realization/mark-bohr-2014-reduced.pdf -------------------------------------------------------------------------------- /material/200923_processor_realization/slides.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diku-compSys/compSys-e2020-pub/2117354114df749a5327584885c88a0b3ad5f9d9/material/200923_processor_realization/slides.pdf -------------------------------------------------------------------------------- /material/200928_simple_uarch/exercises.md: -------------------------------------------------------------------------------- 1 | # Øvelser til 28. sept. 2019 2 | 3 | 4 | Færdiggør eventuelle overskydende øvelser fra sidste uge. 5 | 6 | 7 | # Afviklingsplot 8 | 9 | Nedenfor ses afviklingen af en stump x86prime kode på en simpel pipeline: 10 | 11 | Den viste kode er den indre løkke i en funktion som multiplicerer 12 | alle elementer i en nul-termineret tabel med et argument. 13 | 14 | Ved indgang til løkken indeholder %r10 pointeren til tabellen og 15 | %r12 det tal alle elementer skal multipliceres med. 16 | 17 | ~~~ 18 | Loop: 19 | movq (%r10),%r11 FDXMYW 20 | cbe $0,%r11,Done FDDXMYW 21 | multq %r12,%r11 FFDXMYW 22 | movq %r11,(%r10) FDDDXMYW 23 | addq $8,%r10 FFFDXMYW 24 | jmp Loop FDXMYW 25 | Done: 26 | ~~~ 27 | 28 | Bogstaverne til højre viser hver instruktions passage gennem pipelinen. 29 | Betydningen af bogstaverne er: 30 | 31 | * F: Fetch, instruktionhentning 32 | * D: Decode, afkodning, læsning af registre, evt venten på operander 33 | * X: eXecute, udførelse af ALU op, af adresseberegning eller af første del af multiplikation 34 | * M: Memory, læsning/skrivning af data fra data-cache, midterste del af multiplikation 35 | * Y: sidste del af multiplikation 36 | * W: Writeback, opdatering af registre 37 | 38 | Alle instruktioner passerer gennem de samme 6 trin. Multiplikation udføres over 3 pipeline-trin, 39 | E, M og Y. Et ubetinget hop udføres i D-trinnet, dvs den instruktion der hoppes til kan blive 40 | hentet i cyklussen efter. Et betinget hop udføres derimod først i X-trinnet. 41 | 42 | Der er fuld forwarding af operander fra en instruktion til en afhængig instruktion. 43 | Instruktioner venter i D-trinnet indtil operander er tilgængelige. 44 | 45 | ## Spg 1: 46 | 47 | Vi indfører en særlig undtagelse for movq instruktioner som skriver til lageret. 48 | De skal stadig vente i D på operander til adresseberegning, men skal først vente 49 | i X på selve den værdi der skal skrives til lageret. 50 | 51 | Gentegn afviklingsplottet ovenfor under hensyntagen til denne ændring. 52 | 53 | ## Spg 2: 54 | 55 | Hvor mange clock-cyklusser (sic) tager hvert gennemløb af løkken. Udvid eventuelt figuren 56 | med instruktioner fra efterfølgende gennemløb, indtil du er sikker på dit svar. 57 | 58 | ## Spg 3: 59 | 60 | Kan du optimere koden ved at flytte rundt på instruktionerne således at der er færre 61 | instruktioner der skal vente på vej gennem pipelinen? 62 | 63 | Vis den optimerede kode og tegn det tilsvarende afviklingsplot der viser hvordan den udføres 64 | i pipelinen. Hvor meget hurtigere er din optimerede kode? 65 | 66 | -------------------------------------------------------------------------------- /material/200928_simple_uarch/slides.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diku-compSys/compSys-e2020-pub/2117354114df749a5327584885c88a0b3ad5f9d9/material/200928_simple_uarch/slides.pdf -------------------------------------------------------------------------------- /material/200930_memory_hierachy/exercise_code/Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | CFLAGS = -O3 -Wall 3 | 4 | all: cols rows 5 | 6 | cols: sum-array-cols.c 7 | $(CC) $(CFLAGS) -o cols sum-array-cols.c 8 | 9 | rows: sum-array-rows.c 10 | $(CC) $(CFLAGS) -o rows sum-array-rows.c 11 | 12 | clean: 13 | rm -f rows cols 14 | 15 | 16 | -------------------------------------------------------------------------------- /material/200930_memory_hierachy/exercise_code/sum-array-cols.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define BAD_INPUT 0 5 | 6 | long sum_array_cols(long *a, int M, int N) 7 | { 8 | unsigned long i, j; 9 | long sum = 0; 10 | 11 | for (j = 0; j < N; j++) { 12 | for (i = 0; i < M; i++) { 13 | sum += a[i * M + j]; 14 | } 15 | } 16 | return sum; 17 | } 18 | 19 | int main (int argc, char* argv[]) { 20 | unsigned long n,m; // Array size 21 | if (argc != 3) { // 2 argument 22 | printf("I want two ints as arguments!\n"); 23 | return EXIT_SUCCESS; 24 | } 25 | int res; 26 | res = sscanf(argv[1],"%lu", &m); 27 | if (res == BAD_INPUT) { 28 | printf("I want two ints as arguments!\n"); 29 | return EXIT_SUCCESS; 30 | } 31 | res = sscanf(argv[1],"%lu", &n); 32 | if (res == BAD_INPUT) { 33 | printf("I want two ints as arguments!\n"); 34 | return EXIT_SUCCESS; 35 | } 36 | 37 | // Give me some memory with the size of the array 38 | long* input = (long*) malloc(m * n * sizeof(long)); 39 | // Note, I do not care about the input 40 | 41 | // use volatile to prevent compiler from optimizing this away! 42 | volatile long l = sum_array_cols(input, m, n); 43 | 44 | printf("Sum is: %ld\n", l); 45 | 46 | // Give the memory back 47 | free(input); 48 | 49 | return EXIT_SUCCESS; 50 | } 51 | -------------------------------------------------------------------------------- /material/200930_memory_hierachy/exercise_code/sum-array-rows.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define BAD_INPUT 0 5 | 6 | long sum_array_rows(long *a, int M, int N) 7 | { 8 | unsigned long i, j; 9 | long sum = 0; 10 | 11 | for (i = 0; i < M; i++) { 12 | for (j = 0; j < N; j++) { 13 | sum += a[i * M + j]; 14 | } 15 | } 16 | return sum; 17 | } 18 | 19 | int main (int argc, char* argv[]) { 20 | unsigned long n,m; // Array size 21 | if (argc != 3) { // 2 argument 22 | printf("I want two ints as arguments!\n"); 23 | return EXIT_SUCCESS; 24 | } 25 | int res; 26 | res = sscanf(argv[1],"%lu", &m); 27 | if (res == BAD_INPUT) { 28 | printf("I want two ints as arguments!\n"); 29 | return EXIT_SUCCESS; 30 | } 31 | res = sscanf(argv[1],"%lu", &n); 32 | if (res == BAD_INPUT) { 33 | printf("I want two ints as arguments!\n"); 34 | return EXIT_SUCCESS; 35 | } 36 | 37 | // Give me some memory with the size of the array 38 | long* input = (long*) malloc(m * n * sizeof(long)); 39 | 40 | // Note, I do not care about the input 41 | volatile long l = sum_array_rows(input, m, n); 42 | printf("Sum is: %ld\n", l); 43 | 44 | 45 | // Give the memory back 46 | free(input); 47 | 48 | return EXIT_SUCCESS; 49 | } 50 | -------------------------------------------------------------------------------- /material/200930_memory_hierachy/slides.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diku-compSys/compSys-e2020-pub/2117354114df749a5327584885c88a0b3ad5f9d9/material/200930_memory_hierachy/slides.pdf -------------------------------------------------------------------------------- /material/201005_caching/exercises.md: -------------------------------------------------------------------------------- 1 | # Exercises for 5/10-2019 2 | 3 | 4 | ## Locality and performance 5 | 6 | Start with any leftover exercises from Monday. 7 | 8 | ## From CSapp 9 | 10 | * PP 6.7, page 644 11 | * PP 6.8, page 645 12 | * HP 6.24, page 685 13 | * HP 6.29, page 687 14 | 15 | -------------------------------------------------------------------------------- /material/201005_caching/matmult/Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | CFLAGS = -O3 -Wall -mavx2 3 | 4 | all: mm bmm 5 | 6 | mm: mm.c clock.c fcycmm.c mm.h 7 | $(CC) $(CFLAGS) -o mm mm.c clock.c fcycmm.c 8 | 9 | bmm: bmm.c clock.c fcycbmm.c mm.h 10 | $(CC) $(CFLAGS) -o bmm bmm.c clock.c fcycbmm.c 11 | 12 | clean: 13 | rm -f *.o mm bmm *~ 14 | 15 | 16 | -------------------------------------------------------------------------------- /material/201005_caching/matmult/README.txt: -------------------------------------------------------------------------------- 1 | This is the code that generated the various matrix multiplication 2 | performance charts in Introduction to Computer Systems. 3 | 4 | Files: 5 | mm.{c,h} - regular matmult 6 | bmm.c - blocked matmult 7 | clock.{c,h} - routines for accessing the Pentium cycle timers 8 | fcycmm.{c,h} - routines that use the K-best scheme for estimating the 9 | number of cycles required by a function with 4 args. 10 | 11 | To compile: 12 | linux> make clean 13 | linux> make 14 | 15 | To run: 16 | linux> mm 17 | linux> bmm 18 | -------------------------------------------------------------------------------- /material/201005_caching/matmult/clock.h: -------------------------------------------------------------------------------- 1 | /* Routines for using cycle counter */ 2 | 3 | /* Start the counter */ 4 | void start_counter(); 5 | 6 | /* Get # cycles since counter started */ 7 | double get_counter(); 8 | 9 | 10 | /* Measure overhead for counter */ 11 | double ovhd(); 12 | 13 | /* Determine clock rate of processor */ 14 | double mhz(int verbose); 15 | 16 | /* Determine clock rate of processor, having more control over accuracy */ 17 | double mhz_full(int verbose, int sleeptime); 18 | 19 | /** Special counters that compensate for timer interrupt overhead */ 20 | 21 | void start_comp_counter(); 22 | 23 | double get_comp_counter(); 24 | -------------------------------------------------------------------------------- /material/201005_caching/matmult/fcycbmm.h: -------------------------------------------------------------------------------- 1 | /* Find number of cycles used by bmm functions */ 2 | 3 | /* Function to be tested takes three array and two integer arguments */ 4 | typedef void (*test_funct)(array, array, array, int, int); 5 | 6 | /* Compute time used by function f */ 7 | double fcyc(test_funct f, int n, int bsize, int clearcache); 8 | 9 | /********* These routines are used to help with the analysis *********/ 10 | 11 | /* 12 | Parameters: 13 | k: How many samples must be within epsilon for convergence 14 | epsilon: What is tolerance 15 | maxsamples: How many samples until give up? 16 | */ 17 | 18 | /* Full version of fcyc with control over parameters */ 19 | double fcyc_full(test_funct f, int n, int bsize, int clear_cache, 20 | int k, double epsilon, int maxsamples, int compensate); 21 | 22 | /* Get current minimum */ 23 | double get_min(); 24 | 25 | /* What is convergence status for k minimum measurements within epsilon 26 | Returns 0 if not converged, #samples if converged, and -1 if can't 27 | reach convergence 28 | */ 29 | 30 | int has_converged(int k, double epsilon, int maxsamples); 31 | 32 | /* What is error of current measurement */ 33 | double err(int k); 34 | -------------------------------------------------------------------------------- /material/201005_caching/matmult/fcycmm.h: -------------------------------------------------------------------------------- 1 | /* Find number of cycles used by function */ 2 | 3 | /* Function to be tested takes single integer argument */ 4 | typedef void (*test_funct)(array, array, array, int); 5 | 6 | /* Compute time used by function f. Optionally clear cache 7 | before each measurement */ 8 | double fcyc(test_funct f, int param, int clear_cache); 9 | 10 | /********* These routines are used to help with the analysis *********/ 11 | 12 | /* 13 | Parameters: 14 | k: How many samples must be within epsilon for convergence 15 | epsilon: What is tolerance 16 | maxsamples: How many samples until give up? 17 | */ 18 | 19 | /* Full version of fcyc with control over parameters */ 20 | double fcyc_full(test_funct f, int param, int clear_cache, 21 | int k, double epsilon, int maxsamples, int compensate); 22 | 23 | /* Get current minimum */ 24 | double get_min(); 25 | 26 | /* What is convergence status for k minimum measurements within epsilon 27 | Returns 0 if not converged, #samples if converged, and -1 if can't 28 | reach convergence 29 | */ 30 | 31 | int has_converged(int k, double epsilon, int maxsamples); 32 | 33 | /* What is error of current measurement */ 34 | double err(int k); 35 | 36 | /************* Try other clocking methods *****************/ 37 | 38 | /* Full version that uses the time of day clock */ 39 | double fcyc_full_tod(test_funct f, int param, int clear_cache, 40 | int k, double epsilon, int maxsamples, int compensate); 41 | 42 | double fcyc_tod(test_funct f, int param, int clear_cache); 43 | -------------------------------------------------------------------------------- /material/201005_caching/matmult/mm-corei7h.txt: -------------------------------------------------------------------------------- 1 | matmult cycles/loop iteration 2 | n jki kji ijk jik kij ikj 3 | 50 4.80 4.83 3.75 3.93 1.86 1.78 4 | 100 4.68 4.72 4.08 4.14 1.78 1.80 5 | 150 4.65 4.64 4.33 4.36 2.14 2.12 6 | 200 4.80 4.69 4.45 4.47 2.30 2.03 7 | 250 6.84 6.83 4.45 4.52 2.23 1.96 8 | 300 15.03 15.10 4.45 4.56 2.18 1.92 9 | 350 22.78 22.68 4.45 4.57 2.14 1.89 10 | 400 29.39 29.18 4.47 4.60 2.12 1.86 11 | 450 40.39 40.26 7.73 7.96 2.12 1.86 12 | 500 57.06 57.02 18.77 19.05 2.13 1.88 13 | 550 60.54 60.53 20.36 20.59 2.13 1.89 14 | 600 63.33 63.34 21.67 21.86 2.14 1.90 15 | 650 65.61 65.62 22.76 22.92 2.16 1.91 16 | 700 67.49 67.53 23.71 23.82 2.22 1.95 17 | -------------------------------------------------------------------------------- /material/201005_caching/matmult/mm.h: -------------------------------------------------------------------------------- 1 | #define MINN 100 2 | #define MAXN 1000 3 | #define INCN 100 4 | 5 | typedef double array[MAXN][MAXN+513]; 6 | 7 | #define min(x,y) (x 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | int main(int argc, char** argv) { 8 | 9 | pid_t ret = fork(); 10 | 11 | if (ret == 0) { 12 | // Child 13 | exit(execvp(argv[1], argv+1)); 14 | } else { 15 | // Parent 16 | int wstatus; 17 | waitpid(ret, &wstatus, 0); 18 | 19 | return WEXITSTATUS(wstatus); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /material/201019_exceptional_control_flow/exec1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | int main(int argc, char** argv) { 9 | 10 | pid_t ret = fork(); 11 | 12 | if (ret == 0) { 13 | // Child 14 | FILE* out = fopen("output", "w"); 15 | assert(dup2(fileno(out), 1) == 1); 16 | exit(execvp(argv[1], argv+1)); 17 | } else { 18 | // Parent 19 | int wstatus; 20 | waitpid(ret, &wstatus, 0); 21 | 22 | return WEXITSTATUS(wstatus); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /material/201019_exceptional_control_flow/exercises.md: -------------------------------------------------------------------------------- 1 | * 8.3 (page 781) 2 | * 8.4 (page 784) 3 | * 8.6 (page 788) 4 | * 8.9 (page 824) 5 | * 8.12 (page 825) 6 | * 8.22 (page 829) 7 | 8 | -------------------------------------------------------------------------------- /material/201019_exceptional_control_flow/fork0.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | pid_t ret = fork(); 6 | 7 | if (ret == 0) { 8 | // Child 9 | pid_t my_pid = getpid(); 10 | printf("Child: ret=%d; my_pid=%d\n", (int)ret, (int)my_pid); 11 | } else { 12 | // Parent 13 | pid_t my_pid = getpid(); 14 | printf("Parent: ret=%d; my_pid=%d\n", (int)ret, (int)my_pid); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /material/201019_exceptional_control_flow/fork1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | int main() { 8 | pid_t ret = fork(); 9 | 10 | if (ret == 0) { 11 | // Child 12 | pid_t my_pid = getpid(); 13 | printf("Child: ret=%d; my_pid=%d\n", (int)ret, (int)my_pid); 14 | *((int*)NULL) = 0; 15 | exit(42); 16 | } else { 17 | // Parent 18 | 19 | // Wait for child. 20 | int wstatus; 21 | waitpid(ret, &wstatus, 0); 22 | 23 | pid_t my_pid = getpid(); 24 | printf("Parent: ret=%d; my_pid=%d\n", (int)ret, (int)my_pid); 25 | 26 | if (WIFSIGNALED(wstatus)) { 27 | printf("Child was killed by signal %d\n", WTERMSIG(wstatus)); 28 | } else { 29 | printf("Child returned %d\n", WEXITSTATUS(wstatus)); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /material/201019_exceptional_control_flow/fork2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | int main() { 9 | 10 | FILE *f = fopen("file", "r"); 11 | assert(f != NULL); 12 | 13 | char c; 14 | assert(fread(&c, sizeof(char), 1, f) == 1); 15 | 16 | printf("Read: %c\n", c); 17 | 18 | pid_t ret = fork(); 19 | 20 | if (ret == 0) { 21 | // Child 22 | assert(fread(&c, sizeof(char), 1, f) == 1); 23 | printf("Child read: %c\n", c); 24 | } else { 25 | // Parent 26 | assert(fread(&c, sizeof(char), 1, f) == 1); 27 | printf("Parent read: %c\n", c); 28 | 29 | // Wait for child. 30 | waitpid(ret, NULL, 0); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /material/201019_exceptional_control_flow/forkbomb.c: -------------------------------------------------------------------------------- 1 | /* Cool kids run this program on a shared system. */ 2 | 3 | #include 4 | 5 | int main() { 6 | while (1) { fork(); } 7 | } 8 | -------------------------------------------------------------------------------- /material/201019_exceptional_control_flow/pipe0.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int file_pipe(FILE* files[2]) { 7 | int fds[2]; 8 | 9 | int r = pipe(fds); 10 | 11 | if (r == 0) { 12 | files[0] = fdopen(fds[0], "r"); 13 | files[1] = fdopen(fds[1], "w"); 14 | 15 | if (files[0] && files[1]) { 16 | return 0; 17 | } else { 18 | return 1; 19 | } 20 | } else { 21 | return r; 22 | } 23 | } 24 | 25 | int main() { 26 | FILE* files[2]; 27 | assert(file_pipe(files) == 0); 28 | FILE *read_end = files[0]; 29 | FILE *write_end = files[1]; 30 | 31 | pid_t ret = fork(); 32 | 33 | if (ret == 0) { 34 | // Child 35 | pid_t my_pid = getpid(); 36 | printf("Child: ret=%d; my_pid=%d\n", (int)ret, (int)my_pid); 37 | fprintf(write_end, "Hello parent!\n"); 38 | fprintf(write_end, "I think I am PID %d!\n", my_pid); 39 | } else { 40 | // Parent 41 | pid_t my_pid = getpid(); 42 | printf("Parent: ret=%d; my_pid=%d\n", (int)ret, (int)my_pid); 43 | 44 | // Remember to close the write end of the pipe, or else we will 45 | // never get EOFs from the fread() below. 46 | fclose(write_end); 47 | 48 | char c; 49 | while (fread(&c, sizeof(char), 1, read_end) == 1) { 50 | putchar(c); 51 | fflush(stdout); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /material/201021_dynamic_memory/calc/Makefile: -------------------------------------------------------------------------------- 1 | CC=gcc 2 | CFLAGS=-g -pedantic -std=c99 -Wall -Wextra 3 | 4 | calc: calc.o stack.o 5 | $(CC) $(CFLAGS) calc.o stack.o -o calc 6 | 7 | calc.o: calc.c stack.h 8 | $(CC) $(CFLAGS) -c calc.c 9 | 10 | stack.o: stack.c stack.h 11 | $(CC) $(CFLAGS) -c stack.c 12 | 13 | clean: 14 | rm -f *o 15 | rm -f calc 16 | 17 | all: calc 18 | -------------------------------------------------------------------------------- /material/201021_dynamic_memory/calc/calc.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "stack.h" 4 | 5 | typedef double (*binop)(double,double); 6 | 7 | static void out_of_memory() { 8 | printf("Out of memory.\n"); 9 | exit(EXIT_FAILURE); 10 | } 11 | 12 | static void perform_binop(struct stack *stack, binop op) { 13 | double *x; 14 | double *y; 15 | double *z; 16 | if ((z = (double*) malloc(sizeof(double))) == NULL) { 17 | out_of_memory(); 18 | } 19 | if (!stack_empty(stack)) { 20 | x = stack_pop(stack); 21 | if (!stack_empty(stack)) { 22 | y = stack_pop(stack); 23 | *z = (*op)(*y, *x); 24 | free(x); 25 | free(y); 26 | if (stack_push(stack, z) == 1) { 27 | out_of_memory(); 28 | } 29 | return; 30 | } else { 31 | if (stack_push(stack, x) == 1) { 32 | out_of_memory(); 33 | } 34 | } 35 | free(x); 36 | } 37 | free(z); 38 | printf("Too few elements on stack.\n"); 39 | } 40 | 41 | static double plus(double x, double y) { 42 | return x+y; 43 | } 44 | 45 | static double sub(double x, double y) { 46 | return x-y; 47 | } 48 | 49 | static double mult(double x, double y) { 50 | return x*y; 51 | } 52 | 53 | static double divn(double x, double y) { 54 | return x/y; 55 | } 56 | 57 | int main() { 58 | double x; 59 | int c; 60 | struct stack stack; 61 | stack_init(&stack); 62 | while (1) { 63 | c=getc(stdin); 64 | switch (c) { 65 | case EOF: 66 | exit(EXIT_SUCCESS); 67 | case '+': 68 | perform_binop(&stack, &plus); 69 | break; 70 | case '-': 71 | perform_binop(&stack, &sub); 72 | break; 73 | case '*': 74 | perform_binop(&stack, &mult); 75 | break; 76 | case '/': 77 | perform_binop(&stack, &divn); 78 | break; 79 | case 'p': 80 | if (stack_empty(&stack)) { 81 | printf("Stack is empty.\n"); 82 | } else { 83 | printf("%lf\n", *(double*)stack_top(&stack)); 84 | } 85 | break; 86 | default: 87 | ungetc(c,stdin); 88 | if (scanf("%lf", &x) == 1) { 89 | double* d; 90 | if ((d = (double*)malloc(sizeof(double))) == NULL) { 91 | out_of_memory(); 92 | } else { 93 | *d = x; 94 | if (stack_push(&stack,d) != 0) { 95 | out_of_memory(); 96 | } 97 | } 98 | } else { 99 | printf("Bad input.\n"); 100 | } 101 | } 102 | while (getc(stdin)!='\n'); 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /material/201021_dynamic_memory/calc/stack.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "stack.h" 4 | 5 | void stack_init(struct stack* stack) { 6 | assert(0); 7 | } 8 | 9 | int stack_empty(struct stack* stack) { 10 | assert(0); 11 | } 12 | 13 | void* stack_top(struct stack* stack) { 14 | assert(0); 15 | } 16 | 17 | void* stack_pop(struct stack* stack) { 18 | assert(0); 19 | } 20 | 21 | int stack_push(struct stack* stack, void* data) { 22 | assert(0); 23 | } 24 | -------------------------------------------------------------------------------- /material/201021_dynamic_memory/calc/stack.h: -------------------------------------------------------------------------------- 1 | #ifndef STACK_H 2 | #define STACK_H 3 | 4 | struct stack { 5 | } stack; 6 | 7 | void stack_init(struct stack*); 8 | 9 | int stack_empty(struct stack*); 10 | 11 | void* stack_top(struct stack*); 12 | 13 | void* stack_pop(struct stack*); 14 | 15 | int stack_push(struct stack*, void*); 16 | 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /material/201021_dynamic_memory/calc_solution/Makefile: -------------------------------------------------------------------------------- 1 | CC=gcc 2 | CFLAGS=-pedantic -std=c99 -Wall -Wextra -g3 3 | 4 | 5 | calc: calc.o stack.o 6 | $(CC) $(CFLAGS) calc.o stack.o -o calc 7 | 8 | calc.o: calc.c stack.h 9 | $(CC) $(CFLAGS) -c calc.c 10 | 11 | stack.o: stack.c stack.h 12 | $(CC) $(CFLAGS) -c stack.c 13 | 14 | clean: 15 | rm -f *o 16 | rm -f calc 17 | 18 | all: calc 19 | -------------------------------------------------------------------------------- /material/201021_dynamic_memory/calc_solution/calc.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "stack.h" 4 | 5 | typedef double (*binop)(double,double); 6 | 7 | static void out_of_memory() { 8 | printf("Out of memory.\n"); 9 | exit(EXIT_FAILURE); 10 | } 11 | 12 | static void perform_binop(struct stack *stack, binop op) { 13 | double *x; 14 | double *y; 15 | double *z; 16 | if ((z = (double*) malloc(sizeof(double))) == NULL) { 17 | out_of_memory(); 18 | } 19 | if (!stack_empty(stack)) { 20 | x = stack_pop(stack); 21 | if (!stack_empty(stack)) { 22 | y = stack_pop(stack); 23 | *z = (*op)(*y, *x); 24 | free(x); 25 | free(y); 26 | if (stack_push(stack, z) == 1) { 27 | out_of_memory(); 28 | } 29 | return; 30 | } else { 31 | if (stack_push(stack, x) == 1) { 32 | out_of_memory(); 33 | } 34 | } 35 | free(x); 36 | } 37 | free(z); 38 | printf("Too few elements on stack.\n"); 39 | } 40 | 41 | static double plus(double x, double y) { 42 | return x+y; 43 | } 44 | 45 | static double sub(double x, double y) { 46 | return x-y; 47 | } 48 | 49 | static double mult(double x, double y) { 50 | return x*y; 51 | } 52 | 53 | static double divn(double x, double y) { 54 | return x/y; 55 | } 56 | 57 | int main() { 58 | double x; 59 | int c; 60 | struct stack stack; 61 | stack_init(&stack); 62 | while (1) { 63 | c=getc(stdin); 64 | switch (c) { 65 | case EOF: 66 | exit(EXIT_SUCCESS); 67 | case '+': 68 | perform_binop(&stack, &plus); 69 | break; 70 | case '-': 71 | perform_binop(&stack, &sub); 72 | break; 73 | case '*': 74 | perform_binop(&stack, &mult); 75 | break; 76 | case '/': 77 | perform_binop(&stack, &divn); 78 | break; 79 | case 'p': 80 | if (stack_empty(&stack)) { 81 | printf("Stack is empty.\n"); 82 | } else { 83 | printf("%lf\n", *(double*)stack_top(&stack)); 84 | } 85 | break; 86 | default: 87 | ungetc(c,stdin); 88 | if (scanf("%lf", &x) == 1) { 89 | double* d; 90 | if ((d = (double*)malloc(sizeof(double))) == NULL) { 91 | out_of_memory(); 92 | } else { 93 | *d = x; 94 | if (stack_push(&stack,d) != 0) { 95 | out_of_memory(); 96 | } 97 | } 98 | } else { 99 | printf("Bad input.\n"); 100 | } 101 | } 102 | while (getc(stdin)!='\n'); 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /material/201021_dynamic_memory/calc_solution/stack.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "stack.h" 4 | 5 | 6 | void stack_init(struct stack *stack) { 7 | stack->top = NULL; 8 | } 9 | 10 | int stack_empty(struct stack *stack) { 11 | if (stack == NULL) { 12 | fprintf(stderr, "stack_empty() error: stack uninitialized\n"); 13 | exit(1); 14 | } 15 | 16 | return stack->top == NULL; 17 | } 18 | 19 | void *stack_top(struct stack *stack) { 20 | if (stack == NULL) { 21 | fprintf(stderr, "stackop() error: stack uninitialized\n"); 22 | exit(1); 23 | } 24 | 25 | return stack->top->data; 26 | } 27 | 28 | void *stack_pop(struct stack *stack) { 29 | if (stack == NULL) { 30 | fprintf(stderr, "stack_pop() error: stack uninitialized\n"); 31 | exit(1); 32 | } 33 | 34 | struct node *old_top = stack->top; 35 | 36 | if (old_top == NULL) 37 | return NULL; 38 | 39 | void *data = old_top->data; 40 | 41 | stack->top = old_top->next; 42 | 43 | free(old_top); 44 | 45 | return data; 46 | } 47 | 48 | int stack_push(struct stack *stack, void *data) { 49 | if (stack == NULL) { 50 | fprintf(stderr, "stack_push() error: stack uninitialized\n"); 51 | exit(1); 52 | } 53 | 54 | struct node *new_top = malloc(sizeof(struct node)); 55 | 56 | new_top->data = data; 57 | new_top->next = stack->top; 58 | 59 | stack->top = new_top; 60 | 61 | return 0; 62 | } 63 | -------------------------------------------------------------------------------- /material/201021_dynamic_memory/calc_solution/stack.h: -------------------------------------------------------------------------------- 1 | #ifndef STACK_H 2 | #define STACK_H 3 | 4 | struct node { 5 | void *data; 6 | struct node *next; 7 | }; 8 | 9 | struct stack { 10 | struct node *top; 11 | }; 12 | 13 | void stack_init(struct stack*); 14 | 15 | int stack_empty(struct stack*); 16 | 17 | void* stack_top(struct stack*); 18 | 19 | void* stack_pop(struct stack*); 20 | 21 | int stack_push(struct stack*, void*); 22 | 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /material/201021_dynamic_memory/exercises.md: -------------------------------------------------------------------------------- 1 | # Implementing a stack 2 | 3 | The `calc/` directory contains the code for a simple calculator that 4 | uses Reverse Polish Notation. For example, to compute the expression 5 | `(3 - 4) / (5 + 6) == -0.090909` and print the result, we would input: 6 | 7 | ~~~ 8 | $ ./calc 9 | 3 10 | 4 11 | - 12 | 5 13 | 6 14 | + 15 | / 16 | p 17 | Result: -0.090909 18 | ~~~ 19 | 20 | *Note the newlines after each symbol.* 21 | 22 | And to compute the expression `3 - (4 - 5) == 4` and print the result, 23 | we would input: 24 | ~~~ 25 | $ ./calc 26 | 3 27 | 4 28 | 5 29 | - 30 | - 31 | p 32 | Result: 4 33 | ~~~ 34 | 35 | Unfortunately I ran late and forgot to finish the 36 | implementation of `stack.h` and `stack.c`. 37 | Finish it for me so the stack calculator will work. 38 | 39 | # List implementation 40 | 41 | Change the implementation of the list library covered in the lectures 42 | (in the `list/`) subdirectory to use a different representation. Do 43 | not change `list.h`. For example, an implementation with doubly 44 | linked lists: 45 | 46 | struct node { 47 | void *elem; 48 | struct node *next; 49 | struct node *prev; 50 | }; 51 | 52 | struct list { 53 | struct node *first; 54 | struct node *last; 55 | }; 56 | 57 | Or one where the representation is a flat array: 58 | 59 | struct list { 60 | void **data; 61 | int length; 62 | }; 63 | 64 | Consider how these affect the performance of the API, without changing 65 | its semantics. 66 | -------------------------------------------------------------------------------- /material/201021_dynamic_memory/fib/Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS=-Wall -Wextra -pedantic 2 | CC=gcc 3 | 4 | all: test 5 | 6 | test: fib.o test.o 7 | $(CC) test.o fib.o -o test $(CFLAGS) 8 | 9 | fib.o: fib.c 10 | $(CC) -c fib.c $(CFLAGS) 11 | 12 | test.o: test.c 13 | $(CC) -c test.c $(CFLAGS) 14 | 15 | do_test: test 16 | ./test 17 | 18 | clean: 19 | rm -f fib.o test.o test 20 | -------------------------------------------------------------------------------- /material/201021_dynamic_memory/fib/fib.c: -------------------------------------------------------------------------------- 1 | #include "fib.h" 2 | 3 | int fib(int n) { 4 | if (n <= 1) { 5 | return 1; 6 | } else { 7 | return fib(n-1) + fib(n-2); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /material/201021_dynamic_memory/fib/fib.h: -------------------------------------------------------------------------------- 1 | #ifndef _FIB_H 2 | #define _FIB_H 3 | 4 | // Computes the nth fibonacci number. 5 | int fib(int n); 6 | 7 | #endif 8 | -------------------------------------------------------------------------------- /material/201021_dynamic_memory/fib/test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "fib.h" 3 | 4 | int main() { 5 | int n = 10; 6 | printf("fib(%d) = %d\n", n, fib(n)); 7 | } 8 | -------------------------------------------------------------------------------- /material/201021_dynamic_memory/list/Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS=-Wall -Wextra -pedantic -g 2 | CC=gcc 3 | 4 | 5 | run: clean test_list 6 | ./test_list 7 | 8 | test_list: test_list.o list.o 9 | $(CC) test_list.o list.o -o test_list $(CFLAGS) 10 | 11 | test_list.o: test_list.c 12 | $(CC) -c test_list.c $(CFLAGS) 13 | 14 | test.o: list.c 15 | $(CC) -c list.c $(CFLAGS) 16 | 17 | clean: 18 | rm -rf test_list *.o 19 | -------------------------------------------------------------------------------- /material/201021_dynamic_memory/list/doubly_linked/Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS=-Wall -Wextra -pedantic -g 2 | CC=gcc 3 | 4 | 5 | run: clean test_list 6 | ./test_list 7 | 8 | test_list: test_list.o list.o 9 | $(CC) test_list.o list.o -o test_list $(CFLAGS) 10 | 11 | test_list.o: test_list.c 12 | $(CC) -c test_list.c $(CFLAGS) 13 | 14 | test.o: list.c 15 | $(CC) -c list.c $(CFLAGS) 16 | 17 | clean: 18 | rm -rf test_list *.o 19 | -------------------------------------------------------------------------------- /material/201021_dynamic_memory/list/doubly_linked/list.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "list.h" 3 | #include 4 | 5 | struct node { 6 | void *data; 7 | struct node *next; 8 | struct node *prev; 9 | }; 10 | 11 | struct list { 12 | struct node *first; 13 | struct node *last; 14 | }; 15 | 16 | 17 | struct list *list_create() { 18 | struct list *list = malloc(sizeof(struct list)); 19 | 20 | list->first = NULL; 21 | list->last = NULL; 22 | 23 | return list; 24 | } 25 | 26 | 27 | void list_free(struct list *list) { 28 | 29 | if (list == NULL) // nothing to free 30 | return; 31 | 32 | struct node *node = list->first; 33 | 34 | while (node != NULL) { // free nodes in list, if any 35 | struct node *next = node->next; 36 | free(node); 37 | node = next; 38 | } 39 | 40 | free(list); 41 | } 42 | 43 | 44 | int list_insert_first(struct list *list, void *data) { 45 | 46 | if (list == NULL) { // if list un-initialized 47 | return 1; 48 | // list = list_create(); // could also create new list here instead of returning error 49 | } 50 | 51 | struct node *new_first = malloc(sizeof(struct node)); 52 | 53 | new_first->data = data; 54 | new_first->next = list->first; 55 | 56 | if (list->first == NULL) 57 | list->last = new_first; // if list previously empty, new node is also last 58 | else 59 | list->first->prev = new_first; 60 | 61 | list->first = new_first; 62 | return 0; } 63 | 64 | 65 | int list_remove_first(struct list* list, void** dest) { 66 | 67 | if (list == NULL || list->first == NULL) // if list un-initialized or empty 68 | return 1; 69 | 70 | struct node *old_first = list->first; 71 | 72 | *dest = old_first->data; // pop data 73 | list->first = old_first->next; 74 | 75 | if (list->first == NULL) // if list is now empty 76 | list->last = NULL; 77 | 78 | free(old_first); 79 | return 0; 80 | } 81 | 82 | void list_map(struct list* list, map_fn f, void *aux) { 83 | 84 | if (list == NULL) // if list-uninitialized; nothing to map :) 85 | return; 86 | 87 | struct node *node = list->first; 88 | while (node != NULL) { 89 | node->data = f(node->data, aux); 90 | node = node->next; 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /material/201021_dynamic_memory/list/doubly_linked/list.h: -------------------------------------------------------------------------------- 1 | #ifndef LIST_H 2 | #define LIST_H 3 | 4 | struct list; 5 | 6 | // Create new list. Initially empty. NULL on error. 7 | struct list* list_create(); 8 | 9 | // Deallocates list. 10 | void list_free(struct list*); 11 | 12 | // Insert element at head of list. Returns 0 on success. 13 | int list_insert_first(struct list*, void*); 14 | 15 | int list_remove_first(struct list*, void**); 16 | 17 | typedef void* (*map_fn)(void*, void*); 18 | 19 | void list_map(struct list*, map_fn, void*); 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /material/201021_dynamic_memory/list/doubly_linked/test_list.c: -------------------------------------------------------------------------------- 1 | #include "list.h" 2 | #include 3 | #include 4 | 5 | void* print_elem(void *data, void *aux_data) { 6 | (void)aux_data; 7 | int *int_data = (int*)data; 8 | printf("elem: %d\n", *int_data); 9 | return data; 10 | } 11 | 12 | void print_list(struct list *l) { 13 | list_map(l, print_elem, NULL); 14 | } 15 | 16 | void* inc_elem(void *data, void *aux_data) { 17 | int *int_data = (int*)data; 18 | int *aux_int_data = (int*)aux_data; 19 | *int_data += *aux_int_data; 20 | return data; 21 | } 22 | 23 | void inc_list(struct list *l, int K) { 24 | list_map(l, inc_elem, &K); 25 | } 26 | 27 | int main() { 28 | int K = 42; 29 | 30 | int x = 1, y = 2, z = 3; 31 | void *d; 32 | 33 | struct list *l = list_create(); 34 | assert(l != NULL); 35 | 36 | // test removing from initially empty list 37 | assert(list_remove_first(l, &d) == 1); 38 | 39 | // test inserting a couple of elements 40 | assert(list_insert_first(l, &x) == 0); 41 | assert(list_insert_first(l, &y) == 0); 42 | assert(list_insert_first(l, &z) == 0); 43 | 44 | 45 | // test removing elements 46 | assert(list_remove_first(l, &d) == 0); 47 | assert(d == &z); 48 | assert(list_remove_first(l, &d) == 0); 49 | assert(d == &y); 50 | assert(list_remove_first(l, &d) == 0); 51 | assert(d == &x); 52 | 53 | // test removing from newly empty list 54 | assert(list_remove_first(l, &d) == 1); 55 | 56 | 57 | assert(list_insert_first(l, &x) == 0); 58 | assert(list_insert_first(l, &y) == 0); 59 | assert(list_insert_first(l, &z) == 0); 60 | 61 | print_list(l); 62 | inc_list(l, K); 63 | print_list(l); 64 | 65 | // assert list properly mapped 66 | assert(list_remove_first(l, &d) == 0); 67 | assert(d == &z && z == 3+42); 68 | assert(list_remove_first(l, &d) == 0); 69 | assert(d == &y && y == 2+42); 70 | assert(list_remove_first(l, &d) == 0); 71 | assert(d == &x && x == 1+42); 72 | 73 | list_free(l); 74 | } 75 | -------------------------------------------------------------------------------- /material/201021_dynamic_memory/list/flat_array/Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS=-Wall -Wextra -pedantic -g 2 | CC=gcc 3 | 4 | 5 | run: clean test_list 6 | ./test_list 7 | 8 | test_list: test_list.o list.o 9 | $(CC) test_list.o list.o -o test_list $(CFLAGS) 10 | 11 | test_list.o: test_list.c 12 | $(CC) -c test_list.c $(CFLAGS) 13 | 14 | test.o: list.c 15 | $(CC) -c list.c $(CFLAGS) 16 | 17 | clean: 18 | rm -rf test_list *.o 19 | -------------------------------------------------------------------------------- /material/201021_dynamic_memory/list/flat_array/list.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "list.h" 3 | #include 4 | 5 | struct list { 6 | void **data; 7 | int length; 8 | }; 9 | 10 | 11 | struct list *list_create() { 12 | struct list *list = malloc(sizeof(struct list)); 13 | 14 | list->length = 0; 15 | list->data = NULL; 16 | 17 | return list; 18 | } 19 | 20 | 21 | void list_free(struct list *list) { 22 | 23 | if (list == NULL) 24 | return; 25 | 26 | if (list->data != NULL) { 27 | free(list->data); 28 | } 29 | 30 | free(list); 31 | } 32 | 33 | 34 | int list_insert_first(struct list *list, void *data) { 35 | 36 | if (list == NULL) 37 | return 1; 38 | 39 | int old_length = list->length; 40 | int new_length = old_length + 1; 41 | 42 | void **old_data = list->data; 43 | void **new_data = malloc(new_length * sizeof(void*)); 44 | 45 | new_data[0] = data; 46 | 47 | if (old_data != NULL) { 48 | for (int i = 0; i < old_length; i++) { 49 | new_data[i+1] = old_data[i]; 50 | } 51 | 52 | free(old_data); 53 | } 54 | 55 | list->data = new_data; 56 | list->length = new_length; 57 | return 0; 58 | } 59 | 60 | 61 | int list_remove_first(struct list *list, void **dest) { 62 | if (list == NULL || list->data == NULL) 63 | return 1; 64 | 65 | int old_length = list->length; 66 | int new_length = old_length - 1; 67 | 68 | void **old_data = list->data; 69 | void **new_data; 70 | 71 | *dest = old_data[0]; 72 | 73 | 74 | if (new_length >= 1) { 75 | new_data = malloc(new_length * sizeof(void*)); 76 | for (int i = 0; i < new_length; i++) { 77 | new_data[i] = old_data[i+1]; 78 | } 79 | 80 | } else { 81 | new_data = NULL; 82 | } 83 | 84 | list->data = new_data; 85 | list->length = new_length; 86 | 87 | free(old_data); 88 | 89 | return 0; 90 | } 91 | 92 | 93 | void list_map(struct list *list, map_fn f, void *aux) { 94 | 95 | if (list == NULL) 96 | return; 97 | 98 | void **data = list->data; 99 | 100 | for (int i = 0; i < list->length; i++) { 101 | data[i] = f(data[i], aux); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /material/201021_dynamic_memory/list/flat_array/list.h: -------------------------------------------------------------------------------- 1 | #ifndef LIST_H 2 | #define LIST_H 3 | 4 | struct list; 5 | 6 | // Create new list. Initially empty. NULL on error. 7 | struct list* list_create(); 8 | 9 | // Deallocates list. 10 | void list_free(struct list*); 11 | 12 | // Insert element at head of list. Returns 0 on success. 13 | int list_insert_first(struct list*, void*); 14 | 15 | int list_remove_first(struct list*, void**); 16 | 17 | typedef void* (*map_fn)(void*, void*); 18 | 19 | void list_map(struct list*, map_fn, void*); 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /material/201021_dynamic_memory/list/flat_array/test_list.c: -------------------------------------------------------------------------------- 1 | #include "list.h" 2 | #include 3 | #include 4 | 5 | void* print_elem(void *data, void *aux_data) { 6 | (void)aux_data; 7 | int *int_data = (int*)data; 8 | printf("elem: %d\n", *int_data); 9 | return data; 10 | } 11 | 12 | void print_list(struct list *l) { 13 | list_map(l, print_elem, NULL); 14 | } 15 | 16 | void* inc_elem(void *data, void *aux_data) { 17 | int *int_data = (int*)data; 18 | int *aux_int_data = (int*)aux_data; 19 | *int_data += *aux_int_data; 20 | return data; 21 | } 22 | 23 | void inc_list(struct list *l, int K) { 24 | list_map(l, inc_elem, &K); 25 | } 26 | 27 | int main() { 28 | int K = 42; 29 | 30 | int x = 1, y = 2, z = 3; 31 | void *d; 32 | 33 | struct list *l = list_create(); 34 | assert(l != NULL); 35 | 36 | // test removing from initially empty list 37 | assert(list_remove_first(l, &d) == 1); 38 | 39 | // test inserting a couple of elements 40 | assert(list_insert_first(l, &x) == 0); 41 | assert(list_insert_first(l, &y) == 0); 42 | assert(list_insert_first(l, &z) == 0); 43 | 44 | 45 | // test removing elements 46 | assert(list_remove_first(l, &d) == 0); 47 | assert(d == &z); 48 | assert(list_remove_first(l, &d) == 0); 49 | assert(d == &y); 50 | assert(list_remove_first(l, &d) == 0); 51 | assert(d == &x); 52 | 53 | // test removing from newly empty list 54 | assert(list_remove_first(l, &d) == 1); 55 | 56 | 57 | assert(list_insert_first(l, &x) == 0); 58 | assert(list_insert_first(l, &y) == 0); 59 | assert(list_insert_first(l, &z) == 0); 60 | 61 | print_list(l); 62 | inc_list(l, K); 63 | print_list(l); 64 | 65 | // assert list properly mapped 66 | assert(list_remove_first(l, &d) == 0); 67 | assert(d == &z && z == 3+42); 68 | assert(list_remove_first(l, &d) == 0); 69 | assert(d == &y && y == 2+42); 70 | assert(list_remove_first(l, &d) == 0); 71 | assert(d == &x && x == 1+42); 72 | 73 | list_free(l); 74 | } 75 | -------------------------------------------------------------------------------- /material/201021_dynamic_memory/list/list.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "list.h" 3 | 4 | struct list_node { 5 | void *data; 6 | struct list_node *next; 7 | }; 8 | 9 | struct list { 10 | struct list_node *head; 11 | }; 12 | 13 | struct list* list_create() { 14 | struct list *list = malloc(sizeof(list)); 15 | list->head = NULL; 16 | return list; 17 | } 18 | 19 | void list_free(struct list* list) { 20 | struct list_node *node = list->head; 21 | while (node != NULL) { 22 | struct list_node *next = node->next; 23 | free(node); 24 | node = next; 25 | } 26 | free(list); 27 | } 28 | 29 | int list_insert_first(struct list* list, void* data) { 30 | struct list_node *new_head = malloc(sizeof(struct list_node)); 31 | new_head->data = data; 32 | new_head->next = list->head; 33 | 34 | list->head = new_head; 35 | return 0; 36 | } 37 | 38 | 39 | 40 | int list_remove_first(struct list* list, void** dest) { 41 | struct list_node *old_head = list->head; 42 | if (old_head == NULL) { 43 | return 1; 44 | } 45 | *dest = old_head->data; 46 | list->head = old_head->next; 47 | free(old_head); 48 | return 0; 49 | } 50 | 51 | void list_map(struct list* list, map_fn f, void *aux) { 52 | struct list_node *node = list->head; 53 | while (node != NULL) { 54 | node->data = f(node->data, aux); 55 | node = node->next; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /material/201021_dynamic_memory/list/list.h: -------------------------------------------------------------------------------- 1 | #ifndef LIST_H 2 | #define LIST_H 3 | 4 | struct list; 5 | 6 | // Create new list. Initially empty. NULL on error. 7 | struct list* list_create(); 8 | 9 | // Deallocates list. 10 | void list_free(struct list*); 11 | 12 | // Insert element at head of list. Returns 0 on success. 13 | int list_insert_first(struct list*, void*); 14 | 15 | int list_remove_first(struct list*, void**); 16 | 17 | typedef void* (*map_fn)(void*, void*); 18 | 19 | void list_map(struct list*, map_fn, void*); 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /material/201021_dynamic_memory/list/test_list.c: -------------------------------------------------------------------------------- 1 | #include "list.h" 2 | #include 3 | #include 4 | 5 | void* print_elem(void *data, void *aux_data) { 6 | (void)aux_data; 7 | int *int_data = (int*)data; 8 | printf("elem: %d\n", *int_data); 9 | return data; 10 | } 11 | 12 | void print_list(struct list *l) { 13 | list_map(l, print_elem, NULL); 14 | } 15 | 16 | void* inc_elem(void *data, void *aux_data) { 17 | int *int_data = (int*)data; 18 | int *aux_int_data = (int*)aux_data; 19 | *int_data += *aux_int_data; 20 | return data; 21 | } 22 | 23 | void inc_list(struct list *l, int K) { 24 | list_map(l, inc_elem, &K); 25 | } 26 | 27 | int main() { 28 | int K = 42; 29 | 30 | int x = 1, y = 2, z = 3; 31 | void *d; 32 | 33 | struct list *l = list_create(); 34 | assert(l != NULL); 35 | 36 | // test removing from initially empty list 37 | assert(list_remove_first(l, &d) == 1); 38 | 39 | // test inserting a couple of elements 40 | assert(list_insert_first(l, &x) == 0); 41 | assert(list_insert_first(l, &y) == 0); 42 | assert(list_insert_first(l, &z) == 0); 43 | 44 | 45 | // test removing elements 46 | assert(list_remove_first(l, &d) == 0); 47 | assert(d == &z); 48 | assert(list_remove_first(l, &d) == 0); 49 | assert(d == &y); 50 | assert(list_remove_first(l, &d) == 0); 51 | assert(d == &x); 52 | 53 | // test removing from newly empty list 54 | assert(list_remove_first(l, &d) == 1); 55 | 56 | 57 | assert(list_insert_first(l, &x) == 0); 58 | assert(list_insert_first(l, &y) == 0); 59 | assert(list_insert_first(l, &z) == 0); 60 | 61 | print_list(l); 62 | inc_list(l, K); 63 | print_list(l); 64 | 65 | // assert list properly mapped 66 | assert(list_remove_first(l, &d) == 0); 67 | assert(d == &z && z == 3+42); 68 | assert(list_remove_first(l, &d) == 0); 69 | assert(d == &y && y == 2+42); 70 | assert(list_remove_first(l, &d) == 0); 71 | assert(d == &x && x == 1+42); 72 | 73 | list_free(l); 74 | } 75 | -------------------------------------------------------------------------------- /material/201026_signals/exercises.md: -------------------------------------------------------------------------------- 1 | * 8.23 2 | * 8.24 3 | * 8.25 4 | -------------------------------------------------------------------------------- /material/201026_signals/forks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diku-compSys/compSys-e2020-pub/2117354114df749a5327584885c88a0b3ad5f9d9/material/201026_signals/forks -------------------------------------------------------------------------------- /material/201026_signals/lecture/fork.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | int main() { 8 | pid_t pid; 9 | 10 | int parent_fds[2]; 11 | assert(pipe(parent_fds) == 0); 12 | 13 | int child_fds[2]; 14 | assert(pipe(child_fds) == 0); 15 | 16 | FILE *parent_read_f = fdopen(parent_fds[0], "r"); 17 | FILE *parent_write_f = fdopen(parent_fds[1], "w"); 18 | 19 | FILE *child_read_f = fdopen(child_fds[0], "r"); 20 | FILE *child_write_f = fdopen(child_fds[1], "w"); 21 | 22 | if ((pid = fork()) == 0) { 23 | // In child 24 | int x; 25 | assert(fread(&x, sizeof(int), 1, parent_read_f) == 1); 26 | x = x * 2; 27 | assert(fwrite(&x, sizeof(int), 1, child_write_f) == 1); 28 | } else { 29 | // In parent 30 | int x = 2; 31 | assert(fwrite(&x, sizeof(int), 1, parent_write_f) == 1); 32 | assert(fread(&x, sizeof(int), 1, child_read_f) == 1); 33 | printf("Parent received: %d\n", x); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /material/201026_signals/primes.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | // Some large primes: 10 | // 11 | // 982451653 12 | // 2147483647 13 | 14 | int file_pipe(FILE* files[2]) { 15 | int fds[2]; 16 | 17 | int r = pipe(fds); 18 | 19 | if (r == 0) { 20 | files[0] = fdopen(fds[0], "r"); 21 | files[1] = fdopen(fds[1], "w"); 22 | 23 | if (files[0] && files[1]) { 24 | return 0; 25 | } else { 26 | return 1; 27 | } 28 | } else { 29 | return r; 30 | } 31 | } 32 | 33 | int divisor_in(int x, int from, int to) { 34 | for (int d = from; d < to; d++) { 35 | if (x % d == 0) { 36 | return 1; 37 | } 38 | } 39 | return 0; 40 | } 41 | 42 | int main(int argc, char **argv) { 43 | if (argc != 3) { 44 | printf("usage: %s \n", argv[0]); 45 | return 1; 46 | } 47 | 48 | int nprocs = atoi(argv[1]); 49 | int x = atoi(argv[2]); 50 | int chunk_size = (x-2) / nprocs; 51 | 52 | FILE* child_pipes[nprocs]; 53 | pid_t children[nprocs]; 54 | 55 | for (int i = 0; i < nprocs; i++) { 56 | FILE* files[2]; 57 | assert(file_pipe(files) == 0); 58 | pid_t pid = fork(); 59 | assert(pid >= 0); 60 | if (pid == 0) { 61 | // We are child. 62 | fclose(files[0]); 63 | 64 | int divisible = divisor_in(x, 2 + chunk_size * i, 2 + chunk_size * (i+1)); 65 | assert(fwrite(&divisible, sizeof(int), 1, files[1]) == 1); 66 | fclose(files[1]); 67 | exit(0); 68 | } else { 69 | // We are parent. 70 | fclose(files[1]); 71 | 72 | children[i] = pid; 73 | child_pipes[i] = files[0]; 74 | } 75 | } 76 | 77 | int prime = 1; 78 | for (int i = 0; i < nprocs; i++) { 79 | int divisible; 80 | assert(fread(&divisible, sizeof(int), 1, child_pipes[i]) == 1); 81 | if (divisible) { 82 | prime = 0; 83 | } 84 | waitpid(children[i], NULL, 0); 85 | } 86 | 87 | if (prime) { 88 | printf("%d is prime.\n", x); 89 | } else { 90 | printf("%d is not prime.\n", x); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /material/201026_signals/sigint: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diku-compSys/compSys-e2020-pub/2117354114df749a5327584885c88a0b3ad5f9d9/material/201026_signals/sigint -------------------------------------------------------------------------------- /material/201026_signals/sigint.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "csapp.h" 5 | 6 | void message() 7 | { 8 | printf("So you think you can stop the bomb with ctrl-c, do you?\n"); 9 | sleep(2); 10 | printf("Well..."); 11 | fflush(stdout); 12 | sleep(1); 13 | printf("OK. :-)\n"); 14 | exit(0); 15 | } 16 | 17 | volatile sig_atomic_t pending = 0; 18 | 19 | void sigint_handler(int sig) /* SIGINT handler */ 20 | { 21 | pending = 1; 22 | } 23 | 24 | int main() 25 | { 26 | /* Install the SIGINT handler */ 27 | if (signal(SIGINT, sigint_handler) == SIG_ERR) 28 | unix_error("signal error"); 29 | /* Wait for the receipt of a signal */ 30 | while (1) { 31 | pause(); 32 | while (pending) { 33 | message(); 34 | pending = 0; 35 | } 36 | } 37 | 38 | return 0; 39 | } 40 | -------------------------------------------------------------------------------- /material/201026_signals/signals.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diku-compSys/compSys-e2020-pub/2117354114df749a5327584885c88a0b3ad5f9d9/material/201026_signals/signals.c -------------------------------------------------------------------------------- /material/201026_signals/signals.odp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diku-compSys/compSys-e2020-pub/2117354114df749a5327584885c88a0b3ad5f9d9/material/201026_signals/signals.odp -------------------------------------------------------------------------------- /material/201026_signals/signals.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diku-compSys/compSys-e2020-pub/2117354114df749a5327584885c88a0b3ad5f9d9/material/201026_signals/signals.pdf -------------------------------------------------------------------------------- /material/201026_signals/solutions/homework_problem_8.24/Makefile: -------------------------------------------------------------------------------- 1 | gcc=gcc -g -Werror -Wpedantic -Wall -o 2 | executable=illegal_activity_in_child_process 3 | src=$(executable).c 4 | 5 | 6 | compile: $(executable) 7 | 8 | run: compile 9 | ./$(executable) 10 | 11 | $(executable): $(src) 12 | $(gcc) $(executable) $(src) 13 | 14 | 15 | clean: 16 | rm -f $(executable) 17 | -------------------------------------------------------------------------------- /material/201026_signals/solutions/homework_problem_8.24/illegal_activity_in_child_process.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #define NUM_CHILDREN 2 10 | 11 | void child_lifespan(); 12 | int make_illegal_write(); 13 | 14 | int main() { 15 | int status, i; 16 | pid_t pid; 17 | 18 | for (i = 0; i < NUM_CHILDREN; i++) { 19 | if ((pid = fork()) == 0) { 20 | child_lifespan(); 21 | } 22 | sleep(1); 23 | } 24 | 25 | while ((pid = waitpid(-1, &status, 0)) > 0) { 26 | if (WIFSIGNALED(status)) { 27 | int sig_num = WTERMSIG(status); // fetch number of the terminating signal 28 | char msg[42]; 29 | sprintf(msg, "child %d terminated by signal %d", pid, sig_num); 30 | psignal(sig_num, msg); 31 | } 32 | 33 | else if (WIFEXITED(status)) { 34 | printf("child %d terminated normally with exit status = %d\n", 35 | pid, WEXITSTATUS(status)); 36 | } 37 | else { 38 | printf("child %d terminated abnormally ://\n", pid); 39 | } 40 | } 41 | 42 | /* The only normal termination is if there are no more children */ 43 | if (errno != ECHILD) { 44 | fprintf(stderr, "waitpid() error\n"); 45 | exit(1); 46 | } 47 | 48 | exit(0); 49 | } 50 | 51 | 52 | /* 53 | * during its lifespan of 20 seconds, a child process will do the following 10 times: 54 | * - sleep for 2 seconds. 55 | * - wake up and, with probability 1/8, 56 | * attempt to write to read-only segment. 57 | * 58 | * if child survives for 20 seconds without any 59 | * illegal activity; terminates with exit code 0. 60 | */ 61 | void child_lifespan() { 62 | srand(time(NULL)); 63 | 64 | int my_pid = getpid(); 65 | 66 | printf("child %d spawned: going to sleep for 2 seconds ...\n", my_pid); 67 | for (int i = 10; i >= 0; i--) { 68 | 69 | sleep(2); 70 | 71 | if (rand() % 8 == 0) // with probability 1/8, make an illegal write !! 72 | make_illegal_write(); 73 | 74 | printf("child %d: nothing illegal going on here !! going back to sleep for 2 secs ...\n", my_pid); 75 | } 76 | 77 | exit(0); 78 | } 79 | 80 | int make_illegal_write() { 81 | char *address_probably_in_read_only_segment = (char*) 0x7; 82 | *address_probably_in_read_only_segment = ' '; 83 | return 0; 84 | } 85 | 86 | -------------------------------------------------------------------------------- /material/201026_signals/solutions/homework_problem_8.25/Makefile: -------------------------------------------------------------------------------- 1 | gcc=gcc -g -Werror -Wpedantic -Wall -o 2 | src=tfgets.c 3 | executable=tfgets 4 | 5 | 6 | compile: $(executable) 7 | 8 | run: compile 9 | ./$(executable) 10 | 11 | $(executable): $(src) 12 | $(gcc) $(executable) $(src) 13 | 14 | clean: 15 | rm -f $(executable) 16 | -------------------------------------------------------------------------------- /material/201026_signals/solutions/homework_problem_8.25/tfgets: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diku-compSys/compSys-e2020-pub/2117354114df749a5327584885c88a0b3ad5f9d9/material/201026_signals/solutions/homework_problem_8.25/tfgets -------------------------------------------------------------------------------- /material/201028_virtual_memory_i/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !*.pdf 3 | !*.odp 4 | !*.md 5 | !.gitignore 6 | !*.c -------------------------------------------------------------------------------- /material/201028_virtual_memory_i/exercises.md: -------------------------------------------------------------------------------- 1 | # Exercises for 30/10/18 2 | 3 | Problems from CSapp: 4 | 5 | * 9.2 6 | * 9.3 7 | * 9.4 (most important) 8 | * 9.11, 9.12, 9.13 (like 9.4, with different constants) 9 | 10 | It is *extremely likely* that something like (9.4, 9.11-9.13) is in 11 | the exam. 12 | -------------------------------------------------------------------------------- /material/201028_virtual_memory_i/mem0.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(int argc, char** argv) { 5 | size_t num_gib = atoi(argv[1]); 6 | size_t to_alloc = num_gib * 1024 * 1024 * 1024; 7 | 8 | printf("allocating %ld bytes\n", (long)to_alloc); 9 | 10 | unsigned char *p = malloc(to_alloc); 11 | 12 | if (p) { 13 | while (1) ; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /material/201028_virtual_memory_i/mem1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(int argc, char** argv) { 5 | size_t num_gib = atoi(argv[1]); 6 | int num_writes = atoi(argv[2]); 7 | int stride = atoi(argv[3]); 8 | size_t to_alloc = num_gib * 1024 * 1024 * 1024; 9 | 10 | printf("allocating %ld bytes\n", (long)to_alloc); 11 | 12 | unsigned char *p = malloc(to_alloc); 13 | 14 | if (p) { 15 | while (1) { 16 | for (int i = 0; i < num_writes; i++) { 17 | p[(i*stride) % to_alloc] = rand(); 18 | } 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /material/201028_virtual_memory_i/memfork.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main(int argc, char** argv) { 6 | size_t num_gib = atoi(argv[1]); 7 | int num_procs = atoi(argv[2]); 8 | size_t to_alloc = num_gib * 1024 * 1024 * 1024; 9 | 10 | printf("allocating %ld bytes\n", (long)to_alloc); 11 | 12 | unsigned char *p = malloc(to_alloc); 13 | 14 | for (size_t i = 0; i < to_alloc; i++) { 15 | p[i] = rand(); 16 | } 17 | 18 | for (int i = 0; i < num_procs; i++) { 19 | if (fork() == 0) { 20 | // In child. 21 | while (1) ; 22 | } 23 | } 24 | 25 | while (1) ; 26 | } 27 | -------------------------------------------------------------------------------- /material/201028_virtual_memory_i/virtual_memory_i.odp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diku-compSys/compSys-e2020-pub/2117354114df749a5327584885c88a0b3ad5f9d9/material/201028_virtual_memory_i/virtual_memory_i.odp -------------------------------------------------------------------------------- /material/201028_virtual_memory_i/virtual_memory_i.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diku-compSys/compSys-e2020-pub/2117354114df749a5327584885c88a0b3ad5f9d9/material/201028_virtual_memory_i/virtual_memory_i.pdf -------------------------------------------------------------------------------- /material/201102_virtual_memory_ii/compsys_malloc.h: -------------------------------------------------------------------------------- 1 | #ifndef COMPSYS_MALLOC_H 2 | #define COMPSYS_MALLOC_H 3 | 4 | void compsys_heap_init(); 5 | void *compsys_calloc(size_t nmemb, size_t size); 6 | void *compsys_malloc(size_t size); 7 | void compsys_free(void *ptr); 8 | void *compsys_realloc(void *ptr, size_t size); 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /material/201102_virtual_memory_ii/exercises.md: -------------------------------------------------------------------------------- 1 | # Exercises from the book 2 | 3 | * 9.10 4 | * 9.14 5 | * 9.15 6 | * 9.16 7 | * 9.17 (harder) 8 | * 9.19 9 | 10 | Questions like 9.15, 9.16, and 9.19 are likely to appear in the exam. 11 | 12 | # Improving compsys_malloc.c (The Fun One) 13 | 14 | The provided `compsys_malloc.c` allocates out of a fixed-size heap 15 | (256 bytes by default). Rewrite it to use `mmap()` to instead request 16 | memory from the kernel as necessary. 17 | -------------------------------------------------------------------------------- /material/201102_virtual_memory_ii/mallocs.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main() { 6 | for (int i = 1; i < 30; i++) { 7 | int num_bytes = 1 << i; 8 | printf("malloc(%d): ", num_bytes); 9 | printf("%p\n", malloc(num_bytes)); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /material/201102_virtual_memory_ii/mmap_fork.c: -------------------------------------------------------------------------------- 1 | // Demonstrates sharing memory between parent and child. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | int main(int argc, char** argv) { 11 | char *filename = argv[1]; 12 | int num_bytes = 10000; 13 | 14 | FILE* file = fopen(filename, "r"); 15 | assert(file != NULL); 16 | fseek(file, 0, SEEK_END); 17 | int size = ftell(file); 18 | fseek(file, 0, SEEK_SET); 19 | 20 | unsigned char *data = mmap(NULL, 21 | size, 22 | PROT_WRITE | PROT_READ, 23 | MAP_ANON | MAP_SHARED, 24 | 0, 0); 25 | assert(data != MAP_FAILED); 26 | 27 | pid_t pid = fork(); 28 | if (pid == 0) { 29 | assert(fread(data, 1, size, file) == size); 30 | exit(0); 31 | } else { 32 | fclose(file); 33 | waitpid(pid, NULL, 0); 34 | for (int i = 0; i < size; i++) { 35 | putchar(data[i]); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /material/201102_virtual_memory_ii/small_mallocs.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | for (int i = 1; i < 30000000; i++) { 6 | int num_bytes = 64; 7 | printf("malloc(%d) = %p\n", num_bytes, malloc(num_bytes)); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /material/201102_virtual_memory_ii/virtual_memory_ii.odp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diku-compSys/compSys-e2020-pub/2117354114df749a5327584885c88a0b3ad5f9d9/material/201102_virtual_memory_ii/virtual_memory_ii.odp -------------------------------------------------------------------------------- /material/201102_virtual_memory_ii/virtual_memory_ii.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diku-compSys/compSys-e2020-pub/2117354114df749a5327584885c88a0b3ad5f9d9/material/201102_virtual_memory_ii/virtual_memory_ii.pdf -------------------------------------------------------------------------------- /material/201106_concurrent_programming/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !*.pdf 3 | !*.odp 4 | !*.md 5 | !.gitignore 6 | !*.c -------------------------------------------------------------------------------- /material/201106_concurrent_programming/badcnt.c: -------------------------------------------------------------------------------- 1 | /* 2 | * gcc badcnt.c csapp.c -o badcnt -pthread 3 | */ 4 | 5 | #include "csapp.h" 6 | 7 | /* Global shared variable */ 8 | volatile long cnt = 0; /* Counter */ 9 | 10 | /* Thread routine */ 11 | void *thread(void *vargp) 12 | { 13 | long niters = 14 | *((long *)vargp); 15 | 16 | for (long i = 0; i < niters; i++) 17 | cnt++; 18 | 19 | return NULL; 20 | } 21 | 22 | int main(int argc, char **argv) 23 | { 24 | long niters; 25 | pthread_t tid1, tid2; 26 | 27 | niters = atoi(argv[1]); 28 | Pthread_create(&tid1, NULL, 29 | thread, &niters); 30 | Pthread_create(&tid2, NULL, 31 | thread, &niters); 32 | Pthread_join(tid1, NULL); 33 | Pthread_join(tid2, NULL); 34 | 35 | /* Check result */ 36 | if (cnt != (2 * niters)) 37 | printf("BOOM! cnt=%ld\n", cnt); 38 | else 39 | printf("OK cnt=%ld\n", cnt); 40 | exit(0); 41 | } 42 | -------------------------------------------------------------------------------- /material/201106_concurrent_programming/concurrent_programming.odp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diku-compSys/compSys-e2020-pub/2117354114df749a5327584885c88a0b3ad5f9d9/material/201106_concurrent_programming/concurrent_programming.odp -------------------------------------------------------------------------------- /material/201106_concurrent_programming/concurrent_programming.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diku-compSys/compSys-e2020-pub/2117354114df749a5327584885c88a0b3ad5f9d9/material/201106_concurrent_programming/concurrent_programming.pdf -------------------------------------------------------------------------------- /material/201106_concurrent_programming/exercises.md: -------------------------------------------------------------------------------- 1 | # Exercises for 2019-11-08 2 | 3 | * 12.6 (page 1031) 4 | * 12.9 (page 1042) 5 | * 12.10 (page 1044) 6 | * 12.17 (page 1067) 7 | * 12.18 (page 1068) 8 | * 12.19 (page 1068) 9 | -------------------------------------------------------------------------------- /material/201106_concurrent_programming/goodcnt.c: -------------------------------------------------------------------------------- 1 | /* 2 | * gcc goodcnt.c csapp.c -o goodcnt -pthread 3 | */ 4 | 5 | #include "csapp.h" 6 | 7 | /* Global shared variable */ 8 | volatile long cnt = 0; /* Counter */ 9 | pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 10 | 11 | /* Thread routine */ 12 | void *thread(void *vargp) 13 | { 14 | long i, niters = 15 | *((long *)vargp); 16 | 17 | for (i = 0; i < niters; i++) { 18 | pthread_mutex_lock(&mutex); 19 | cnt++; 20 | pthread_mutex_unlock(&mutex); 21 | } 22 | 23 | return NULL; 24 | } 25 | 26 | int main(int argc, char **argv) 27 | { 28 | long niters; 29 | pthread_t tid1, tid2; 30 | 31 | niters = atoi(argv[1]); 32 | Pthread_create(&tid1, NULL, 33 | thread, &niters); 34 | Pthread_create(&tid2, NULL, 35 | thread, &niters); 36 | Pthread_join(tid1, NULL); 37 | Pthread_join(tid2, NULL); 38 | 39 | /* Check result */ 40 | if (cnt != (2 * niters)) 41 | printf("BOOM! cnt=%ld\n", cnt); 42 | else 43 | printf("OK cnt=%ld\n", cnt); 44 | exit(0); 45 | } 46 | -------------------------------------------------------------------------------- /material/201106_concurrent_programming/hello.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | void* thread_fn(void* arg) { 6 | (void)arg; 7 | printf("Hello, world!\n"); 8 | 9 | return NULL; 10 | } 11 | 12 | int main() { 13 | pthread_t tid; 14 | 15 | assert(pthread_create(&tid, NULL, thread_fn, NULL) == 0); 16 | 17 | void *result; 18 | assert(pthread_join(tid, &result) == 0); 19 | 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /material/201106_concurrent_programming/parcat.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 5 | 6 | void* thread_fn(void* arg) { 7 | FILE *file = (FILE*)arg; 8 | char c; 9 | int cont = 1; 10 | 11 | 12 | while (cont) { 13 | pthread_mutex_lock(&mutex); 14 | r = fread(&c, sizeof(c), 1, file); 15 | if (r == 0) { 16 | cont = 0; 17 | } else { 18 | putchar(c); 19 | } 20 | pthread_mutex_unlock(&mutex); 21 | } 22 | 23 | return NULL; 24 | } 25 | 26 | int main(int argc, char** argv) { 27 | FILE *file = fopen(argv[1], "r"); 28 | pthread_t tid1, tid2; 29 | pthread_create(&tid1, NULL, thread_fn, (void*)file); 30 | pthread_create(&tid2, NULL, thread_fn, (void*)file); 31 | pthread_join(tid1, NULL); 32 | pthread_join(tid2, NULL); 33 | } 34 | -------------------------------------------------------------------------------- /material/201106_concurrent_programming/sharing.c: -------------------------------------------------------------------------------- 1 | #include "csapp.h" 2 | 3 | char **ptr; /* global var */ 4 | 5 | void *thread(void *vargp) 6 | { 7 | long myid = (long)vargp; 8 | static int cnt = 0; 9 | 10 | printf("[%ld]: %s (cnt=%d)\n", 11 | myid, ptr[myid], ++cnt); 12 | return NULL; 13 | } 14 | 15 | int main() 16 | { 17 | long i; 18 | pthread_t tid; 19 | char *msgs[2] = { 20 | "Hello from foo", 21 | "Hello from bar" 22 | }; 23 | 24 | ptr = msgs; 25 | for (i = 0; i < 2; i++) 26 | Pthread_create(&tid, 27 | NULL, 28 | thread, 29 | (void *)i); 30 | Pthread_exit(NULL); 31 | } 32 | -------------------------------------------------------------------------------- /material/201106_concurrent_programming/sumbytes.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | struct work { 10 | unsigned char *data; 11 | int start; 12 | int end; 13 | }; 14 | 15 | pthread_mutex_t sum_mutex = PTHREAD_MUTEX_INITIALIZER; 16 | 17 | long sum = 0; 18 | 19 | void* thread(void* p) { 20 | struct work work = *(struct work*)p; 21 | free(p); 22 | 23 | long local_sum = 0; 24 | 25 | for (int i = work.start; i < work.end; i++) { 26 | local_sum += work.data[i]; 27 | } 28 | 29 | pthread_mutex_lock(&sum_mutex); 30 | sum += local_sum; 31 | pthread_mutex_unlock(&sum_mutex); 32 | 33 | return NULL; 34 | } 35 | 36 | int main(int argc, char** argv) { 37 | int nthreads = atoi(argv[1]); 38 | char *filename = argv[2]; 39 | 40 | FILE* file = fopen(filename, "r"); 41 | assert(file != NULL); 42 | fseek(file, 0, SEEK_END); 43 | int size = ftell(file); 44 | fseek(file, 0, SEEK_SET); 45 | 46 | int chunk_size = (size + nthreads - 1) / nthreads; 47 | 48 | unsigned char *data = mmap(NULL, 49 | size, 50 | PROT_READ, 51 | MAP_PRIVATE, 52 | fileno(file), 0); 53 | assert(data != MAP_FAILED); 54 | 55 | pthread_t ptids[nthreads]; 56 | 57 | for (int i = 0; i < nthreads; i++) { 58 | struct work *work = malloc(sizeof(struct work)); 59 | work->data = data; 60 | work->start = i * chunk_size; 61 | work->end = (i+1) * chunk_size; 62 | if (work->end > size) { 63 | work->end = size; 64 | } 65 | 66 | assert(pthread_create(&ptids[i], NULL, thread, work) == 0); 67 | } 68 | 69 | for (int i = 0; i < nthreads; i++) { 70 | assert(pthread_join(ptids[i], NULL) == 0); 71 | } 72 | 73 | printf("sum: %ld\n", sum); 74 | } 75 | -------------------------------------------------------------------------------- /material/201116_advanced_concurrency/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !*.md 3 | !*.md 4 | !*.c 5 | !*.h 6 | !*.input 7 | !.gitignore 8 | !*.pdf 9 | !Makefile 10 | !README 11 | -------------------------------------------------------------------------------- /material/201116_advanced_concurrency/Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS=-O3 -pthread -Wall -Wextra -pedantic 2 | CC=gcc 3 | PROGS=fibs fibs-futures fibs-mt fibs-threadpool fibs-threadpool-spin main-one-cv-while main-two-cvs-if main-two-cvs-while main-two-cvs-while-extra-unlock 4 | 5 | all: $(PROGS) 6 | 7 | %: %.c 8 | $(CC) -o $@ $< $(CFLAGS) 9 | 10 | clean: 11 | rm -f $(PROGS) 12 | -------------------------------------------------------------------------------- /material/201116_advanced_concurrency/exercises.md: -------------------------------------------------------------------------------- 1 | # Exercises for 2020-11-16 2 | 3 | Solve the exercises from the end of the [reading material on condition 4 | variables](http://pages.cs.wisc.edu/~remzi/OSTEP/threads-cv.pdf). The 5 | files you need are in this directory. 6 | 7 | ## And a fun one 8 | 9 | Modify the futures implementation used by `fibs-futures.c` to also use 10 | a thread pool or task queue to avoid having to launch a thread for 11 | every future. Combine this with `fibs-threadpool.c` to efficiently 12 | exploit all degrees of parallelism. 13 | -------------------------------------------------------------------------------- /material/201116_advanced_concurrency/fibs-futures.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "futures.h" 6 | 7 | static const int PAR_THRESHOLD = 30; 8 | 9 | int fib (int n); 10 | 11 | void* fib_thread(void *arg) { 12 | int *r = malloc(sizeof(int)); 13 | int n = *(int*)arg; 14 | 15 | *r = fib(n); 16 | 17 | return r; 18 | } 19 | 20 | int fib (int n) { 21 | if (n < 2) { 22 | return 1; 23 | } else { 24 | if (n >= PAR_THRESHOLD) { 25 | int *x, *y; 26 | int n1 = n-1, n2 = n-2; 27 | struct future *f1 = future_create(fib_thread, &n1); 28 | struct future *f2 = future_create(fib_thread, &n2); 29 | x = future_get(f1); 30 | y = future_get(f2); 31 | return *x + *y; 32 | } else { 33 | return fib(n-1) + fib(n-2); 34 | } 35 | } 36 | } 37 | 38 | int main() { 39 | char *line = NULL; 40 | ssize_t line_len; 41 | size_t buf_len = 0; 42 | 43 | while ((line_len = getline(&line, &buf_len, stdin)) != -1) { 44 | int n = atoi(line); 45 | printf("fib(%d) = %d\n", n, fib(n)); 46 | } 47 | 48 | free(line); 49 | } 50 | -------------------------------------------------------------------------------- /material/201116_advanced_concurrency/fibs-huge.input: -------------------------------------------------------------------------------- 1 | 40 2 | 41 3 | 42 4 | 43 5 | 45 6 | -------------------------------------------------------------------------------- /material/201116_advanced_concurrency/fibs-medium.input: -------------------------------------------------------------------------------- 1 | 20 2 | 21 3 | 22 4 | 23 5 | 24 6 | 25 7 | 26 8 | 27 9 | 28 10 | 29 11 | 30 12 | 20 13 | 21 14 | 22 15 | 23 16 | 24 17 | 25 18 | 26 19 | 27 20 | 28 21 | 29 22 | 30 23 | -------------------------------------------------------------------------------- /material/201116_advanced_concurrency/fibs-mt.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int fib (int n) { 7 | if (n < 2) { 8 | return 1; 9 | } else { 10 | return fib(n-1) + fib(n-2); 11 | } 12 | } 13 | 14 | void* fib_thread(void* arg) { 15 | char *line = arg; 16 | int n = atoi(line); 17 | printf("fib(%d) = %d\n", n, fib(n)); 18 | free(arg); 19 | return NULL; 20 | } 21 | 22 | int main() { 23 | char *line = NULL; 24 | ssize_t line_len; 25 | size_t buf_len = 0; 26 | 27 | int i = 0; 28 | pthread_t threads[200000]; 29 | 30 | while ((line_len = getline(&line, &buf_len, stdin)) != -1) { 31 | pthread_create(&threads[i], NULL, fib_thread, strdup(line)); 32 | i++; 33 | } 34 | 35 | for (int j = 0; j < i; j++) { 36 | pthread_join(threads[j], NULL); 37 | } 38 | 39 | free(line); 40 | } 41 | -------------------------------------------------------------------------------- /material/201116_advanced_concurrency/fibs-threadpool-spin.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | int fib (int n) { 9 | if (n < 2) { 10 | return 1; 11 | } else { 12 | return fib(n-1) + fib(n-2); 13 | } 14 | } 15 | 16 | pthread_mutex_t line_mutex = PTHREAD_MUTEX_INITIALIZER; 17 | char *volatile line = NULL; 18 | volatile int die = 0; 19 | 20 | void* worker(void* arg) { 21 | arg=arg; 22 | int done = 0; 23 | 24 | while (!done) { 25 | char *my_line = NULL; 26 | assert(pthread_mutex_lock(&line_mutex) == 0); 27 | 28 | if (line == NULL && die) { 29 | done = 1; 30 | } 31 | 32 | if (line != NULL) { 33 | my_line = line; 34 | line = NULL; 35 | } 36 | 37 | assert(pthread_mutex_unlock(&line_mutex) == 0); 38 | 39 | if (my_line != NULL) { 40 | int n = atoi(my_line); 41 | printf("fib(%d) = %d\n", n, fib(n)); 42 | free(my_line); 43 | } 44 | } 45 | 46 | return NULL; 47 | } 48 | 49 | int main() { 50 | char *my_line = NULL; 51 | ssize_t line_len; 52 | size_t buf_len = 0; 53 | 54 | // Create the threads. 55 | int num_threads = sysconf(_SC_NPROCESSORS_ONLN); 56 | pthread_t *threads = malloc(num_threads*sizeof(pthread_t)); 57 | for (int i = 0; i < num_threads; i++) { 58 | pthread_create(&threads[i], NULL, worker, NULL); 59 | } 60 | 61 | while ((line_len = getline(&my_line, &buf_len, stdin)) != -1) { 62 | int done = 0; 63 | while (!done) { 64 | assert(pthread_mutex_lock(&line_mutex) == 0); 65 | if (line == NULL) { 66 | line = strdup(my_line); 67 | done = 1; 68 | } 69 | assert(pthread_mutex_unlock(&line_mutex) == 0); 70 | } 71 | } 72 | 73 | die = 1; 74 | 75 | for (int i = 0; i < num_threads; i++) { 76 | pthread_join(threads[i], NULL); 77 | } 78 | 79 | free(my_line); 80 | } 81 | -------------------------------------------------------------------------------- /material/201116_advanced_concurrency/fibs-threadpool.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | int fib (int n) { 9 | if (n < 2) { 10 | return 1; 11 | } else { 12 | return fib(n-1) + fib(n-2); 13 | } 14 | } 15 | 16 | pthread_cond_t line_cond = PTHREAD_COND_INITIALIZER; 17 | pthread_mutex_t line_mutex = PTHREAD_MUTEX_INITIALIZER; 18 | char *volatile line = NULL; 19 | volatile int die = 0; 20 | 21 | void* worker(void* arg) { 22 | arg=arg; 23 | int done = 0; 24 | 25 | while (!done) { 26 | char *my_line = NULL; 27 | assert(pthread_mutex_lock(&line_mutex) == 0); 28 | 29 | if (line == NULL && !die) { 30 | pthread_cond_wait(&line_cond, &line_mutex); 31 | } else if (line == NULL && die) { 32 | done = 1; 33 | } else if (line != NULL) { 34 | my_line = line; 35 | line = NULL; 36 | pthread_cond_broadcast(&line_cond); 37 | } 38 | 39 | assert(pthread_mutex_unlock(&line_mutex) == 0); 40 | 41 | if (my_line != NULL) { 42 | int n = atoi(my_line); 43 | printf("fib(%d) = %d\n", n, fib(n)); 44 | free(my_line); 45 | } 46 | } 47 | 48 | return NULL; 49 | } 50 | 51 | int main() { 52 | char *my_line = NULL; 53 | ssize_t line_len; 54 | size_t buf_len = 0; 55 | 56 | // Create the threads. 57 | int num_threads = sysconf(_SC_NPROCESSORS_ONLN); 58 | pthread_t *threads = malloc(num_threads*sizeof(pthread_t)); 59 | for (int i = 0; i < num_threads; i++) { 60 | pthread_create(&threads[i], NULL, worker, NULL); 61 | } 62 | 63 | while ((line_len = getline(&my_line, &buf_len, stdin)) != -1) { 64 | int done = 0; 65 | while (!done) { 66 | assert(pthread_mutex_lock(&line_mutex) == 0); 67 | if (line == NULL) { 68 | line = strdup(my_line); 69 | pthread_cond_signal(&line_cond); 70 | done = 1; 71 | } else { 72 | pthread_cond_wait(&line_cond, &line_mutex); 73 | } 74 | assert(pthread_mutex_unlock(&line_mutex) == 0); 75 | } 76 | } 77 | 78 | assert(pthread_mutex_lock(&line_mutex) == 0); 79 | die = 1; 80 | pthread_cond_broadcast(&line_cond); 81 | assert(pthread_mutex_unlock(&line_mutex) == 0); 82 | 83 | for (int i = 0; i < num_threads; i++) { 84 | pthread_join(threads[i], NULL); 85 | } 86 | 87 | free(my_line); 88 | } 89 | -------------------------------------------------------------------------------- /material/201116_advanced_concurrency/fibs.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int fib (int n) { 6 | if (n < 2) { 7 | return 1; 8 | } else { 9 | return fib(n-1) + fib(n-2); 10 | } 11 | } 12 | 13 | int main() { 14 | char *line = NULL; 15 | ssize_t line_len; 16 | size_t buf_len = 0; 17 | 18 | while ((line_len = getline(&line, &buf_len, stdin)) != -1) { 19 | int n = atoi(line); 20 | printf("fib(%d) = %d\n", n, fib(n)); 21 | } 22 | 23 | free(line); 24 | } 25 | -------------------------------------------------------------------------------- /material/201116_advanced_concurrency/futures.h: -------------------------------------------------------------------------------- 1 | // Futures are a programming abstraction where we can asynchronously 2 | // create a value by providing a pointer to a function that creates 3 | // it. When we then later ask for the actual value, we either receive 4 | // the value immediately, or block until it is available. Futures are 5 | // a pretty simple way to exploit parallelism. The implementation in 6 | // this header file is simplistic, in that it does not do any thread 7 | // pooling. 8 | 9 | #include 10 | #include 11 | 12 | // We represent a future as the data and a thread handle. 13 | struct future { 14 | void *data; 15 | pthread_t p; 16 | }; 17 | 18 | // Create a new future whose value is computed by the given function, 19 | // which returns the address of the value. 20 | typedef void* (*future_fn)(void*); 21 | struct future* future_create(future_fn, void*); 22 | 23 | // Get the value from the future and destroy the future. Blocks if 24 | // necessary. 25 | void* future_get(struct future*); 26 | 27 | struct future* future_create(future_fn f, void *arg) { 28 | struct future *future = malloc(sizeof(struct future)); 29 | int ret = pthread_create(&future->p, NULL, f, arg); 30 | assert(ret == 0); 31 | return future; 32 | } 33 | 34 | void* future_get(struct future* future) { 35 | void *vp; 36 | int ret = pthread_join(future->p, &vp); 37 | assert(ret == 0); 38 | free(future); 39 | return vp; 40 | } 41 | -------------------------------------------------------------------------------- /material/201116_advanced_concurrency/main-one-cv-while.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "mythreads.h" 12 | 13 | #include "pc-header.h" 14 | 15 | pthread_cond_t cv = PTHREAD_COND_INITIALIZER; 16 | pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER; 17 | 18 | #include "main-header.h" 19 | 20 | void do_fill(int value) { 21 | // ensure empty before usage 22 | ensure(buffer[fill_ptr] == EMPTY, "error: tried to fill a non-empty buffer"); 23 | buffer[fill_ptr] = value; 24 | fill_ptr = (fill_ptr + 1) % max; 25 | num_full++; 26 | } 27 | 28 | int do_get() { 29 | int tmp = buffer[use_ptr]; 30 | ensure(tmp != EMPTY, "error: tried to get an empty buffer"); 31 | buffer[use_ptr] = EMPTY; 32 | use_ptr = (use_ptr + 1) % max; 33 | num_full--; 34 | return tmp; 35 | } 36 | 37 | void *producer(void *arg) { 38 | int id = (uintptr_t) arg; 39 | // make sure each producer produces unique values 40 | int base = id * loops; 41 | int i; 42 | for (i = 0; i < loops; i++) { p0; 43 | Mutex_lock(&m); p1; 44 | while (num_full == max) { p2; 45 | Cond_wait(&cv, &m); p3; 46 | } 47 | do_fill(base + i); p4; 48 | Cond_signal(&cv); p5; 49 | Mutex_unlock(&m); p6; 50 | } 51 | return NULL; 52 | } 53 | 54 | void *consumer(void *arg) { 55 | int id = (uintptr_t) arg; 56 | int tmp = 0; 57 | int consumed_count = 0; 58 | while (tmp != END_OF_STREAM) { c0; 59 | Mutex_lock(&m); c1; 60 | while (num_full == 0) { c2; 61 | Cond_wait(&cv, &m); c3; 62 | } 63 | tmp = do_get(); c4; 64 | Cond_signal(&cv); c5; 65 | Mutex_unlock(&m); c6; 66 | consumed_count++; 67 | } 68 | 69 | // return consumer_count-1 because END_OF_STREAM does not count 70 | return (void *) (long long) (consumed_count - 1); 71 | } 72 | 73 | // must set these appropriately to use "main-common.c" 74 | pthread_cond_t *fill_cv = &cv; 75 | pthread_cond_t *empty_cv = &cv; 76 | 77 | // all codes use this common base to start producers/consumers 78 | // and all the other related stuff 79 | #include "main-common.c" 80 | -------------------------------------------------------------------------------- /material/201116_advanced_concurrency/main-two-cvs-if.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "mythreads.h" 12 | #include "pc-header.h" 13 | 14 | pthread_cond_t empty = PTHREAD_COND_INITIALIZER; 15 | pthread_cond_t fill = PTHREAD_COND_INITIALIZER; 16 | pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER; 17 | 18 | #include "main-header.h" 19 | 20 | void do_fill(int value) { 21 | // ensure empty before usage 22 | ensure(buffer[fill_ptr] == EMPTY, "error: tried to fill a non-empty buffer"); 23 | buffer[fill_ptr] = value; 24 | fill_ptr = (fill_ptr + 1) % max; 25 | num_full++; 26 | } 27 | 28 | int do_get() { 29 | int tmp = buffer[use_ptr]; 30 | ensure(tmp != EMPTY, "error: tried to get an empty buffer"); 31 | buffer[use_ptr] = EMPTY; 32 | use_ptr = (use_ptr + 1) % max; 33 | num_full--; 34 | return tmp; 35 | } 36 | 37 | void *producer(void *arg) { 38 | int id = (uintptr_t) arg; 39 | // make sure each producer produces unique values 40 | int base = id * loops; 41 | int i; 42 | for (i = 0; i < loops; i++) { p0; 43 | Mutex_lock(&m); p1; 44 | if (num_full == max) { p2; 45 | Cond_wait(&empty, &m); p3; 46 | } 47 | do_fill(base + i); p4; 48 | Cond_signal(&fill); p5; 49 | Mutex_unlock(&m); p6; 50 | } 51 | return NULL; 52 | } 53 | 54 | void *consumer(void *arg) { 55 | int id = (uintptr_t) arg; 56 | int tmp = 0; 57 | int consumed_count = 0; 58 | while (tmp != END_OF_STREAM) { c0; 59 | Mutex_lock(&m); c1; 60 | if (num_full == 0) { c2; 61 | Cond_wait(&fill, &m); c3; 62 | } 63 | tmp = do_get(); c4; 64 | Cond_signal(&empty); c5; 65 | Mutex_unlock(&m); c6; 66 | consumed_count++; 67 | } 68 | 69 | // return consumer_count-1 because END_OF_STREAM does not count 70 | return (void *) (long long) (consumed_count - 1); 71 | } 72 | 73 | // must set these appropriately to use "main-common.c" 74 | pthread_cond_t *fill_cv = &fill; 75 | pthread_cond_t *empty_cv = ∅ 76 | 77 | // all codes use this common base to start producers/consumers 78 | // and all the other related stuff 79 | #include "main-common.c" 80 | -------------------------------------------------------------------------------- /material/201116_advanced_concurrency/main-two-cvs-while-extra-unlock.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "mythreads.h" 12 | 13 | #include "pc-header.h" 14 | 15 | pthread_cond_t empty = PTHREAD_COND_INITIALIZER; 16 | pthread_cond_t fill = PTHREAD_COND_INITIALIZER; 17 | pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER; 18 | 19 | #include "main-header.h" 20 | 21 | void do_fill(int value) { 22 | // ensure empty before usage 23 | ensure(buffer[fill_ptr] == EMPTY, "error: tried to fill a non-empty buffer"); 24 | buffer[fill_ptr] = value; 25 | fill_ptr = (fill_ptr + 1) % max; 26 | num_full++; 27 | } 28 | 29 | int do_get() { 30 | int tmp = buffer[use_ptr]; 31 | ensure(tmp != EMPTY, "error: tried to get an empty buffer"); 32 | buffer[use_ptr] = EMPTY; 33 | use_ptr = (use_ptr + 1) % max; 34 | num_full--; 35 | return tmp; 36 | } 37 | 38 | void *producer(void *arg) { 39 | int id = (uintptr_t) arg; 40 | // make sure each producer produces unique values 41 | int base = id * loops; 42 | int i; 43 | for (i = 0; i < loops; i++) { p0; 44 | Mutex_lock(&m); p1; 45 | while (num_full == max) { p2; 46 | Cond_wait(&empty, &m); p3; 47 | } 48 | Mutex_unlock(&m); 49 | do_fill(base + i); p4; 50 | Mutex_lock(&m); 51 | Cond_signal(&fill); p5; 52 | Mutex_unlock(&m); p6; 53 | } 54 | return NULL; 55 | } 56 | 57 | void *consumer(void *arg) { 58 | int id = (uintptr_t) arg; 59 | int tmp = 0; 60 | int consumed_count = 0; 61 | while (tmp != END_OF_STREAM) { c0; 62 | Mutex_lock(&m); c1; 63 | while (num_full == 0) { c2; 64 | Cond_wait(&fill, &m); c3; 65 | } 66 | Mutex_unlock(&m); 67 | tmp = do_get(); c4; 68 | Mutex_lock(&m); 69 | Cond_signal(&empty); c5; 70 | Mutex_unlock(&m); c6; 71 | consumed_count++; 72 | } 73 | 74 | // return consumer_count-1 because END_OF_STREAM does not count 75 | return (void *) (long long) (consumed_count - 1); 76 | } 77 | 78 | // must set these appropriately to use "main-common.c" 79 | pthread_cond_t *fill_cv = &fill; 80 | pthread_cond_t *empty_cv = ∅ 81 | 82 | // all codes use this common base to start producers/consumers 83 | // and all the other related stuff 84 | #include "main-common.c" 85 | -------------------------------------------------------------------------------- /material/201116_advanced_concurrency/main-two-cvs-while.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "mythreads.h" 12 | 13 | #include "pc-header.h" 14 | 15 | // used in producer/consumer signaling protocol 16 | pthread_cond_t empty = PTHREAD_COND_INITIALIZER; 17 | pthread_cond_t fill = PTHREAD_COND_INITIALIZER; 18 | pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER; 19 | 20 | #include "main-header.h" 21 | 22 | void do_fill(int value) { 23 | // ensure empty before usage 24 | ensure(buffer[fill_ptr] == EMPTY, "error: tried to fill a non-empty buffer"); 25 | buffer[fill_ptr] = value; 26 | fill_ptr = (fill_ptr + 1) % max; 27 | num_full++; 28 | } 29 | 30 | int do_get() { 31 | int tmp = buffer[use_ptr]; 32 | ensure(tmp != EMPTY, "error: tried to get an empty buffer"); 33 | buffer[use_ptr] = EMPTY; 34 | use_ptr = (use_ptr + 1) % max; 35 | num_full--; 36 | return tmp; 37 | } 38 | 39 | void *producer(void *arg) { 40 | int id = (uintptr_t) arg; 41 | // make sure each producer produces unique values 42 | int base = id * loops; 43 | int i; 44 | for (i = 0; i < loops; i++) { p0; 45 | Mutex_lock(&m); p1; 46 | while (num_full == max) { p2; 47 | Cond_wait(&empty, &m); p3; 48 | } 49 | do_fill(base + i); p4; 50 | Cond_signal(&fill); p5; 51 | Mutex_unlock(&m); p6; 52 | } 53 | return NULL; 54 | } 55 | 56 | void *consumer(void *arg) { 57 | int id = (uintptr_t) arg; 58 | int tmp = 0; 59 | int consumed_count = 0; 60 | while (tmp != END_OF_STREAM) { c0; 61 | Mutex_lock(&m); c1; 62 | while (num_full == 0) { c2; 63 | Cond_wait(&fill, &m); c3; 64 | } 65 | tmp = do_get(); c4; 66 | Cond_signal(&empty); c5; 67 | Mutex_unlock(&m); c6; 68 | consumed_count++; 69 | } 70 | 71 | // return consumer_count-1 because END_OF_STREAM does not count 72 | return (void *) (long long) (consumed_count - 1); 73 | } 74 | 75 | // must set these appropriately to use "main-common.c" 76 | pthread_cond_t *fill_cv = &fill; 77 | pthread_cond_t *empty_cv = ∅ 78 | 79 | // all codes use this common base to start producers/consumers 80 | // and all the other related stuff 81 | #include "main-common.c" 82 | -------------------------------------------------------------------------------- /material/201116_advanced_concurrency/mythreads.h: -------------------------------------------------------------------------------- 1 | #ifndef __MYTHREADS_h__ 2 | #define __MYTHREADS_h__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | void *Malloc(size_t size) { 10 | void *p = malloc(size); 11 | assert(p != NULL); 12 | return p; 13 | } 14 | 15 | double Time_GetSeconds() { 16 | struct timeval t; 17 | int rc = gettimeofday(&t, NULL); 18 | assert(rc == 0); 19 | return (double) ((double)t.tv_sec + (double)t.tv_usec / 1e6); 20 | } 21 | 22 | void work(int seconds) { 23 | double t0 = Time_GetSeconds(); 24 | while ((Time_GetSeconds() - t0) < (double)seconds) 25 | ; 26 | } 27 | 28 | void Mutex_init(pthread_mutex_t *m) { 29 | assert(pthread_mutex_init(m, NULL) == 0); 30 | } 31 | 32 | void Mutex_lock(pthread_mutex_t *m) { 33 | int rc = pthread_mutex_lock(m); 34 | assert(rc == 0); 35 | } 36 | 37 | void Mutex_unlock(pthread_mutex_t *m) { 38 | int rc = pthread_mutex_unlock(m); 39 | assert(rc == 0); 40 | } 41 | 42 | void Cond_init(pthread_cond_t *c) { 43 | assert(pthread_cond_init(c, NULL) == 0); 44 | } 45 | 46 | void Cond_wait(pthread_cond_t *c, pthread_mutex_t *m) { 47 | int rc = pthread_cond_wait(c, m); 48 | assert(rc == 0); 49 | } 50 | 51 | void Cond_signal(pthread_cond_t *c) { 52 | int rc = pthread_cond_signal(c); 53 | assert(rc == 0); 54 | } 55 | 56 | 57 | void Pthread_create(pthread_t *thread, const pthread_attr_t *attr, 58 | void *(*start_routine)(void*), void *arg) { 59 | int rc = pthread_create(thread, attr, start_routine, arg); 60 | assert(rc == 0); 61 | } 62 | 63 | void Pthread_join(pthread_t thread, void **value_ptr) { 64 | int rc = pthread_join(thread, value_ptr); 65 | assert(rc == 0); 66 | } 67 | 68 | 69 | #endif // __MYTHREADS_h__ 70 | -------------------------------------------------------------------------------- /material/201116_advanced_concurrency/pc-header.h: -------------------------------------------------------------------------------- 1 | #ifndef __pc_header_h__ 2 | #define __pc_header_h__ 3 | 4 | #define MAX_THREADS (100) // maximum number of producers/consumers 5 | 6 | int producers = 1; // number of producers 7 | int consumers = 1; // number of consumers 8 | 9 | int *buffer; // the buffer itself: malloc in main() 10 | int max; // size of the producer/consumer buffer 11 | 12 | int use_ptr = 0; // tracks where next consume should come from 13 | int fill_ptr = 0; // tracks where next produce should go to 14 | int num_full = 0; // counts how many entries are full 15 | 16 | int loops; // number of items that each producer produces 17 | 18 | #define EMPTY (-2) // buffer slot has nothing in it 19 | #define END_OF_STREAM (-1) // consumer who grabs this should exit 20 | 21 | #endif // __pc_header_h__ 22 | 23 | -------------------------------------------------------------------------------- /material/201118_system_io/copy-buffered-byte.c: -------------------------------------------------------------------------------- 1 | #include "csapp.h" 2 | #include 3 | #include 4 | 5 | #define BUFSIZE 4096 6 | 7 | int main(int argc, char** argv) 8 | { 9 | int n; 10 | rio_t rio; 11 | char c; 12 | 13 | assert(argc == 3); 14 | int from = Open(argv[1], O_RDONLY, 0); 15 | int to = Open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0666); 16 | 17 | Rio_readinitb(&rio, from); 18 | while((n = Rio_readnb(&rio, &c, 1)) != 0) 19 | Rio_writen(to, &c, 1); 20 | 21 | close(from); 22 | close(to); 23 | } 24 | -------------------------------------------------------------------------------- /material/201118_system_io/copy-buffered.c: -------------------------------------------------------------------------------- 1 | #include "csapp.h" 2 | #include 3 | #include 4 | 5 | #define BUFSIZE 4096 6 | 7 | int main(int argc, char** argv) 8 | { 9 | int n; 10 | rio_t rio; 11 | char buf[BUFSIZE]; 12 | 13 | assert(argc == 3); 14 | int from = Open(argv[1], O_RDONLY, 0); 15 | int to = Open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0666); 16 | 17 | Rio_readinitb(&rio, from); 18 | while((n = Rio_readnb(&rio, buf, BUFSIZE)) != 0) 19 | Rio_writen(to, buf, n); 20 | 21 | close(from); 22 | close(to); 23 | } 24 | -------------------------------------------------------------------------------- /material/201118_system_io/copy-chunks.c: -------------------------------------------------------------------------------- 1 | #include "csapp.h" 2 | #include 3 | #include 4 | 5 | #define BUFSIZE 4096 6 | 7 | int main(int argc, char** argv) { 8 | int n; 9 | char buf[BUFSIZE]; 10 | 11 | assert(argc == 3); 12 | int from = Open(argv[1], O_RDONLY, 0); 13 | int to = Open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0666); 14 | 15 | while((n = Rio_readn(from, buf, BUFSIZE)) != 0) 16 | Rio_writen(to, buf, n); 17 | 18 | close(from); 19 | close(to); 20 | } 21 | -------------------------------------------------------------------------------- /material/201118_system_io/copy-mmap.c: -------------------------------------------------------------------------------- 1 | #include "csapp.h" 2 | #include 3 | #include 4 | 5 | int main(int argc, char** argv) 6 | { 7 | char c; 8 | struct stat stat; 9 | 10 | assert(argc == 3); 11 | int from = Open(argv[1], O_RDONLY, 0); 12 | int to = Open(argv[2], O_RDWR | O_CREAT, 0666); 13 | 14 | Stat(argv[1], &stat); 15 | size_t from_size = stat.st_size; 16 | 17 | void *from_p = Mmap(NULL, from_size, PROT_READ, 18 | MAP_FILE | MAP_PRIVATE | MAP_NOCACHE, 19 | from, 0); 20 | 21 | assert(ftruncate(to, from_size) == 0); 22 | 23 | void *to_p = Mmap(NULL, from_size, MAP_FILE | PROT_WRITE, MAP_SHARED, to, 0); 24 | 25 | memcpy(to_p, from_p, from_size); 26 | Munmap(to_p, from_size); 27 | close(from); 28 | close(to); 29 | } 30 | -------------------------------------------------------------------------------- /material/201118_system_io/copy-unbuffered.c: -------------------------------------------------------------------------------- 1 | #include "csapp.h" 2 | #include 3 | #include 4 | 5 | int main(int argc, char** argv) 6 | { 7 | char c; 8 | 9 | assert(argc == 3); 10 | int from = Open(argv[1], O_RDONLY, 0); 11 | int to = Open(argv[2], O_WRONLY | O_CREAT, 0666); 12 | 13 | while(Read(from, &c, 1) != 0) 14 | Write(to, &c, 1); 15 | 16 | close(from); 17 | close(to); 18 | } 19 | -------------------------------------------------------------------------------- /material/201118_system_io/exercise_code/Makefile: -------------------------------------------------------------------------------- 1 | gcc=gcc -g -Werror -Wpedantic -Wall -pthread -o 2 | # csapp=../csapp.c ../csapp.h 3 | 4 | all: fstatcheck cpfile 5 | 6 | fstatcheck: fstatcheck.c csapp.c csapp.h 7 | $(gcc) fstatcheck fstatcheck.c csapp.c 8 | 9 | cpfile: cpfile.c csapp.c csapp.h 10 | $(gcc) cpfile cpfile.c csapp.c # $(csapp) 11 | 12 | clean: 13 | rm -f cpfile fstatcheck 14 | -------------------------------------------------------------------------------- /material/201118_system_io/exercise_code/cpfile.c: -------------------------------------------------------------------------------- 1 | #include "csapp.h" 2 | 3 | int main(int argc, char **argv) { 4 | int n; 5 | rio_t rio; 6 | char buf[MAXLINE]; 7 | 8 | Rio_readinitb(&rio, STDIN_FILENO); 9 | 10 | while ((n = Rio_readlineb(&rio, buf, MAXLINE)) != 0) { 11 | Rio_writen(STDOUT_FILENO, buf, n); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /material/201118_system_io/exercise_code/fstatcheck.c: -------------------------------------------------------------------------------- 1 | #include "csapp.h" 2 | 3 | int main(int argc, char **argv) { 4 | struct stat stat; 5 | char *type, *readok; 6 | 7 | Stat(argv[1], &stat); 8 | if (S_ISREG(stat.st_mode)) /* Determine file type */ 9 | type = "regular"; 10 | else if (S_ISDIR(stat.st_mode)) 11 | type = "directory"; 12 | else 13 | type = "other"; 14 | 15 | 16 | if ((stat.st_mode & S_IRUSR)) /* Check read access */ 17 | readok = "yes"; 18 | else 19 | readok = "no"; 20 | 21 | printf("type: %s, read-enable: %s\n", type, readok); 22 | exit(0); 23 | } 24 | -------------------------------------------------------------------------------- /material/201118_system_io/exercise_code/solutions/Makefile: -------------------------------------------------------------------------------- 1 | gcc=gcc -I../../ -g -Werror -Wpedantic -Wall -pthread -o 2 | 3 | all: fstatcheck cpfile cpfile_infile 4 | 5 | fstatcheck: fstatcheck.c 6 | $(gcc) fstatcheck fstatcheck.c csapp.c 7 | 8 | cpfile: cpfile.c 9 | $(gcc) cpfile cpfile.c csapp.c 10 | 11 | cpfile_infile: cpfile_infile.c 12 | $(gcc) cpfile_infile cpfile_infile.c csapp.c 13 | 14 | 15 | clean: 16 | rm -f cpfile fstatcheck cpfile_infile 17 | -------------------------------------------------------------------------------- /material/201118_system_io/exercise_code/solutions/cpfile.c: -------------------------------------------------------------------------------- 1 | #include "csapp.h" 2 | 3 | int main(int argc, char **argv) { 4 | int n; 5 | rio_t rio; 6 | char buf[MAXBUF]; 7 | 8 | Rio_readinitb(&rio, STDIN_FILENO); 9 | 10 | while ((n = Rio_readn(STDIN_FILENO, buf, MAXBUF)) != 0) { 11 | Rio_writen(STDOUT_FILENO, buf, n); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /material/201118_system_io/exercise_code/solutions/cpfile_infile.c: -------------------------------------------------------------------------------- 1 | #include "csapp.h" 2 | 3 | int main(int argc, char **argv) { 4 | int n; 5 | rio_t rio; 6 | char buf[MAXLINE]; 7 | 8 | 9 | /* 10 | * the exercise explicitly states to solve the problem without changing 11 | * the while loop in the bottom of main(). 12 | * 13 | * to achieve this, I use dup2() to copy the file table entry from the 14 | * file descriptor of the opened file to descriptor 0 (stdin), meaning 15 | * bytes read from "stdin" will actually come from the file :):) 16 | * 17 | */ 18 | 19 | /* changes start here */ 20 | if (argc == 2) { 21 | 22 | char *filename = argv[1]; 23 | 24 | FILE *file = fopen(filename, "r"); 25 | if (file == NULL) { 26 | fprintf(stderr, "fopen() error: %s\n", strerror(errno)); 27 | exit(1); 28 | } 29 | 30 | int fd = fileno(file); // according to the man page, fileno never fails :PP 31 | if (dup2(fd, STDIN_FILENO) < 0) { // dup2 returns the dupped fd on success, -1 on error 32 | fprintf(stderr, "dup2() error: %s\n", strerror(errno)); 33 | exit(1); 34 | } 35 | } 36 | /* changes end here */ 37 | 38 | 39 | Rio_readinitb(&rio, STDIN_FILENO); 40 | 41 | while ((n = Rio_readlineb(&rio, buf, MAXLINE)) != 0) { 42 | Rio_writen(STDOUT_FILENO, buf, n); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /material/201118_system_io/exercise_code/solutions/fstatcheck.c: -------------------------------------------------------------------------------- 1 | #include "csapp.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | int main(int argc, char **argv) { 8 | struct stat stat; 9 | char *type, *readok; 10 | 11 | /* changes start here */ 12 | if (argc != 2) { 13 | fprintf(stderr, "Usage: %s \n", argv[0]); 14 | exit(0); 15 | } 16 | 17 | char *endptr; 18 | int fd = (int) strtol(argv[1], &endptr, 10); 19 | 20 | if (endptr != NULL || endptr == argv[1]) { // if conversion of command line arg failed 21 | fprintf(stderr, "strtol() error: %s\n", strerror(errno)); 22 | exit(1); 23 | } 24 | 25 | if (fstat(fd, &stat) != 0) { 26 | fprintf(stderr, "fstat() error: %s\n", strerror(errno)); 27 | exit(1); 28 | } 29 | /* changes end here */ 30 | 31 | 32 | if (S_ISREG(stat.st_mode)) /* Determine file type */ 33 | type = "regular"; 34 | else if (S_ISDIR(stat.st_mode)) 35 | type = "directory"; 36 | else 37 | type = "other"; 38 | 39 | 40 | if ((stat.st_mode & S_IRUSR)) /* Check read access */ 41 | readok = "yes"; 42 | else 43 | readok = "no"; 44 | 45 | printf("type: %s, read-enable: %s\n", type, readok); 46 | exit(0); 47 | } 48 | -------------------------------------------------------------------------------- /material/201118_system_io/exercises.md: -------------------------------------------------------------------------------- 1 | # Exercises for system IO 2 | 3 | Kode til dagens øvelser ligger i ``./exercise_code``. 4 | 5 | Kompiler programmerne med ``make`` og kør med ``./cpfile`` og ``./fstatcheck ``. 6 | 7 | Løsninger til opgaverne ligger i ``./exercise_code/solutions``. 8 | Kør igen ``make`` for at kompilere, og her ``./cpfile_infile `` for at køre løsningen til 10.10. 9 | 10 | 11 | * 10.1 12 | * 10.4 13 | * 10.7 (løsning i ``./exercise_code/solutions/cpfile.c``) 14 | * 10.8 (løsning i ``./exercise_code/solutions/fstatcheck.c``) 15 | * 10.10 (løsning i ``./exercise_code/solutions/cpfile_infile.c``) 16 | -------------------------------------------------------------------------------- /material/201118_system_io/system_io.odp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diku-compSys/compSys-e2020-pub/2117354114df749a5327584885c88a0b3ad5f9d9/material/201118_system_io/system_io.odp -------------------------------------------------------------------------------- /material/201123_os_summary/exercises.md: -------------------------------------------------------------------------------- 1 | # Exercises 2 | 3 | * Try solving the old exam sets (available on Absalon). 4 | 5 | * Pick exercises from previous weeks and try solving them. 6 | -------------------------------------------------------------------------------- /material/201123_os_summary/os_summary.odp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diku-compSys/compSys-e2020-pub/2117354114df749a5327584885c88a0b3ad5f9d9/material/201123_os_summary/os_summary.odp -------------------------------------------------------------------------------- /material/201125_introduction_to_computer_network/exercises.md: -------------------------------------------------------------------------------- 1 | # Exercises for Introduction to Computer Network 2 | 3 | The following exercises relate to Chapter 1 in Kurose and Ross on the topic "Introduction to Computer Networks". 4 | 5 | * R13 6 | * R14 7 | * P4 8 | * P13 9 | * P31 (optional) 10 | * P33 (optional) 11 | 12 | # Wireshark lab 13 | 14 | We will be using the packet sniffer tool Wireshark to visualize the networking protocols in action. 15 | 16 | * Install wireshark 17 | * Linux: `sudo apt-get install wireshark` 18 | * MacOS: `brew cask install wireshark` 19 | * Windows: [https://www.wireshark.org/download.html](https://www.wireshark.org/download.html) 20 | * Do the [Wireshark lab](https://www-net.cs.umass.edu/wireshark-labs/) on "Getting Started". 21 | 22 | -------------------------------------------------------------------------------- /material/201125_introduction_to_computer_network/slides.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diku-compSys/compSys-e2020-pub/2117354114df749a5327584885c88a0b3ad5f9d9/material/201125_introduction_to_computer_network/slides.pdf -------------------------------------------------------------------------------- /material/201130_application_layer_http/exercises.md: -------------------------------------------------------------------------------- 1 | # Exercises for CN, Application layer 2 | 3 | Finish the exercises from the first Computer Network lecture. 4 | 5 | ## Exercises from Chapter 2 of Kurose and Ross on "Application Layer" 6 | 7 | Review questions 8 | 9 | * R3 10 | * R4 11 | * R5 12 | * R10 13 | * R12 14 | * R15 15 | 16 | Problems 17 | 18 | * P1 19 | * P4 20 | * P5 21 | * P10 22 | * P14 23 | 24 | # Wireshark lab 25 | 26 | * Do the [Wireshark lab](https://www-net.cs.umass.edu/wireshark-labs/) on "HTTP". 27 | 28 | -------------------------------------------------------------------------------- /material/201130_application_layer_http/slides.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diku-compSys/compSys-e2020-pub/2117354114df749a5327584885c88a0b3ad5f9d9/material/201130_application_layer_http/slides.pdf -------------------------------------------------------------------------------- /material/201202_network_programming/code/Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | CFLAGS =-Wall -Wextra -pedantic -std=gnu11 3 | LD_FLAGS = -lpthread 4 | 5 | all : hostinfo 6 | 7 | rebuild : clean all 8 | 9 | csapp.o : csapp.c csapp.h 10 | $(CC) $(CFLAGS) -c $< -o $@ 11 | 12 | hostinfo : hostinfo.c csapp.o 13 | $(CC) $(CFLAGS) $< *.o -o $@ $(LD_FLAGS) 14 | 15 | clean : 16 | rm -rf *.o hostinfo 17 | -------------------------------------------------------------------------------- /material/201202_network_programming/code/hostinfo.c: -------------------------------------------------------------------------------- 1 | /* $begin hostinfo */ 2 | #include "csapp.h" 3 | 4 | int main(int argc, char **argv) 5 | { 6 | struct addrinfo *p, *listp, hints; 7 | char buf[MAXLINE]; 8 | int rc, flags; 9 | 10 | if (argc != 2) { 11 | fprintf(stderr, "usage: %s \n", argv[0]); 12 | exit(0); 13 | } 14 | 15 | /* Get a list of addrinfo records */ 16 | memset(&hints, 0, sizeof(struct addrinfo)); 17 | hints.ai_family = AF_INET; /* IPv4 only */ //line:netp:hostinfo:family 18 | hints.ai_socktype = SOCK_STREAM; /* Connections only */ //line:netp:hostinfo:socktype 19 | if ((rc = getaddrinfo(argv[1], NULL, &hints, &listp)) != 0) { 20 | fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(rc)); 21 | exit(1); 22 | } 23 | 24 | /* Walk the list and display each IP address */ 25 | for (p = listp; p; p = p->ai_next) { 26 | flags = NI_NUMERICHOST; /* Display address string instead of domain name */ 27 | Getnameinfo(p->ai_addr, p->ai_addrlen, buf, MAXLINE, NULL, 0, flags); 28 | printf("%s : ", buf); 29 | flags = NI_NUMERICSERV; /* Display address string instead of domain name */ 30 | Getnameinfo(p->ai_addr, p->ai_addrlen, buf, MAXLINE, NULL, 0, flags); 31 | printf("%s\n", buf); 32 | } 33 | 34 | /* Clean up */ 35 | Freeaddrinfo(listp); 36 | 37 | exit(0); 38 | } 39 | /* $end hostinfo */ 40 | -------------------------------------------------------------------------------- /material/201202_network_programming/code/netpfragments.c: -------------------------------------------------------------------------------- 1 | #include "csapp.h" 2 | 3 | void fragments() 4 | { 5 | int clientfd; 6 | 7 | /* $begin socketcall */ 8 | clientfd = Socket(AF_INET, SOCK_STREAM, 0); 9 | /* $end socketcall */ 10 | 11 | clientfd = clientfd; /* keep gcc happy */ 12 | 13 | /* $begin inaddr */ 14 | /* IP address structure */ 15 | struct in_addr { 16 | uint32_t s_addr; /* Address in network byte order (big-endian) */ 17 | }; 18 | /* $end inaddr */ 19 | 20 | /* $begin addrinfo */ 21 | struct addrinfo { 22 | int ai_flags; /* Hints argument flags */ 23 | int ai_family; /* First arg to socket function */ 24 | int ai_socktype; /* Second arg to socket function */ 25 | int ai_protocol; /* Third arg to socket function */ 26 | char *ai_canonname; /* Canonical hostname */ 27 | size_t ai_addrlen; /* Size of ai_addr struct */ 28 | struct sockaddr *ai_addr; /* Ptr to socket address structure */ 29 | struct addrinfo *ai_next; /* Ptr to next item in linked list */ 30 | }; 31 | /* $end addrinfo */ 32 | 33 | 34 | /* $begin sockaddr */ 35 | /* IP socket address structure */ 36 | struct sockaddr_in { 37 | uint16_t sin_family; /* Protocol family (always AF_INET) */ 38 | uint16_t sin_port; /* Port number in network byte order */ 39 | struct in_addr sin_addr; /* IP address in network byte order */ 40 | unsigned char sin_zero[8]; /* Pad to sizeof(struct sockaddr) */ 41 | }; 42 | 43 | /* Generic socket address structure (for connect, bind, and accept) */ 44 | struct sockaddr { 45 | uint16_t sa_family; /* Protocol family */ 46 | char sa_data[14]; /* Address data */ 47 | }; 48 | /* $end sockaddr */ 49 | 50 | } 51 | -------------------------------------------------------------------------------- /material/201202_network_programming/code_echo/Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | CFLAGS =-Wall -Wextra -pedantic -std=gnu11 3 | LD_FLAGS = -lpthread 4 | 5 | all : echoclient echoserveri echoserverp echoservert 6 | 7 | rebuild : clean all 8 | 9 | csapp.o : csapp.c csapp.h 10 | $(CC) $(CFLAGS) -c $< -o $@ 11 | 12 | echoclient : echoclient.c csapp.o 13 | $(CC) $(CFLAGS) $< *.o -o $@ $(LD_FLAGS) 14 | 15 | echoserveri : echoserveri.c echo.c csapp.o 16 | $(CC) $(CFLAGS) $< echo.c *.o -o $@ $(LD_FLAGS) 17 | 18 | echoserverp : echoserverp.c echo.c csapp.o 19 | $(CC) $(CFLAGS) $< echo.c *.o -o $@ $(LD_FLAGS) 20 | 21 | echoservert : echoservert.c echo.c csapp.o 22 | $(CC) $(CFLAGS) $< echo.c *.o -o $@ $(LD_FLAGS) 23 | 24 | clean : 25 | rm -rf *.o echoclient echoserveri echoserverp echoservert 26 | -------------------------------------------------------------------------------- /material/201202_network_programming/code_echo/echo.c: -------------------------------------------------------------------------------- 1 | /* 2 | * echo - read and echo text lines until client closes connection 3 | */ 4 | /* $begin echo */ 5 | #include "csapp.h" 6 | 7 | void echo(int connfd) 8 | { 9 | size_t n; 10 | char buf[MAXLINE]; 11 | rio_t rio; 12 | 13 | Rio_readinitb(&rio, connfd); 14 | while((n = Rio_readlineb(&rio, buf, MAXLINE)) != 0) { //line:netp:echo:eof 15 | printf("server received %d bytes\n", (int)n); 16 | Rio_writen(connfd, buf, n); 17 | } 18 | } 19 | /* $end echo */ 20 | 21 | -------------------------------------------------------------------------------- /material/201202_network_programming/code_echo/echoclient.c: -------------------------------------------------------------------------------- 1 | /* 2 | * echoclient.c - An echo client 3 | */ 4 | /* $begin echoclientmain */ 5 | #include "csapp.h" 6 | 7 | int main(int argc, char **argv) 8 | { 9 | int clientfd; 10 | char *host, *port, buf[MAXLINE]; 11 | rio_t rio; 12 | 13 | if (argc != 3) { 14 | fprintf(stderr, "usage: %s \n", argv[0]); 15 | exit(0); 16 | } 17 | host = argv[1]; 18 | port = argv[2]; 19 | 20 | clientfd = Open_clientfd(host, port); 21 | Rio_readinitb(&rio, clientfd); 22 | 23 | while (Fgets(buf, MAXLINE, stdin) != NULL) { 24 | Rio_writen(clientfd, buf, strlen(buf)); 25 | Rio_readlineb(&rio, buf, MAXLINE); 26 | Fputs(buf, stdout); 27 | } 28 | Close(clientfd); //line:netp:echoclient:close 29 | exit(0); 30 | } 31 | /* $end echoclientmain */ 32 | -------------------------------------------------------------------------------- /material/201202_network_programming/code_echo/echoserveri.c: -------------------------------------------------------------------------------- 1 | /* 2 | * echoserveri.c - An iterative echo server 3 | */ 4 | /* $begin echoserverimain */ 5 | #include "csapp.h" 6 | 7 | void echo(int connfd); 8 | 9 | int main(int argc, char **argv) 10 | { 11 | int listenfd, connfd; 12 | socklen_t clientlen; 13 | struct sockaddr_storage clientaddr; /* Enough space for any address */ //line:netp:echoserveri:sockaddrstorage 14 | char client_hostname[MAXLINE], client_port[MAXLINE]; 15 | 16 | if (argc != 2) { 17 | fprintf(stderr, "usage: %s \n", argv[0]); 18 | exit(0); 19 | } 20 | 21 | listenfd = Open_listenfd(argv[1]); 22 | while (1) { 23 | clientlen = sizeof(struct sockaddr_storage); 24 | connfd = Accept(listenfd, (SA *)&clientaddr, &clientlen); 25 | Getnameinfo((SA *) &clientaddr, clientlen, client_hostname, MAXLINE, 26 | client_port, MAXLINE, 0); 27 | printf("Connected to (%s, %s)\n", client_hostname, client_port); 28 | echo(connfd); 29 | Close(connfd); 30 | } 31 | exit(0); 32 | } 33 | /* $end echoserverimain */ 34 | -------------------------------------------------------------------------------- /material/201202_network_programming/code_echo/echoserverp.c: -------------------------------------------------------------------------------- 1 | /* 2 | * echoserverp.c - A concurrent echo server based on processes 3 | */ 4 | /* $begin echoserverpmain */ 5 | #include "csapp.h" 6 | void echo(int connfd); 7 | 8 | void sigchld_handler(int sig) //line:conc:echoserverp:handlerstart 9 | { 10 | while (waitpid(-1, 0, WNOHANG) > 0) 11 | ; 12 | return; 13 | } //line:conc:echoserverp:handlerend 14 | 15 | int main(int argc, char **argv) 16 | { 17 | int listenfd, connfd; 18 | socklen_t clientlen; 19 | struct sockaddr_storage clientaddr; 20 | char client_hostname[MAXLINE], client_port[MAXLINE]; 21 | 22 | if (argc != 2) { 23 | fprintf(stderr, "usage: %s \n", argv[0]); 24 | exit(0); 25 | } 26 | 27 | Signal(SIGCHLD, sigchld_handler); 28 | listenfd = Open_listenfd(argv[1]); 29 | while (1) { 30 | clientlen = sizeof(struct sockaddr_storage); 31 | connfd = Accept(listenfd, (SA *) &clientaddr, &clientlen); 32 | if (Fork() == 0) { 33 | Close(listenfd); /* Child closes its listening socket */ 34 | pid_t childpid = getpid(); 35 | Getnameinfo((SA *) &clientaddr, clientlen, client_hostname, MAXLINE, 36 | client_port, MAXLINE, 0); 37 | printf("Connected to (%s, %s) via pid %d\n", client_hostname, client_port, childpid); 38 | echo(connfd); /* Child services client */ //line:conc:echoserverp:echofun 39 | Close(connfd); /* Child closes connection with client */ //line:conc:echoserverp:childclose 40 | exit(0); /* Child exits */ 41 | } 42 | Close(connfd); /* Parent closes connected socket (important!) */ //line:conc:echoserverp:parentclose 43 | } 44 | } 45 | /* $end echoserverpmain */ 46 | -------------------------------------------------------------------------------- /material/201202_network_programming/code_echo/echoservert.c: -------------------------------------------------------------------------------- 1 | /* 2 | * echoservert.c - A concurrent echo server using threads 3 | */ 4 | /* $begin echoservertmain */ 5 | #include "csapp.h" 6 | 7 | void echo(int connfd); 8 | void *thread(void *vargp); 9 | 10 | int main(int argc, char **argv) 11 | { 12 | int listenfd, *connfdp; 13 | socklen_t clientlen; 14 | struct sockaddr_storage clientaddr; 15 | pthread_t tid; 16 | char client_hostname[MAXLINE], client_port[MAXLINE]; 17 | 18 | if (argc != 2) { 19 | fprintf(stderr, "usage: %s \n", argv[0]); 20 | exit(0); 21 | } 22 | listenfd = Open_listenfd(argv[1]); 23 | 24 | while (1) { 25 | clientlen=sizeof(struct sockaddr_storage); 26 | connfdp = Malloc(sizeof(int)); //line:conc:echoservert:beginmalloc 27 | *connfdp = Accept(listenfd, (SA *) &clientaddr, &clientlen); //line:conc:echoservert:endmalloc 28 | Pthread_create(&tid, NULL, thread, connfdp); 29 | Getnameinfo((SA *) &clientaddr, clientlen, client_hostname, MAXLINE, 30 | client_port, MAXLINE, 0); 31 | printf("Connected to (%s, %s) via thread %lu\n", 32 | client_hostname, client_port, (long) tid); 33 | } 34 | } 35 | 36 | /* Thread routine */ 37 | void *thread(void *vargp) 38 | { 39 | int connfd = *((int *)vargp); 40 | Pthread_detach(pthread_self()); //line:conc:echoservert:detach 41 | Free(vargp); //line:conc:echoservert:free 42 | echo(connfd); 43 | Close(connfd); 44 | return NULL; 45 | } 46 | /* $end echoservertmain */ 47 | -------------------------------------------------------------------------------- /material/201202_network_programming/code_iVar/Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | CFLAGS =-Wall -Wextra -pedantic -std=gnu11 3 | LD_FLAGS = -lpthread 4 | 5 | all : get put iVar-server 6 | 7 | rebuild : clean all 8 | 9 | csapp.o : csapp.c csapp.h 10 | $(CC) $(CFLAGS) -c $< -o $@ 11 | 12 | get : get.c csapp.o 13 | $(CC) $(CFLAGS) $< *.o -o $@ $(LD_FLAGS) 14 | 15 | put : put.c csapp.o 16 | $(CC) $(CFLAGS) $< *.o -o $@ $(LD_FLAGS) 17 | 18 | iVar-server : iVar-server.c csapp.o 19 | $(CC) $(CFLAGS) $< *.o -o $@ $(LD_FLAGS) 20 | 21 | clean : 22 | rm -rf *.o get put iVar-server 23 | -------------------------------------------------------------------------------- /material/201202_network_programming/code_iVar/get.c: -------------------------------------------------------------------------------- 1 | /* 2 | * get.c - retrives a values from a iVar 3 | */ 4 | #include "csapp.h" 5 | 6 | int main(int argc, char **argv) 7 | { 8 | int clientfd; 9 | char *host, *port, buf[MAXLINE]; 10 | rio_t rio; 11 | 12 | if (argc != 3) { 13 | fprintf(stderr, "Retrieves a value from an iVar\n"); 14 | fprintf(stderr, "usage: %s \n", argv[0]); 15 | exit(0); 16 | } 17 | host = argv[1]; 18 | port = argv[2]; 19 | 20 | clientfd = Open_clientfd(host, port); 21 | Rio_readinitb(&rio, clientfd); 22 | 23 | // Rio_written writes a line (ending with \n). even though the protocol doesn't specify this, I should add it here. 24 | char* cmd = "GET\n"; 25 | strncpy(buf,cmd,strlen(cmd)); 26 | 27 | Rio_writen(clientfd, buf, strlen(buf)); 28 | Rio_readlineb(&rio, buf, MAXLINE); 29 | 30 | Fputs(buf, stdout); 31 | 32 | Close(clientfd); //line:netp:echoclient:close 33 | 34 | exit(0); 35 | } 36 | -------------------------------------------------------------------------------- /material/201202_network_programming/code_iVar/put.c: -------------------------------------------------------------------------------- 1 | /* 2 | * put.c - Puts a value to an iVar 3 | */ 4 | #include "csapp.h" 5 | 6 | int main(int argc, char **argv) 7 | { 8 | int clientfd; 9 | char *host, *port, buf[MAXLINE]; 10 | rio_t rio; 11 | 12 | if (argc != 3) { 13 | fprintf(stderr, "Puts a value to an iVar, given by stdin\n"); 14 | fprintf(stderr, "usage: %s \n", argv[0]); 15 | exit(0); 16 | } 17 | host = argv[1]; 18 | port = argv[2]; 19 | 20 | clientfd = Open_clientfd(host, port); 21 | Rio_readinitb(&rio, clientfd); 22 | 23 | char* cmd = "PUT "; 24 | strncpy(buf,cmd,4); 25 | 26 | Fgets(buf+4, MAXLINE-4, stdin); 27 | // I get the line ending from stdin, so I don't have to add it 28 | 29 | Rio_writen(clientfd, buf, strlen(buf)); 30 | Rio_readlineb(&rio, buf, MAXLINE); 31 | 32 | Fputs(buf, stdout); 33 | 34 | Close(clientfd); //line:netp:echoclient:close 35 | exit(0); 36 | } 37 | -------------------------------------------------------------------------------- /material/201202_network_programming/code_iVar/test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | PORT=2500 4 | TESTVAL="This is my value" 5 | TESTOK=1 6 | 7 | # make all 8 | 9 | echo "TESTING: two gets waiting for a put" 10 | 11 | # Reset outputs 12 | echo "" > out1.txt 13 | echo "" > out2.txt 14 | 15 | # Start server -- use "&" to make it run in background 16 | ./iVar-server $PORT & 17 | # Get server PID for later kill 18 | serverpid=$(echo "$!") 19 | echo "Server running on pid: $serverpid" 20 | 21 | # Sleeps are not needed but make my presentation dramatic :) 22 | sleep 1 23 | 24 | # Start a couple of gets that should wait 25 | echo "Starting gets" 26 | ./get localhost $PORT > out1.txt & 27 | ./get localhost $PORT > out2.txt & 28 | 29 | sleep 1 30 | 31 | # Test that output has not been written 32 | out1cont=$(cat out1.txt) 33 | echo "Out1 is still empty: \"$out1cont\"" 34 | if [ "$out1cont" != "" ]; then 35 | TESTOK=0 36 | echo ">> FAILED WAIT" 37 | fi 38 | 39 | sleep 1 40 | 41 | # Put value to storage 42 | echo "Putting value" 43 | putval=$(echo $TESTVAL | ./put localhost $PORT) 44 | 45 | echo "The put reply: \"$putval\"" 46 | if [ "$putval" != "OK" ]; then 47 | TESTOK=0 48 | echo ">> FAILED PUT" 49 | fi 50 | 51 | sleep 1 52 | 53 | # Check put value 54 | out1cont=$(cat out1.txt) 55 | echo "Out1 is : \"$out1cont\"" 56 | if [ "$out1cont" != "$TESTVAL" ]; then 57 | TESTOK=0 58 | echo ">> FAILED WAIT" 59 | fi 60 | 61 | # Clean up 62 | kill $serverpid 63 | rm out1.txt out2.txt 64 | 65 | if [ $TESTOK == 1 ]; then 66 | echo ">> TEST SUCCESS" 67 | else 68 | echo ">> TEST FAILED" 69 | fi 70 | -------------------------------------------------------------------------------- /material/201202_network_programming/slides.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diku-compSys/compSys-e2020-pub/2117354114df749a5327584885c88a0b3ad5f9d9/material/201202_network_programming/slides.pdf -------------------------------------------------------------------------------- /material/201207_dns_bittorrent_udp/exercises.md: -------------------------------------------------------------------------------- 1 | # Exercises for DNS 2 | 3 | ## Exercises from Chapter 2 of Kurose and Ross on "Application Layer" 4 | 5 | * P19 6 | * Read the dig and nslookup man pages. [This short tutorial on dig](https://www.linode.com/docs/networking/dns/use-dig-to-perform-manual-dns-queries/) might be of interest to you. 7 | * You can install it by installing [bind-tools](http://www.isc.org/downloads/bind/) package if you are on a UNIX machine or the client bind tools for Windows. 8 | * P21 9 | * P25 10 | 11 | 12 | ## Wireshark lab 13 | 14 | * Do the [Wireshark labs](https://www-net.cs.umass.edu/wireshark-labs/) on "DNS". 15 | 16 | -------------------------------------------------------------------------------- /material/201207_dns_bittorrent_udp/slides-dns.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diku-compSys/compSys-e2020-pub/2117354114df749a5327584885c88a0b3ad5f9d9/material/201207_dns_bittorrent_udp/slides-dns.pdf -------------------------------------------------------------------------------- /material/201207_dns_bittorrent_udp/slides-p2p.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diku-compSys/compSys-e2020-pub/2117354114df749a5327584885c88a0b3ad5f9d9/material/201207_dns_bittorrent_udp/slides-p2p.pdf -------------------------------------------------------------------------------- /material/201207_dns_bittorrent_udp/slides-udp.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diku-compSys/compSys-e2020-pub/2117354114df749a5327584885c88a0b3ad5f9d9/material/201207_dns_bittorrent_udp/slides-udp.pdf -------------------------------------------------------------------------------- /material/201209_tcp/exercises.md: -------------------------------------------------------------------------------- 1 | # Exercises for TCP 2 | 3 | ## Exercises from Chapter 3 of Kurose and Ross on "Transport Layer" 4 | 5 | * P14 6 | * P15 7 | * P27 8 | * P36 9 | * P37 10 | 11 | ## Wireshark lab 12 | 13 | * Do the [Wireshark lab](https://www-net.cs.umass.edu/wireshark-labs/) on "TCP". 14 | 15 | -------------------------------------------------------------------------------- /material/201209_tcp/slides.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diku-compSys/compSys-e2020-pub/2117354114df749a5327584885c88a0b3ad5f9d9/material/201209_tcp/slides.pdf -------------------------------------------------------------------------------- /material/201214_network_layer_forwarding_ip/exercises.md: -------------------------------------------------------------------------------- 1 | # Exercises for Network layer: Forwarding and IP 2 | 3 | ## Exercises from Chapter 3 of Kurose and Ross on "Transport Layer" 4 | 5 | * P40 6 | * P51 7 | 8 | ## Exercises from Chapter 4 of Kurose and Ross on "Network Layer: Data Plane" 9 | 10 | * P5 11 | * P8 12 | * P14 13 | 14 | ## Exercises from Chapter 5 of Kurose and Ross on "Network Layer: Control Plane" 15 | 16 | * We will be looking at routing algorithms in Wednesday's lecture. The link state routing algorithm uses Dijkstra's shortest path algorithm that you have studied previously in your algorithms course. The following exercises allow you to recap the algorithm. 17 | * P3 18 | * P4 (Optional) 19 | 20 | -------------------------------------------------------------------------------- /material/201214_network_layer_forwarding_ip/slides.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diku-compSys/compSys-e2020-pub/2117354114df749a5327584885c88a0b3ad5f9d9/material/201214_network_layer_forwarding_ip/slides.pdf -------------------------------------------------------------------------------- /material/201216_network_layer_dhcp_nat_routing/exercises.md: -------------------------------------------------------------------------------- 1 | # Exercises for Network layer: DHCP NAT and routing 2 | 3 | ## Exercises from Chapter 5 of Kurose and Ross on "Network Layer: Control Plane" 4 | 5 | * P3 (repeated from the last exercise session) 6 | * P4 (repeated from the last exercise session) 7 | * P8 8 | * P11 9 | 10 | ## Wireshark lab 11 | 12 | * Do the [Wireshark lab](https://www-net.cs.umass.edu/wireshark-labs/) on "DHCP". 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /material/201216_network_layer_dhcp_nat_routing/slides.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diku-compSys/compSys-e2020-pub/2117354114df749a5327584885c88a0b3ad5f9d9/material/201216_network_layer_dhcp_nat_routing/slides.pdf -------------------------------------------------------------------------------- /material/210104_link_layer_ethernet/exercises.md: -------------------------------------------------------------------------------- 1 | # Exercises for Link Layer 2 | 3 | ## Exercises from Chapter 5 of Kurose and Ross on "Network Layer: Control Plane" 4 | 5 | * P3 (repeated from the last exercise session) 6 | * P4 (repeated from the last exercise session) 7 | * P8 8 | * P11 9 | 10 | ## Exercises from Chapter 6 of Kurose and Ross on "The Link Layer and LANs" 11 | * Exercises on error detection and correction codes repeated from the previous exercise 12 | * P1 13 | * P3 14 | * P5 15 | * P14 16 | * P15 17 | 18 | ## Wireshark lab 19 | 20 | * Do the [Wireshark lab](https://www-net.cs.umass.edu/wireshark-labs/) on "DHCP". 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /material/210104_link_layer_ethernet/slides.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diku-compSys/compSys-e2020-pub/2117354114df749a5327584885c88a0b3ad5f9d9/material/210104_link_layer_ethernet/slides.pdf -------------------------------------------------------------------------------- /material/210106_encryption_security/exercises.md: -------------------------------------------------------------------------------- 1 | # Exercises for Introduction to security and encryption 2 | 3 | ## Exercises from Chapter 8 of Kurose and Ross on "Security" 4 | * P3 5 | * P8 6 | * P9 7 | * P10 8 | 9 | -------------------------------------------------------------------------------- /material/210106_encryption_security/slides.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diku-compSys/compSys-e2020-pub/2117354114df749a5327584885c88a0b3ad5f9d9/material/210106_encryption_security/slides.pdf -------------------------------------------------------------------------------- /material/210111_network_security/exercises.md: -------------------------------------------------------------------------------- 1 | # Exercises for Network security 2 | 3 | ## Security 4 | * Exercises from Chapter 8 pp 696-697 5 | * P13 6 | * P15 7 | * P17 8 | * P19 9 | 10 | * Wireshark SSL lab: https://www-net.cs.umass.edu/wireshark-labs/ 11 | -------------------------------------------------------------------------------- /material/210111_network_security/slides.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diku-compSys/compSys-e2020-pub/2117354114df749a5327584885c88a0b3ad5f9d9/material/210111_network_security/slides.pdf -------------------------------------------------------------------------------- /material/210113_cloud computers_datacenters/recap-decompilation/answer.c: -------------------------------------------------------------------------------- 1 | long prog(long* rsi, long size, long max){ 2 | long fibn = 0; // %r10 3 | long fibn1; // %r10 4 | rsi = fibn; // %rsi 5 | long* array = rsi+1; // %rax 6 | fibn = 1; // %r10 7 | *array = fibn; // %rax 8 | while(2 < size){ 9 | fibn = *array // %rcx 10 | fibn1 = *(array-1) // %r10 11 | fibn += fibn1 // %r10 12 | if (max < fibn) { // cbl %rdi, %rcx, .L5 13 | return 1; // movq $1, %rax 14 | // ret %r11 15 | } 16 | array++; // addq $8, %rax 17 | *array = fibn; // movq %rcx, (%rax) 18 | size--; // subq $1, %size 19 | } 20 | return 0; // movq $0, %rax 21 | // ret %r11 22 | } -------------------------------------------------------------------------------- /material/210113_cloud computers_datacenters/recap-decompilation/decompilation.prime: -------------------------------------------------------------------------------- 1 | .prog: 2 | subq $8, %rsp # ignore 3 | movq %r11, (%rsp) # ignore 4 | leaq (%rsi), %r11 5 | movq $0, %r10 6 | movq %r10, (%r11) 7 | leaq 8(%rsi), %rax 8 | leaq 8(%rsi), %r11 9 | movq $1, %r10 10 | movq %r10, (%rax) 11 | .L2: 12 | cbge $2, %rdx, .L6 # guard 13 | movq (%rax), %rcx 14 | movq -8(%rax), %r10 15 | addq %r10, %rcx 16 | cbl %rdi, %rcx, .L5 17 | addq $8, %rax 18 | movq %rcx, (%rax) 19 | subq $1, %rdx 20 | jmp .L2 # while start 21 | .L6: 22 | movq $0, %rax 23 | movq (%rsp), %r11 # ignore 24 | addq $8, %rsp # ignore 25 | ret %r11 26 | .L5: 27 | movq $1, %rax 28 | movq (%rsp), %r11 # ignore 29 | addq $8, %rsp # ignore 30 | ret %r11 31 | .LFE0: 32 | -------------------------------------------------------------------------------- /material/210113_cloud computers_datacenters/slides.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diku-compSys/compSys-e2020-pub/2117354114df749a5327584885c88a0b3ad5f9d9/material/210113_cloud computers_datacenters/slides.pdf -------------------------------------------------------------------------------- /material/210115_recap/LocalityCache_slides.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diku-compSys/compSys-e2020-pub/2117354114df749a5327584885c88a0b3ad5f9d9/material/210115_recap/LocalityCache_slides.pdf -------------------------------------------------------------------------------- /material/210115_recap/concurrency-protection-recap-slides.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diku-compSys/compSys-e2020-pub/2117354114df749a5327584885c88a0b3ad5f9d9/material/210115_recap/concurrency-protection-recap-slides.pdf -------------------------------------------------------------------------------- /material/210115_recap/recap-network-layer.odp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diku-compSys/compSys-e2020-pub/2117354114df749a5327584885c88a0b3ad5f9d9/material/210115_recap/recap-network-layer.odp -------------------------------------------------------------------------------- /material/210115_recap/tcp-slides.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diku-compSys/compSys-e2020-pub/2117354114df749a5327584885c88a0b3ad5f9d9/material/210115_recap/tcp-slides.pdf -------------------------------------------------------------------------------- /relevant-material/README.md: -------------------------------------------------------------------------------- 1 | # Relevant material 2 | 3 | ## Keeping your C# up-to-date 4 | Most of you are still inexperienced programmers and CompSys in very heavy on programming and program understanding. You need to think of programming as a _craft_, like playing an instrument. You have during the first year learned the basics of how it works. But if you lay it away over the summer (do not program for two months) you will lose much of these skills that you have gain over the first year. 5 | 6 | It is therefore important that you practice your C# skills and to help you with this we will point you to the follow two resources. 7 | 8 | ### Edabit 9 | On Edabit you can filter C# problems after level and topic. You can always start with the medium and work your way upwards. I will also recommend problems under the topics `logic` and `string`. There are much relevant to the problems you will face during CompSys. 10 | [https://edabit.com/challenges/csharp](https://edabit.com/challenges/csharp) 11 | 12 | ### Programmr 13 | Programmr is one of the more popular sources of problems and they also have a section on C#. 14 | [http://www.programmr.com/exercises?lang=csharp](http://www.programmr.com/exercises?lang=csharp) 15 | 16 | ## The Linux/Unix terminal and its tools 17 | We will extensively use the terminal throughout the course. Being able to work from the terminal is an important skill for a programmer/computer scientist. 18 | 19 | To start we will point you to [Over The Wire](http://overthewire.org/wargames/bandit/) which is a game that helps you get start. 20 | 21 | For more expert use, we will point you to the notes from the former course on [Unix-like data processing](uldp17-2018-08-16.pdf). 22 | 23 | ### Make 24 | We will throughout the course use the build system Make. We strongly recommend that you become familiar with it and it will also be useful in the future. There exists many manuals on the internet, but will suggest this one: 25 | [https://oleks.github.io/compsys-archive/make.html](https://oleks.github.io/compsys-archive/make.html). 26 | In the note on [Unix-like data processing](uldp17-2018-08-16.pdf) you can also find a detailed chapter. 27 | 28 | ### Shell Scripting 29 | Throughout the course we will give you different shell scripts that can aid your testing of assignments and other tasks. A shell script is useful for automating a sequence commands into a single call. Later in the course it can be useful for you to update these scripts and create new ones based on the ones we have given; or just have the skills for making them in the future. 30 | 31 | In the note on [Unix-like data processing](uldp17-2018-08-16.pdf) you can again find a chapter on shell scripting. 32 | -------------------------------------------------------------------------------- /relevant-material/uldp17-2018-08-16.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diku-compSys/compSys-e2020-pub/2117354114df749a5327584885c88a0b3ad5f9d9/relevant-material/uldp17-2018-08-16.pdf -------------------------------------------------------------------------------- /tools/README.md: -------------------------------------------------------------------------------- 1 | # Tools 2 | 3 | Throughout the course we will use C as programming language, so it is important that you have access to a compiler on your machine. For this we recommend GCC (https://gcc.gnu.org/), which is also the compiler we will use check correctness of your implementations. For what we are to use, there should be no difference between the later versions, so need not to install the latest GCC that is larger than version 8.2. We will also from second week introduce GDB, so you can just as well also install this. 4 | 5 | We will also later during the course use a simulation tool that might (or might not) cause problems on non-Linux machines. We will at this time release a VM image that you can use in case of problems. See more about running the image further below. 6 | 7 | ## Roll Your Own Toolchain 8 | Most of you should not have a problem with running needed software on your local machine, so see OS specific pages for rolling out your toolchain. 9 | 10 | * [Linux tools](linux.md) 11 | * [maxOS tools](macos.md) 12 | * [Windows tools](windows.md) 13 | 14 | ## Virtualbox 15 | However, there might can be problems on the specific systems, in which case we will generally point you to a virtual machine. 16 | 17 | * This will be posted later.. 18 | 19 | ## Script alternatives 20 | For some purposes we have also designed some specific scripts you can run from your terminal. These require internet access, but can be an easy alternative in some specific situations 21 | 22 | * To be posted later... 23 | 24 | 25 | ## Editor vs. IDE 26 | We do not ask you to use any specific editor or IDE for the course. I can say that different teachers usage range from VIM over Emacs to Sublime Text. Most important is that you have easy access from your editor to a terminal where you can run the Make build tool and scripts for testing. See the [Preparation](../preparations/README.md) for further details. 27 | 28 | 29 | -------------------------------------------------------------------------------- /tools/linux.md: -------------------------------------------------------------------------------- 1 | # Linux tools -- Roll Your Own Toolchain on Linux 2 | 3 | Given that the course will focus on Linux systems, rolling your toolchain is easy. Here is a conservative list of the software you'll need for this course: 4 | 5 | * `apt-get` is the general package manager for your 6 | Debian/Ubuntu. You can use it to install the following packages. 7 | * [GCC](https://gcc.gnu.org/) and 8 | [Binutils](https://www.gnu.org/software/binutils/)". On 9 | Debian/Ubuntu you get these with the `build-essential` package. On 10 | Arch Linux/Antergos this is called base-devel. 11 | * [GDB](https://www.gnu.org/software/gdb/). In most package managers 12 | this is called `gdb`. You can also use 13 | [LLDB](https://lldb.llvm.org/) if you wish. 14 | * `make`. The build tool. You also get this with the `build-essential` package. 15 | 16 | Further, the following tools are recommended: 17 | 18 | * [Valgrind](http://www.valgrind.org/) for detecting memory errors 19 | in C programs. Available as `valgrind` in most package managers. 20 | -------------------------------------------------------------------------------- /tools/macos.md: -------------------------------------------------------------------------------- 1 | # macOS tools -- Roll Your Own Toolchain 2 | 3 | ## Homebrew 4 | Homebrew is a package manager (similar to apt on Linux) that contain ports of many Linux programs. When you get a new Mac, this should be the first program to install, as it is the most useful. 5 | 6 | Install Homebrew ([http://brew.sh/](http://brew.sh/)) 7 | 8 | ## GCC 9 | As standard macOS is setup for using Clang and has even linked `gcc` to run `clang`. We recommend changing it to gcc. The easiest way is the following: 10 | 11 | type 12 | 13 | ``` 14 | brew install gcc 15 | brew install binutils 16 | ``` 17 | 18 | First time Homebrew will install many needed programs (including compiling them for you system), so it can take a long time. 19 | 20 | 21 | ## Use LLDB instead of GDB 22 | 23 | GDB (a C debugger) is tricky to get working on macOS. Instead, you 24 | should use LLDB (`lldb`), which has equivalent functionality for our 25 | purposes, and almost the same commands. [See this GDB to LLDB command 26 | map](https://lldb.llvm.org/use/map.html), and note that you likely 27 | need only a small fraction of these commands for CompSys. 28 | -------------------------------------------------------------------------------- /tools/vm/login.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -euo pipefail 4 | 5 | PORT=1339 6 | 7 | ssh \ 8 | -p ${PORT} \ 9 | -o UserKnownHostsFile=/dev/null \ 10 | -o StrictHostKeyChecking=no \ 11 | -o LogLevel=ERROR \ 12 | neumann@localhost 13 | -------------------------------------------------------------------------------- /tools/vm/mount.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | if [ "$#" -ne 1 ]; then 4 | echo "[CompSys] Scripts for mounting VM disk locally." 5 | echo "Usage:" 6 | echo " ./mount.sh [dir]" 7 | echo " dir: The local directory to which the file should be mounted. Ensure that it is empty." 8 | exit 1; 9 | fi 10 | 11 | set -euo pipefail 12 | 13 | VMPORT=1339 14 | SSHPORT=22 15 | MOUNTPOINT=$1 16 | 17 | if [[ ! -d "${MOUNTPOINT}" ]] ; then 18 | echo "The given directory does not exist!" 19 | exit 20 | fi 21 | 22 | username=$(id -un) 23 | 24 | if [ ${username} != "neumann" ] ; then 25 | # Mount from host machine 26 | port=${VMPORT} 27 | host=neumann@localhost:. 28 | else 29 | port=${SSHPORT} 30 | read -r host < .vm_host 31 | fi 32 | 33 | sshfs \ 34 | ${host} \ 35 | ${MOUNTPOINT} \ 36 | -ocache=no \ 37 | -oport=${port} 38 | -------------------------------------------------------------------------------- /tools/vm/rev_mount.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # echo "[CompSys] Scripts for setting up reverse-mounting local file system to VM." 4 | 5 | set -euo pipefail 6 | 7 | PORT=1339 8 | 9 | ip=$(ifconfig | grep "inet " | grep -Fv 127.0.0.1 | awk '{print $2}') 10 | username=$(id -un) 11 | read -r mountdir < .revmountdir 12 | 13 | # echo ${line} > vm_host.txt 14 | 15 | echo ${username}@${ip}:${mountdir} > .vm_host 16 | 17 | scp \ 18 | -P ${PORT} \ 19 | .vm_host \ 20 | neumann@localhost:. 21 | 22 | rm .vm_host 23 | -------------------------------------------------------------------------------- /tools/vm/setup_rev_mount.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | if [ "$#" -ne 1 ]; then 4 | echo "[CompSys] Scripts for setting up reverse-mounting local file system to VM." 5 | echo "Usage:" 6 | echo " ./rev_mount.sh [dir]" 7 | echo " dir: The local directory that you want to get mounted on the VM" 8 | echo "" 9 | echo "We recommend that your restrict this at much as possible. Use only your" 10 | echo "CompSys-related directory. Mounting your entire file system can be a " 11 | echo "security risk." 12 | exit 1; 13 | fi 14 | 15 | set -euo pipefail 16 | 17 | MOUNTPOINT=$1 18 | 19 | if [[ ! -d "${MOUNTPOINT}" ]] ; then 20 | echo "The given directory does not exist!" 21 | exit 22 | fi 23 | 24 | echo ${MOUNTPOINT} > .revmountdir 25 | -------------------------------------------------------------------------------- /tools/vm/startup.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | 3 | set -euo pipefail 4 | 5 | VBoxManage startvm compSys19 --type headless 6 | -------------------------------------------------------------------------------- /tools/windows.md: -------------------------------------------------------------------------------- 1 | # Windows tools -- Roll Your Own Toolchain 2 | 3 | ## Windows Subsystem for Linux (WSL) 4 | We strongly recommend that you are using a 64-bit Windows 10. That way you can in most cases avoid the virtual machine and run native Linux command-line tools directly on Windows. This means you can use your own Windows files and don't have to bother transferring files to a virtual machine. 5 | 6 | To install Windows Subsystem for Linux, [click here for Microsoft's own instructions](https://docs.microsoft.com/en-us/windows/wsl/install-win10). 7 | 8 | After this you should look at the [Linux manual](linux.md). 9 | -------------------------------------------------------------------------------- /x86prime_tools/gdb-online.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys, re, os, mimetypes, argparse, requests 4 | 5 | parser = argparse.ArgumentParser(description='Compiles a C program into a gcc output x86_64.') 6 | 7 | parser.add_argument('gdb', metavar='gdb-script', 8 | help='Your gdb script') 9 | parser.add_argument('file', metavar='C-file', 10 | help='your implementation of file') 11 | 12 | 13 | args = parser.parse_args() 14 | 15 | extensions = args.file.split(".") 16 | fileextension = extensions[-1] 17 | 18 | if not os.path.isfile(args.gdb): 19 | print("Input file does not exist: "+args.gdb+"\n") 20 | exit() 21 | 22 | gdb = open(args.gdb, 'r') 23 | args.gdbCont = gdb.read() 24 | gdb.close() 25 | 26 | 27 | if fileextension != "c": 28 | print("The input is expected to be a C program; fileextension 'c'.\n") 29 | exit() 30 | 31 | if not os.path.isfile(args.file): 32 | print("Input file does not exist: "+args.file+"\n") 33 | exit() 34 | 35 | file = open(args.file, 'r') 36 | args.fileCont = file.read() 37 | file.close() 38 | 39 | 40 | # gdb online location 41 | URL = "http://topps.diku.dk/compsys/gdb.php" 42 | # defining a params dict for the parameters to be sent to the API 43 | DATA = {"file":args.fileCont, "gdb":args.gdbCont} 44 | # sending get request and saving the response as response object 45 | r = requests.post(url = URL, data = DATA) 46 | 47 | URLDIR = "http://topps.diku.dk/compsys/gcc_runs/" 48 | # extracting data in json format 49 | runid = r.text 50 | 51 | error = requests.get(url = URLDIR+runid+".error") 52 | 53 | if error.text != "": 54 | print(error.text) 55 | exit() 56 | else: 57 | gdb = requests.get(url = URLDIR+runid+".out") 58 | print (gdb.text) 59 | -------------------------------------------------------------------------------- /x86prime_tools/install.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | echo ">> Installing x86prime tools." 4 | 5 | # The list of tools 6 | declare -a tools=("gcc-online" "gdb-online" "prasm" "prerf" "primify" "prun") 7 | # Fint my path 8 | x86prime_path="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" 9 | 10 | # Does the path exist? 11 | if [[ ! -d "${x86prime_path}" ]] ; then 12 | echo "The given directory does not exist!" 13 | exit 14 | fi 15 | 16 | # Does the tools exist? 17 | for tool in ${tools[@]}; do 18 | if [[ ! -e "${x86prime_path}/${tool}.py" ]] ; then 19 | echo "Cannot find ${tool}.py in ${x86prime_path} !!!" 20 | exit 21 | fi 22 | done 23 | 24 | # Path for tools 25 | mkdir -p /usr/local/lib/x86prime 26 | 27 | # Move each tool and create executable script for these. 28 | for tool in ${tools[@]}; do 29 | cp ${x86prime_path}/${tool}.py /usr/local/lib/x86prime/ 30 | echo '#!/usr/bin/env bash 31 | 32 | set -euo pipefail 33 | args=$(echo "${*:1}") 34 | python3 /usr/local/lib/x86prime/'${tool}'.py $args 35 | ' > /usr/local/bin/${tool} 36 | chmod a+x /usr/local/bin/${tool} 37 | done 38 | 39 | echo "All done." 40 | echo "Restart the terminal for the installation to have effect." 41 | -------------------------------------------------------------------------------- /x86prime_tools/prasm.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys, re, os, mimetypes, argparse, requests 4 | 5 | parser = argparse.ArgumentParser(description='Transform gcc output to x86prime\', assemble and simulate.') 6 | parser.add_argument('file', metavar='prime-file', 7 | help='translate assemble file to x86prime') 8 | 9 | 10 | args = parser.parse_args() 11 | 12 | if args.file==None : 13 | print("Program needs an input file.\n") 14 | parser.print_help() 15 | exit() 16 | 17 | extensions = args.file.split(".") 18 | fileextension = extensions[-1] 19 | 20 | expected_fileextension = "prime" 21 | if fileextension != expected_fileextension: 22 | print("The input is expected to be a assembler program; fileextension '"+expected_fileextension+"'.\n") 23 | exit() 24 | 25 | if not os.path.isfile(args.file): 26 | print("Input file does not exist: "+args.file+"\n") 27 | exit() 28 | 29 | file = open(args.file, 'r') 30 | args.fileCont = file.read() 31 | file.close() 32 | 33 | # x86prime Online location 34 | URL = "http://topps.diku.dk/compsys/prasm.php" 35 | # defining a params dict for the parameters to be sent to the API 36 | DATA = {'file':args.fileCont} 37 | # sending get request and saving the response as response object 38 | r = requests.post(url = URL, data = DATA) 39 | 40 | # location of results 41 | URLDIR = "http://topps.diku.dk/compsys/x86prime_runs/" 42 | # extracting data in json format 43 | runid = r.text 44 | 45 | # get possible error code from execution 46 | error = requests.get(url = URLDIR+runid+".error") 47 | 48 | if error.text != "": 49 | # if error print this 50 | print(error.text) 51 | exit() 52 | else: 53 | # if success write the output to file in same dir as input file 54 | # This is the behaviour of primify, though not the best. 55 | extenstion_to_get = "hex" 56 | extensions[-1] = extenstion_to_get 57 | outfile = '.'.join(extensions) 58 | output = requests.get(url = URLDIR+runid+"."+extenstion_to_get) 59 | f=open(outfile,"w+") 60 | f.write(output.text) 61 | f.close 62 | 63 | extenstion_to_get = "sym" 64 | extensions[-1] = extenstion_to_get 65 | outfile = '.'.join(extensions) 66 | output = requests.get(url = URLDIR+runid+"."+extenstion_to_get) 67 | f=open(outfile,"w+") 68 | f.write(output.text) 69 | f.close 70 | -------------------------------------------------------------------------------- /x86prime_tools/primify.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys, re, os, mimetypes, argparse, requests 4 | 5 | parser = argparse.ArgumentParser(description='Transform gcc output to x86prime\', assemble and simulate.') 6 | parser.add_argument('file', metavar='s-file', 7 | help='translate assemble file to x86prime') 8 | 9 | 10 | args = parser.parse_args() 11 | 12 | if args.file==None : 13 | print("Program needs an input file.\n") 14 | parser.print_help() 15 | exit() 16 | 17 | extensions = args.file.split(".") 18 | fileextension = extensions[-1] 19 | 20 | expected_fileextension = "s" 21 | if fileextension != expected_fileextension: 22 | print("The input is expected to be a assembler program; fileextension '"+expected_fileextension+"'.\n") 23 | exit() 24 | 25 | if not os.path.isfile(args.file): 26 | print("Input file does not exist: "+args.file+"\n") 27 | exit() 28 | 29 | file = open(args.file, 'r') 30 | args.fileCont = file.read() 31 | file.close() 32 | 33 | # x86prime Online location 34 | URL = "http://topps.diku.dk/compsys/primify.php" 35 | # defining a params dict for the parameters to be sent to the API 36 | DATA = {'file':args.fileCont} 37 | # sending get request and saving the response as response object 38 | r = requests.post(url = URL, data = DATA) 39 | 40 | # location of results 41 | URLDIR = "http://topps.diku.dk/compsys/x86prime_runs/" 42 | # extracting data in json format 43 | runid = r.text 44 | 45 | # get possible error code from execution 46 | error = requests.get(url = URLDIR+runid+".error") 47 | 48 | if error.text != "": 49 | # if error print this 50 | print(error.text) 51 | exit() 52 | else: 53 | # if success write the output to file in same dir as input file 54 | # This is the behaviour of primify, though not the best. 55 | extenstion_to_get = "prime" 56 | extensions[-1] = extenstion_to_get 57 | outfile = '.'.join(extensions) 58 | output = requests.get(url = URLDIR+runid+"."+extenstion_to_get) 59 | f=open(outfile,"w+") 60 | f.write(output.text) 61 | f.close 62 | -------------------------------------------------------------------------------- /x86prime_tools/uninstall.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | echo ">> Uninstalling x86prime tools." 4 | 5 | declare -a tools=("gcc-online" "gdb-online" "prasm" "prerf" "primify" "prun") 6 | 7 | rm -r /usr/local/lib/x86prime 8 | 9 | for tool in ${tools[@]}; do 10 | rm /usr/local/bin/${tool} 11 | done 12 | 13 | echo "All removed." 14 | --------------------------------------------------------------------------------