├── lab4 └── starter │ ├── lab4_eceubuntu1.csv │ ├── tools │ ├── sample_output.txt │ ├── results │ │ ├── T10_M1.dat │ │ ├── T10_M10.dat │ │ ├── T10_M20.dat │ │ ├── T10_M30.dat │ │ ├── T10_M40.dat │ │ ├── T10_M50.dat │ │ ├── T1_M1.dat │ │ ├── T1_M10.dat │ │ ├── T1_M100.dat │ │ ├── T1_M20.dat │ │ ├── T1_M30.dat │ │ ├── T1_M40.dat │ │ ├── T1_M50.dat │ │ ├── T20_M1.dat │ │ ├── T20_M10.dat │ │ ├── T20_M20.dat │ │ ├── T20_M30.dat │ │ ├── T20_M40.dat │ │ ├── T20_M50.dat │ │ ├── T10_M100.dat │ │ ├── T20_M100.dat │ │ ├── tb2_31390.txt │ │ └── tb1_31390.txt │ ├── findpng2 │ ├── README.md │ └── run_lab4.sh │ └── curl_xml │ └── Makefile ├── lab5 └── starter │ ├── lab5_eceubuntu1.csv │ ├── tools │ ├── sample_output.txt │ ├── results │ │ ├── T10_M1.dat │ │ ├── T10_M10.dat │ │ ├── T10_M20.dat │ │ ├── T10_M30.dat │ │ ├── T10_M40.dat │ │ ├── T10_M50.dat │ │ ├── T1_M1.dat │ │ ├── T1_M10.dat │ │ ├── T1_M100.dat │ │ ├── T1_M20.dat │ │ ├── T1_M30.dat │ │ ├── T1_M40.dat │ │ ├── T1_M50.dat │ │ ├── T20_M1.dat │ │ ├── T20_M10.dat │ │ ├── T20_M20.dat │ │ ├── T20_M30.dat │ │ ├── T20_M40.dat │ │ ├── T20_M50.dat │ │ ├── T10_M100.dat │ │ ├── T20_M100.dat │ │ ├── tb2_26250.txt │ │ └── tb1_26250.txt │ ├── findpng3 │ ├── README.md │ └── run_lab5.sh │ └── curl_multi │ ├── Makefile │ └── curl_multi_test.c ├── lab3 └── starter │ ├── lab3_eceubuntu1.csv │ ├── tools │ ├── paster2 │ ├── sample_output.txt │ ├── results │ │ ├── B10_P10_C10_X0_N1.dat │ │ ├── B10_P10_C1_X0_N1.dat │ │ ├── B10_P10_C5_X0_N1.dat │ │ ├── B10_P1_C10_X0_N1.dat │ │ ├── B10_P1_C1_X0_N1.dat │ │ ├── B10_P1_C1_X200_N1.dat │ │ ├── B10_P1_C1_X400_N1.dat │ │ ├── B10_P1_C5_X0_N1.dat │ │ ├── B10_P1_C5_X200_N1.dat │ │ ├── B10_P1_C5_X400_N1.dat │ │ ├── B10_P5_C10_X0_N1.dat │ │ ├── B10_P5_C1_X0_N1.dat │ │ ├── B10_P5_C1_X200_N1.dat │ │ ├── B10_P5_C1_X400_N1.dat │ │ ├── B10_P5_C5_X0_N1.dat │ │ ├── B10_P5_C5_X200_N1.dat │ │ ├── B10_P5_C5_X400_N1.dat │ │ ├── B5_P1_C1_X0_N1.dat │ │ ├── B5_P1_C1_X200_N1.dat │ │ ├── B5_P1_C1_X400_N1.dat │ │ ├── B5_P1_C5_X0_N1.dat │ │ ├── B5_P1_C5_X200_N1.dat │ │ ├── B5_P1_C5_X400_N1.dat │ │ ├── B5_P5_C1_X0_N1.dat │ │ ├── B5_P5_C1_X200_N1.dat │ │ ├── B5_P5_C1_X400_N1.dat │ │ ├── B5_P5_C5_X0_N1.dat │ │ ├── B5_P5_C5_X200_N1.dat │ │ ├── B5_P5_C5_X400_N1.dat │ │ ├── B10_P10_C10_X200_N1.dat │ │ ├── B10_P10_C10_X400_N1.dat │ │ ├── B10_P10_C1_X200_N1.dat │ │ ├── B10_P10_C1_X400_N1.dat │ │ ├── B10_P10_C5_X200_N1.dat │ │ ├── B10_P10_C5_X400_N1.dat │ │ ├── B10_P1_C10_X200_N1.dat │ │ ├── B10_P1_C10_X400_N1.dat │ │ ├── B10_P5_C10_X200_N1.dat │ │ ├── B10_P5_C10_X400_N1.dat │ │ ├── tb2_N1_32592.txt │ │ └── tb1_N1_32592.txt │ ├── clean_ipcs.sh │ ├── README.md │ └── run_lab3.sh │ ├── shm │ ├── shm_stack.h │ ├── Makefile │ ├── shm_simple.c │ ├── shm_struct.c │ └── shm_stack.c │ ├── sem │ ├── Makefile │ └── sem_simple.c │ ├── cURL_IPC │ ├── Makefile │ ├── main.c │ └── main_2proc.c │ └── fork │ ├── Makefile │ ├── zombie.c │ └── forkN.c ├── lab2 └── starter │ ├── img1.md5 │ ├── READM.md │ ├── pthreads │ ├── Makefile │ └── main.c │ ├── getopt │ ├── Makefile │ └── main_getopt.c │ ├── fn_ptr │ ├── Makefile │ └── main.c │ ├── times │ ├── Makefile │ ├── util_times.h │ ├── util_times.c │ └── main.c │ └── cURL │ ├── Makefile │ ├── main_simple.c │ ├── main_write_callback.c │ └── main_write_header_cb.c ├── lab1 └── starter │ ├── segfault │ ├── README.md │ ├── Makefile │ └── main_segv.c │ ├── png_util │ ├── README.md │ ├── crc.h │ ├── Makefile │ ├── zutil.h │ ├── crc.c │ ├── lab_png.h │ ├── main.c │ └── zutil.c │ ├── cmd_arg │ ├── README.md │ ├── Makefile │ └── cmd_arg.c │ ├── images │ ├── uweng.png │ ├── WEEF_1.png │ ├── Disguise.png │ ├── red-green-16x16.png │ ├── cropped │ │ ├── pic_cropped_0.png │ │ ├── pic_cropped_1.png │ │ ├── pic_cropped_2.png │ │ ├── pic_cropped_3.png │ │ └── pic_cropped_4.png │ ├── red-green-16x16-corrupted.png │ ├── uweng_cropped │ │ ├── uweng_cropped_0.png │ │ ├── uweng_cropped_1.png │ │ ├── uweng_cropped_2.png │ │ ├── uweng_cropped_3.png │ │ ├── uweng_cropped_4.png │ │ ├── uweng_cropped_5.png │ │ └── uweng_cropped_6.png │ └── README.md │ ├── pointer │ ├── README.md │ ├── Makefile │ └── pointer.c │ └── ls │ ├── README.md │ ├── Makefile │ ├── ls_fname.c │ └── ls_ftype.c ├── manual ├── ece252_manual.pdf ├── code │ └── linux │ │ └── HelloWorld │ │ ├── Makefile1 │ │ ├── Makefile1.tex │ │ ├── main.c │ │ ├── helloworld.c │ │ ├── Makefile │ │ ├── Makefile2.tex │ │ ├── makefile.tex │ │ ├── Makefile3.tex │ │ └── Makefile4.tex ├── img │ ├── img_concatenation.PNG │ ├── lab0 │ │ ├── lab0_P_Drive.PNG │ │ └── MobaXterm │ │ │ ├── MobaXterm_Path.PNG │ │ │ ├── MobaXterm_Start_Page.PNG │ │ │ └── MobaXterm_Login_Password.PNG │ ├── png_chunk_format.PNG │ └── png_file_format.PNG ├── main_book.tex ├── Makefile ├── bib │ └── bibliography_book.tex ├── mainmatter.tex ├── preemble_book_class.tex ├── app_group_split_request_form.tex ├── preemble │ ├── preemble_all.tex │ ├── preemble_cmds_book_class.tex │ ├── preemble_packages.tex │ └── util_listings.tex ├── frontmatter.tex ├── frontmatter_title.tex ├── main.bib ├── lab5_aio.tex └── p1_policy.tex ├── README.md └── .gitignore /lab4/starter/lab4_eceubuntu1.csv: -------------------------------------------------------------------------------- 1 | T,M,Time 2 | -------------------------------------------------------------------------------- /lab5/starter/lab5_eceubuntu1.csv: -------------------------------------------------------------------------------- 1 | T,M,Time 2 | -------------------------------------------------------------------------------- /lab3/starter/lab3_eceubuntu1.csv: -------------------------------------------------------------------------------- 1 | B,P,C,X,N,Time 2 | -------------------------------------------------------------------------------- /lab2/starter/img1.md5: -------------------------------------------------------------------------------- 1 | 1bb70face6c84b902c7603e752837aeb all.png 2 | -------------------------------------------------------------------------------- /lab3/starter/tools/paster2: -------------------------------------------------------------------------------- 1 | echo "paster2 execution time: 15.123456 seconds" 2 | -------------------------------------------------------------------------------- /lab3/starter/tools/sample_output.txt: -------------------------------------------------------------------------------- 1 | paster2 execution time: 15.123456 seconds 2 | -------------------------------------------------------------------------------- /lab4/starter/tools/sample_output.txt: -------------------------------------------------------------------------------- 1 | findpng2 execution time: 15.123456 seconds 2 | -------------------------------------------------------------------------------- /lab5/starter/tools/sample_output.txt: -------------------------------------------------------------------------------- 1 | findpng3 execution time: 15.123456 seconds 2 | -------------------------------------------------------------------------------- /lab1/starter/segfault/README.md: -------------------------------------------------------------------------------- 1 | The sample code demonstrates a segmentation fault. 2 | -------------------------------------------------------------------------------- /manual/ece252_manual.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/broehl/ece252/HEAD/manual/ece252_manual.pdf -------------------------------------------------------------------------------- /lab1/starter/png_util/README.md: -------------------------------------------------------------------------------- 1 | The code provides utility functions to process a PNG image file. 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | University of Waterloo ECE252 Systems Programming and Concurrency Lab Starter Files and Manual 2 | -------------------------------------------------------------------------------- /lab1/starter/cmd_arg/README.md: -------------------------------------------------------------------------------- 1 | The sample code demonstrates how to capture command line input arguments 2 | -------------------------------------------------------------------------------- /lab1/starter/images/uweng.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/broehl/ece252/HEAD/lab1/starter/images/uweng.png -------------------------------------------------------------------------------- /lab1/starter/pointer/README.md: -------------------------------------------------------------------------------- 1 | The sample code demonstrates how to use pointers to access a C structure. 2 | -------------------------------------------------------------------------------- /lab4/starter/tools/results/T10_M1.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab4/starter/tools/results/T10_M10.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab4/starter/tools/results/T10_M20.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab4/starter/tools/results/T10_M30.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab4/starter/tools/results/T10_M40.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab4/starter/tools/results/T10_M50.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab4/starter/tools/results/T1_M1.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab4/starter/tools/results/T1_M10.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab4/starter/tools/results/T1_M100.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab4/starter/tools/results/T1_M20.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab4/starter/tools/results/T1_M30.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab4/starter/tools/results/T1_M40.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab4/starter/tools/results/T1_M50.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab4/starter/tools/results/T20_M1.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab4/starter/tools/results/T20_M10.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab4/starter/tools/results/T20_M20.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab4/starter/tools/results/T20_M30.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab4/starter/tools/results/T20_M40.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab4/starter/tools/results/T20_M50.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab5/starter/tools/results/T10_M1.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab5/starter/tools/results/T10_M10.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab5/starter/tools/results/T10_M20.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab5/starter/tools/results/T10_M30.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab5/starter/tools/results/T10_M40.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab5/starter/tools/results/T10_M50.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab5/starter/tools/results/T1_M1.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab5/starter/tools/results/T1_M10.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab5/starter/tools/results/T1_M100.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab5/starter/tools/results/T1_M20.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab5/starter/tools/results/T1_M30.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab5/starter/tools/results/T1_M40.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab5/starter/tools/results/T1_M50.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab5/starter/tools/results/T20_M1.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab5/starter/tools/results/T20_M10.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab5/starter/tools/results/T20_M20.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab5/starter/tools/results/T20_M30.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab5/starter/tools/results/T20_M40.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab5/starter/tools/results/T20_M50.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab1/starter/images/WEEF_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/broehl/ece252/HEAD/lab1/starter/images/WEEF_1.png -------------------------------------------------------------------------------- /lab4/starter/tools/results/T10_M100.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab4/starter/tools/results/T20_M100.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab5/starter/tools/results/T10_M100.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab5/starter/tools/results/T20_M100.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /manual/code/linux/HelloWorld/Makefile1: -------------------------------------------------------------------------------- 1 | helloworld.out: helloworld.c 2 | gcc -o helloworld.out helloworld.c 3 | -------------------------------------------------------------------------------- /manual/img/img_concatenation.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/broehl/ece252/HEAD/manual/img/img_concatenation.PNG -------------------------------------------------------------------------------- /manual/img/lab0/lab0_P_Drive.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/broehl/ece252/HEAD/manual/img/lab0/lab0_P_Drive.PNG -------------------------------------------------------------------------------- /manual/img/png_chunk_format.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/broehl/ece252/HEAD/manual/img/png_chunk_format.PNG -------------------------------------------------------------------------------- /manual/img/png_file_format.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/broehl/ece252/HEAD/manual/img/png_file_format.PNG -------------------------------------------------------------------------------- /lab3/starter/tools/results/B10_P10_C10_X0_N1.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab3/starter/tools/results/B10_P10_C1_X0_N1.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab3/starter/tools/results/B10_P10_C5_X0_N1.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab3/starter/tools/results/B10_P1_C10_X0_N1.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab3/starter/tools/results/B10_P1_C1_X0_N1.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab3/starter/tools/results/B10_P1_C1_X200_N1.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab3/starter/tools/results/B10_P1_C1_X400_N1.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab3/starter/tools/results/B10_P1_C5_X0_N1.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab3/starter/tools/results/B10_P1_C5_X200_N1.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab3/starter/tools/results/B10_P1_C5_X400_N1.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab3/starter/tools/results/B10_P5_C10_X0_N1.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab3/starter/tools/results/B10_P5_C1_X0_N1.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab3/starter/tools/results/B10_P5_C1_X200_N1.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab3/starter/tools/results/B10_P5_C1_X400_N1.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab3/starter/tools/results/B10_P5_C5_X0_N1.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab3/starter/tools/results/B10_P5_C5_X200_N1.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab3/starter/tools/results/B10_P5_C5_X400_N1.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab3/starter/tools/results/B5_P1_C1_X0_N1.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab3/starter/tools/results/B5_P1_C1_X200_N1.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab3/starter/tools/results/B5_P1_C1_X400_N1.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab3/starter/tools/results/B5_P1_C5_X0_N1.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab3/starter/tools/results/B5_P1_C5_X200_N1.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab3/starter/tools/results/B5_P1_C5_X400_N1.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab3/starter/tools/results/B5_P5_C1_X0_N1.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab3/starter/tools/results/B5_P5_C1_X200_N1.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab3/starter/tools/results/B5_P5_C1_X400_N1.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab3/starter/tools/results/B5_P5_C5_X0_N1.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab3/starter/tools/results/B5_P5_C5_X200_N1.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab3/starter/tools/results/B5_P5_C5_X400_N1.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /manual/code/linux/HelloWorld/Makefile1.tex: -------------------------------------------------------------------------------- 1 | helloworld.out: helloworld.c 2 | gcc -o helloworld.out helloworld.c 3 | -------------------------------------------------------------------------------- /lab1/starter/ls/README.md: -------------------------------------------------------------------------------- 1 | The sample code demonstrates how to list all files under a directory and obtain file types. 2 | -------------------------------------------------------------------------------- /lab3/starter/tools/results/B10_P10_C10_X200_N1.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab3/starter/tools/results/B10_P10_C10_X400_N1.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab3/starter/tools/results/B10_P10_C1_X200_N1.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab3/starter/tools/results/B10_P10_C1_X400_N1.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab3/starter/tools/results/B10_P10_C5_X200_N1.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab3/starter/tools/results/B10_P10_C5_X400_N1.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab3/starter/tools/results/B10_P1_C10_X200_N1.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab3/starter/tools/results/B10_P1_C10_X400_N1.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab3/starter/tools/results/B10_P5_C10_X200_N1.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab3/starter/tools/results/B10_P5_C10_X400_N1.dat: -------------------------------------------------------------------------------- 1 | 15.123456 2 | 15.123456 3 | 15.123456 4 | 15.123456 5 | 15.123456 6 | -------------------------------------------------------------------------------- /lab1/starter/images/Disguise.png: -------------------------------------------------------------------------------- 1 | This is a text file, not a real PNG image file!!! 2 | The .png file extension is incorrect. 3 | -------------------------------------------------------------------------------- /lab1/starter/images/red-green-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/broehl/ece252/HEAD/lab1/starter/images/red-green-16x16.png -------------------------------------------------------------------------------- /manual/img/lab0/MobaXterm/MobaXterm_Path.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/broehl/ece252/HEAD/manual/img/lab0/MobaXterm/MobaXterm_Path.PNG -------------------------------------------------------------------------------- /lab1/starter/images/cropped/pic_cropped_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/broehl/ece252/HEAD/lab1/starter/images/cropped/pic_cropped_0.png -------------------------------------------------------------------------------- /lab1/starter/images/cropped/pic_cropped_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/broehl/ece252/HEAD/lab1/starter/images/cropped/pic_cropped_1.png -------------------------------------------------------------------------------- /lab1/starter/images/cropped/pic_cropped_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/broehl/ece252/HEAD/lab1/starter/images/cropped/pic_cropped_2.png -------------------------------------------------------------------------------- /lab1/starter/images/cropped/pic_cropped_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/broehl/ece252/HEAD/lab1/starter/images/cropped/pic_cropped_3.png -------------------------------------------------------------------------------- /lab1/starter/images/cropped/pic_cropped_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/broehl/ece252/HEAD/lab1/starter/images/cropped/pic_cropped_4.png -------------------------------------------------------------------------------- /lab1/starter/images/red-green-16x16-corrupted.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/broehl/ece252/HEAD/lab1/starter/images/red-green-16x16-corrupted.png -------------------------------------------------------------------------------- /manual/img/lab0/MobaXterm/MobaXterm_Start_Page.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/broehl/ece252/HEAD/manual/img/lab0/MobaXterm/MobaXterm_Start_Page.PNG -------------------------------------------------------------------------------- /lab1/starter/images/uweng_cropped/uweng_cropped_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/broehl/ece252/HEAD/lab1/starter/images/uweng_cropped/uweng_cropped_0.png -------------------------------------------------------------------------------- /lab1/starter/images/uweng_cropped/uweng_cropped_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/broehl/ece252/HEAD/lab1/starter/images/uweng_cropped/uweng_cropped_1.png -------------------------------------------------------------------------------- /lab1/starter/images/uweng_cropped/uweng_cropped_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/broehl/ece252/HEAD/lab1/starter/images/uweng_cropped/uweng_cropped_2.png -------------------------------------------------------------------------------- /lab1/starter/images/uweng_cropped/uweng_cropped_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/broehl/ece252/HEAD/lab1/starter/images/uweng_cropped/uweng_cropped_3.png -------------------------------------------------------------------------------- /lab1/starter/images/uweng_cropped/uweng_cropped_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/broehl/ece252/HEAD/lab1/starter/images/uweng_cropped/uweng_cropped_4.png -------------------------------------------------------------------------------- /lab1/starter/images/uweng_cropped/uweng_cropped_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/broehl/ece252/HEAD/lab1/starter/images/uweng_cropped/uweng_cropped_5.png -------------------------------------------------------------------------------- /lab1/starter/images/uweng_cropped/uweng_cropped_6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/broehl/ece252/HEAD/lab1/starter/images/uweng_cropped/uweng_cropped_6.png -------------------------------------------------------------------------------- /manual/img/lab0/MobaXterm/MobaXterm_Login_Password.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/broehl/ece252/HEAD/manual/img/lab0/MobaXterm/MobaXterm_Login_Password.PNG -------------------------------------------------------------------------------- /manual/code/linux/HelloWorld/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() 5 | { 6 | printf("Hello World!\n"); 7 | exit(0); 8 | } 9 | -------------------------------------------------------------------------------- /manual/code/linux/HelloWorld/helloworld.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() 5 | { 6 | printf("Hello World!\n"); 7 | exit(0); 8 | } 9 | -------------------------------------------------------------------------------- /manual/code/linux/HelloWorld/Makefile: -------------------------------------------------------------------------------- 1 | helloworld.out: helloworld.o 2 | gcc -o helloworld.out helloworld.o 3 | 4 | helloworld.o: helloworld.c 5 | gcc -c helloworld.c 6 | -------------------------------------------------------------------------------- /manual/code/linux/HelloWorld/Makefile2.tex: -------------------------------------------------------------------------------- 1 | helloworld.out: helloworld.o 2 | gcc -o helloworld.out helloworld.o 3 | helloworld.o: helloworld.c 4 | gcc -c helloworld.c 5 | -------------------------------------------------------------------------------- /manual/code/linux/HelloWorld/makefile.tex: -------------------------------------------------------------------------------- 1 | helloworld.out: helloworld.o 2 | gcc -o helloworld.out helloworld.o 3 | 4 | helloworld.o: helloworld.c 5 | gcc -c helloworld.c 6 | -------------------------------------------------------------------------------- /manual/code/linux/HelloWorld/Makefile3.tex: -------------------------------------------------------------------------------- 1 | all: app.out 2 | app.out: src1.o src2.o 3 | gcc -o app.out src1.o src2.o 4 | src1.o: src1.c 5 | gcc -c src1.c 6 | src2.o: src2.c 7 | gcc -c src2.c 8 | clean: 9 | rm *.o app.out 10 | -------------------------------------------------------------------------------- /lab4/starter/tools/findpng2: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ $# -lt 5 ]; then 4 | echo "Usage: $0 -t T -m M seed_url" 5 | echo "Example: $0 -t 10 -m 50 http://ece252-1.uwaterloo.ca/lab4" 6 | exit 1 7 | fi 8 | echo "findpng2 execution time: 15.123456 seconds" 9 | touch png_urls.txt 10 | -------------------------------------------------------------------------------- /lab5/starter/tools/findpng3: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ $# -lt 5 ]; then 4 | echo "Usage: $0 -t T -m M seed_url" 5 | echo "Example: $0 -t 10 -m 50 http://ece252-1.uwaterloo.ca/lab5" 6 | exit 1 7 | fi 8 | echo "findpng3 execution time: 15.123456 seconds" 9 | touch png_urls.txt 10 | -------------------------------------------------------------------------------- /lab1/starter/png_util/crc.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file: crc.h 3 | * @brief: crc calculation functions for PNG file 4 | */ 5 | 6 | #pragma once 7 | 8 | void make_crc_table(void); 9 | unsigned long update_crc(unsigned long crc, unsigned char *buf, int len); 10 | unsigned long crc(unsigned char *buf, int len); 11 | -------------------------------------------------------------------------------- /lab1/starter/pointer/Makefile: -------------------------------------------------------------------------------- 1 | CC=gcc 2 | CFLAGS=-Wall -g 3 | LD=gcc 4 | LDFLAGS=-g 5 | 6 | 7 | OBJS=pointer.o 8 | 9 | all: pointer.out 10 | 11 | pointer.out: $(OBJS) 12 | $(LD) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJS) 13 | 14 | .c.o: 15 | $(CC) $(CFLAGS) -c $< 16 | 17 | .PHONY: clean 18 | clean: 19 | rm -f *.o *.out 20 | -------------------------------------------------------------------------------- /lab1/starter/segfault/Makefile: -------------------------------------------------------------------------------- 1 | CC=gcc 2 | CFLAGS=-Wall -g 3 | LD=gcc 4 | LDFLAGS=-g 5 | 6 | 7 | OBJS=main_segv.o 8 | 9 | all: main_segv.out 10 | 11 | main_segv.out: $(OBJS) 12 | $(LD) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJS) 13 | 14 | .c.o: 15 | $(CC) $(CFLAGS) -c $< 16 | 17 | .PHONY: clean 18 | clean: 19 | rm -f *.o *.out 20 | -------------------------------------------------------------------------------- /manual/code/linux/HelloWorld/Makefile4.tex: -------------------------------------------------------------------------------- 1 | # Makefile to build app.out 2 | CC=gcc 3 | CFLAGS=-Wall -g 4 | LD=gcc 5 | LDFLAGS=-g 6 | 7 | OBJS=src1.o src2.o 8 | 9 | all: app.out 10 | app.out: $(OBJS) 11 | $(LD) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJS) 12 | .c.o: 13 | $(CC) $(CFLAGS) -c $< 14 | .PHONY: clean 15 | clean: 16 | rm -f *.o *.out 17 | -------------------------------------------------------------------------------- /manual/main_book.tex: -------------------------------------------------------------------------------- 1 | \input{preemble_book_class} 2 | \begin{document} 3 | % reset chapter number to 1 for each part 4 | \makeatletter 5 | \@addtoreset{chapter}{part} 6 | \makeatother 7 | \input{frontmatter} 8 | \input{mainmatter} 9 | %\input{backmatter} 10 | %\input{bibliography_book} 11 | \subimport{bib/}{bibliography_book} 12 | \end{document} 13 | 14 | %%% Local Variables: 15 | %%% mode: latex 16 | %%% TeX-master: t 17 | %%% End: 18 | -------------------------------------------------------------------------------- /lab4/starter/tools/results/tb2_31390.txt: -------------------------------------------------------------------------------- 1 | T,M,Time 2 | 1,1,0.000000 3 | 1,10,0.000000 4 | 1,20,0.000000 5 | 1,30,0.000000 6 | 1,40,0.000000 7 | 1,50,0.000000 8 | 1,100,0.000000 9 | 10,1,0.000000 10 | 10,10,0.000000 11 | 10,20,0.000000 12 | 10,30,0.000000 13 | 10,40,0.000000 14 | 10,50,0.000000 15 | 10,100,0.000000 16 | 20,1,0.000000 17 | 20,10,0.000000 18 | 20,20,0.000000 19 | 20,30,0.000000 20 | 20,40,0.000000 21 | 20,50,0.000000 22 | 20,100,0.000000 23 | -------------------------------------------------------------------------------- /lab5/starter/tools/results/tb2_26250.txt: -------------------------------------------------------------------------------- 1 | T,M,Time 2 | 1,1,0.000000 3 | 1,10,0.000000 4 | 1,20,0.000000 5 | 1,30,0.000000 6 | 1,40,0.000000 7 | 1,50,0.000000 8 | 1,100,0.000000 9 | 10,1,0.000000 10 | 10,10,0.000000 11 | 10,20,0.000000 12 | 10,30,0.000000 13 | 10,40,0.000000 14 | 10,50,0.000000 15 | 10,100,0.000000 16 | 20,1,0.000000 17 | 20,10,0.000000 18 | 20,20,0.000000 19 | 20,30,0.000000 20 | 20,40,0.000000 21 | 20,50,0.000000 22 | 20,100,0.000000 23 | -------------------------------------------------------------------------------- /lab3/starter/tools/clean_ipcs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh -x 2 | 3 | # clean shared memory regions and semaphores owned by the current user 4 | 5 | USERID=`whoami` 6 | 7 | # clean all shared memory regions owned by USERID 8 | for id in `ipcs -m | grep $USERID | awk -F' ' '{print $2}' ` 9 | do 10 | ipcrm -m $id 11 | done 12 | 13 | # clean all semaphores owned by USERID 14 | for id in `ipcs -s | grep $USERID | awk -F' ' '{print $2}' ` 15 | do 16 | ipcrm -s $id 17 | done 18 | -------------------------------------------------------------------------------- /manual/Makefile: -------------------------------------------------------------------------------- 1 | .SILENT: 2 | 3 | .PHONY: all clean 4 | 5 | LATEX = pdflatex 6 | PAPER = main_book 7 | OUTPUT = ece252_manual.pdf 8 | 9 | main: 10 | $(LATEX) $(PAPER) 11 | bibtex $(PAPER) 12 | $(LATEX) $(PAPER) 13 | mv $(PAPER).pdf $(OUTPUT) 14 | 15 | clean: 16 | rm -f *~ $(PAPER).dvi $(PAPER).log $(PAPER).pdf $(PAPER).ind $(OUTPUT) 17 | rm -f $(PAPER).bbl $(PAPER).blg $(PAPER).ps $(PAPER).aux 18 | rm -f $(PAPER).out $(PAPER).lot $(PAPER).lof $(PAPER).toc 19 | -------------------------------------------------------------------------------- /lab4/starter/tools/results/tb1_31390.txt: -------------------------------------------------------------------------------- 1 | T,M,Time 2 | 1,1,15.123456 3 | 1,10,15.123456 4 | 1,20,15.123456 5 | 1,30,15.123456 6 | 1,40,15.123456 7 | 1,50,15.123456 8 | 1,100,15.123456 9 | 10,1,15.123456 10 | 10,10,15.123456 11 | 10,20,15.123456 12 | 10,30,15.123456 13 | 10,40,15.123456 14 | 10,50,15.123456 15 | 10,100,15.123456 16 | 20,1,15.123456 17 | 20,10,15.123456 18 | 20,20,15.123456 19 | 20,30,15.123456 20 | 20,40,15.123456 21 | 20,50,15.123456 22 | 20,100,15.123456 23 | -------------------------------------------------------------------------------- /lab5/starter/tools/results/tb1_26250.txt: -------------------------------------------------------------------------------- 1 | T,M,Time 2 | 1,1,15.123456 3 | 1,10,15.123456 4 | 1,20,15.123456 5 | 1,30,15.123456 6 | 1,40,15.123456 7 | 1,50,15.123456 8 | 1,100,15.123456 9 | 10,1,15.123456 10 | 10,10,15.123456 11 | 10,20,15.123456 12 | 10,30,15.123456 13 | 10,40,15.123456 14 | 10,50,15.123456 15 | 10,100,15.123456 16 | 20,1,15.123456 17 | 20,10,15.123456 18 | 20,20,15.123456 19 | 20,30,15.123456 20 | 20,40,15.123456 21 | 20,50,15.123456 22 | 20,100,15.123456 23 | -------------------------------------------------------------------------------- /manual/bib/bibliography_book.tex: -------------------------------------------------------------------------------- 1 | %========================================================== 2 | % BIBLIOGRAPHY 3 | %========================================================== 4 | 5 | \bibliographystyle{plain} 6 | \bibliography{main} 7 | \renewcommand{\bibname}{References} % for the report or book class 8 | \addcontentsline{toc}{chapter}{\textbf{References}} % for book/report class 9 | %\renewcommand{\refname}{References} % for the article class 10 | %\addcontentsline{toc}{section}{\textbf{References}} % for article class 11 | -------------------------------------------------------------------------------- /lab1/starter/ls/Makefile: -------------------------------------------------------------------------------- 1 | # ECE252 File System Lab Makefile 2 | # Y. Huang, 2018/10/15 3 | 4 | CC=gcc 5 | CFLAGS=-Wall -g 6 | LD=gcc 7 | LDFLAGS=-g 8 | 9 | 10 | OBJS1=ls_ftype.o 11 | OBJS2=ls_fname.o 12 | 13 | all: ls_ftype.out ls_fname.out 14 | 15 | ls_ftype.out: $(OBJS1) 16 | $(LD) $(LDFLAGS) -o $@ $^ 17 | 18 | ls_fname.out: $(OBJS2) 19 | $(LD) $(LDFLAGS) -o $@ $^ 20 | 21 | .c.o: 22 | $(CC) $(CFLAGS) -c $< 23 | 24 | %.d: %.c 25 | gcc -MM -MF $@ $< 26 | 27 | 28 | .PHONY: clean 29 | clean: 30 | rm -f *.d *.o *.out 31 | -------------------------------------------------------------------------------- /lab2/starter/READM.md: -------------------------------------------------------------------------------- 1 | ECE252 Lab2 starter files: 2 | * `cURL` demonstrate using curl to download one random image segement of picture 1 from a lab server. 3 | * `fn_ptr` demonstrate C function pointer. 4 | * `getopt` demonstrate how to use `getopt` to parse command line input options. 5 | * `pthread` demonstrate how to create two threads. 6 | * `times` demonstrate various timing API usage. For reference only, not required to do timing analysis in lab2. 7 | * `img1.md5` The concatenated img1 md5 checksum. Use `md5sum ` to compute the checksum. 8 | -------------------------------------------------------------------------------- /lab2/starter/pthreads/Makefile: -------------------------------------------------------------------------------- 1 | 2 | # Makefile, ECE252 3 | # Yiqing Huang 4 | 5 | CC = gcc 6 | CFLAGS = -Wall -g -std=c99 7 | LD = gcc 8 | LDFLAGS = -g -std=c99 9 | LDLIBS = -pthread 10 | 11 | SRCS = main.c 12 | OBJS = main.o 13 | TARGETS= main.out 14 | 15 | all: ${TARGETS} 16 | 17 | main.out: $(OBJS) 18 | $(LD) -o $@ $^ $(LDLIBS) $(LDFLAGS) 19 | 20 | %.o: %.c 21 | $(CC) $(CFLAGS) -c $< 22 | 23 | %.d: %.c 24 | gcc -MM -MF $@ $< 25 | 26 | -include $(SRCS:.c=.d) 27 | 28 | .PHONY: clean 29 | clean: 30 | rm -f *~ *.d *.o $(TARGETS) 31 | -------------------------------------------------------------------------------- /lab1/starter/images/README.md: -------------------------------------------------------------------------------- 1 | The directory contains some PNG images. 2 | 3 | * WEEF\_1.png: a complete image. 4 | * uweng.png: a complete image. 5 | * red-green-16x16.png: an image containing one red bar on the left and one green bar on the right. 6 | * cropped: cropped images by splitting the WEEF\_1.png from top to bottom (i.e. vertically). Each cropped image is a horizontal strip of the original image. 7 | * uweng\_cropped: cropped images by splitting the uweng.png from top to bottom (i.e. vertically). Each cropped image is a horizontal strip of the original image. 8 | -------------------------------------------------------------------------------- /lab2/starter/getopt/Makefile: -------------------------------------------------------------------------------- 1 | 2 | # Makefile, ECE252 3 | # Yiqing Huang 4 | 5 | CC = gcc 6 | CFLAGS = -Wall -g -std=gnu99 7 | LD = gcc 8 | LDFLAGS = -g 9 | LDLIBS = 10 | 11 | SRCS = main_getopt.c 12 | OBJS = main_getopt.o 13 | TARGETS= main_getopt.out 14 | 15 | all: ${TARGETS} 16 | 17 | main_getopt.out: $(OBJS) 18 | $(LD) -o $@ $^ $(LDLIBS) $(LDFLAGS) 19 | 20 | %.o: %.c 21 | $(CC) $(CFLAGS) -c $< 22 | 23 | %.d: %.c 24 | gcc -MM -MF $@ $< 25 | 26 | -include $(SRCS:.c=.d) 27 | 28 | .PHONY: clean 29 | clean: 30 | rm -f *~ *.d *.o $(TARGETS) 31 | -------------------------------------------------------------------------------- /lab2/starter/fn_ptr/Makefile: -------------------------------------------------------------------------------- 1 | 2 | # Makefile, ECE252 3 | # Yiqing Huang, 2018/11/02 4 | 5 | CC = gcc 6 | CFLAGS = -Wall -g 7 | LD = gcc 8 | LDFLAGS = -g 9 | LDLIBS = 10 | 11 | SRCS_LIB = 12 | SRCS = main.c $(SRCS_LIB) 13 | LIBS = 14 | OBJS = main.o $(LIBS) 15 | TARGETS= main.out 16 | 17 | all: ${TARGETS} 18 | 19 | main.out: $(OBJS) 20 | $(LD) -o $@ $^ $(LDLIBS) $(LDFLAGS) 21 | 22 | %.o: %.c 23 | $(CC) $(CFLAGS) -c $< 24 | 25 | %.d: %.c 26 | gcc -MM -MF $@ $< 27 | 28 | -include $(SRCS:.c=.d) 29 | 30 | .PHONY: clean 31 | clean: 32 | rm -f *~ *.d *.o $(TARGETS) 33 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | #LaTex generated files 2 | 3 | **/*.aux 4 | **/*.blg 5 | **/*.brf 6 | **/*.dvi 7 | **/*.lof 8 | **/*.log 9 | **/*.lot 10 | **/*.synctex.gz 11 | **/*.toc 12 | 13 | 14 | # Object files 15 | **/*.o 16 | 17 | # Libraries 18 | **/*.lib 19 | **/*.a 20 | 21 | # Shared objects (inc. Windows DLLs) 22 | **/*.dll 23 | **/*.so 24 | **/*.so.* 25 | **/*.dylib 26 | 27 | # Executables 28 | **/*.exe 29 | **/*.out 30 | **/*.app 31 | 32 | # backup from from editor 33 | **/*~ 34 | **/#**# 35 | 36 | # emacs intermediate files 37 | **/*.el 38 | 39 | # flymd intermediate files 40 | **/flymd.* 41 | -------------------------------------------------------------------------------- /lab1/starter/cmd_arg/Makefile: -------------------------------------------------------------------------------- 1 | ######################################################################### 2 | # ECE252 Lab Makefile 3 | # Y. Huang, 2018/10/15 4 | ######################################################################### 5 | 6 | CC=gcc 7 | CFLAGS=-Wall -g 8 | LD=gcc 9 | LDFLAGS=-g 10 | 11 | SRCS=cmd_arg.c 12 | OBJS=cmd_arg.o 13 | 14 | all: cmd_arg.out 15 | 16 | cmd_arg.out: $(OBJS) 17 | $(LD) $(LDFLAGS) -o $@ $^ 18 | 19 | .c.o: 20 | $(CC) $(CFLAGS) -c $< 21 | 22 | %.d: %.c 23 | gcc -MM -MF $@ $< 24 | 25 | -include $(SRCS:.c=.d) 26 | 27 | .PHONY: clean 28 | clean: 29 | rm -f *.d *.o *.out 30 | -------------------------------------------------------------------------------- /lab1/starter/png_util/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile, ECE252 2 | # Yiqing Huang 3 | 4 | CC = gcc # compiler 5 | CFLAGS = -Wall -g -std=c99 # compilation flags 6 | LD = gcc # linker 7 | LDFLAGS = -g # debugging symbols in build 8 | LDLIBS = -lz # link with libz 9 | 10 | # For students 11 | LIB_UTIL = zutil.o crc.o 12 | SRCS = main.c crc.c zutil.c 13 | OBJS = main.o $(LIB_UTIL) 14 | 15 | TARGETS= main.out 16 | 17 | all: ${TARGETS} 18 | 19 | main.out: $(OBJS) 20 | $(LD) -o $@ $^ $(LDLIBS) $(LDFLAGS) 21 | 22 | %.o: %.c 23 | $(CC) $(CFLAGS) -c $< 24 | 25 | %.d: %.c 26 | gcc -MM -MF $@ $< 27 | 28 | -include $(SRCS:.c=.d) 29 | 30 | .PHONY: clean 31 | clean: 32 | rm -f *.d *.o $(TARGETS) 33 | -------------------------------------------------------------------------------- /lab5/starter/curl_multi/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile, ECE252 2 | # Yiqing Huang 3 | 4 | CC = gcc 5 | CFLAGS_LIBS = $(shell pkg-config --cflags libxml-2.0 libcurl) 6 | CFLAGS = -Wall $(CFLAGS_LIBS) -std=gnu99 -g 7 | LD = gcc 8 | LDFLAGS = -std=gnu99 -g 9 | LDLIBS = $(shell pkg-config --libs libxml-2.0 libcurl) 10 | 11 | SRCS = curl_multi_test.c 12 | OBJS1 = curl_multi_test.o 13 | TARGETS= curl_multi_test.out 14 | 15 | all: ${TARGETS} 16 | 17 | curl_multi_test.out: $(OBJS1) 18 | $(LD) -o $@ $^ $(LDLIBS) $(LDFLAGS) 19 | 20 | %.o: %.c 21 | $(CC) $(CFLAGS) -c $< 22 | 23 | %.d: %.c 24 | gcc -MM -MF $@ $< 25 | 26 | -include $(SRCS:.c=.d) 27 | 28 | .PHONY: clean 29 | clean: 30 | rm -f *~ *.d *.o $(TARGETS) 31 | -------------------------------------------------------------------------------- /lab3/starter/shm/shm_stack.h: -------------------------------------------------------------------------------- 1 | 2 | /* The code is 3 | * Copyright(c) 2018-2019 Yiqing Huang, . 4 | * 5 | * This software may be freely redistributed under the terms of the X11 License. 6 | */ 7 | /** 8 | * @brief stack to push/pop integer(s), API header 9 | * @author yqhuang@uwaterloo.ca 10 | */ 11 | 12 | struct int_stack; 13 | 14 | int sizeof_shm_stack(int size); 15 | int init_shm_stack(struct int_stack *p, int stack_size); 16 | struct int_stack *create_stack(int size); 17 | void destroy_stack(struct int_stack *p); 18 | int is_full(struct int_stack *p); 19 | int is_empty(struct int_stack *p); 20 | int push(struct int_stack *p, int item); 21 | int pop(struct int_stack *p, int *p_item); 22 | -------------------------------------------------------------------------------- /lab3/starter/sem/Makefile: -------------------------------------------------------------------------------- 1 | 2 | # Makefile, ECE252 3 | # Yiqing Huang, 2019/06/12 4 | 5 | CC = gcc # compiler 6 | CFLAGS = -Wall -g -std=gnu99# compilation flg 7 | LD = gcc # linker 8 | LDFLAGS = -g -std=gnu99 # debugging symbols in build 9 | LDLIBS =-lpthread # link with libpthread 10 | 11 | # For students 12 | LIB_UTIL = 13 | SRCS = sem_simple.c 14 | OBJS3 = sem_simple.o 15 | 16 | TARGETS=sem_simple.out 17 | 18 | all: ${TARGETS} 19 | sem_simple.out: ${OBJS3} 20 | $(LD) -o $@ $^ $(LDLIBS) $(LDFLAGS) 21 | 22 | %.o: %.c 23 | $(CC) $(CFLAGS) -c $< 24 | 25 | %.d: %.c 26 | gcc -MM -MF $@ $< 27 | 28 | -include $(SRCS:.c=.d) 29 | 30 | .PHONY: clean 31 | clean: 32 | rm -f *.d *.o *~ $(TARGETS) 33 | -------------------------------------------------------------------------------- /lab3/starter/cURL_IPC/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile, ECE252 2 | # Yiqing Huang 3 | 4 | CC = gcc 5 | CFLAGS = -Wall -std=c99 -g # "curl-config --cflags" output is empty 6 | LD = gcc 7 | LDFLAGS = -std=c99 -g 8 | LDLIBS = -lcurl -pthread# "curl-config --libs" output 9 | 10 | SRCS = main.c main_2proc.c main_sem.c 11 | OBJS1 = main.o 12 | OBJS2 = main_2proc.o 13 | TARGETS= main.out main_2proc.out 14 | 15 | all: ${TARGETS} 16 | 17 | main.out: $(OBJS1) 18 | $(LD) -o $@ $^ $(LDLIBS) $(LDFLAGS) 19 | 20 | main_2proc.out: $(OBJS2) 21 | $(LD) -o $@ $^ $(LDLIBS) $(LDFLAGS) 22 | 23 | %.o: %.c 24 | $(CC) $(CFLAGS) -c $< 25 | 26 | %.d: %.c 27 | gcc -MM -MF $@ $< 28 | 29 | -include $(SRCS:.c=.d) 30 | 31 | .PHONY: clean 32 | clean: 33 | rm -f *~ *.d *.o *~ $(TARGETS) *.png 34 | -------------------------------------------------------------------------------- /lab2/starter/times/Makefile: -------------------------------------------------------------------------------- 1 | 2 | # Makefile, ECE252 3 | # Yiqing Huang, 2018/11/02 4 | 5 | CC = gcc 6 | CFLAGS = -Wall -g # "curl-config --cflags" output is NULL 7 | LD = gcc 8 | LDFLAGS = -g 9 | #LDLIBS = -L/usr/lib/x86_64-linux-gnu -lcurl # "curl-config --libs" output 10 | LDLIBS = #-lcurl -lpng# "curl-config --libs" output 11 | 12 | SRCS_LIB = # util_curl.c util.c 13 | SRCS = main.c $(SRCS_LIB) 14 | LIBS = # util_curl.o util.o 15 | OBJS = main.o $(LIBS) 16 | TARGETS= main.out 17 | 18 | all: ${TARGETS} 19 | 20 | main.out: $(OBJS) 21 | $(LD) -o $@ $^ $(LDLIBS) $(LDFLAGS) 22 | 23 | %.o: %.c 24 | $(CC) $(CFLAGS) -c $< 25 | 26 | %.d: %.c 27 | gcc -MM -MF $@ $< 28 | 29 | -include $(SRCS:.c=.d) 30 | 31 | .PHONY: clean 32 | clean: 33 | rm -f *.d *.o $(TARGETS) 34 | -------------------------------------------------------------------------------- /lab4/starter/curl_xml/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile, ECE252 2 | # Yiqing Huang 3 | 4 | CC = gcc 5 | CFLAGS_XML2 = $(shell xml2-config --cflags) 6 | CFLAGS_CURL = $(shell curl-config --cflags) 7 | CFLAGS = -Wall $(CFLAGS_XML2) $(CFLAGS_CURL) -std=gnu99 -g -DDEBUG1_ 8 | LD = gcc 9 | LDFLAGS = -std=gnu99 -g 10 | LDLIBS_XML2 = $(shell xml2-config --libs) 11 | LDLIBS_CURL = $(shell curl-config --libs) 12 | LDLIBS = $(LDLIBS_XML2) $(LDLIBS_CURL) 13 | 14 | SRCS = main.c 15 | OBJS3 = main.o 16 | TARGETS= main.out 17 | 18 | all: ${TARGETS} 19 | 20 | main.out: $(OBJS3) 21 | $(LD) -o $@ $^ $(LDLIBS) $(LDFLAGS) 22 | 23 | %.o: %.c 24 | $(CC) $(CFLAGS) -c $< 25 | 26 | %.d: %.c 27 | gcc -MM -MF $@ $< 28 | 29 | -include $(SRCS:.c=.d) 30 | 31 | .PHONY: clean 32 | clean: 33 | rm -f *~ *.d *.o $(TARGETS) *.png *.html 34 | -------------------------------------------------------------------------------- /lab3/starter/fork/Makefile: -------------------------------------------------------------------------------- 1 | 2 | # Makefile, ECE252 3 | # Yiqing Huang, 2019/06/12 4 | 5 | CC = gcc # compiler 6 | CFLAGS = -Wall -g -std=gnu99# compilation flg 7 | LD = gcc # linker 8 | LDFLAGS = -g # debugging symbols in build 9 | LDLIBS = # link with libz 10 | 11 | # For students 12 | LIB_UTIL = 13 | SRCS = forkN.c zombie.c 14 | OBJS1 = forkN.o $(LIB_UTIL) 15 | OBJS2 = zombie.o $(LIB_UTIL) 16 | 17 | TARGETS= forkN.out zombie.out 18 | 19 | all: ${TARGETS} 20 | 21 | forkN.out: $(OBJS1) 22 | $(LD) -o $@ $^ $(LDLIBS) $(LDFLAGS) 23 | 24 | zombie.out: $(OBJS2) 25 | $(LD) -o $@ $^ $(LDLIBS) $(LDFLAGS) 26 | 27 | %.o: %.c 28 | $(CC) $(CFLAGS) -c $< 29 | 30 | %.d: %.c 31 | gcc -MM -MF $@ $< 32 | 33 | -include $(SRCS:.c=.d) 34 | 35 | .PHONY: clean 36 | clean: 37 | rm -f *.d *.o *~ $(TARGETS) 38 | -------------------------------------------------------------------------------- /lab3/starter/shm/Makefile: -------------------------------------------------------------------------------- 1 | 2 | # Makefile, ECE252 3 | # Yiqing Huang, 2019/06/12 4 | 5 | CC = gcc # compiler 6 | CFLAGS = -Wall -g # compilation flg 7 | LD = gcc # linker 8 | LDFLAGS = -g # debugging symbols in build 9 | LDLIBS = # link with libz 10 | 11 | # For students 12 | LIB_UTIL = 13 | SRCS = shm_stack.c shm_simple.c shm_struct.c 14 | OBJS1 = shm_simple.o $(LIB_UTIL) 15 | OBJS2 = shm_struct.c shm_stack.o $(LIB_UTIL) 16 | 17 | TARGETS= shm_simple.out shm_struct.out 18 | 19 | all: ${TARGETS} 20 | 21 | shm_simple.out: $(OBJS1) 22 | $(LD) -o $@ $^ $(LDLIBS) $(LDFLAGS) 23 | 24 | shm_struct.out: $(OBJS2) 25 | $(LD) -o $@ $^ $(LDLIBS) $(LDFLAGS) 26 | 27 | %.o: %.c 28 | $(CC) $(CFLAGS) -c $< 29 | 30 | %.d: %.c 31 | gcc -MM -MF $@ $< 32 | 33 | -include $(SRCS:.c=.d) 34 | 35 | .PHONY: clean 36 | clean: 37 | rm -f *.d *.o *~ $(TARGETS) 38 | -------------------------------------------------------------------------------- /manual/mainmatter.tex: -------------------------------------------------------------------------------- 1 | \mainmatter 2 | 3 | %PART I, Lab Administration 4 | \part{Lab Administration} 5 | \label{part_admin} 6 | \input{p1_policy} 7 | 8 | %PART II, Lab Projects 9 | \part{Lab Projects} 10 | \renewcommand{\chaptername}{Lab} 11 | \label{part_proj_description} 12 | \input{lab1_intro_linux_sys_prog} 13 | \input{lab2_curl_pthreads} 14 | \input{lab3_producer_consumer} 15 | \input{lab4_crawler} 16 | \input{lab5_aio} 17 | 18 | %PART III, Development Tools Reference 19 | \part{Software Development Environment Quick Reference Guide} 20 | \label{part_ref} 21 | \makeatletter 22 | \renewcommand{\chaptername}{Chapter} 23 | \renewcommand{\thefigure}{C\@arabic\c@figure} 24 | \renewcommand{\thetable}{C\@arabic\c@table} 25 | \makeatother 26 | \input{p3_linux_dev_tools} 27 | 28 | % Appendix 29 | \appendix 30 | \input{app_group_split_request_form} 31 | 32 | 33 | %%% Local Variables: 34 | %%% mode: latex 35 | %%% TeX-master: "main_book" 36 | %%% End: 37 | -------------------------------------------------------------------------------- /manual/preemble_book_class.tex: -------------------------------------------------------------------------------- 1 | %%%%%%%%%%%%% PREEMBLE HEADER %%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2 | 3 | %========================================================== 4 | % 1. DOCUMENT TYPE AND OPTIONS 5 | %========================================================== 6 | 7 | \documentclass[letterpaper, 12pt, titlepage, oneside, final]{book} 8 | 9 | %========================================================== 10 | % 2. PACKAGES 11 | %========================================================== 12 | \usepackage{import} 13 | \subimport{preemble/}{preemble_packages} 14 | 15 | %============================================================ 16 | % 3. COMMANDS 17 | %========================================================== 18 | 19 | \subimport{preemble/}{preemble_cmds_book_class} 20 | 21 | %============================================================ 22 | % 4. MISC 23 | %========================================================== 24 | \subimport{preemble/}{util_listings} 25 | -------------------------------------------------------------------------------- /lab2/starter/cURL/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile, ECE252 2 | # Yiqing Huang, 2018/11/02 3 | 4 | CC = gcc 5 | CFLAGS = -Wall -std=c99 -g # "curl-config --cflags" output is empty 6 | LD = gcc 7 | LDFLAGS = -std=c99 -g 8 | LDLIBS = -lcurl # "curl-config --libs" output 9 | 10 | SRCS = main_simple.c main_write_callback.c main_write_header_cb.c 11 | OBJS1 = main_simple.o 12 | OBJS2 = main_write_callback.o 13 | OBJS3 = main_write_header_cb.o 14 | TARGETS= main_simple.out main_write_callback.out main_write_header_cb.out 15 | 16 | all: ${TARGETS} 17 | 18 | main_simple.out: $(OBJS1) 19 | $(LD) -o $@ $^ $(LDLIBS) $(LDFLAGS) 20 | 21 | main_write_callback.out: $(OBJS2) 22 | $(LD) -o $@ $^ $(LDLIBS) $(LDFLAGS) 23 | 24 | main_write_header_cb.out: $(OBJS3) 25 | $(LD) -o $@ $^ $(LDLIBS) $(LDFLAGS) 26 | 27 | %.o: %.c 28 | $(CC) $(CFLAGS) -c $< 29 | 30 | %.d: %.c 31 | gcc -MM -MF $@ $< 32 | 33 | -include $(SRCS:.c=.d) 34 | 35 | .PHONY: clean 36 | clean: 37 | rm -f *~ *.d *.o $(TARGETS) *.png 38 | -------------------------------------------------------------------------------- /lab1/starter/segfault/main_segv.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @brief: To demonstrate segmentation fault 3 | */ 4 | #include 5 | #include 6 | #include 7 | 8 | struct buf { 9 | size_t size; /* buffer size */ 10 | char *data ; /* data */ 11 | }; 12 | 13 | /* To model a point on 2D terminal screen */ 14 | struct point 15 | { 16 | int x; 17 | int y; 18 | }; 19 | 20 | 21 | int main(void) 22 | { 23 | struct buf *p, *q; 24 | struct point pt={1,2}; 25 | 26 | p = (struct buf *)malloc(sizeof(struct buf)); 27 | q = p; 28 | 29 | p->data = (char *)&pt ; 30 | p->size = sizeof(struct point); 31 | 32 | printf("p->x = %d, p->y =%d\n", ((struct point*)(p->data))->x, ((struct point *)(p->data))->y); 33 | 34 | /* remove pointe p */ 35 | p->data = NULL; 36 | p->size = 0; 37 | free(p); 38 | 39 | printf("q->x = %d, q->y =%d\n", ((struct point*)(q->data))->x, ((struct point *)(q->data))->y); 40 | 41 | 42 | return(0); 43 | } 44 | -------------------------------------------------------------------------------- /lab3/starter/tools/results/tb2_N1_32592.txt: -------------------------------------------------------------------------------- 1 | B,P,C,X,N,Time 2 | 5,1,1,0,1,0.000000 3 | 5,1,5,0,1,0.000000 4 | 5,5,1,0,1,0.000000 5 | 5,5,5,0,1,0.000000 6 | 10,1,1,0,1,0.000000 7 | 10,1,5,0,1,0.000000 8 | 10,1,10,0,1,0.000000 9 | 10,5,1,0,1,0.000000 10 | 10,5,5,0,1,0.000000 11 | 10,5,10,0,1,0.000000 12 | 10,10,1,0,1,0.000000 13 | 10,10,5,0,1,0.000000 14 | 10,10,10,0,1,0.000000 15 | 5,1,1,200,1,0.000000 16 | 5,1,5,200,1,0.000000 17 | 5,5,1,200,1,0.000000 18 | 5,5,5,200,1,0.000000 19 | 10,1,1,200,1,0.000000 20 | 10,1,5,200,1,0.000000 21 | 10,1,10,200,1,0.000000 22 | 10,5,1,200,1,0.000000 23 | 10,5,5,200,1,0.000000 24 | 10,5,10,200,1,0.000000 25 | 10,10,1,200,1,0.000000 26 | 10,10,5,200,1,0.000000 27 | 10,10,10,200,1,0.000000 28 | 5,1,1,400,1,0.000000 29 | 5,1,5,400,1,0.000000 30 | 5,5,1,400,1,0.000000 31 | 5,5,5,400,1,0.000000 32 | 10,1,1,400,1,0.000000 33 | 10,1,5,400,1,0.000000 34 | 10,1,10,400,1,0.000000 35 | 10,5,1,400,1,0.000000 36 | 10,5,5,400,1,0.000000 37 | 10,5,10,400,1,0.000000 38 | 10,10,1,400,1,0.000000 39 | 10,10,5,400,1,0.000000 40 | 10,10,10,400,1,0.000000 41 | -------------------------------------------------------------------------------- /manual/app_group_split_request_form.tex: -------------------------------------------------------------------------------- 1 | \chapter{Forms} 2 | Lab administration related forms are given in this appendix. 3 | \newpage 4 | \begin{center} 5 | {\bf ECE252 Request to Leave a Project Group Form} 6 | \end{center} 7 | 8 | \begin{table*}[h] 9 | \begin{center} 10 | \begin{tabular}{|p{6cm}|p{6cm}|} 11 | \hline 12 | Name: & \\ \hline 13 | Quest ID: & \\ \hline 14 | Student ID: & \\ \hline 15 | Lab Assignment ID & \\ \hline 16 | Group ID: & \\ \hline 17 | Name of Other Group Members: & \\ \hline 18 | \end{tabular} 19 | \end{center} 20 | \end{table*} 21 | 22 | Provide the reason for leaving the project group here: 23 | 24 | \vspace{9cm} 25 | 26 | \begin{table*} 27 | \begin{center} 28 | \begin{tabular}{p{6cm} p{1cm} p{6cm}} 29 | Signature && Date \\ 30 | \cline{1-1} 31 | \cline{3-3} 32 | \end{tabular} 33 | \end{center} 34 | \end{table*} 35 | %%% Local Variables: 36 | %%% mode: latex 37 | %%% TeX-master: "main_book" 38 | %%% End: 39 | -------------------------------------------------------------------------------- /lab2/starter/times/util_times.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file util_times.h 3 | * @brief utility function to obtain time resource usage. 4 | * @author yqhuang@uwaterloo.ca 5 | */ 6 | #pragma once 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include /* man sysconf(3) */ 14 | #include /* man times(2) */ 15 | 16 | #define BUF_SIZE_256 256 17 | #define NUM_FUNS 3 18 | 19 | typedef struct fn_info 20 | { 21 | void *(*fnp)(void *args); /* function pointer */ 22 | const char name[64]; /* function name */ 23 | } *FN_INFO_P; 24 | 25 | typedef struct fn_info_map 26 | { 27 | unsigned int size; /* size of the fn_info_strutp */ 28 | FN_INFO_P fn_info_structp; /* array of fn_info structures*/ 29 | } *FN_INFO_MAP_P; 30 | 31 | const char *get_name_by_fnp (FN_INFO_P ptr, void *(*fnp)(void *args)); 32 | void *time_it(FN_INFO_P ptr, void *(*fnp)(void *args), void *args); 33 | void pr_times(clock_t real, struct tms *tmsstart, struct tms *tmsend); 34 | -------------------------------------------------------------------------------- /lab3/starter/tools/results/tb1_N1_32592.txt: -------------------------------------------------------------------------------- 1 | B,P,C,X,N,Time 2 | 5,1,1,0,1,15.123456 3 | 5,1,5,0,1,15.123456 4 | 5,5,1,0,1,15.123456 5 | 5,5,5,0,1,15.123456 6 | 10,1,1,0,1,15.123456 7 | 10,1,5,0,1,15.123456 8 | 10,1,10,0,1,15.123456 9 | 10,5,1,0,1,15.123456 10 | 10,5,5,0,1,15.123456 11 | 10,5,10,0,1,15.123456 12 | 10,10,1,0,1,15.123456 13 | 10,10,5,0,1,15.123456 14 | 10,10,10,0,1,15.123456 15 | 5,1,1,200,1,15.123456 16 | 5,1,5,200,1,15.123456 17 | 5,5,1,200,1,15.123456 18 | 5,5,5,200,1,15.123456 19 | 10,1,1,200,1,15.123456 20 | 10,1,5,200,1,15.123456 21 | 10,1,10,200,1,15.123456 22 | 10,5,1,200,1,15.123456 23 | 10,5,5,200,1,15.123456 24 | 10,5,10,200,1,15.123456 25 | 10,10,1,200,1,15.123456 26 | 10,10,5,200,1,15.123456 27 | 10,10,10,200,1,15.123456 28 | 5,1,1,400,1,15.123456 29 | 5,1,5,400,1,15.123456 30 | 5,5,1,400,1,15.123456 31 | 5,5,5,400,1,15.123456 32 | 10,1,1,400,1,15.123456 33 | 10,1,5,400,1,15.123456 34 | 10,1,10,400,1,15.123456 35 | 10,5,1,400,1,15.123456 36 | 10,5,5,400,1,15.123456 37 | 10,5,10,400,1,15.123456 38 | 10,10,1,400,1,15.123456 39 | 10,10,5,400,1,15.123456 40 | 10,10,10,400,1,15.123456 41 | -------------------------------------------------------------------------------- /lab1/starter/cmd_arg/cmd_arg.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @brief: How to pass command line input arguments to main program 3 | * To execute: [arg1] [arg2]...[argN] 4 | * EXAMPLE: ./cmd_arg.out Hello ECE252 101 201 5 | */ 6 | 7 | #include /* printf needs to include this header file */ 8 | 9 | /** 10 | *@brief: main function that lists all command line arguments 11 | *@param: int argc is the number of command line arguments. 12 | * The executable itself is the first argument. 13 | *@param: char *argv is an array to hold each command line argument as an element. 14 | * argv[0] contains the string representation of executable's name 15 | * argv[1] contains the string representation of the 1st input argument 16 | * ... 17 | * argv[n] contains the string representation of the n'th input argument 18 | */ 19 | int main(int argc, char *argv[]) 20 | { 21 | int i; 22 | 23 | printf("A complete list of command line arguments:\n"); 24 | for (i = 0; i < argc; i++) { 25 | printf("argv[%d]=%s\n", i, argv[i]); 26 | } 27 | return 0; 28 | } 29 | -------------------------------------------------------------------------------- /lab1/starter/png_util/zutil.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @brief: header file of in memory deflation and inflation using zlib. 3 | * Based on the zlib example zpipe.c at https://www.zlib.net/zlib_how.html 4 | * 5 | * Modification is 6 | * Copyright 2018-2020 Yiqing Huang 7 | * 8 | * This software may be freely redistributed under the terms of MIT License 9 | * https://www.zlib.net/zlib_how.html 10 | */ 11 | 12 | #pragma once 13 | 14 | /* INCLUDES */ 15 | #include 16 | #include 17 | #include 18 | #include "zlib.h" 19 | 20 | /* DEFINES */ 21 | #if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__) 22 | # include 23 | # include 24 | # define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY) 25 | #else 26 | # define SET_BINARY_MODE(file) 27 | #endif 28 | 29 | #define CHUNK 16384 /* =256*64 on the order of 128K or 256K should be used */ 30 | 31 | /* TYPEDEFS */ 32 | typedef unsigned char U8; 33 | typedef unsigned long int U64; 34 | 35 | /* FUNCTION PROTOTYPES */ 36 | int mem_def(U8 *dest, U64 *dest_len, U8 *source, U64 source_len, int level); 37 | int mem_inf(U8 *dest, U64 *dest_len, U8 *source, U64 source_len); 38 | void zerr(int ret); 39 | -------------------------------------------------------------------------------- /lab3/starter/fork/zombie.c: -------------------------------------------------------------------------------- 1 | /* 2 | * The code Copyright(c) 2018-2019 Yiqing Huang, . 3 | * This software may be freely redistributed under the terms of the X11 License. 4 | */ 5 | 6 | /** 7 | * @brief To doemostrate a zombie process 8 | * @file zombie.c 9 | */ 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #define _XOPEN_SOURCE 500 16 | 17 | int main () 18 | { 19 | pid_t child_pid; 20 | /* Create a child process. */ 21 | child_pid = fork (); 22 | 23 | if ( child_pid > 0 ) { 24 | int pid=getpid(); 25 | sleep(1); 26 | printf("Parent pid=%d.\n", pid); 27 | printf("Use command \"ps -eo ruser,pid,ppid,pgid,stat,cmd | grep %d| grep -v grep\" to see both processes.\n", pid); 28 | /* Parent process sleeps for 120 seconds. */ 29 | sleep (120); 30 | } else if ( child_pid == 0 ) { 31 | /* The child process exits immediately after printf. 32 | will be in zombie status before parent exits, 33 | since parent does not wait on child process. 34 | */ 35 | 36 | printf("Child pid = %d.\n", getpid()); 37 | exit (0); 38 | } else { 39 | perror("fork"); 40 | abort(); 41 | } 42 | return 0; 43 | } 44 | -------------------------------------------------------------------------------- /lab1/starter/ls/ls_fname.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file: ls_fname.c 3 | * @brief: simple ls command to list file names of a directory 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include /* for printf(). man 3 printf */ 11 | #include /* for exit(). man 3 exit */ 12 | #include /* for strcat(). man strcat */ 13 | 14 | int main(int argc, char *argv[]) 15 | { 16 | DIR *p_dir; 17 | struct dirent *p_dirent; 18 | char str[64]; 19 | 20 | if (argc == 1) { 21 | fprintf(stderr, "Usage: %s \n", argv[0]); 22 | exit(1); 23 | } 24 | 25 | if ((p_dir = opendir(argv[1])) == NULL) { 26 | sprintf(str, "opendir(%s)", argv[1]); 27 | perror(str); 28 | exit(2); 29 | } 30 | 31 | while ((p_dirent = readdir(p_dir)) != NULL) { 32 | char *str_path = p_dirent->d_name; /* relative path name! */ 33 | 34 | if (str_path == NULL) { 35 | fprintf(stderr,"Null pointer found!"); 36 | exit(3); 37 | } else { 38 | printf("%s\n", str_path); 39 | } 40 | } 41 | 42 | if ( closedir(p_dir) != 0 ) { 43 | perror("closedir"); 44 | exit(3); 45 | } 46 | 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /lab1/starter/ls/ls_ftype.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file: ECE252/lab1/starter/ls/ls_ftype.c 3 | * @brief: Print the type of file for each command-line argument 4 | * @author: W. Richard Stevens, Advanced Programming in the UNIX Environment 5 | * @date: 2018/10/15 6 | */ 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | int main(int argc, char *argv[]) 15 | { 16 | int i; 17 | char *ptr; 18 | struct stat buf; 19 | 20 | for (i = 1; i < argc; i++) { 21 | printf("%s: ", argv[i]); 22 | if (lstat(argv[i], &buf) < 0) { 23 | perror("lstat error"); 24 | continue; 25 | } 26 | 27 | if (S_ISREG(buf.st_mode)) ptr = "regular"; 28 | else if (S_ISDIR(buf.st_mode)) ptr = "directory"; 29 | else if (S_ISCHR(buf.st_mode)) ptr = "character special"; 30 | else if (S_ISBLK(buf.st_mode)) ptr = "block special"; 31 | else if (S_ISFIFO(buf.st_mode)) ptr = "fifo"; 32 | #ifdef S_ISLNK 33 | else if (S_ISLNK(buf.st_mode)) ptr = "symbolic link"; 34 | #endif 35 | #ifdef S_ISSOCK 36 | else if (S_ISSOCK(buf.st_mode)) ptr = "socket"; 37 | #endif 38 | else ptr = "**unknown mode**"; 39 | printf("%s\n", ptr); 40 | } 41 | return 0; 42 | } 43 | -------------------------------------------------------------------------------- /manual/preemble/preemble_all.tex: -------------------------------------------------------------------------------- 1 | %%%%%%%%%%%%% PREEMBLE HEADER %%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2 | 3 | %========================================================== 4 | % 1. DOCUMENT TYPE AND OPTIONS 5 | %========================================================== 6 | 7 | \documentclass[letterpaper, 12pt]{article} 8 | 9 | %========================================================== 10 | % 2. PACKAGES 11 | %========================================================== 12 | 13 | \usepackage{palatino} % Use Palatino fonts 14 | 15 | \usepackage{amsmath} % Add extra math functions 16 | \usepackage[margin=1.5cm, % Page layout specification 17 | vmargin={0pt, 1cm}, 18 | includefoot]{geometry} 19 | \usepackage{hyperref} % Enable text hyperlink 20 | \hypersetup{ 21 | colorlinks=true, 22 | linkcolor=blue, 23 | urlcolor=blue, 24 | %urlcolor=cyan, 25 | %filecolor=magenta, % links to local file 26 | } 27 | \urlstyle{same} % link fonts follow the same style as the rest of text 28 | \usepackage{graphicx} % Enable graphics importation 29 | \usepackage{float} 30 | \usepackage{subfigure} % Enable subfigure 31 | \usepackage{wrapfig} % wrapping text around figure 32 | \usepackage{booktabs} 33 | \usepackage{listings} % code listing 34 | \usepackage{color} % colored font in listing 35 | 36 | %%% Local Variables: 37 | %%% mode: latex 38 | %%% TeX-master: "main" 39 | %%% End: 40 | -------------------------------------------------------------------------------- /manual/preemble/preemble_cmds_book_class.tex: -------------------------------------------------------------------------------- 1 | %------ PREEMBLE HEADER ----------- 2 | 3 | %========================================================== 4 | % 3. COMMANDS 5 | %========================================================== 6 | 7 | %--------------SETTINGS------------------------------------ 8 | %******** Paragraph space, indentations***** 9 | \setlength{\parskip}{1ex} 10 | %\setlength{\parskip}{\baselineskip} % paragraph spacing 11 | %\setlength{\parindent}{0pt} % does not indent paragraphs 12 | 13 | 14 | %******** list spacing ********** 15 | \setlist[itemize]{topsep=0pt} 16 | \setlist[enumerate]{topsep=0pt} 17 | 18 | %........ Re-numbering Floats............. 19 | \counterwithin{figure}{chapter} 20 | \counterwithin{table}{chapter} 21 | %\counterwithin{lstlisting}{section} 22 | 23 | %--------------NEW COMMANDS-------------------------------- 24 | 25 | % simple customized highlight commands 26 | \newcommand{\hlc}[2][yellow]{ {\sethlcolor{#1} \hl{#2}} } 27 | \newcommand{\codeA}[1]{ {\sethlcolor{lightgray} \ttfamily{\hl{#1}}} } 28 | 29 | % round corner highlight, mono space font, for inline code/cmd 30 | \newtcbox{\inline}[1][darkgray]{on line, 31 | arc=1pt,colback=#1!10!white,colframe=#1!10!white, 32 | before upper={\rule[-3pt]{0pt}{10pt}},boxrule=1pt, 33 | boxsep=0pt,left=1pt,right=1pt,top=1pt,bottom=1pt} 34 | \newcommand{\code}[1]{ \inline{\ttfamily{#1}} } 35 | 36 | 37 | %%% Local Variables: 38 | %%% mode: latex 39 | %%% TeX-master: "main_book" 40 | %%% End: 41 | -------------------------------------------------------------------------------- /lab2/starter/cURL/main_simple.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright(c) 2018-2019 Yiqing Huang, . 3 | * 4 | * This software may be freely redistributed under the terms of the X11 License. 5 | */ 6 | 7 | /** 8 | * @file main_simple.c 9 | * @brief Using cURL to get request a URL and output the response 10 | * from the server to standard output 11 | * SYNOPSIS 12 | * [URL] 13 | * NOTES: -DDEBUG_1 will show more debugging messages to stderr 14 | */ 15 | #include 16 | #include 17 | #include 18 | 19 | #define IMG_URL "http://ece252-1.uwaterloo.ca:2520/image?img=1" 20 | #define DUM_URL "https://example.com/" 21 | 22 | int main( int argc, char** argv ) 23 | { 24 | CURL *curl_handle; 25 | CURLcode res; 26 | char url[256]; 27 | 28 | if (argc == 1) { 29 | strcpy(url, IMG_URL); 30 | } else { 31 | strcpy(url, argv[1]); 32 | } 33 | #ifdef DEBUG_1 34 | fprintf(stderr, "%s: URL is %s\n", argv[0], url); 35 | #endif /* DEBUG_1 */ 36 | curl_global_init(CURL_GLOBAL_DEFAULT); 37 | 38 | curl_handle = curl_easy_init(); 39 | if(curl_handle) { 40 | curl_easy_setopt(curl_handle, CURLOPT_URL, url); 41 | res = curl_easy_perform(curl_handle); 42 | 43 | if( res != CURLE_OK) { 44 | fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); 45 | } 46 | curl_easy_cleanup(curl_handle); 47 | } 48 | 49 | curl_global_cleanup(); 50 | return 0; 51 | } 52 | -------------------------------------------------------------------------------- /manual/preemble/preemble_packages.tex: -------------------------------------------------------------------------------- 1 | %------ PREEMBLE HEADER ----------- 2 | 3 | %========================================================== 4 | % 2. PACKAGES 5 | %========================================================== 6 | \usepackage{import} 7 | \usepackage{palatino} % Use Palatino fonts 8 | 9 | \usepackage{amsmath} % Add extra math functions 10 | \usepackage[margin={3cm, 2cm}, % Page layout specification 11 | includefoot]{geometry} 12 | %\usepackage{showframe} % show frames, for debugging only 13 | \usepackage{hyperref} % Enable text hyperlink 14 | \hypersetup{ 15 | colorlinks=true, 16 | linkcolor=blue, 17 | urlcolor=blue, 18 | %urlcolor=cyan, 19 | %filecolor=magenta, % links to local file 20 | } 21 | \urlstyle{same} % link fonts follow the same style as the rest of text 22 | \usepackage{graphicx} % Enable graphics importation 23 | \usepackage{float} 24 | \usepackage{subfigure} % Enable subfigure 25 | \usepackage{wrapfig} % wrapping text around figure 26 | \usepackage{booktabs} 27 | \usepackage{listings} % code listing 28 | \usepackage{color} % colored font in listing 29 | \usepackage{xcolor} % more color names 30 | \usepackage{soul} % highlight text 31 | \usepackage{tcolorbox} % colored box, for round corner highlight 32 | \usepackage{tikz} % for future use 33 | 34 | \usepackage{enumitem} % cusomize lists and their spacing 35 | \usepackage{chngcntr} % floats re-numbering 36 | 37 | %%% Local Variables: 38 | %%% mode: latex 39 | %%% TeX-master: "main_book" 40 | %%% End: 41 | -------------------------------------------------------------------------------- /lab1/starter/png_util/crc.c: -------------------------------------------------------------------------------- 1 | /******************************************************************** 2 | * @file: crc.c 3 | * @brief: PNG crc calculation 4 | * Reference: https://www.w3.org/TR/PNG-CRCAppendix.html 5 | */ 6 | 7 | /* Table of CRCs of all 8-bit messages. */ 8 | unsigned long crc_table[256]; 9 | 10 | /* Flag: has the table been computed? Initially false. */ 11 | int crc_table_computed = 0; 12 | 13 | /* Make the table for a fast CRC. */ 14 | void make_crc_table(void) 15 | { 16 | unsigned long c; 17 | int n, k; 18 | 19 | for (n = 0; n < 256; n++) { 20 | c = (unsigned long) n; 21 | for (k = 0; k < 8; k++) { 22 | if (c & 1) 23 | c = 0xedb88320L ^ (c >> 1); 24 | else 25 | c = c >> 1; 26 | } 27 | crc_table[n] = c; 28 | } 29 | crc_table_computed = 1; 30 | } 31 | 32 | /* Update a running CRC with the bytes buf[0..len-1]--the CRC 33 | should be initialized to all 1's, and the transmitted value 34 | is the 1's complement of the final running CRC (see the 35 | crc() routine below)). */ 36 | 37 | unsigned long update_crc(unsigned long crc, unsigned char *buf, int len) 38 | { 39 | unsigned long c = crc; 40 | int n; 41 | 42 | if (!crc_table_computed) 43 | make_crc_table(); 44 | for (n = 0; n < len; n++) { 45 | c = crc_table[(c ^ buf[n]) & 0xff] ^ (c >> 8); 46 | } 47 | return c; 48 | } 49 | 50 | /* Return the CRC of the bytes buf[0..len-1]. */ 51 | unsigned long crc(unsigned char *buf, int len) 52 | { 53 | return update_crc(0xffffffffL, buf, len) ^ 0xffffffffL; 54 | } 55 | -------------------------------------------------------------------------------- /lab2/starter/fn_ptr/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Yiqing Huang, . 3 | * 4 | * This software may be freely redistributred under the terms of the X11 license. 5 | */ 6 | 7 | /** 8 | * @file main.c 9 | * @brief demonstrate C function pointer usage 10 | */ 11 | 12 | #include 13 | #include 14 | 15 | int sum(int x, int y); 16 | 17 | int wrapper_double(int x, unsigned int choice); 18 | int double_0(int x); 19 | int double_1(int x); 20 | 21 | int sum(int x, int y) 22 | { 23 | return (x+y); 24 | } 25 | 26 | /** 27 | * @brief a wrapper function. 28 | */ 29 | int wrapper_double(int x, unsigned int choice) 30 | { 31 | int (*fnp_double[])(int) = {double_0, double_1}; 32 | if (choice < 0 || choice > 1) { 33 | printf("Invalide choice: %d. Default to 0.\n", choice); 34 | choice = 0; 35 | } 36 | return (*fnp_double[choice])(x); 37 | } 38 | 39 | 40 | int double_0(int x) { 41 | printf("double_0 is called.\n"); 42 | return (x*2); 43 | } 44 | 45 | int double_1(int x) { 46 | printf("doubl_1 is called.\n"); 47 | return (x<<1); 48 | } 49 | 50 | int main(int argc, char **argv) 51 | { 52 | int (*fnp_sum)(int, int) = sum; 53 | int ret; 54 | int x = 3; 55 | int y = 2; 56 | unsigned int choice = 0; 57 | 58 | ret = (*fnp_sum)(x, y); 59 | printf("sum(%d, %d) = %d.\n", x, y, ret); 60 | 61 | printf("choose 0 for double_0() and 1 for double_1().\n"); 62 | scanf("%d", &choice); 63 | printf("Your choice is %d.\n", choice); 64 | 65 | ret = wrapper_double(x, choice); 66 | printf("double of %d is %d.\n", x, ret); 67 | 68 | 69 | return 0; 70 | } 71 | -------------------------------------------------------------------------------- /lab3/starter/tools/README.md: -------------------------------------------------------------------------------- 1 | This directory contains a script named `run_lab3.sh` to help you gather the timing data of your `paster2` program. 2 | 3 | The `run_lab3.sh` script generates thirty nine .dat files. Each .dat file contains timing data generated by 5 trials of the `paster2` executable for a given (B,P,C,X,N) value. Assuming you follow the timing data output format as specified in the `run_lab3.sh` file (see `sample_output.txt` for an example output format at stdout from your `paster2`), then the .dat file records down each trial's execution time. 4 | 5 | The run_lab3.sh then generates the average time and standard deviation of average time tables from the .dat files. The two tables generated are 6 | 7 | * `tb1_$$.txt`, which contains the average paster2 execution time; and 8 | * `tb2_$$.txt`, which contains the standard deviation of the paster2 execution time. 9 | 10 | The `$$` in the file names is the pid of process that runs the script. Run the script on eceubuntu1 once your program is in a good status and then rename the `tb1_$$.txt` file to `lab3_eceubuntu1.csv` for submission purpose. 11 | 12 | The script will take about 30-40 minutes to run depending on your implementation. If you find the script hangs, most likely your program hangs under certain situation caused by a race condition. 13 | 14 | Other files under this directory are: 15 | 16 | * `clean_ipcs.sh` is a script to delete all shared memory regions and semaphores owned yourself 17 | * `paster2` is an executable that produces expected output. The timing data it produces is a fake one for demonstration purpose only. 18 | * `sample_output.txt` is the expected output format that the script expects the paster2 will produce. 19 | * `results` directory contains the output from the script when running the script on the paster2 in this directory. 20 | -------------------------------------------------------------------------------- /lab4/starter/tools/README.md: -------------------------------------------------------------------------------- 1 | This directory contains a script named `run_lab4.sh` to help you gather the timing data of your `findpng2` program when the seed\_url is [http://ece252-1.uwaterloo.ca/lab4](http://ece252-1.uwaterloo.ca/lab4). 2 | 3 | The `run_lab4.sh` script generates twenty one .dat files. Each .dat file contains timing data generated by 5 trials of the `findpng2` executable for a given (t, m) value. Assuming you follow the timing data output format as specified in the `run_lab4.sh` file (see `sample_output.txt` for an example output format at stdout from your `findpng2`), then the .dat file records down each trial's execution time. 4 | 5 | The run_lab4.sh then generates the average time and standard deviation of average time tables from the .dat files. The two tables generated are 6 | 7 | * `tb1_$$.txt`, which contains the average findpng2 execution time; and 8 | * `tb2_$$.txt`, which contains the standard deviation of the findpng2 execution time. 9 | 10 | The `$$` in the file names is the pid of process that runs the script. Run the script on eceubuntu1 once your program is in a good status and then rename the `tb1_$$.txt` file to `lab4_eceubuntu1.csv` for submission purpose. 11 | 12 | The script will take about 30-40 minutes to run depending on your implementation. If you find the script hangs, most likely your program hangs under certain situation caused by a race condition. 13 | 14 | Other files under this directory are: 15 | 16 | * `findpng2` is an executable that produces expected output. The timing data it produces is a fake one for demonstration purpose only. 17 | * `sample_output.txt` is the expected output format that the script expects the findpng2 will produce. 18 | * `results` directory contains the output from the script when running the script on the findpng2 in this directory. 19 | 20 | -------------------------------------------------------------------------------- /lab5/starter/tools/README.md: -------------------------------------------------------------------------------- 1 | This directory contains a script named `run_lab5.sh` to help you gather the timing data of your `findpng3` program when the seed\_url is [http://ece252-1.uwaterloo.ca/lab5](http://ece252-1.uwaterloo.ca/lab5). 2 | 3 | The `run_lab5.sh` script generates twenty one .dat files. Each .dat file contains timing data generated by 5 trials of the `findpng3` executable for a given (t, m) value. Assuming you follow the timing data output format as specified in the `run_lab5.sh` file (see `sample_output.txt` for an example output format at stdout from your `findpng3`), then the .dat file records down each trial's execution time. 4 | 5 | The run_lab5.sh then generates the average time and standard deviation of average time tables from the .dat files. The two tables generated are 6 | 7 | * `tb1_$$.txt`, which contains the average findpng3 execution time; and 8 | * `tb2_$$.txt`, which contains the standard deviation of the findpng3 execution time. 9 | 10 | The `$$` in the file names is the pid of process that runs the script. Run the script on eceubuntu1 once your program is in a good status and then rename the `tb1_$$.txt` file to `lab5_eceubuntu1.csv` for submission purpose. 11 | 12 | The script will take about 30-40 minutes to run depending on your implementation. If you find the script hangs, most likely your program hangs under certain situation caused by a race condition. 13 | 14 | Other files under this directory are: 15 | 16 | * `findpng3` is an executable that produces expected output. The timing data it produces is a fake one for demonstration purpose only. 17 | * `sample_output.txt` is the expected output format that the script expects the findpng3 will produce. 18 | * `results` directory contains the output from the script when running the script on the findpng3 in this directory. 19 | 20 | -------------------------------------------------------------------------------- /lab2/starter/getopt/main_getopt.c: -------------------------------------------------------------------------------- 1 | /* 2 | * The code is derived from paster.c 3 | * Copyright (C) 2013-2019, Patrick Lam, . 4 | * 5 | * Modifications to the code are 6 | * Copyright 2019, Yiqing Huang, 7 | * 8 | * This software may be freely redistributed under the terms 9 | * of the X11 license. 10 | */ 11 | 12 | 13 | /** 14 | * @file main_getopt.c 15 | * @brief using getopt to parse command-line options 16 | */ 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | /** 24 | * @brief: a command that takes -t and -n options 25 | * -t , default value 1 (i.e. single threaded) 26 | * -n , default value 1 (valid values: 1, 2, and 3) 27 | * There are three images in total on the server side. 28 | * SYNOPSIS 29 | * [-t ] [-n ] 30 | */ 31 | 32 | int main(int argc, char **argv) 33 | { 34 | int c; 35 | int t = 1; 36 | int n = 1; 37 | char *str = "option requires an argument"; 38 | 39 | while ((c = getopt (argc, argv, "t:n:")) != -1) { 40 | switch (c) { 41 | case 't': 42 | t = strtoul(optarg, NULL, 10); 43 | printf("option -t specifies a value of %d.\n", t); 44 | if (t <= 0) { 45 | fprintf(stderr, "%s: %s > 0 -- 't'\n", argv[0], str); 46 | return -1; 47 | } 48 | break; 49 | case 'n': 50 | n = strtoul(optarg, NULL, 10); 51 | printf("option -n specifies a value of %d.\n", n); 52 | if (n <= 0 || n > 3) { 53 | fprintf(stderr, "%s: %s 1, 2, or 3 -- 'n'\n", argv[0], str); 54 | return -1; 55 | } 56 | break; 57 | default: 58 | return -1; 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /lab1/starter/pointer/pointer.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file: pointer.c 3 | * @brief: To demonstrate C structure and pointer usage 4 | */ 5 | #include 6 | #include 7 | 8 | /* To model a point on 2D terminal screen */ 9 | struct point { 10 | int x; /* x coordinate */ 11 | int y; /* y coordinate */ 12 | }; 13 | 14 | 15 | int main(void) 16 | { 17 | /* The memory of a_point is allocated on the process stack at run time */ 18 | struct point a_point; 19 | 20 | /* The ptr contains the address of a_point variable */ 21 | struct point *ptr = &a_point; 22 | 23 | /* First method: set the value of a point structure through a struct variable*/ 24 | a_point.x = 0; 25 | a_point.y = 1; 26 | /* Use debugger: we can see the following are true: 27 | a_point.x == 0; 28 | ptr->x == 0; 29 | 30 | a_point.y == 1; 31 | ptr->y == 1. 32 | */ 33 | 34 | 35 | /* Second method: set the value of a point structure through a pointer */ 36 | ptr->x = 3; 37 | ptr->y = 4; 38 | /* Use debugger: we can see the following are true: 39 | a_point.x == 3; 40 | ptr->x == 3; 41 | 42 | a_point.y == 4; 43 | ptr->y == 4. 44 | */ 45 | 46 | /* Third method: set the value of a point structure by deferencing a pointer */ 47 | (*ptr).x = 5; 48 | (*ptr).y = 6; 49 | 50 | /* Use debugger: we can see the following are true: 51 | a_point.x == 5; 52 | ptr->x == 5; 53 | 54 | a_point.y == 6; 55 | ptr->y == 6. 56 | */ 57 | 58 | /* Switch the ptr to memory dynamically allocated from heap */ 59 | ptr = (struct point *)malloc(sizeof(struct point)); 60 | 61 | 62 | /* 63 | Assign new value to the new point 64 | NOTE that ptr no longer points to a_point! 65 | */ 66 | ptr->x = 10; 67 | ptr->y = 11; 68 | 69 | /* 70 | Use debugger: we can see the following are true: 71 | a_point.x == 5 ; 72 | ptr->x == 10; 73 | 74 | a_point.y == 6 ; 75 | ptr->y == 11. 76 | */ 77 | 78 | free(ptr); 79 | 80 | return(0); 81 | } 82 | -------------------------------------------------------------------------------- /lab3/starter/shm/shm_simple.c: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @brief A simple shared memory, no structure involved. 4 | * @author yqhuang@uwaterloo.ca 5 | */ 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #define SHM_SIZE 256 15 | 16 | int g_val = 0; 17 | 18 | int main( int argc, char** argv ) { 19 | pid_t cpid = 0; 20 | int shmid = shmget(IPC_PRIVATE, SHM_SIZE, IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR); 21 | if ( shmid == -1 ){ 22 | perror("shmget"); 23 | } 24 | 25 | printf("Parent and child processes cannot use global variables to communicate!\n"); 26 | printf("Because they do not share the same address space. Global variable only works within the same address space.\n"); 27 | printf("Before fork: g_val=%d\n", g_val); 28 | cpid = fork(); 29 | if ( cpid > 0 ) { /* Parent */ 30 | void *buf = shmat(shmid, NULL, 0); 31 | 32 | if ( buf == (void *) -1 ) { 33 | perror("shmat"); 34 | abort(); 35 | } 36 | 37 | g_val = 100; 38 | printf("After fork: parent (pid=%d) sees g_val = %d\n", getpid(), g_val); 39 | waitpid(cpid, NULL, 0); 40 | printf("They can use shared memory to communicate.\n"); 41 | printf("Parent received a message from a child: %s.\n", (char*) buf); 42 | if ( shmdt(buf) != 0 ) { 43 | perror("shmdt"); 44 | abort(); 45 | } 46 | if ( shmctl(shmid, IPC_RMID, NULL) == -1 ) { 47 | perror("shmctl"); 48 | abort(); 49 | } 50 | } else if ( cpid == 0 ) { /* Child */ 51 | void* buf = shmat( shmid, NULL, 0 ); 52 | if ( buf == (void *) -1 ) { 53 | perror("shmat"); 54 | abort(); 55 | } 56 | 57 | printf("After fork: child (pid=%d) sees g_val = %d\n", getpid(), g_val); 58 | memset(buf, 0, SHM_SIZE); 59 | sprintf(buf, "I am the child (pid=%d)", getpid()); 60 | if ( shmdt(buf) != 0 ) { 61 | perror("shmdt"); 62 | abort(); 63 | } 64 | } else { 65 | perror("fork"); 66 | abort(); 67 | } 68 | return 0; 69 | } 70 | -------------------------------------------------------------------------------- /lab3/starter/fork/forkN.c: -------------------------------------------------------------------------------- 1 | /* The code is 2 | * Copyright(c) 2018-2019 Yiqing Huang, . 3 | * 4 | * This software may be freely redistributed under the terms of the X11 License. 5 | */ 6 | 7 | /** 8 | * @file forkN.c 9 | * @brief fork N child processes and time the overall execution time 10 | */ 11 | 12 | /****************************************************************************** 13 | * INCLUDE HEADER FILES 14 | *****************************************************************************/ 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #define NUM_CHILD 5 25 | 26 | int worker(int n); 27 | 28 | /** 29 | * @brief sleeps (n+1)*1000 milliseconds 30 | */ 31 | int worker(int n) 32 | { 33 | usleep((n+1)*1000); 34 | printf("Worker ID=%d, pid = %d, ppid = %d.\n", n, getpid(), getppid()); 35 | 36 | return 0; 37 | } 38 | 39 | int main() 40 | { 41 | int i=0; 42 | pid_t pid=0; 43 | pid_t cpids[NUM_CHILD]; 44 | int state; 45 | double times[2]; 46 | struct timeval tv; 47 | 48 | if (gettimeofday(&tv, NULL) != 0) { 49 | perror("gettimeofday"); 50 | abort(); 51 | } 52 | times[0] = (tv.tv_sec) + tv.tv_usec/1000000.; 53 | 54 | for ( i = 0; i < NUM_CHILD; i++) { 55 | 56 | pid = fork(); 57 | 58 | if ( pid > 0 ) { /* parent proc */ 59 | cpids[i] = pid; 60 | } else if ( pid == 0 ) { /* child proc */ 61 | worker(i); 62 | break; 63 | } else { 64 | perror("fork"); 65 | abort(); 66 | } 67 | 68 | } 69 | 70 | if ( pid > 0 ) { /* parent process */ 71 | for ( i = 0; i < NUM_CHILD; i++ ) { 72 | waitpid(cpids[i], &state, 0); 73 | if (WIFEXITED(state)) { 74 | printf("Child cpid[%d]=%d terminated with state: %d.\n", i, cpids[i], state); 75 | } 76 | 77 | } 78 | if (gettimeofday(&tv, NULL) != 0) { 79 | perror("gettimeofday"); 80 | abort(); 81 | } 82 | times[1] = (tv.tv_sec) + tv.tv_usec/1000000.; 83 | printf("Parent pid = %d: total execution time is %.6lf seconds\n", getpid(), times[1] - times[0]); 84 | } 85 | return 0; 86 | } 87 | -------------------------------------------------------------------------------- /manual/frontmatter.tex: -------------------------------------------------------------------------------- 1 | \frontmatter 2 | 3 | % title page, list of tables, list of figures 4 | \input{frontmatter_title} 5 | 6 | %Brief overview of the document, acknowledgement, disclaimer 7 | \chapter{Preface} 8 | 9 | \section*{Who Should Read This Lab Manual?} 10 | This lab manual is written for students who are taking the Systems Programming and Concurrency course ECE252 at the University of Waterloo. 11 | 12 | \section*{What is in This Lab Manual?} 13 | 14 | The first purpose of this document is to provide the descriptions of each laboratory project. 15 | The second purpose of this document is to provide a quick reference guide to the relevant development tools 16 | for completing laboratory projects. 17 | 18 | This manual is divided into three parts. 19 | 20 | Part I describes the lab administration policies 21 | 22 | Part II describes a set of course laboratory projects as follows: 23 | 24 | \begin{itemize} 25 | \item Lab1: Introduction to systems programming in the Linux computing environment 26 | \item Lab2: Multi-threaded concurrency programming with blocking I/O 27 | \item Lab3: Inter-process communication and concurrency control 28 | \item Lab4: Parallel web crawling 29 | \item Lab5: Single-threaded concurrency programming with asynchronous I/O 30 | \end{itemize} 31 | 32 | Part III is a quick reference guide to the Linux software development tools. We will be using the Ubuntu 18.04 LTS operating system. The material in this part needs to be self-studied before the labs start. 33 | The main topics are as follows. 34 | 35 | \begin{itemize} 36 | \item The Linux hardware environment 37 | \item Editors 38 | \item Compiler 39 | \item Debugger 40 | \item Automated builds 41 | \item Version control 42 | \end{itemize} 43 | 44 | 45 | % A C K N O W L E D G E M E N T S 46 | % ------------------------------- 47 | 48 | \section*{Acknowledgments} 49 | 50 | We are grateful that Professor Patrick Lam shared his ECE459 projects with us. Eric Praetzel has provided continuous IT support, which makes the Linux computing environment available to our students. 51 | 52 | We would like to sincerely thank our students who took the ECE254 and ECE459 courses in the past few years. They provided constructive feedback every term to make the manual more useful, in order to address problems that students would encounter when working on each lab assignment. 53 | 54 | %%% Local Variables: 55 | %%% mode: latex 56 | %%% TeX-master: "main_book" 57 | %%% End: 58 | -------------------------------------------------------------------------------- /lab2/starter/pthreads/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright(c) 2018-2019 Yiqing Huang, . 3 | * 4 | * This software may be freely redistributed under the terms of the X11 License. 5 | */ 6 | 7 | /** 8 | * @file main.c 9 | * @biref To create and join 2 threads. Each thread takes more than one input parameter 10 | * and returns more than one result value. 11 | */ 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #define NUM_THREADS 2 19 | 20 | struct thread_args /* thread input parameters struct */ 21 | { 22 | int x; 23 | int y; 24 | }; 25 | 26 | struct thread_ret /* thread return values struct */ 27 | { 28 | int sum; 29 | int product; 30 | }; 31 | 32 | void *do_work(void *arg); /* a routine that can run as a thread by pthreads */ 33 | 34 | void *do_work(void *arg) 35 | { 36 | struct thread_args *p_in = arg; 37 | struct thread_ret *p_out = malloc(sizeof(struct thread_ret)); 38 | /* the root thread will need to free the memory */ 39 | 40 | p_out->sum = p_in->x + p_in->y; 41 | p_out->product = p_in->x * p_in->y; 42 | 43 | /* pthread_exit memory leak bug 44 | @see https://bugzilla.redhat.com/show_bug.cgi?id=483821 45 | replacing it with return will avoid the bug 46 | */ 47 | 48 | /* pthread_exit((void *)p_out);*/ 49 | 50 | return ((void *)p_out); 51 | } 52 | 53 | 54 | int main(int argc, char **argv) 55 | { 56 | pthread_t *p_tids = malloc(sizeof(pthread_t) * NUM_THREADS); 57 | struct thread_args in_params[NUM_THREADS]; 58 | struct thread_ret *p_results[NUM_THREADS]; 59 | 60 | for (int i=0; isum); 71 | printf("product(%d,%d) = %d.\n\n", \ 72 | in_params[i].x, in_params[i].y, p_results[i]->product); 73 | } 74 | 75 | /* cleaning up */ 76 | 77 | free(p_tids); 78 | 79 | /* the memory was allocated in the do_work thread for return values */ 80 | /* we need to free the memory here */ 81 | for (int i=0; i 14 | 15 | /****************************************************************************** 16 | * DEFINED MACROS 17 | *****************************************************************************/ 18 | 19 | #define PNG_SIG_SIZE 8 /* number of bytes of png image signature data */ 20 | #define CHUNK_LEN_SIZE 4 /* chunk length field size in bytes */ 21 | #define CHUNK_TYPE_SIZE 4 /* chunk type field size in bytes */ 22 | #define CHUNK_CRC_SIZE 4 /* chunk CRC field size in bytes */ 23 | #define DATA_IHDR_SIZE 13 /* IHDR chunk data field size */ 24 | 25 | /****************************************************************************** 26 | * STRUCTURES and TYPEDEFS 27 | *****************************************************************************/ 28 | typedef unsigned char U8; 29 | typedef unsigned int U32; 30 | 31 | typedef struct chunk { 32 | U32 length; /* length of data in the chunk, host byte order */ 33 | U8 type[4]; /* chunk type */ 34 | U8 *p_data; /* pointer to location where the actual data are */ 35 | U32 crc; /* CRC field */ 36 | } *chunk_p; 37 | 38 | /* note that there are 13 Bytes valid data, compiler will padd 3 bytes to make 39 | the structure 16 Bytes due to alignment. So do not use the size of this 40 | structure as the actual data size, use 13 Bytes (i.e DATA_IHDR_SIZE macro). 41 | */ 42 | typedef struct data_IHDR {// IHDR chunk data 43 | U32 width; /* width in pixels, big endian */ 44 | U32 height; /* height in pixels, big endian */ 45 | U8 bit_depth; /* num of bits per sample or per palette index. 46 | valid values are: 1, 2, 4, 8, 16 */ 47 | U8 color_type; /* =0: Grayscale; =2: Truecolor; =3 Indexed-color 48 | =4: Greyscale with alpha; =6: Truecolor with alpha */ 49 | U8 compression; /* only method 0 is defined for now */ 50 | U8 filter; /* only method 0 is defined for now */ 51 | U8 interlace; /* =0: no interlace; =1: Adam7 interlace */ 52 | } *data_IHDR_p; 53 | 54 | /* A simple PNG file format, three chunks only*/ 55 | typedef struct simple_PNG { 56 | struct chunk *p_IHDR; 57 | struct chunk *p_IDAT; /* only handles one IDAT chunk */ 58 | struct chunk *p_IEND; 59 | } *simple_PNG_p; 60 | 61 | /****************************************************************************** 62 | * FUNCTION PROTOTYPES 63 | *****************************************************************************/ 64 | int is_png(U8 *buf, size_t n); 65 | int get_png_height(struct data_IHDR *buf); 66 | int get_png_width(struct data_IHDR *buf); 67 | int get_png_data_IHDR(struct data_IHDR *out, FILE *fp, long offset, int whence); 68 | 69 | /* declare your own functions prototypes here */ 70 | -------------------------------------------------------------------------------- /manual/main.bib: -------------------------------------------------------------------------------- 1 | @book{mitchell2001advanced, 2 | author = {Mitchell, Mark and Samuel, Alex}, 3 | title = {Advanced Linux Programming}, 4 | year = {2001}, 5 | isbn = {0735710430}, 6 | publisher = {New Riders Publishing}, 7 | address = {Thousand Oaks, CA, USA}, 8 | } 9 | 10 | @article{marshall1999programming, 11 | title={Programming in C UNIX System Calls and Subroutines using C}, 12 | author={Marshall, AD}, 13 | journal={Available on-line at http://www.cs.cf.ac.uk/Dave/C/CE.html}, 14 | year={1999} 15 | } 16 | 17 | @article{boys2010keil, 18 | title={{Keil RTX RTOS: The Easy Way V0.4}}, 19 | author={Robert Boys}, 20 | year={2010} 21 | } 22 | 23 | @book{stallings2011operating, 24 | title={Operating systems: internals and design principles}, 25 | author={Stallings, W.}, 26 | year={2011}, 27 | edition={seventh}, 28 | publisher={Prentice Hall} 29 | } 30 | 31 | 32 | % Bibliography of key references for "LaTeX for Thesis and Large Documents" 33 | % For use with BibTeX 34 | 35 | @book{goossens.book, 36 | author = "Michel Goossens and Frank Mittelbach and 37 | Alexander Samarin", 38 | title = "The \LaTeX\ Companion", 39 | year = "1994", 40 | publisher = "Addison-Wesley", 41 | address = "Reading, Massachusetts" 42 | } 43 | 44 | @book{knuth.book, 45 | author = "Donald Knuth", 46 | title = "The \TeX book", 47 | year = "1986", 48 | publisher = "Addison-Wesley", 49 | address = "Reading, Massachusetts" 50 | } 51 | 52 | @book{lamport.book, 53 | author = "Leslie Lamport", 54 | title = "\LaTeX\ --- A Document Preparation System", 55 | edition = "Second", 56 | year = "1994", 57 | publisher = "Addison-Wesley", 58 | address = "Reading, Massachusetts" 59 | } 60 | 61 | 62 | @book{yiu2009definitive, 63 | title={The Definitive Guide to the ARM Cortex-M3}, 64 | author={Yiu, J.}, 65 | year={2009}, 66 | publisher={Newnes} 67 | } 68 | 69 | @book{Roelofs1999PNG, 70 | author = {Roelofs, Greg}, 71 | title = {PNG: The Definitive Guide}, 72 | year = {1999}, 73 | isbn = {1565925424}, 74 | publisher = {O'Reilly \& Associates, Inc.}, 75 | address = {Sebastopol, CA, USA}, 76 | } 77 | 78 | 79 | @misc{png.w3c.ref, 80 | title = {Portable Network Graphics ({PNG}) Specification (Second Edition)}, 81 | year = {2003}, 82 | howpublished = {\url{}} 83 | } 84 | 85 | @misc{arm.cm3.trm, 86 | title={Cortex-M3 Technical Reference Manual, ARM DDI 0337G}, 87 | year={2005-2008}, 88 | publisher ="ARM Limited." 89 | } 90 | 91 | @misc{arm.rvct.comp.ref, 92 | title={RealView Compilation Tools Version 4.0: Compiler Reference Guide}, 93 | year={2007-2010}, 94 | publisher="ARM Limited." 95 | } 96 | 97 | @misc{keil.mcb1700.guide, 98 | title = {{MCB}1700 {U}ser's {G}uide}, 99 | note={http://www.keil.com/support/man/docs/mcb1700} 100 | } 101 | 102 | @misc{nxp.lpc17xx.manual, 103 | title = {L{PC}17xx {U}ser {M}anual, {R}ev2.0}, 104 | year = {2010} 105 | } 106 | 107 | @misc{keil.mdk.primer, 108 | title = {{MDK} {Primer}}, 109 | note={http://www.keil.com/support/man/docs/gsac} 110 | } 111 | 112 | -------------------------------------------------------------------------------- /lab1/starter/png_util/main.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @biref To demonstrate how to use zutil.c and crc.c functions 3 | * 4 | * Copyright 2018-2020 Yiqing Huang 5 | * 6 | * This software may be freely redistributed under the terms of MIT License 7 | */ 8 | 9 | #include /* for printf(), perror()... */ 10 | #include /* for malloc() */ 11 | #include /* for errno */ 12 | #include "crc.h" /* for crc() */ 13 | #include "zutil.h" /* for mem_def() and mem_inf() */ 14 | #include "lab_png.h" /* simple PNG data structures */ 15 | 16 | /****************************************************************************** 17 | * DEFINED MACROS 18 | *****************************************************************************/ 19 | #define BUF_LEN (256*16) 20 | #define BUF_LEN2 (256*32) 21 | 22 | /****************************************************************************** 23 | * GLOBALS 24 | *****************************************************************************/ 25 | U8 gp_buf_def[BUF_LEN2]; /* output buffer for mem_def() */ 26 | U8 gp_buf_inf[BUF_LEN2]; /* output buffer for mem_inf() */ 27 | 28 | /****************************************************************************** 29 | * FUNCTION PROTOTYPES 30 | *****************************************************************************/ 31 | 32 | void init_data(U8 *buf, int len); 33 | 34 | /****************************************************************************** 35 | * FUNCTIONS 36 | *****************************************************************************/ 37 | 38 | /** 39 | * @brief initialize memory with 256 chars 0 - 255 cyclically 40 | */ 41 | void init_data(U8 *buf, int len) 42 | { 43 | int i; 44 | for ( i = 0; i < len; i++) { 45 | buf[i] = i%256; 46 | } 47 | } 48 | 49 | int main (int argc, char **argv) 50 | { 51 | U8 *p_buffer = NULL; /* a buffer that contains some data to play with */ 52 | U32 crc_val = 0; /* CRC value */ 53 | int ret = 0; /* return value for various routines */ 54 | U64 len_def = 0; /* compressed data length */ 55 | U64 len_inf = 0; /* uncompressed data length */ 56 | 57 | /* Step 1: Initialize some data in a buffer */ 58 | /* Step 1.1: Allocate a dynamic buffer */ 59 | p_buffer = malloc(BUF_LEN); 60 | if (p_buffer == NULL) { 61 | perror("malloc"); 62 | return errno; 63 | } 64 | 65 | /* Step 1.2: Fill the buffer with some data */ 66 | init_data(p_buffer, BUF_LEN); 67 | 68 | /* Step 2: Demo how to use zlib utility */ 69 | ret = mem_def(gp_buf_def, &len_def, p_buffer, BUF_LEN, Z_DEFAULT_COMPRESSION); 70 | if (ret == 0) { /* success */ 71 | printf("original len = %d, len_def = %lu\n", BUF_LEN, len_def); 72 | } else { /* failure */ 73 | fprintf(stderr,"mem_def failed. ret = %d.\n", ret); 74 | return ret; 75 | } 76 | 77 | ret = mem_inf(gp_buf_inf, &len_inf, gp_buf_def, len_def); 78 | if (ret == 0) { /* success */ 79 | printf("original len = %d, len_def = %lu, len_inf = %lu\n", \ 80 | BUF_LEN, len_def, len_inf); 81 | } else { /* failure */ 82 | fprintf(stderr,"mem_def failed. ret = %d.\n", ret); 83 | } 84 | 85 | /* Step 3: Demo how to use the crc utility */ 86 | crc_val = crc(gp_buf_def, len_def); // down cast the return val to U32 87 | printf("crc_val = %u\n", crc_val); 88 | 89 | /* Clean up */ 90 | free(p_buffer); /* free dynamically allocated memory */ 91 | 92 | return 0; 93 | } 94 | -------------------------------------------------------------------------------- /lab5/starter/curl_multi/curl_multi_test.c: -------------------------------------------------------------------------------- 1 | /* curl_multi_test.c 2 | 3 | Clemens Gruber, 2013 4 | 5 | 6 | Code description: 7 | Requests 4 Web pages via the CURL multi interface 8 | and checks if the HTTP status code is 200. 9 | 10 | Update: Fixed! The check for !numfds was the problem. 11 | */ 12 | 13 | #include 14 | #include 15 | #ifndef WIN32 16 | #include 17 | #endif 18 | #include 19 | 20 | #define MAX_WAIT_MSECS 30*1000 /* Wait max. 30 seconds */ 21 | 22 | static const char *urls[] = { 23 | "http://www.microsoft.com", 24 | "http://www.yahoo.com", 25 | "http://www.wikipedia.org", 26 | "http://slashdot.org" 27 | }; 28 | #define CNT 4 29 | 30 | static size_t cb(char *d, size_t n, size_t l, void *p) 31 | { 32 | /* take care of the data here, ignored in this example */ 33 | (void)d; 34 | (void)p; 35 | return n*l; 36 | } 37 | 38 | static void init(CURLM *cm, int i) 39 | { 40 | CURL *eh = curl_easy_init(); 41 | curl_easy_setopt(eh, CURLOPT_WRITEFUNCTION, cb); 42 | curl_easy_setopt(eh, CURLOPT_HEADER, 0L); 43 | curl_easy_setopt(eh, CURLOPT_URL, urls[i]); 44 | curl_easy_setopt(eh, CURLOPT_PRIVATE, urls[i]); 45 | curl_easy_setopt(eh, CURLOPT_VERBOSE, 0L); 46 | curl_multi_add_handle(cm, eh); 47 | } 48 | 49 | int main(void) 50 | { 51 | CURLM *cm=NULL; 52 | CURL *eh=NULL; 53 | CURLMsg *msg=NULL; 54 | CURLcode return_code=0; 55 | int still_running=0, i=0, msgs_left=0; 56 | int http_status_code; 57 | const char *szUrl; 58 | 59 | curl_global_init(CURL_GLOBAL_ALL); 60 | 61 | cm = curl_multi_init(); 62 | 63 | for (i = 0; i < CNT; ++i) { 64 | init(cm, i); 65 | } 66 | 67 | curl_multi_perform(cm, &still_running); 68 | 69 | do { 70 | int numfds=0; 71 | int res = curl_multi_wait(cm, NULL, 0, MAX_WAIT_MSECS, &numfds); 72 | if(res != CURLM_OK) { 73 | fprintf(stderr, "error: curl_multi_wait() returned %d\n", res); 74 | return EXIT_FAILURE; 75 | } 76 | /* 77 | if(!numfds) { 78 | fprintf(stderr, "error: curl_multi_wait() numfds=%d\n", numfds); 79 | return EXIT_FAILURE; 80 | } 81 | */ 82 | curl_multi_perform(cm, &still_running); 83 | 84 | } while(still_running); 85 | 86 | while ((msg = curl_multi_info_read(cm, &msgs_left))) { 87 | if (msg->msg == CURLMSG_DONE) { 88 | eh = msg->easy_handle; 89 | 90 | return_code = msg->data.result; 91 | if(return_code!=CURLE_OK) { 92 | fprintf(stderr, "CURL error code: %d\n", msg->data.result); 93 | continue; 94 | } 95 | 96 | // Get HTTP status code 97 | http_status_code=0; 98 | szUrl = NULL; 99 | 100 | curl_easy_getinfo(eh, CURLINFO_RESPONSE_CODE, &http_status_code); 101 | curl_easy_getinfo(eh, CURLINFO_PRIVATE, &szUrl); 102 | 103 | if(http_status_code==200) { 104 | printf("200 OK for %s\n", szUrl); 105 | } else { 106 | fprintf(stderr, "GET of %s returned http status code %d\n", szUrl, http_status_code); 107 | } 108 | 109 | curl_multi_remove_handle(cm, eh); 110 | curl_easy_cleanup(eh); 111 | } 112 | else { 113 | fprintf(stderr, "error: after curl_multi_info_read(), CURLMsg=%d\n", msg->msg); 114 | } 115 | } 116 | 117 | curl_multi_cleanup(cm); 118 | 119 | return EXIT_SUCCESS; 120 | } 121 | -------------------------------------------------------------------------------- /lab3/starter/sem/sem_simple.c: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @brief An example of POSIX unamed semaphore shared between processes 4 | * @author yqhuang@uwaterloo.ca 5 | */ 6 | 7 | //#define _XOPEN_SOURCE 500 8 | //#define _POSIX_C_SOURCE 200808L 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #define SHM_SIZE 1024 21 | #define SEM_PROC 1 22 | #define NUM_SEMS 2 23 | 24 | 25 | int main( int argc, char** argv ) { 26 | pid_t cpid = 0; 27 | sem_t *sems; 28 | void *buf; 29 | 30 | /* allocate two shared memory regions */ 31 | int shmid = shmget(IPC_PRIVATE, SHM_SIZE, IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR); 32 | int shmid_sems = shmget(IPC_PRIVATE, sizeof(sem_t) * NUM_SEMS, IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR); 33 | 34 | if (shmid == -1 || shmid_sems == -1) { 35 | perror("shmget"); 36 | abort(); 37 | } 38 | 39 | /* attach to shared memory regions */ 40 | buf = shmat(shmid, NULL, 0); 41 | sems = shmat(shmid_sems, NULL, 0); 42 | if ( buf == (void *) -1 || sems == (void *) -1 ) { 43 | perror("shmat"); 44 | abort(); 45 | } 46 | 47 | /* initialize shared memory varaibles */ 48 | memset(buf, 0, SHM_SIZE); 49 | if ( sem_init(&sems[0], SEM_PROC, 1) != 0 ) { 50 | perror("sem_init(sem[0])"); 51 | abort(); 52 | } 53 | if ( sem_init(&sems[1], SEM_PROC, 0) != 0 ) { 54 | perror("sem_init(sem[1])"); 55 | abort(); 56 | } 57 | 58 | cpid = fork(); 59 | if ( cpid > 0 ) { /* Parent */ 60 | 61 | printf("Parent is blocked, waiting for a message from the child.\n"); 62 | if ( sem_wait(&sems[1]) != 0 ) { 63 | perror("sem_wait on sems[1]"); 64 | abort(); 65 | } 66 | 67 | printf("Parent received a message from the child: %s.\n", (char*) buf); 68 | 69 | if ( sem_post(&sems[0]) != 0 ) { 70 | perror("sem_post on sems[0]"); 71 | abort(); 72 | } 73 | 74 | if ( shmdt(buf) != 0 ) { 75 | perror("shmdt"); 76 | abort(); 77 | } 78 | if ( shmctl(shmid, IPC_RMID, NULL) == -1 ) { 79 | perror("shmctl"); 80 | abort(); 81 | } 82 | 83 | if ( shmdt(sems) != 0 ) { 84 | perror("shmdt"); 85 | abort(); 86 | } 87 | 88 | waitpid(cpid, NULL, 0); 89 | 90 | if ( shmctl(shmid_sems, IPC_RMID, NULL) == -1 ) { 91 | perror("shmctl"); 92 | abort(); 93 | } 94 | 95 | if (sem_destroy(&sems[0]) || sem_destroy(&sems[1])) { 96 | perror("sem_destroy"); 97 | abort(); 98 | } 99 | 100 | } else if ( cpid == 0 ) { /* Child */ 101 | printf("Child is sleeping before sending a message to the parent.\n"); 102 | usleep(rand()%50000); 103 | if ( sem_wait(&sems[0]) != 0 ) { 104 | perror("sem_wait on sem[0]"); 105 | abort(); 106 | } 107 | sprintf(buf, "I am the child (pid=%d)", getpid()); 108 | if ( sem_post(&sems[1]) != 0 ) { 109 | perror("sem_post on sem[1]"); 110 | abort(); 111 | } 112 | if ( shmdt(buf) != 0 ) { 113 | perror("shmdt"); 114 | abort(); 115 | } 116 | 117 | if ( shmdt(sems) != 0 ) { 118 | perror("shmdt"); 119 | abort(); 120 | } 121 | } else { 122 | perror("fork"); 123 | abort(); 124 | } 125 | return 0; 126 | } 127 | -------------------------------------------------------------------------------- /lab3/starter/shm/shm_struct.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @brief A shared memory that makes use of C struct 3 | * @author yqhuang@uwaterloo.ca 4 | */ 5 | 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include "shm_stack.h" 18 | 19 | #define STACK_SIZE 3 20 | void push_all(struct int_stack *p, int start); 21 | void pop_all(struct int_stack *p); 22 | void test_local(); 23 | void test_shm(); 24 | 25 | /* pushing STACK_SIZE items to the stack */ 26 | void push_all(struct int_stack *p, int start) 27 | { 28 | int i; 29 | 30 | if ( p == NULL) { 31 | abort(); 32 | } 33 | 34 | for( i = 0; ; i++ ) { 35 | int ret; 36 | int item = start - i; 37 | 38 | ret = push(p, item); 39 | if ( ret != 0 ) { 40 | break; 41 | } 42 | printf("item[%d] = 0x%4X pushed onto the stack\n", i, item); 43 | 44 | } 45 | printf("%d items pushed onto the stack.\n", i); 46 | 47 | } 48 | 49 | /* pop STACK_SIZE items off the stack */ 50 | void pop_all(struct int_stack *p) 51 | { 52 | int i; 53 | if ( p == NULL) { 54 | abort(); 55 | } 56 | 57 | for ( i = 0; ; i++ ) { 58 | int item; 59 | int ret = pop(p, &item); 60 | if ( ret != 0 ) { 61 | break; 62 | } 63 | printf("item[%d] = 0x%4X popped\n", i, item); 64 | } 65 | 66 | printf("%d items popped off the stack.\n", i); 67 | 68 | } 69 | 70 | void test_local() 71 | { 72 | int i; 73 | struct int_stack *pstack; 74 | 75 | if ( (pstack = create_stack(STACK_SIZE)) == NULL) { 76 | fprintf(stderr, "Failed to create a new stack, abort...\n"); 77 | abort(); 78 | }; 79 | 80 | push_all(pstack, 0xFF00); 81 | pop_all(pstack); 82 | destroy_stack(pstack); 83 | } 84 | 85 | void test_shm() 86 | { 87 | int i; 88 | int shmid; 89 | pid_t cpid = 0; 90 | int shm_size = sizeof_shm_stack(STACK_SIZE); 91 | 92 | printf("shm_size=%d\n", shm_size); 93 | /* We do not use malloc() to create shared memory, use shmget() */ 94 | shmid = shmget(IPC_PRIVATE, shm_size, IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR); 95 | if (shmid == -1 ) { 96 | perror("shmget"); 97 | abort(); 98 | } 99 | cpid = fork(); 100 | if ( cpid > 0 ) { /* parent proc pops */ 101 | struct int_stack *pstack; 102 | pstack = shmat(shmid, NULL, 0); 103 | if ( pstack == (void *) -1 ) { 104 | perror("shmat"); 105 | abort(); 106 | } 107 | printf("parent: pstack = %p\n", pstack); 108 | waitpid(cpid, NULL, 0); 109 | pop_all(pstack); 110 | if ( shmdt(pstack) != 0 ) { 111 | perror("shmdt"); 112 | abort(); 113 | } 114 | /* We do not use free() to release the shared memory, use shmctl() */ 115 | if ( shmctl(shmid, IPC_RMID, NULL) == -1 ) { 116 | perror("shmctl"); 117 | abort(); 118 | } 119 | } else if ( cpid == 0 ) { /* child proc pushes */ 120 | struct int_stack *pstack; 121 | pstack = shmat(shmid, NULL, 0); 122 | if ( pstack == (void *) -1 ) { 123 | perror("shmat"); 124 | abort(); 125 | } 126 | printf("child: pstack = %p\n", pstack); 127 | init_shm_stack(pstack, STACK_SIZE); 128 | push_all(pstack, 0xABCD); 129 | if ( shmdt(pstack) != 0 ) { 130 | perror("shmdt"); 131 | abort(); 132 | } 133 | } else { 134 | perror("fork"); 135 | abort(); 136 | } 137 | 138 | } 139 | 140 | int main() 141 | { 142 | test_local(); 143 | test_shm(); 144 | return 0; 145 | 146 | } 147 | -------------------------------------------------------------------------------- /lab4/starter/tools/run_lab4.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -x 2 | ############################################################################ 3 | # File Name : run_lab4.sh 4 | # Author : Yiqing Huang 5 | # Usage : Name your executable as "paster2" and put it in the 6 | # same directory where you put this shell script. 7 | # Make sure the script has x bit set for user. If not, type 8 | # chmod u+x ./run_lab4.sh 9 | # The script requires no input argument and output nothing to 10 | # the standard output if runs successfully. 11 | # nohup ./run_lab4.sh & 12 | # will put the script in the background and logging out from the 13 | # the machine will not affect it. 14 | # 15 | # Course Name: ECE252 Systems Programming and Concurrency 16 | # Description: Lab4 utility - extracting timing info. 17 | # The script assumes the following output format at stdout. 18 | # Please do not output anything else to stdout. 19 | # It will affect the timing results otherwise. 20 | # ------------------------------------------- 21 | # findpng2 execution time: S seconds 22 | # ------------------------------------------- 23 | # The script reads the last line where the timing info is and 24 | # then extract the S and output to a file. 25 | # The outputfile naming convention is: T[0-9]+_M[0-9]+.dat. 26 | # The script then compute for tables. 27 | # tb1_$$.txt: average system execution time 28 | # tb2_$$.txt: standard deviation of system execution time 29 | # where $$ is the pid of process that executing this shell script. 30 | ############################################################################# 31 | PROG="./findpng2" 32 | T="1 10 20" 33 | M="1 10 20 30 40 50 100" 34 | NN=5 35 | 36 | exec_producer () 37 | { 38 | 39 | if [ $# != 4 ]; then 40 | echo "Usage: $0 -t T -m M " 41 | echo " exec_name: executible's name" 42 | echo " T: number of threads" 43 | echo " M: number of valid png links" 44 | echo " NN: number of times to run the executible for a given pair " 45 | exit 1 46 | else 47 | PROGRAM=$1 48 | NUM_T=$2 49 | NUM_M=$3 50 | X_TIMES=$4 51 | SEED_URL="http://ece252-1.uwaterloo.ca/lab4" 52 | fi 53 | 54 | O_FILE='T'${NUM_T}'_M'${NUM_M}'.dat' 55 | touch ${O_FILE} 56 | xx=1 57 | while [ ${xx} -le ${X_TIMES} ] 58 | do 59 | cmd="${PROGRAM} -t ${NUM_T} -m ${NUM_M} ${SEED_URL}" 60 | str=`$cmd | tail -1 | awk -F' ' '{print $4}'` 61 | echo $str >> ${O_FILE} 62 | xx=`expr $xx + 1` 63 | done 64 | } 65 | 66 | gen_data () 67 | { 68 | for t in $T 69 | do 70 | for m in $M 71 | do 72 | exec_producer $PROG $t $m $NN 73 | done 74 | done 75 | } 76 | 77 | # directly writing each timing string to the tb files. 78 | gen_stat_per_pair () 79 | { 80 | if [ $# != 1 ]; then 81 | echo "Usage: $0 <.dat file name>" 82 | exit 1 83 | else 84 | FNAME_DATA=$1 85 | fi 86 | LIST="${FNAME_TB[1]} ${FNAME_TB[2]}" 87 | 88 | awk -v fname_tb_list="$LIST" ' 89 | BEGIN{ 90 | num_files = split(fname_tb_list, fname_tb, " ") 91 | } 92 | { 93 | sum[1] += $1 94 | sumsq[1] += $1*$1 95 | } 96 | END{ 97 | for(i = 1; i <= num_files/2; i++) { 98 | printf("%.6lf\n", sum[i]/NR) >> fname_tb[2*i-1] 99 | printf("%.6lf\n", sqrt(NR/(NR-1) * (sumsq[i]/NR - (sum[i]/NR)**2))) >> fname_tb[2*i] 100 | } 101 | } ' "${FNAME_DATA}" 102 | 103 | } 104 | 105 | #$1 is the image number 106 | gen_table () 107 | { 108 | # assign table names 109 | NUM_TBS=2 110 | FNAME_TB[1]="tb1_$$.txt" 111 | FNAME_TB[2]="tb2_$$.txt" 112 | 113 | # generate the table header 114 | i=1 115 | while [ ${i} -le ${NUM_TBS} ] 116 | do 117 | printf 'T,M,Time\n' >> ${FNAME_TB[${i}]} 118 | i=`expr $i + 1` 119 | done 120 | 121 | for t in $T 122 | do 123 | for m in $M 124 | do 125 | i=1 126 | while [ ${i} -le ${NUM_TBS} ] 127 | do 128 | printf '%d,%d,' "$t" "$m" >> ${FNAME_TB[${i}]} 129 | i=`expr $i + 1` 130 | done 131 | FNAME_DATA="T${t}_M${m}.dat" 132 | echo $FNAME_DATA 133 | gen_stat_per_pair $FNAME_DATA 134 | done 135 | done 136 | } 137 | 138 | gen_data 139 | gen_table 140 | -------------------------------------------------------------------------------- /lab5/starter/tools/run_lab5.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -x 2 | ############################################################################ 3 | # File Name : run_lab5.sh 4 | # Author : Yiqing Huang 5 | # Usage : Name your executable as "paster2" and put it in the 6 | # same directory where you put this shell script. 7 | # Make sure the script has x bit set for user. If not, type 8 | # chmod u+x ./run_lab5.sh 9 | # The script requires no input argument and output nothing to 10 | # the standard output if runs successfully. 11 | # nohup ./run_lab5.sh & 12 | # will put the script in the background and logging out from the 13 | # the machine will not affect it. 14 | # 15 | # Course Name: ECE252 Systems Programming and Concurrency 16 | # Description: Lab5 utility - extracting timing info. 17 | # The script assumes the following output format at stdout. 18 | # Please do not output anything else to stdout. 19 | # It will affect the timing results otherwise. 20 | # ------------------------------------------- 21 | # findpng3 execution time: S seconds 22 | # ------------------------------------------- 23 | # The script reads the last line where the timing info is and 24 | # then extract the S and output to a file. 25 | # The outputfile naming convention is: T[0-9]+_M[0-9]+.dat. 26 | # The script then compute for tables. 27 | # tb1_$$.txt: average system execution time 28 | # tb2_$$.txt: standard deviation of system execution time 29 | # where $$ is the pid of process that executing this shell script. 30 | ############################################################################# 31 | PROG="./findpng3" 32 | T="1 10 20" 33 | M="1 10 20 30 40 50 100" 34 | NN=5 35 | 36 | exec_producer () 37 | { 38 | 39 | if [ $# != 4 ]; then 40 | echo "Usage: $0 -t T -m M " 41 | echo " exec_name: executible's name" 42 | echo " T: number of threads" 43 | echo " M: number of valid png links" 44 | echo " NN: number of times to run the executible for a given pair " 45 | exit 1 46 | else 47 | PROGRAM=$1 48 | NUM_T=$2 49 | NUM_M=$3 50 | X_TIMES=$4 51 | SEED_URL="http://ece252-1.uwaterloo.ca/lab5" 52 | fi 53 | 54 | O_FILE='T'${NUM_T}'_M'${NUM_M}'.dat' 55 | touch ${O_FILE} 56 | xx=1 57 | while [ ${xx} -le ${X_TIMES} ] 58 | do 59 | cmd="${PROGRAM} -t ${NUM_T} -m ${NUM_M} ${SEED_URL}" 60 | str=`$cmd | tail -1 | awk -F' ' '{print $4}'` 61 | echo $str >> ${O_FILE} 62 | xx=`expr $xx + 1` 63 | done 64 | } 65 | 66 | gen_data () 67 | { 68 | for t in $T 69 | do 70 | for m in $M 71 | do 72 | exec_producer $PROG $t $m $NN 73 | done 74 | done 75 | } 76 | 77 | # directly writing each timing string to the tb files. 78 | gen_stat_per_pair () 79 | { 80 | if [ $# != 1 ]; then 81 | echo "Usage: $0 <.dat file name>" 82 | exit 1 83 | else 84 | FNAME_DATA=$1 85 | fi 86 | LIST="${FNAME_TB[1]} ${FNAME_TB[2]}" 87 | 88 | awk -v fname_tb_list="$LIST" ' 89 | BEGIN{ 90 | num_files = split(fname_tb_list, fname_tb, " ") 91 | } 92 | { 93 | sum[1] += $1 94 | sumsq[1] += $1*$1 95 | } 96 | END{ 97 | for(i = 1; i <= num_files/2; i++) { 98 | printf("%.6lf\n", sum[i]/NR) >> fname_tb[2*i-1] 99 | printf("%.6lf\n", sqrt(NR/(NR-1) * (sumsq[i]/NR - (sum[i]/NR)**2))) >> fname_tb[2*i] 100 | } 101 | } ' "${FNAME_DATA}" 102 | 103 | } 104 | 105 | #$1 is the image number 106 | gen_table () 107 | { 108 | # assign table names 109 | NUM_TBS=2 110 | FNAME_TB[1]="tb1_$$.txt" 111 | FNAME_TB[2]="tb2_$$.txt" 112 | 113 | # generate the table header 114 | i=1 115 | while [ ${i} -le ${NUM_TBS} ] 116 | do 117 | printf 'T,M,Time\n' >> ${FNAME_TB[${i}]} 118 | i=`expr $i + 1` 119 | done 120 | 121 | for t in $T 122 | do 123 | for m in $M 124 | do 125 | i=1 126 | while [ ${i} -le ${NUM_TBS} ] 127 | do 128 | printf '%d,%d,' "$t" "$m" >> ${FNAME_TB[${i}]} 129 | i=`expr $i + 1` 130 | done 131 | FNAME_DATA="T${t}_M${m}.dat" 132 | echo $FNAME_DATA 133 | gen_stat_per_pair $FNAME_DATA 134 | done 135 | done 136 | } 137 | 138 | gen_data 139 | gen_table 140 | -------------------------------------------------------------------------------- /lab2/starter/times/util_times.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include /* man sysconf(3) */ 7 | #include /* man times(2) */ 8 | #include "util_times.h" 9 | 10 | #if 0 11 | #define BUF_SIZE 256 12 | #define NUM_FUNS 2 13 | 14 | struct fn_info 15 | { 16 | void *(*fnp)(void *args); /* function pointer */ 17 | const char name[32]; /* function name */ 18 | }; 19 | 20 | void *f1(void *args); 21 | void *f2(void *args); 22 | int sprintf_time(void *buf, time_t t); 23 | const char *get_name_by_fnp (void *(*fnp)(void *args)); 24 | void *time_it(void *(*fnp)(void *args), void *args); 25 | void pr_times(clock_t real, struct tms *tmsstart, struct tms *tmsend); 26 | 27 | 28 | struct fn_info g_fn_map[NUM_FUNS] = \ 29 | { 30 | {f1, "f1()"}, \ 31 | {f2, "f2()"} 32 | }; 33 | 34 | void *f1(void *args) 35 | { 36 | int x = 0; 37 | sleep(2); 38 | /* 39 | for (int i=0; i<100000000; i++) { 40 | x = i; 41 | } 42 | */ 43 | printf("x=%d.\n", x); 44 | return NULL; 45 | } 46 | 47 | void *f2(void *args) 48 | { 49 | int status = 0; 50 | //status = system("du -ks /home/yqhuang"); 51 | status = system("./paster2.out"); 52 | printf("status = %d.\n", status); 53 | return NULL; 54 | }; 55 | 56 | #endif 57 | int sprintf_time(void *buf, time_t t) 58 | { 59 | struct tm *tm_ptr; 60 | int ret = 0; 61 | 62 | if (buf == NULL) { 63 | fprintf(stderr, "cannot access memory of destination buffer.\n"); 64 | return -1; 65 | } 66 | 67 | tm_ptr = localtime(&t); 68 | ret = strftime(buf, BUF_SIZE_256, "time and date: %r, %a %b %d, %Y", tm_ptr); 69 | if (ret == 0) { 70 | perror("strftime"); 71 | return -errno; 72 | } 73 | 74 | return ret; 75 | } 76 | 77 | const char *get_name_by_fnp (FN_INFO_P ptr, void *(*fnp)(void *args)) { 78 | int index = -1; 79 | 80 | for (int i = 0; i < NUM_FUNS; i++) { 81 | if (ptr[i].fnp == fnp) { 82 | index = i; 83 | break; 84 | } 85 | } 86 | if (index != -1) { 87 | return ptr[index].name; 88 | } 89 | 90 | return NULL; 91 | } 92 | 93 | void *time_it(FN_INFO_P ptr, void *(*fnp)(void *args), void *args) 94 | { 95 | struct tms tms_start; 96 | struct tms tms_end; 97 | clock_t start; 98 | clock_t end; 99 | 100 | printf("function: %s\n", get_name_by_fnp(ptr, fnp)); 101 | if ((start = times(&tms_start)) == -1) { /* starting time */ 102 | perror("start times"); 103 | } 104 | 105 | (*fnp)(NULL); /* execute the function */ 106 | 107 | if ((end = times(&tms_end)) == -1) { /* ending time */ 108 | perror("end times"); 109 | } 110 | 111 | pr_times(end-start, &tms_start, &tms_end); 112 | 113 | return NULL; 114 | } 115 | 116 | void pr_times(clock_t real, struct tms *tmsstart, struct tms *tmsend) 117 | { 118 | static long clktck = 0; 119 | 120 | if (clktck == 0) { /* fetch clock ticks per second first time */ 121 | if ((clktck = sysconf(_SC_CLK_TCK)) < 0) { 122 | perror("sysconf"); 123 | } 124 | } 125 | printf(" real: %7.2f\n", real / (double) clktck); 126 | printf(" user: %7.2f\n", 127 | (tmsend->tms_utime - tmsstart->tms_utime) / (double) clktck); 128 | printf(" sys: %7.2f\n", 129 | (tmsend->tms_stime - tmsstart->tms_stime) / (double) clktck); 130 | printf(" child user: %7.2f\n", 131 | (tmsend->tms_cutime - tmsstart->tms_cutime) / (double) clktck); 132 | printf(" child sys: %7.2f\n", 133 | (tmsend->tms_cstime - tmsstart->tms_cstime) / (double) clktck); 134 | 135 | } 136 | 137 | #if 0 138 | 139 | int main(int argc, char **argv) 140 | { 141 | struct timespec tsp; 142 | struct timeval tv; 143 | time_t t; 144 | int ret; 145 | char *buf = NULL; 146 | char clocks[] = {CLOCK_REALTIME, CLOCK_MONOTONIC, 147 | CLOCK_PROCESS_CPUTIME_ID, CLOCK_THREAD_CPUTIME_ID}; 148 | 149 | buf = malloc(BUF_SIZE); 150 | if (buf == NULL) { 151 | perror("malloc"); 152 | return errno; 153 | } 154 | /* Time resolution in seconds */ 155 | time(&t); 156 | sprintf_time(buf, t); 157 | printf("%s.\n", buf); 158 | 159 | /* Time resolution in microseconds */ 160 | ret = gettimeofday(&tv, NULL); 161 | printf("tv.sec = %ld, tv.tv_usec = %ld.\n", tv.tv_sec, tv.tv_usec); 162 | 163 | /* Time resolution in nanoseconds */ 164 | for (int i=0; i<4; i++) { 165 | ret = clock_getres(clocks[i], &tsp); 166 | ret = clock_gettime(clocks[i], &tsp); 167 | 168 | printf("clock[%d]: tsp.tv_sec = %ld, tsp.tv_nsec = %ld.\n", 169 | i, tsp.tv_sec, tsp.tv_nsec); 170 | } 171 | 172 | /* get _SC_CLK_TCK, num of clock ticks per second from sysconf */ 173 | int long ticks = 0; 174 | ticks = sysconf(_SC_CLK_TCK); 175 | printf("_SC_CLK_TCK = %ld.\n", ticks); 176 | 177 | time_it(f2, NULL); 178 | time_it(f1, NULL); 179 | 180 | return 0; 181 | } 182 | #endif 183 | -------------------------------------------------------------------------------- /lab2/starter/times/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include /* man sysconf(3) */ 7 | #include /* man times(2) */ 8 | 9 | #define _GNU_SOURCE /* man secure_getenv, see Feature Test Macro */ 10 | #define BUF_SIZE 256 11 | #define CMD_LEN 256 12 | #define NUM_FUNS 2 13 | 14 | struct fn_info 15 | { 16 | void *(*fnp)(void *args); /* function pointer */ 17 | const char name[32]; /* function name */ 18 | }; 19 | 20 | void *f1(void *args); 21 | void *f2(void *args); 22 | int sprintf_time(void *buf, time_t t); 23 | const char *get_name_by_fnp (void *(*fnp)(void *args)); 24 | void *time_it(void *(*fnp)(void *args), void *args); 25 | void pr_times(clock_t real, struct tms *tmsstart, struct tms *tmsend); 26 | 27 | struct fn_info g_fn_map[NUM_FUNS] = \ 28 | { 29 | {f1, "f1()"}, \ 30 | {f2, "f2()"} 31 | }; 32 | 33 | void *f1(void *args) 34 | { 35 | int x = 0; 36 | sleep(2); 37 | /* 38 | for (int i=0; i<100000000; i++) { 39 | x = i; 40 | } 41 | */ 42 | printf("x=%d.\n", x); 43 | return NULL; 44 | } 45 | 46 | void *f2(void *args) 47 | { 48 | int status = 0; 49 | char cmd[CMD_LEN]; 50 | char *dir = getenv("HOME"); 51 | if (dir == NULL) { 52 | return NULL; 53 | } 54 | printf("dir = %s \n", dir); 55 | sprintf(cmd, "du -ks %s/*", dir); 56 | status = system(cmd); 57 | printf("status = %d.\n", status); 58 | return NULL; 59 | }; 60 | 61 | int sprintf_time(void *buf, time_t t) 62 | { 63 | struct tm *tm_ptr; 64 | int ret = 0; 65 | 66 | if (buf == NULL) { 67 | fprintf(stderr, "cannot access memory of destination buffer.\n"); 68 | return -1; 69 | } 70 | 71 | tm_ptr = localtime(&t); 72 | ret = strftime(buf, BUF_SIZE, "time and date: %r, %a %b %d, %Y", tm_ptr); 73 | if (ret == 0) { 74 | perror("strftime"); 75 | return -errno; 76 | } 77 | 78 | return ret; 79 | } 80 | 81 | const char *get_name_by_fnp (void *(*fnp)(void *args)) { 82 | int index = -1; 83 | 84 | for (int i = 0; i < NUM_FUNS; i++) { 85 | if (g_fn_map[i].fnp == fnp) { 86 | index = i; 87 | break; 88 | } 89 | } 90 | if (index != -1) { 91 | return g_fn_map[index].name; 92 | } 93 | 94 | return NULL; 95 | } 96 | 97 | void *time_it(void *(*fnp)(void *args), void *args) 98 | { 99 | struct tms tms_start; 100 | struct tms tms_end; 101 | clock_t start; 102 | clock_t end; 103 | 104 | printf("function: %s\n", get_name_by_fnp(fnp)); 105 | if ((start = times(&tms_start)) == -1) { /* starting time */ 106 | perror("start times"); 107 | } 108 | 109 | (*fnp)(NULL); /* execute the function */ 110 | 111 | if ((end = times(&tms_end)) == -1) { /* ending time */ 112 | perror("end times"); 113 | } 114 | 115 | pr_times(end-start, &tms_start, &tms_end); 116 | 117 | return NULL; 118 | } 119 | 120 | void pr_times(clock_t real, struct tms *tmsstart, struct tms *tmsend) 121 | { 122 | //static long clktck = 0; 123 | long clktck = 0; 124 | 125 | if (clktck == 0) { /* fetch clock ticks per second first time */ 126 | if ((clktck = sysconf(_SC_CLK_TCK)) < 0) { 127 | perror("sysconf"); 128 | } 129 | } 130 | printf(" real: %7.2f\n", real / (double) clktck); 131 | printf(" user: %7.2f\n", 132 | (tmsend->tms_utime - tmsstart->tms_utime) / (double) clktck); 133 | printf(" sys: %7.2f\n", 134 | (tmsend->tms_stime - tmsstart->tms_stime) / (double) clktck); 135 | printf(" child user: %7.2f\n", 136 | (tmsend->tms_cutime - tmsstart->tms_cutime) / (double) clktck); 137 | printf(" child sys: %7.2f\n", 138 | (tmsend->tms_cstime - tmsstart->tms_cstime) / (double) clktck); 139 | 140 | } 141 | 142 | 143 | int main(int argc, char **argv) 144 | { 145 | struct timespec tsp; 146 | struct timeval tv; 147 | time_t t; 148 | int ret; 149 | char *buf = NULL; 150 | char clocks[] = {CLOCK_REALTIME, CLOCK_MONOTONIC, 151 | CLOCK_PROCESS_CPUTIME_ID, CLOCK_THREAD_CPUTIME_ID}; 152 | 153 | buf = malloc(BUF_SIZE); 154 | if (buf == NULL) { 155 | perror("malloc"); 156 | return errno; 157 | } 158 | /* Time resolution in seconds */ 159 | time(&t); 160 | sprintf_time(buf, t); 161 | printf("%s.\n", buf); 162 | 163 | /* Time resolution in microseconds */ 164 | ret = gettimeofday(&tv, NULL); 165 | printf("tv.sec = %ld, tv.tv_usec = %ld.\n", tv.tv_sec, tv.tv_usec); 166 | 167 | /* Time resolution in nanoseconds */ 168 | for (int i=0; i<4; i++) { 169 | ret = clock_getres(clocks[i], &tsp); 170 | ret = clock_gettime(clocks[i], &tsp); 171 | 172 | printf("clock[%d]: tsp.tv_sec = %ld, tsp.tv_nsec = %ld.\n", 173 | i, tsp.tv_sec, tsp.tv_nsec); 174 | } 175 | 176 | /* get _SC_CLK_TCK, num of clock ticks per second from sysconf */ 177 | int long ticks = 0; 178 | ticks = sysconf(_SC_CLK_TCK); 179 | printf("_SC_CLK_TCK = %ld.\n", ticks); 180 | 181 | time_it(f1, NULL); 182 | time_it(f2, NULL); 183 | 184 | return 0; 185 | } 186 | -------------------------------------------------------------------------------- /lab3/starter/shm/shm_stack.c: -------------------------------------------------------------------------------- 1 | /* 2 | * The code is derived from 3 | * Copyright(c) 2018-2019 Yiqing Huang, . 4 | * 5 | * This software may be freely redistributed under the terms of the X11 License. 6 | */ 7 | 8 | /** 9 | * @brief stack to push/pop integers. 10 | */ 11 | 12 | #include 13 | #include 14 | #include "shm_stack.h" 15 | 16 | /* a stack that can hold integers */ 17 | /* Note this structure can be used by shared memory, 18 | since the items field points to the memory right after it. 19 | Hence the structure and the data items it holds are in one 20 | continuous chunk of memory. 21 | 22 | The memory layout: 23 | +===============+ 24 | | size | 4 bytes 25 | +---------------+ 26 | | pos | 4 bytes 27 | +---------------+ 28 | | items | 8 bytes 29 | +---------------+ 30 | | items[0] | 4 bytes 31 | +---------------+ 32 | | items[1] | 4 bytes 33 | +---------------+ 34 | | ... | 4 bytes 35 | +---------------+ 36 | | items[size-1] | 4 bytes 37 | +===============+ 38 | */ 39 | typedef struct int_stack 40 | { 41 | int size; /* the max capacity of the stack */ 42 | int pos; /* position of last item pushed onto the stack */ 43 | int *items; /* stack of stored integers */ 44 | } ISTACK; 45 | 46 | /** 47 | * @brief calculate the total memory that the struct int_stack needs and 48 | * the items[size] needs. 49 | * @param int size maximum number of integers the stack can hold 50 | * @return return the sum of ISTACK size and the size of the data that 51 | * items points to. 52 | */ 53 | 54 | int sizeof_shm_stack(int size) 55 | { 56 | return (sizeof(ISTACK) + sizeof(int) * size); 57 | } 58 | 59 | /** 60 | * @brief initialize the ISTACK member fields. 61 | * @param ISTACK *p points to the starting addr. of an ISTACK struct 62 | * @param int stack_size max. number of items the stack can hold 63 | * @return 0 on success; non-zero on failure 64 | * NOTE: 65 | * The caller first calls sizeof_shm_stack() to allocate enough memory; 66 | * then calls the init_shm_stack to initialize the struct 67 | */ 68 | int init_shm_stack(ISTACK *p, int stack_size) 69 | { 70 | if ( p == NULL || stack_size == 0 ) { 71 | return 1; 72 | } 73 | 74 | p->size = stack_size; 75 | p->pos = -1; 76 | p->items = (int *) (p + sizeof(ISTACK)); 77 | return 0; 78 | } 79 | 80 | /** 81 | * @brief create a stack to hold size number of integers and its associated 82 | * ISTACK data structure. Put everything in one continous chunk of memory. 83 | * @param int size maximum number of integers the stack can hold 84 | * @return NULL if size is 0 or malloc fails 85 | */ 86 | 87 | ISTACK *create_stack(int size) 88 | { 89 | int mem_size = 0; 90 | ISTACK *pstack = NULL; 91 | 92 | if ( size == 0 ) { 93 | return NULL; 94 | } 95 | 96 | mem_size = sizeof_shm_stack(size); 97 | pstack = malloc(mem_size); 98 | 99 | if ( pstack == NULL ) { 100 | perror("malloc"); 101 | } else { 102 | char *p = (char *)pstack; 103 | pstack->items = (int *) (p + sizeof(ISTACK)); 104 | pstack->size = size; 105 | pstack->pos = -1; 106 | } 107 | 108 | return pstack; 109 | } 110 | 111 | /** 112 | * @brief release the memory 113 | * @param ISTACK *p the address of the ISTACK data structure 114 | */ 115 | 116 | void destroy_stack(ISTACK *p) 117 | { 118 | if ( p != NULL ) { 119 | free(p); 120 | } 121 | } 122 | 123 | /** 124 | * @brief check if the stack is full 125 | * @param ISTACK *p the address of the ISTACK data structure 126 | * @return non-zero if the stack is full; zero otherwise 127 | */ 128 | 129 | int is_full(ISTACK *p) 130 | { 131 | if ( p == NULL ) { 132 | return 0; 133 | } 134 | return ( p->pos == (p->size -1) ); 135 | } 136 | 137 | /** 138 | * @brief check if the stack is empty 139 | * @param ISTACK *p the address of the ISTACK data structure 140 | * @return non-zero if the stack is empty; zero otherwise 141 | */ 142 | 143 | int is_empty(ISTACK *p) 144 | { 145 | if ( p == NULL ) { 146 | return 0; 147 | } 148 | return ( p->pos == -1 ); 149 | } 150 | 151 | /** 152 | * @brief push one integer onto the stack 153 | * @param ISTACK *p the address of the ISTACK data structure 154 | * @param int item the integer to be pushed onto the stack 155 | * @return 0 on success; non-zero otherwise 156 | */ 157 | 158 | int push(ISTACK *p, int item) 159 | { 160 | if ( p == NULL ) { 161 | return -1; 162 | } 163 | 164 | if ( !is_full(p) ) { 165 | ++(p->pos); 166 | p->items[p->pos] = item; 167 | return 0; 168 | } else { 169 | return -1; 170 | } 171 | } 172 | 173 | /** 174 | * @brief push one integer onto the stack 175 | * @param ISTACK *p the address of the ISTACK data structure 176 | * @param int *item output parameter to save the integer value 177 | * that pops off the stack 178 | * @return 0 on success; non-zero otherwise 179 | */ 180 | 181 | int pop(ISTACK *p, int *p_item) 182 | { 183 | if ( p == NULL ) { 184 | return -1; 185 | } 186 | 187 | if ( !is_empty(p) ) { 188 | *p_item = p->items[p->pos]; 189 | (p->pos)--; 190 | return 0; 191 | } else { 192 | return 1; 193 | } 194 | } 195 | -------------------------------------------------------------------------------- /lab3/starter/tools/run_lab3.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ############################################################################ 3 | # File Name : run_lab3.sh 4 | # Author : Yiqing Huang 5 | # Usage : Name your executable as "paster2" and put it in the 6 | # same directory where you put this shell script. 7 | # Make sure the script has x bit set for user. If not, type 8 | # chmod u+x ./run_lab3.sh 9 | # The script requires one input argument, which is the image number 10 | # ./run_lab3.sh 11 | # where N is the image number. For example 12 | # ./run_lab3.sh 1 13 | # You can put the script in background and subsequent logout does not 14 | # stop it by using the following command: 15 | # nohup ./run_lab3.sh 1 & 16 | # 17 | # Course Name: ECE252 Systems Programming and Concurrency 18 | # Description: Lab3 utility - extracting timing info. 19 | # The script assumes the following output format at stdout 20 | # from the producer process. 21 | # Please do not output anything else to stdout. 22 | # It will affect the timing results otherwise. 23 | # ------------------------------------------- 24 | # paster2 execution time: S seconds 25 | # ------------------------------------------- 26 | # The script reads the last line where the timing info is and 27 | # then extract the S and output to a file. 28 | # The outputfile naming convention is: B*_P*_C*_X*_N*.dat. 29 | # The script then compute for tables. 30 | # tb1_N*_$$.txt: average system execution time 31 | # tb2_N*_$$.txt: standard deviation of system execution time 32 | # where N is the user input $$ is the pid of process that executing this shell script. 33 | ############################################################################# 34 | PROG="./paster2" 35 | B="5 10" 36 | P="1 5 10" 37 | C="1 5 10" 38 | X="0 200 400" 39 | NN=5 40 | 41 | exec_producer () 42 | { 43 | 44 | if [ $# != 7 ]; then 45 | echo "Usage: $0

" 46 | echo " exec_name: executible's name" 47 | echo " B: buffer size" 48 | echo " P: number of producers" 49 | echo " C: number of consumers" 50 | echo " X: number of milliseconds to sleep in consumer" 51 | echo " N: Image number to get" 52 | echo " NN: number of times to run the executible for a given pair " 53 | exit 1 54 | else 55 | PROGRAM=$1 56 | BUFFER_SIZE=$2 57 | NUM_P=$3 58 | NUM_C=$4 59 | NUM2SLEEP=$5 60 | IMG=$6 61 | X_TIMES=$7 62 | fi 63 | 64 | O_FILE='B'${BUFFER_SIZE}'_P'${NUM_P}'_C'${NUM_C}'_X'${NUM2SLEEP}'_N'${IMG}'.dat' 65 | touch ${O_FILE} 66 | xx=1 67 | while [ ${xx} -le ${X_TIMES} ] 68 | do 69 | cmd="${PROGRAM} ${BUFFER_SIZE} ${NUM_P} ${NUM_C} ${NUM2SLEEP} ${IMG}" 70 | str=`$cmd | tail -1 | awk -F' ' '{print $4}'` 71 | echo $str >> ${O_FILE} 72 | xx=`expr $xx + 1` 73 | done 74 | } 75 | 76 | gen_data () 77 | { 78 | for x in $X 79 | do 80 | for b in $B 81 | do 82 | for p in $P 83 | do 84 | if [ $p -gt $(($b+1)) ]; then 85 | break 86 | fi 87 | for c in $C 88 | do 89 | if [ $c -gt $(($b+1)) ]; then 90 | break 91 | fi 92 | exec_producer $PROG $b $p $c $x $1 $NN 93 | done 94 | done 95 | done 96 | done 97 | } 98 | 99 | # directly writing each timing string to the tb files. 100 | gen_stat_per_pair () 101 | { 102 | if [ $# != 1 ]; then 103 | echo "Usage: $0 <.dat file name>" 104 | exit 1 105 | else 106 | FNAME_DATA=$1 107 | fi 108 | LIST="${FNAME_TB[1]} ${FNAME_TB[2]}" 109 | 110 | awk -v fname_tb_list="$LIST" ' 111 | BEGIN{ 112 | num_files = split(fname_tb_list, fname_tb, " ") 113 | } 114 | { 115 | sum[1] += $1 116 | sumsq[1] += $1*$1 117 | } 118 | END{ 119 | for(i = 1; i <= num_files/2; i++) { 120 | printf("%.6lf\n", sum[i]/NR) >> fname_tb[2*i-1] 121 | printf("%.6lf\n", sqrt(NR/(NR-1) * (sumsq[i]/NR - (sum[i]/NR)**2))) >> fname_tb[2*i] 122 | } 123 | } ' "${FNAME_DATA}" 124 | 125 | } 126 | 127 | #$1 is the image number 128 | gen_table () 129 | { 130 | # assign table names 131 | NUM_TBS=2 132 | FNAME_TB[1]="tb1_N$1_$$.txt" 133 | FNAME_TB[2]="tb2_N$1_$$.txt" 134 | 135 | # generate the table header 136 | i=1 137 | while [ ${i} -le ${NUM_TBS} ] 138 | do 139 | printf 'B,P,C,X,N,Time\n' >> ${FNAME_TB[${i}]} 140 | i=`expr $i + 1` 141 | done 142 | 143 | for x in $X 144 | do 145 | for b in $B 146 | do 147 | for p in $P 148 | do 149 | if [ $p -gt $(($b+1)) ]; then 150 | break 151 | fi 152 | for c in $C 153 | do 154 | if [ $c -gt $(($b+1)) ]; then 155 | break 156 | fi 157 | i=1 158 | while [ ${i} -le ${NUM_TBS} ] 159 | do 160 | printf '%d,%d,%d,%d,%d,' "$b" "$p" "$c" "$x" "$1" >> ${FNAME_TB[${i}]} 161 | i=`expr $i + 1` 162 | done 163 | FNAME_DATA="B${b}_P${p}_C${c}_X${x}_N$1.dat" 164 | echo $FNAME_DATA 165 | gen_stat_per_pair $FNAME_DATA 166 | done 167 | done 168 | done 169 | done 170 | } 171 | 172 | if [ $# -ne 1 ]; then 173 | echo "Usage: ./run_lab3.sh " 174 | echo " N: image number, valide values are 1, 2 or 3" 175 | exit 1 176 | fi 177 | 178 | gen_data "$1" 179 | gen_table "$1" 180 | -------------------------------------------------------------------------------- /lab1/starter/png_util/zutil.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @brief: in memory deflation (zip) and inflation (unzip) routines 3 | * 4 | * Based on the zlib example zpipe.c at https://www.zlib.net/zlib_how.html 5 | * 6 | * Modification is 7 | * Copyright 2018-2020 Yiqing Huang 8 | * 9 | * This software may be freely redistributed under the terms of MIT License 10 | */ 11 | 12 | #include 13 | #include "zutil.h" 14 | 15 | /** 16 | * @brief: deflate in memory data from source to dest. 17 | * The memory areas must not overlap. 18 | * @param: dest U8* output buffer, caller supplies, should be big enough 19 | * to hold the deflated data 20 | * @param: dest_len, U64* output parameter, points to length of deflated data 21 | * @param: source U8* source buffer, contains data to be deflated 22 | * @param: source_len U64 length of source data 23 | * @param: level int compression levels (https://www.zlib.net/manual.html) 24 | * Z_NO_COMPRESSION, Z_BEST_SPEED, Z_BEST_COMPRESSION, Z_DEFAULT_COMPRESSION 25 | * @return =0 on success 26 | * <>0 on error 27 | * NOTE: 1. the compressed data length may be longer than the input data length, 28 | * especially when the input data size is very small. 29 | */ 30 | int mem_def(U8 *dest, U64 *dest_len, U8 *source, U64 source_len, int level) 31 | { 32 | z_stream strm; /* pass info. to and from zlib routines */ 33 | U8 out[CHUNK]; /* output buffer for deflate() */ 34 | int ret = 0; /* zlib return code */ 35 | int have = 0; /* amount of data returned from deflate() */ 36 | int def_len = 0; /* accumulated deflated data length */ 37 | U8 *p_dest = dest;/* first empty slot in dest buffer */ 38 | 39 | 40 | strm.zalloc = Z_NULL; 41 | strm.zfree = Z_NULL; 42 | strm.opaque = Z_NULL; 43 | 44 | ret = deflateInit(&strm, level); 45 | if (ret != Z_OK) { 46 | return ret; 47 | } 48 | 49 | /* set input data stream */ 50 | strm.avail_in = source_len; 51 | strm.next_in = source; 52 | 53 | /* call deflate repetitively since the out buffer size is fixed 54 | and the deflated output data length is not known ahead of time */ 55 | 56 | do { 57 | strm.avail_out = CHUNK; 58 | strm.next_out = out; 59 | ret = deflate(&strm, Z_FINISH); /* source contains the whole data */ 60 | assert(ret != Z_STREAM_ERROR); 61 | have = CHUNK - strm.avail_out; 62 | memcpy(p_dest, out, have); 63 | p_dest += have; /* advance to the next free byte to write */ 64 | def_len += have; /* increment deflated data length */ 65 | } while (strm.avail_out == 0); 66 | 67 | assert(strm.avail_in == 0); /* all input will be used */ 68 | assert(ret == Z_STREAM_END); /* stream will be complete */ 69 | 70 | /* clean up and return */ 71 | (void) deflateEnd(&strm); 72 | *dest_len = def_len; 73 | return Z_OK; 74 | } 75 | 76 | /** 77 | * @brief: inflate in memory data from source to dest 78 | * @param: dest U8* output buffer, caller supplies, should be big enough 79 | * to hold the deflated data 80 | * @param: dest_len, U64* output parameter, length of inflated data 81 | * @param: source U8* source buffer, contains zlib data to be inflated 82 | * @param: source_len U64 length of source data 83 | * 84 | * @return =0 on success 85 | * <>0 error 86 | */ 87 | int mem_inf(U8 *dest, U64 *dest_len, U8 *source, U64 source_len) 88 | { 89 | z_stream strm; /* pass info. to and from zlib routines */ 90 | U8 out[CHUNK]; /* output buffer for inflate() */ 91 | int ret = 0; /* zlib return code */ 92 | int have = 0; /* amount of data returned from inflate() */ 93 | int inf_len = 0; /* accumulated inflated data length */ 94 | U8 *p_dest = dest;/* first empty slot in dest buffer */ 95 | 96 | /* allocate inflate state 8 */ 97 | strm.zalloc = Z_NULL; 98 | strm.zfree = Z_NULL; 99 | strm.opaque = Z_NULL; 100 | strm.avail_in = 0; /* no input data being provided */ 101 | strm.next_in = Z_NULL; /* no input data being provided */ 102 | ret = inflateInit(&strm); 103 | if (ret != Z_OK) { 104 | return ret; 105 | } 106 | 107 | /* set input data stream */ 108 | strm.avail_in = source_len; 109 | strm.next_in = source; 110 | 111 | /* run inflate() on input until output buffer not full */ 112 | do { 113 | strm.avail_out = CHUNK; 114 | strm.next_out = out; 115 | 116 | /* zlib format is self-terminating, no need to flush */ 117 | ret = inflate(&strm, Z_NO_FLUSH); 118 | assert(ret != Z_STREAM_ERROR); /* state no t clobbered */ 119 | switch(ret) { 120 | case Z_NEED_DICT: 121 | ret = Z_DATA_ERROR; /* and fall through */ 122 | case Z_DATA_ERROR: 123 | case Z_MEM_ERROR: 124 | (void) inflateEnd(&strm); 125 | return ret; 126 | } 127 | have = CHUNK - strm.avail_out; 128 | memcpy(p_dest, out, have); 129 | p_dest += have; /* advance to the next free byte to write */ 130 | inf_len += have; /* increment inflated data length */ 131 | } while (strm.avail_out == 0 ); 132 | 133 | /* clean up and return */ 134 | (void) inflateEnd(&strm); 135 | *dest_len = inf_len; 136 | 137 | return (ret == Z_STREAM_END) ? Z_OK : Z_DATA_ERROR; 138 | } 139 | 140 | /* report a zlib or i/o error */ 141 | void zerr(int ret) 142 | { 143 | fputs("zutil: ", stderr); 144 | switch (ret) { 145 | case Z_STREAM_ERROR: 146 | fputs("invalid compression level\n", stderr); 147 | break; 148 | case Z_DATA_ERROR: 149 | fputs("invalid or incomplete deflate data\n", stderr); 150 | break; 151 | case Z_MEM_ERROR: 152 | fputs("out of memory\n", stderr); 153 | break; 154 | case Z_VERSION_ERROR: 155 | fputs("zlib version mismatch!\n", stderr); 156 | default: 157 | fprintf(stderr, "zlib returns err %d!\n", ret); 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /lab2/starter/cURL/main_write_callback.c: -------------------------------------------------------------------------------- 1 | /* 2 | * The code is based on the cURL example at URL: 3 | * https://curl.haxx.se/libcurl/c/getinmemory.html 4 | * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al.. 5 | * 6 | * Modifications to the code are 7 | * Copyright 2018-2019, Yiqing Huang, . 8 | * 9 | * This software may be freely redistributed under the terms of the X11 license. 10 | */ 11 | 12 | /** 13 | * @file main_wirte_callback.c 14 | * @brief cURL write call back to save received data in a user defined memory first 15 | * and then write the data to a file for verification purpose. 16 | * @see https://curl.haxx.se/libcurl/c/getinmemory.html 17 | * @see https://curl.haxx.se/libcurl/using/ 18 | * @see https://ec.haxx.se/callback-write.html 19 | */ 20 | 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | #define IMG_URL "http://ece252-1.uwaterloo.ca:2520/image?img=1" 30 | #define DUM_URL "https://example.com/" 31 | #define BUF_SIZE 1048576 /* 1024*1024 = 1M */ 32 | #define BUF_INC 524288 /* 1024*512 = 0.5M */ 33 | 34 | #define max(a, b) \ 35 | ({ __typeof__ (a) _a = (a); \ 36 | __typeof__ (b) _b = (b); \ 37 | _a > _b ? _a : _b; }) 38 | 39 | typedef struct recv_buf { 40 | char *buf; /* memory to hold a copy of received data */ 41 | size_t size; /* size of valid data in buf in bytes*/ 42 | size_t max_size; /* max capacity of buf in bytes*/ 43 | } RECV_BUF; 44 | 45 | 46 | size_t write_cb_curl3(char *p_recv, size_t size, size_t nmemb, void *p_userdata); 47 | int recv_buf_init(RECV_BUF *ptr, size_t max_size); 48 | int recv_buf_cleanup(RECV_BUF *ptr); 49 | int write_file(const char *path, const void *in, size_t len); 50 | 51 | 52 | /** 53 | * @brief write callback function to save a copy of received data in RAM. 54 | * The received libcurl data are pointed by p_recv, 55 | * which is provided by libcurl and is not user allocated memory. 56 | * The user allocated memory is at p_userdata. One needs to 57 | * cast it to the proper struct to make good use of it. 58 | * This function maybe invoked more than once by one invokation of 59 | * curl_easy_perform(). 60 | */ 61 | 62 | size_t write_cb_curl3(char *p_recv, size_t size, size_t nmemb, void *p_userdata) 63 | { 64 | size_t realsize = size * nmemb; 65 | RECV_BUF *p = (RECV_BUF *)p_userdata; 66 | 67 | if (p->size + realsize + 1 > p->max_size) {/* hope this rarely happens */ 68 | /* received data is not 0 terminated, add one byte for terminating 0 */ 69 | size_t new_size = p->max_size + max(BUF_INC, realsize + 1); 70 | char *q = realloc(p->buf, new_size); 71 | if (q == NULL) { 72 | perror("realloc"); /* out of memory */ 73 | return -1; 74 | } 75 | p->buf = q; 76 | p->max_size = new_size; 77 | } 78 | 79 | memcpy(p->buf + p->size, p_recv, realsize); /*copy data from libcurl*/ 80 | p->size += realsize; 81 | p->buf[p->size] = 0; 82 | 83 | return realsize; 84 | } 85 | 86 | 87 | int recv_buf_init(RECV_BUF *ptr, size_t max_size) 88 | { 89 | void *p = NULL; 90 | 91 | if (ptr == NULL) { 92 | return 1; 93 | } 94 | 95 | p = malloc(max_size); 96 | if (p == NULL) { 97 | return 2; 98 | } 99 | 100 | ptr->buf = p; 101 | ptr->size = 0; 102 | ptr->max_size = max_size; 103 | return 0; 104 | } 105 | 106 | int recv_buf_cleanup(RECV_BUF *ptr) 107 | { 108 | if (ptr == NULL) { 109 | return 1; 110 | } 111 | 112 | free(ptr->buf); 113 | ptr->size = 0; 114 | ptr->max_size = 0; 115 | return 0; 116 | } 117 | 118 | 119 | /** 120 | * @brief output data in memory to a file 121 | * @param path const char *, output file path 122 | * @param in U8 *, input data to be written to the file 123 | * @param len U64, length of the input data in bytes 124 | */ 125 | 126 | int write_file(const char *path, const void *in, size_t len) 127 | { 128 | FILE *fp = NULL; 129 | 130 | if (path == NULL) { 131 | fprintf(stderr, "write_file: file name is null!\n"); 132 | return -1; 133 | } 134 | 135 | if (in == NULL) { 136 | fprintf(stderr, "write_file: input data is null!\n"); 137 | return -1; 138 | } 139 | 140 | fp = fopen(path, "wb"); 141 | if (fp == NULL) { 142 | perror("fopen"); 143 | return -2; 144 | } 145 | 146 | if (fwrite(in, 1, len, fp) != len) { 147 | fprintf(stderr, "write_file: incomplete write!\n"); 148 | return -3; 149 | } 150 | return fclose(fp); 151 | } 152 | 153 | 154 | int main( int argc, char** argv ) 155 | { 156 | CURL *curl_handle; 157 | CURLcode res; 158 | char url[256]; 159 | RECV_BUF recv_buf; 160 | char fname[256]; 161 | pid_t pid =getpid(); 162 | 163 | recv_buf_init(&recv_buf, BUF_SIZE); 164 | 165 | if (argc == 1) { 166 | strcpy(url, IMG_URL); 167 | } else { 168 | strcpy(url, argv[1]); 169 | } 170 | printf("%s: URL is %s\n", argv[0], url); 171 | 172 | curl_global_init(CURL_GLOBAL_DEFAULT); 173 | 174 | /* init a curl session */ 175 | curl_handle = curl_easy_init(); 176 | 177 | if (curl_handle == NULL) { 178 | fprintf(stderr, "curl_easy_init: returned NULL\n"); 179 | return 1; 180 | } 181 | 182 | /* specify URL to get */ 183 | curl_easy_setopt(curl_handle, CURLOPT_URL, url); 184 | 185 | /* register write call back function to process received data */ 186 | curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, write_cb_curl3); 187 | /* user defined data structure passed to the call back function */ 188 | curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)&recv_buf); 189 | 190 | /* some servers requires a user-agent field */ 191 | curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0"); 192 | 193 | /* get it! */ 194 | res = curl_easy_perform(curl_handle); 195 | 196 | if( res != CURLE_OK) { 197 | fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); 198 | } else { 199 | printf("%lu bytes received in memory %p\n", recv_buf.size, recv_buf.buf); 200 | } 201 | 202 | sprintf(fname, "./output_%d.png", pid); 203 | write_file(fname, recv_buf.buf, recv_buf.size); 204 | 205 | /* cleaning up */ 206 | curl_easy_cleanup(curl_handle); 207 | curl_global_cleanup(); 208 | recv_buf_cleanup(&recv_buf); 209 | return 0; 210 | } 211 | -------------------------------------------------------------------------------- /manual/preemble/util_listings.tex: -------------------------------------------------------------------------------- 1 | \definecolor{dkgreen}{rgb}{0,0.6,0} 2 | \definecolor{gray}{rgb}{0.5,0.5,0.5} 3 | \definecolor{mauve}{rgb}{0.58,0.0,0.82} 4 | \lstset{ 5 | language=[x86masm]Assembler, 6 | %language=C, 7 | basicstyle=\footnotesize, 8 | %numbers=left, 9 | %numberstyle=\tiny, 10 | %stepnumber=2, 11 | %numbersep=5pt, 12 | backgroundcolor=\color{white}, 13 | showspaces=false, 14 | showstringspaces=false, 15 | showtabs=false, 16 | %frame=single, 17 | frame=trBL, 18 | rulecolor=\color{black}, 19 | tabsize=4, % sets default tabsize to 2 spaces 20 | captionpos=b, % sets the caption-position to bottom 21 | breaklines=true, % sets automatic line breaking 22 | breakatwhitespace=false, % sets if automatic breaks should only 23 | % happen at whitespace 24 | title=\lstname, % show the filename of files included 25 | % with \lstinputlisting; 26 | % also try caption instead of title 27 | keywordstyle=\color{blue}, % keyword style 28 | commentstyle=\color{dkgreen}, % comment style 29 | stringstyle=\color{mauve}, % string literal style 30 | morekeywords={*,__asm} % if u want to add more keywords to the set 31 | %escapeinside={\%*}{*)}, % if you want to add a comment within 32 | } 33 | 34 | \lstdefinestyle{makefile} 35 | { 36 | numberblanklines=false, 37 | language=make, 38 | basicstyle=\ttfamily, %\footnotesize, 39 | tabsize=8, 40 | keywordstyle=\color{red}, 41 | backgroundcolor=\color{white}, 42 | showspaces=false, 43 | showstringspaces=false, 44 | showtabs=false, 45 | backgroundcolor=\color{lightlightgray}, % Choose background color 46 | frame=single, % A frame around the code 47 | %frame=none, 48 | %frame=trBL, 49 | rulecolor=\color{black}, 50 | captionpos=b, % sets the caption-position to bottom 51 | breaklines=true, % sets automatic line breaking 52 | breakatwhitespace=false, % sets if automatic breaks should only 53 | % happen at whitespace 54 | %title=\lstname, % show the filename of files included 55 | % with \lstinputlisting; 56 | % also try caption instead of title 57 | keywordstyle=\color{blue}, % keyword style 58 | commentstyle=\color{dkgreen}, % comment style 59 | stringstyle=\color{mauve}, % string literal style 60 | morekeywords={*,__asm}, % if u want to add more keywords to the set 61 | %escapeinside={\%*}{*)}, % if you want to add a comment within 62 | identifierstyle= %plain identifiers for make 63 | } 64 | \definecolor{Brown}{cmyk}{0,0.81,1,0.60} 65 | \definecolor{OliveGreen}{cmyk}{0.64,0,0.95,0.40} 66 | \definecolor{CadetBlue}{cmyk}{0.62,0.57,0.23,0} 67 | \definecolor{lightlightgray}{gray}{0.9} 68 | \definecolor{dkgreen}{rgb}{0,0.6,0} 69 | \definecolor{gray}{rgb}{0.5,0.5,0.5} 70 | \definecolor{mauve}{rgb}{0.58,0,0.82} 71 | \lstset{ 72 | language=C, % Code langugage 73 | basicstyle=\ttfamily, % Code font, Examples: \footnotesize, \ttfamily 74 | keywordstyle=\color{blue}, % Keywords font ('*' = uppercase) 75 | commentstyle=\color{dkgreen}, % Comments font 76 | stringstyle=\color{mauve}, % string literal font 77 | escapeinside={\%*}{*}, % if you want to add a comment within your code 78 | numbers=left, % Line nums position 79 | numberstyle=\tiny, % Line-numbers fonts 80 | stepnumber=0, % Step between two line-numbers 81 | numbersep=5pt, % How far are line-numbers from code 82 | backgroundcolor=\color{lightlightgray}, % Choose background color 83 | % frame=none, % A frame around the code 84 | frame=single, 85 | tabsize=2, % Default tab size 86 | captionpos=b, % Caption-position = bottom 87 | breaklines=true, % Automatic line breaking? 88 | breakatwhitespace=false, % Automatic breaks only at whitespace? 89 | showspaces=false, % Dont make spaces visible 90 | showtabs=false, % Dont make tabls visible 91 | columns=flexible, % Column format 92 | morekeywords={__global__, __device__}, % CUDA specific keywords 93 | } 94 | \lstdefinestyle{asm} { 95 | language=[x86masm]Assembler, % Code langugage 96 | basicstyle=\ttfamily, % Code font, Examples: \footnotesize, \ttfamily 97 | keywordstyle=\color{blue}, % Keywords font ('*' = uppercase) 98 | commentstyle=\color{dkgreen}, % Comments font 99 | stringstyle=\color{mauve}, % string literal font 100 | escapeinside={\%*}{*}, % if you want to add a comment within your code 101 | numbers=left, % Line nums position 102 | numberstyle=\tiny, % Line-numbers fonts 103 | stepnumber=0, % Step between two line-numbers 104 | numbersep=5pt, % How far are line-numbers from code 105 | backgroundcolor=\color{lightlightgray}, % Choose background color 106 | %frame=none, % A frame around the code 107 | frame=single, 108 | tabsize=2, % Default tab size 109 | captionpos=b, % Caption-position = bottom 110 | breaklines=true, % Automatic line breaking? 111 | breakatwhitespace=false, % Automatic breaks only at whitespace? 112 | showspaces=false, % Dont make spaces visible 113 | showtabs=false, % Dont make tabls visible 114 | columns=flexible, % Column format 115 | morekeywords={__global__, __device__}, % CUDA specific keywords 116 | } 117 | 118 | \lstdefinestyle{bash} 119 | { 120 | numberblanklines=false, 121 | language=bash, 122 | basicstyle=\ttfamily\color{white}\bfseries, %\footnotesize, 123 | tabsize=8, 124 | keywordstyle=\color{red}, 125 | backgroundcolor=\color{black}, 126 | %backgroundcolor=\color{lightlightgray}, % Choose background color 127 | showspaces=false, 128 | showstringspaces=false, 129 | showtabs=false, 130 | %frame=single, % A frame around the code 131 | frame=none, 132 | %frame=trBL, 133 | rulecolor=\color{black}, 134 | captionpos=b, % sets the caption-position to bottom 135 | breaklines=true, % sets automatic line breaking 136 | breakatwhitespace=false, % sets if automatic breaks should only 137 | % happen at whitespace 138 | %title=\lstname, % show the filename of files included 139 | % with \lstinputlisting; 140 | % also try caption instead of title 141 | keywordstyle=\color{blue}, % keyword style 142 | commentstyle=\color{dkgreen}, % comment style 143 | stringstyle=\color{mauve}, % string literal style 144 | morekeywords={*,__asm}, % if u want to add more keywords to the set 145 | %escapeinside={\%*}{*)}, % if you want to add a comment within 146 | identifierstyle= %plain identifiers for make 147 | } 148 | 149 | %%% Local Variables: 150 | %%% mode: latex 151 | %%% TeX-master: "main_book" 152 | %%% End: 153 | -------------------------------------------------------------------------------- /lab2/starter/cURL/main_write_header_cb.c: -------------------------------------------------------------------------------- 1 | /* 2 | * The code is derived from cURL example and paster.c base code. 3 | * The cURL example is at URL: 4 | * https://curl.haxx.se/libcurl/c/getinmemory.html 5 | * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al.. 6 | * 7 | * The paster.c code is 8 | * Copyright 2013 Patrick Lam, . 9 | * 10 | * Modifications to the code are 11 | * Copyright 2018-2019, Yiqing Huang, . 12 | * 13 | * This software may be freely redistributed under the terms of the X11 license. 14 | */ 15 | 16 | /** 17 | * @file main_wirte_read_cb.c 18 | * @brief cURL write call back to save received data in a user defined memory first 19 | * and then write the data to a file for verification purpose. 20 | * cURL header call back extracts data sequence number from header. 21 | * @see https://curl.haxx.se/libcurl/c/getinmemory.html 22 | * @see https://curl.haxx.se/libcurl/using/ 23 | * @see https://ec.haxx.se/callback-write.html 24 | */ 25 | 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | #define IMG_URL "http://ece252-1.uwaterloo.ca:2520/image?img=1" 35 | #define DUM_URL "https://example.com/" 36 | #define ECE252_HEADER "X-Ece252-Fragment: " 37 | #define BUF_SIZE 1048576 /* 1024*1024 = 1M */ 38 | #define BUF_INC 524288 /* 1024*512 = 0.5M */ 39 | 40 | #define max(a, b) \ 41 | ({ __typeof__ (a) _a = (a); \ 42 | __typeof__ (b) _b = (b); \ 43 | _a > _b ? _a : _b; }) 44 | 45 | typedef struct recv_buf2 { 46 | char *buf; /* memory to hold a copy of received data */ 47 | size_t size; /* size of valid data in buf in bytes*/ 48 | size_t max_size; /* max capacity of buf in bytes*/ 49 | int seq; /* >=0 sequence number extracted from http header */ 50 | /* <0 indicates an invalid seq number */ 51 | } RECV_BUF; 52 | 53 | 54 | size_t header_cb_curl(char *p_recv, size_t size, size_t nmemb, void *userdata); 55 | size_t write_cb_curl3(char *p_recv, size_t size, size_t nmemb, void *p_userdata); 56 | int recv_buf_init(RECV_BUF *ptr, size_t max_size); 57 | int recv_buf_cleanup(RECV_BUF *ptr); 58 | int write_file(const char *path, const void *in, size_t len); 59 | 60 | 61 | /** 62 | * @brief cURL header call back function to extract image sequence number from 63 | * http header data. An example header for image part n (assume n = 2) is: 64 | * X-Ece252-Fragment: 2 65 | * @param char *p_recv: header data delivered by cURL 66 | * @param size_t size size of each memb 67 | * @param size_t nmemb number of memb 68 | * @param void *userdata user defined data structurea 69 | * @return size of header data received. 70 | * @details this routine will be invoked multiple times by the libcurl until the full 71 | * header data are received. we are only interested in the ECE252_HEADER line 72 | * received so that we can extract the image sequence number from it. This 73 | * explains the if block in the code. 74 | */ 75 | size_t header_cb_curl(char *p_recv, size_t size, size_t nmemb, void *userdata) 76 | { 77 | int realsize = size * nmemb; 78 | RECV_BUF *p = userdata; 79 | 80 | if (realsize > strlen(ECE252_HEADER) && 81 | strncmp(p_recv, ECE252_HEADER, strlen(ECE252_HEADER)) == 0) { 82 | 83 | /* extract img sequence number */ 84 | p->seq = atoi(p_recv + strlen(ECE252_HEADER)); 85 | 86 | } 87 | return realsize; 88 | } 89 | 90 | 91 | /** 92 | * @brief write callback function to save a copy of received data in RAM. 93 | * The received libcurl data are pointed by p_recv, 94 | * which is provided by libcurl and is not user allocated memory. 95 | * The user allocated memory is at p_userdata. One needs to 96 | * cast it to the proper struct to make good use of it. 97 | * This function maybe invoked more than once by one invokation of 98 | * curl_easy_perform(). 99 | */ 100 | 101 | size_t write_cb_curl3(char *p_recv, size_t size, size_t nmemb, void *p_userdata) 102 | { 103 | size_t realsize = size * nmemb; 104 | RECV_BUF *p = (RECV_BUF *)p_userdata; 105 | 106 | if (p->size + realsize + 1 > p->max_size) {/* hope this rarely happens */ 107 | /* received data is not 0 terminated, add one byte for terminating 0 */ 108 | size_t new_size = p->max_size + max(BUF_INC, realsize + 1); 109 | char *q = realloc(p->buf, new_size); 110 | if (q == NULL) { 111 | perror("realloc"); /* out of memory */ 112 | return -1; 113 | } 114 | p->buf = q; 115 | p->max_size = new_size; 116 | } 117 | 118 | memcpy(p->buf + p->size, p_recv, realsize); /*copy data from libcurl*/ 119 | p->size += realsize; 120 | p->buf[p->size] = 0; 121 | 122 | return realsize; 123 | } 124 | 125 | 126 | int recv_buf_init(RECV_BUF *ptr, size_t max_size) 127 | { 128 | void *p = NULL; 129 | 130 | if (ptr == NULL) { 131 | return 1; 132 | } 133 | 134 | p = malloc(max_size); 135 | if (p == NULL) { 136 | return 2; 137 | } 138 | 139 | ptr->buf = p; 140 | ptr->size = 0; 141 | ptr->max_size = max_size; 142 | ptr->seq = -1; /* valid seq should be non-negative */ 143 | return 0; 144 | } 145 | 146 | int recv_buf_cleanup(RECV_BUF *ptr) 147 | { 148 | if (ptr == NULL) { 149 | return 1; 150 | } 151 | 152 | free(ptr->buf); 153 | ptr->size = 0; 154 | ptr->max_size = 0; 155 | return 0; 156 | } 157 | 158 | 159 | /** 160 | * @brief output data in memory to a file 161 | * @param path const char *, output file path 162 | * @param in void *, input data to be written to the file 163 | * @param len size_t, length of the input data in bytes 164 | */ 165 | 166 | int write_file(const char *path, const void *in, size_t len) 167 | { 168 | FILE *fp = NULL; 169 | 170 | if (path == NULL) { 171 | fprintf(stderr, "write_file: file name is null!\n"); 172 | return -1; 173 | } 174 | 175 | if (in == NULL) { 176 | fprintf(stderr, "write_file: input data is null!\n"); 177 | return -1; 178 | } 179 | 180 | fp = fopen(path, "wb"); 181 | if (fp == NULL) { 182 | perror("fopen"); 183 | return -2; 184 | } 185 | 186 | if (fwrite(in, 1, len, fp) != len) { 187 | fprintf(stderr, "write_file: imcomplete write!\n"); 188 | return -3; 189 | } 190 | return fclose(fp); 191 | } 192 | 193 | 194 | int main( int argc, char** argv ) 195 | { 196 | CURL *curl_handle; 197 | CURLcode res; 198 | char url[256]; 199 | RECV_BUF recv_buf; 200 | char fname[256]; 201 | pid_t pid =getpid(); 202 | 203 | recv_buf_init(&recv_buf, BUF_SIZE); 204 | 205 | if (argc == 1) { 206 | strcpy(url, IMG_URL); 207 | } else { 208 | strcpy(url, argv[1]); 209 | } 210 | printf("%s: URL is %s\n", argv[0], url); 211 | 212 | curl_global_init(CURL_GLOBAL_DEFAULT); 213 | 214 | /* init a curl session */ 215 | curl_handle = curl_easy_init(); 216 | 217 | if (curl_handle == NULL) { 218 | fprintf(stderr, "curl_easy_init: returned NULL\n"); 219 | return 1; 220 | } 221 | 222 | /* specify URL to get */ 223 | curl_easy_setopt(curl_handle, CURLOPT_URL, url); 224 | 225 | /* register write call back function to process received data */ 226 | curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, write_cb_curl3); 227 | /* user defined data structure passed to the call back function */ 228 | curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)&recv_buf); 229 | 230 | /* register header call back function to process received header data */ 231 | curl_easy_setopt(curl_handle, CURLOPT_HEADERFUNCTION, header_cb_curl); 232 | /* user defined data structure passed to the call back function */ 233 | curl_easy_setopt(curl_handle, CURLOPT_HEADERDATA, (void *)&recv_buf); 234 | 235 | /* some servers requires a user-agent field */ 236 | curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0"); 237 | 238 | 239 | /* get it! */ 240 | res = curl_easy_perform(curl_handle); 241 | 242 | if( res != CURLE_OK) { 243 | fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); 244 | } else { 245 | printf("%lu bytes received in memory %p, seq=%d.\n", \ 246 | recv_buf.size, recv_buf.buf, recv_buf.seq); 247 | } 248 | 249 | sprintf(fname, "./output_%d_%d.png", recv_buf.seq, pid); 250 | write_file(fname, recv_buf.buf, recv_buf.size); 251 | 252 | /* cleaning up */ 253 | curl_easy_cleanup(curl_handle); 254 | curl_global_cleanup(); 255 | recv_buf_cleanup(&recv_buf); 256 | return 0; 257 | } 258 | -------------------------------------------------------------------------------- /lab3/starter/cURL_IPC/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * The code is derived from cURL example and paster.c base code. 3 | * The cURL example is at URL: 4 | * https://curl.haxx.se/libcurl/c/getinmemory.html 5 | * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al.. 6 | * 7 | * The paster.c code is 8 | * Copyright 2013 Patrick Lam, . 9 | * 10 | * Modifications to the code are 11 | * Copyright 2018-2019, Yiqing Huang, . 12 | * 13 | * This software may be freely redistributed under the terms of the X11 license. 14 | */ 15 | 16 | /** 17 | * @file main.c 18 | * @brief cURL write call back to save received data in a shared memory first 19 | * and then write the data to a file for verification purpose. 20 | * cURL header call back extracts data sequence number from header. 21 | * @see https://curl.haxx.se/libcurl/c/getinmemory.html 22 | * @see https://curl.haxx.se/libcurl/using/ 23 | * @see https://ec.haxx.se/callback-write.html 24 | * NOTE: we assume each image segment from the server is less than 10K 25 | */ 26 | 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | #define IMG_URL "http://ece252-1.uwaterloo.ca:2530/image?img=1&part=20" 40 | #define DUM_URL "https://example.com/" 41 | #define ECE252_HEADER "X-Ece252-Fragment: " 42 | #define BUF_SIZE 10240 /* 1024*10 = 10K */ 43 | 44 | /* This is a flattened structure, buf points to 45 | the memory address immediately after 46 | the last member field (i.e. seq) in the structure. 47 | Here is the memory layout. 48 | Note that the memory is a chunk of continuous bytes. 49 | 50 | On a 64-bit machine, the memory layout is as follows: 51 | 52 | +================+ 53 | | buf | 8 bytes 54 | +----------------+ 55 | | size | 8 bytes 56 | +----------------+ 57 | | max_size | 8 bytes 58 | +----------------+ 59 | | seq | 4 bytes 60 | +----------------+ 61 | | padding | 4 bytes 62 | +----------------+ 63 | | buf[0] | 1 byte 64 | +----------------+ 65 | | buf[1] | 1 byte 66 | +----------------+ 67 | | ... | 1 byte 68 | +----------------+ 69 | | buf[max_size-1]| 1 byte 70 | +================+ 71 | */ 72 | typedef struct recv_buf_flat { 73 | char *buf; /* memory to hold a copy of received data */ 74 | size_t size; /* size of valid data in buf in bytes*/ 75 | size_t max_size; /* max capacity of buf in bytes*/ 76 | int seq; /* >=0 sequence number extracted from http header */ 77 | /* <0 indicates an invalid seq number */ 78 | } RECV_BUF; 79 | 80 | size_t header_cb_curl(char *p_recv, size_t size, size_t nmemb, void *userdata); 81 | size_t write_cb_curl(char *p_recv, size_t size, size_t nmemb, void *p_userdata); 82 | int recv_buf_init(RECV_BUF *ptr, size_t max_size); 83 | int recv_buf_cleanup(RECV_BUF *ptr); 84 | int write_file(const char *path, const void *in, size_t len); 85 | 86 | 87 | /** 88 | * @brief cURL header call back function to extract image sequence number from 89 | * http header data. An example header for image part n (assume n = 2) is: 90 | * X-Ece252-Fragment: 2 91 | * @param char *p_recv: header data delivered by cURL 92 | * @param size_t size size of each memb 93 | * @param size_t nmemb number of memb 94 | * @param void *userdata user defined data structurea 95 | * @return size of header data received. 96 | * @details this routine will be invoked multiple times by the libcurl until the full 97 | * header data are received. we are only interested in the ECE252_HEADER line 98 | * received so that we can extract the image sequence number from it. This 99 | * explains the if block in the code. 100 | */ 101 | size_t header_cb_curl(char *p_recv, size_t size, size_t nmemb, void *userdata) 102 | { 103 | int realsize = size * nmemb; 104 | RECV_BUF *p = userdata; 105 | 106 | if (realsize > strlen(ECE252_HEADER) && 107 | strncmp(p_recv, ECE252_HEADER, strlen(ECE252_HEADER)) == 0) { 108 | 109 | /* extract img sequence number */ 110 | p->seq = atoi(p_recv + strlen(ECE252_HEADER)); 111 | 112 | } 113 | return realsize; 114 | } 115 | 116 | 117 | /** 118 | * @brief write callback function to save a copy of received data in RAM. 119 | * The received libcurl data are pointed by p_recv, 120 | * which is provided by libcurl and is not user allocated memory. 121 | * The user allocated memory is at p_userdata. One needs to 122 | * cast it to the proper struct to make good use of it. 123 | * This function maybe invoked more than once by one invokation of 124 | * curl_easy_perform(). 125 | */ 126 | 127 | size_t write_cb_curl(char *p_recv, size_t size, size_t nmemb, void *p_userdata) 128 | { 129 | size_t realsize = size * nmemb; 130 | RECV_BUF *p = (RECV_BUF *)p_userdata; 131 | 132 | if (p->size + realsize + 1 > p->max_size) {/* hope this rarely happens */ 133 | fprintf(stderr, "User buffer is too small, abort...\n"); 134 | abort(); 135 | } 136 | 137 | memcpy(p->buf + p->size, p_recv, realsize); /*copy data from libcurl*/ 138 | p->size += realsize; 139 | p->buf[p->size] = 0; 140 | 141 | return realsize; 142 | } 143 | 144 | /** 145 | * @brief calculate the actual size of RECV_BUF 146 | * @param size_t nbytes number of bytes that buf in RECV_BUF struct would hold 147 | * @return the REDV_BUF member fileds size plus the RECV_BUF buf data size 148 | */ 149 | int sizeof_shm_recv_buf(size_t nbytes) 150 | { 151 | return (sizeof(RECV_BUF) + sizeof(char) * nbytes); 152 | } 153 | 154 | /** 155 | * @brief initialize the RECV_BUF structure. 156 | * @param RECV_BUF *ptr memory allocated by user to hold RECV_BUF struct 157 | * @param size_t nbytes the RECV_BUF buf data size in bytes 158 | * NOTE: caller should call sizeof_shm_recv_buf first and then allocate memory. 159 | * caller is also responsible for releasing the memory. 160 | */ 161 | 162 | int shm_recv_buf_init(RECV_BUF *ptr, size_t nbytes) 163 | { 164 | if ( ptr == NULL ) { 165 | return 1; 166 | } 167 | 168 | ptr->buf = (char *)ptr + sizeof(RECV_BUF); 169 | ptr->size = 0; 170 | ptr->max_size = nbytes; 171 | ptr->seq = -1; /* valid seq should be non-negative */ 172 | 173 | return 0; 174 | } 175 | 176 | 177 | /** 178 | * @brief output data in memory to a file 179 | * @param path const char *, output file path 180 | * @param in void *, input data to be written to the file 181 | * @param len size_t, length of the input data in bytes 182 | */ 183 | 184 | int write_file(const char *path, const void *in, size_t len) 185 | { 186 | FILE *fp = NULL; 187 | 188 | if (path == NULL) { 189 | fprintf(stderr, "write_file: file name is null!\n"); 190 | return -1; 191 | } 192 | 193 | if (in == NULL) { 194 | fprintf(stderr, "write_file: input data is null!\n"); 195 | return -1; 196 | } 197 | 198 | fp = fopen(path, "wb"); 199 | if (fp == NULL) { 200 | perror("fopen"); 201 | return -2; 202 | } 203 | 204 | if (fwrite(in, 1, len, fp) != len) { 205 | fprintf(stderr, "write_file: imcomplete write!\n"); 206 | return -3; 207 | } 208 | return fclose(fp); 209 | } 210 | 211 | 212 | int main( int argc, char** argv ) 213 | { 214 | CURL *curl_handle; 215 | CURLcode res; 216 | char url[256]; 217 | RECV_BUF *p_shm_recv_buf; 218 | int shmid; 219 | int shm_size = sizeof_shm_recv_buf(BUF_SIZE); 220 | char fname[256]; 221 | pid_t pid =getpid(); 222 | 223 | printf("shm_size = %d.\n", shm_size); 224 | shmid = shmget(IPC_PRIVATE, shm_size, IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR); 225 | if ( shmid == -1 ) { 226 | perror("shmget"); 227 | abort(); 228 | } 229 | 230 | p_shm_recv_buf = shmat(shmid, NULL, 0); 231 | shm_recv_buf_init(p_shm_recv_buf, BUF_SIZE); 232 | 233 | if (argc == 1) { 234 | strcpy(url, IMG_URL); 235 | } else { 236 | strcpy(url, argv[1]); 237 | } 238 | printf("%s: URL is %s\n", argv[0], url); 239 | 240 | curl_global_init(CURL_GLOBAL_DEFAULT); 241 | 242 | /* init a curl session */ 243 | curl_handle = curl_easy_init(); 244 | 245 | if (curl_handle == NULL) { 246 | fprintf(stderr, "curl_easy_init: returned NULL\n"); 247 | return 1; 248 | } 249 | 250 | /* specify URL to get */ 251 | curl_easy_setopt(curl_handle, CURLOPT_URL, url); 252 | 253 | /* register write call back function to process received data */ 254 | curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, write_cb_curl); 255 | /* user defined data structure passed to the call back function */ 256 | curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)p_shm_recv_buf); 257 | 258 | /* register header call back function to process received header data */ 259 | curl_easy_setopt(curl_handle, CURLOPT_HEADERFUNCTION, header_cb_curl); 260 | /* user defined data structure passed to the call back function */ 261 | curl_easy_setopt(curl_handle, CURLOPT_HEADERDATA, (void *)p_shm_recv_buf); 262 | 263 | /* some servers requires a user-agent field */ 264 | curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0"); 265 | 266 | 267 | /* get it! */ 268 | res = curl_easy_perform(curl_handle); 269 | 270 | if( res != CURLE_OK) { 271 | fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); 272 | } else { 273 | printf("%lu bytes received in memory %p, seq=%d.\n", \ 274 | p_shm_recv_buf->size, p_shm_recv_buf->buf, p_shm_recv_buf->seq); 275 | 276 | } 277 | 278 | sprintf(fname, "./output_%d_%d.png", p_shm_recv_buf->seq, pid); 279 | write_file(fname, p_shm_recv_buf->buf, p_shm_recv_buf->size); 280 | 281 | /* cleaning up */ 282 | curl_easy_cleanup(curl_handle); 283 | curl_global_cleanup(); 284 | shmdt(p_shm_recv_buf); 285 | shmctl(shmid, IPC_RMID, NULL); 286 | return 0; 287 | } 288 | -------------------------------------------------------------------------------- /lab3/starter/cURL_IPC/main_2proc.c: -------------------------------------------------------------------------------- 1 | /* 2 | * The code is derived from cURL example and paster.c base code. 3 | * The cURL example is at URL: 4 | * https://curl.haxx.se/libcurl/c/getinmemory.html 5 | * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al.. 6 | * 7 | * The paster.c code is 8 | * Copyright 2013 Patrick Lam, . 9 | * 10 | * Modifications to the code are 11 | * Copyright 2018-2019, Yiqing Huang, . 12 | * 13 | * This software may be freely redistributed under the terms of the X11 license. 14 | */ 15 | 16 | /** 17 | * @file main_2proc.c 18 | * @brief Two processes system. The child process uses cURL to download data to 19 | * a shared memory region through cURL call back. 20 | * The parent process wait till the child to finish and then 21 | * read the data from the shared memory region and output it to a file. 22 | * cURL header call back extracts data sequence number from header. 23 | * Synchronization is done through waitpid, no semaphores are used. 24 | * @see https://curl.haxx.se/libcurl/c/getinmemory.html 25 | * @see https://curl.haxx.se/libcurl/using/ 26 | * @see https://ec.haxx.se/callback-write.html 27 | */ 28 | 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | 41 | #define IMG_URL "http://ece252-1.uwaterloo.ca:2530/image?img=1&part=20" 42 | #define DUM_URL "https://example.com/" 43 | #define ECE252_HEADER "X-Ece252-Fragment: " 44 | #define BUF_SIZE 10240 /* 1024*10 = 10K */ 45 | 46 | /* This is a flattened structure, buf points to 47 | the memory address immediately after 48 | the last member field (i.e. seq) in the structure. 49 | Here is the memory layout. 50 | Note that the memory is a chunk of continuous bytes. 51 | 52 | On a 64-bit machine, the memory layout is as follows: 53 | +================+ 54 | | buf | 8 bytes 55 | +----------------+ 56 | | size | 8 bytes 57 | +----------------+ 58 | | max_size | 8 bytes 59 | +----------------+ 60 | | seq | 4 bytes 61 | +----------------+ 62 | | padding | 4 bytes 63 | +----------------+ 64 | | buf[0] | 1 byte 65 | +----------------+ 66 | | buf[1] | 1 byte 67 | +----------------+ 68 | | ... | 1 byte 69 | +----------------+ 70 | | buf[max_size-1]| 1 byte 71 | +================+ 72 | */ 73 | typedef struct recv_buf_flat { 74 | char *buf; /* memory to hold a copy of received data */ 75 | size_t size; /* size of valid data in buf in bytes*/ 76 | size_t max_size; /* max capacity of buf in bytes*/ 77 | int seq; /* >=0 sequence number extracted from http header */ 78 | /* <0 indicates an invalid seq number */ 79 | } RECV_BUF; 80 | 81 | size_t header_cb_curl(char *p_recv, size_t size, size_t nmemb, void *userdata); 82 | size_t write_cb_curl(char *p_recv, size_t size, size_t nmemb, void *p_userdata); 83 | int recv_buf_init(RECV_BUF *ptr, size_t max_size); 84 | int recv_buf_cleanup(RECV_BUF *ptr); 85 | int write_file(const char *path, const void *in, size_t len); 86 | 87 | 88 | /** 89 | * @brief cURL header call back function to extract image sequence number from 90 | * http header data. An example header for image part n (assume n = 2) is: 91 | * X-Ece252-Fragment: 2 92 | * @param char *p_recv: header data delivered by cURL 93 | * @param size_t size size of each memb 94 | * @param size_t nmemb number of memb 95 | * @param void *userdata user defined data structurea 96 | * @return size of header data received. 97 | * @details this routine will be invoked multiple times by the libcurl until the full 98 | * header data are received. we are only interested in the ECE252_HEADER line 99 | * received so that we can extract the image sequence number from it. This 100 | * explains the if block in the code. 101 | */ 102 | size_t header_cb_curl(char *p_recv, size_t size, size_t nmemb, void *userdata) 103 | { 104 | int realsize = size * nmemb; 105 | RECV_BUF *p = userdata; 106 | 107 | if (realsize > strlen(ECE252_HEADER) && 108 | strncmp(p_recv, ECE252_HEADER, strlen(ECE252_HEADER)) == 0) { 109 | 110 | /* extract img sequence number */ 111 | p->seq = atoi(p_recv + strlen(ECE252_HEADER)); 112 | 113 | } 114 | return realsize; 115 | } 116 | 117 | 118 | /** 119 | * @brief write callback function to save a copy of received data in RAM. 120 | * The received libcurl data are pointed by p_recv, 121 | * which is provided by libcurl and is not user allocated memory. 122 | * The user allocated memory is at p_userdata. One needs to 123 | * cast it to the proper struct to make good use of it. 124 | * This function maybe invoked more than once by one invokation of 125 | * curl_easy_perform(). 126 | */ 127 | 128 | size_t write_cb_curl(char *p_recv, size_t size, size_t nmemb, void *p_userdata) 129 | { 130 | size_t realsize = size * nmemb; 131 | RECV_BUF *p = (RECV_BUF *)p_userdata; 132 | 133 | if (p->size + realsize + 1 > p->max_size) {/* hope this rarely happens */ 134 | fprintf(stderr, "User buffer is too small, abort...\n"); 135 | abort(); 136 | } 137 | 138 | memcpy(p->buf + p->size, p_recv, realsize); /*copy data from libcurl*/ 139 | p->size += realsize; 140 | p->buf[p->size] = 0; 141 | 142 | return realsize; 143 | } 144 | 145 | /** 146 | * @brief calculate the actual size of RECV_BUF 147 | * @param size_t nbytes number of bytes that buf in RECV_BUF struct would hold 148 | * @return the REDV_BUF member fileds size plus the RECV_BUF buf data size 149 | */ 150 | int sizeof_shm_recv_buf(size_t nbytes) 151 | { 152 | return (sizeof(RECV_BUF) + sizeof(char) * nbytes); 153 | } 154 | 155 | /** 156 | * @brief initialize the RECV_BUF structure. 157 | * @param RECV_BUF *ptr memory allocated by user to hold RECV_BUF struct 158 | * @param size_t nbytes the RECV_BUF buf data size in bytes 159 | * NOTE: caller should call sizeof_shm_recv_buf first and then allocate memory. 160 | * caller is also responsible for releasing the memory. 161 | */ 162 | 163 | int shm_recv_buf_init(RECV_BUF *ptr, size_t nbytes) 164 | { 165 | if ( ptr == NULL ) { 166 | return 1; 167 | } 168 | 169 | ptr->buf = (char *)ptr + sizeof(RECV_BUF); 170 | ptr->size = 0; 171 | ptr->max_size = nbytes; 172 | ptr->seq = -1; /* valid seq should be non-negative */ 173 | 174 | return 0; 175 | } 176 | 177 | 178 | /** 179 | * @brief output data in memory to a file 180 | * @param path const char *, output file path 181 | * @param in void *, input data to be written to the file 182 | * @param len size_t, length of the input data in bytes 183 | */ 184 | 185 | int write_file(const char *path, const void *in, size_t len) 186 | { 187 | FILE *fp = NULL; 188 | 189 | if (path == NULL) { 190 | fprintf(stderr, "write_file: file name is null!\n"); 191 | return -1; 192 | } 193 | 194 | if (in == NULL) { 195 | fprintf(stderr, "write_file: input data is null!\n"); 196 | return -1; 197 | } 198 | 199 | fp = fopen(path, "wb"); 200 | if (fp == NULL) { 201 | perror("fopen"); 202 | return -2; 203 | } 204 | 205 | if (fwrite(in, 1, len, fp) != len) { 206 | fprintf(stderr, "write_file: imcomplete write!\n"); 207 | return -3; 208 | } 209 | return fclose(fp); 210 | } 211 | 212 | int main( int argc, char** argv ) 213 | { 214 | CURL *curl_handle; 215 | CURLcode res; 216 | char url[256]; 217 | RECV_BUF *p_shm_recv_buf; 218 | int shmid; 219 | int shm_size = sizeof_shm_recv_buf(BUF_SIZE); 220 | char fname[256]; 221 | pid_t pid =getpid(); 222 | pid_t cpid = 0; 223 | 224 | printf("shm_size = %d.\n", shm_size); 225 | shmid = shmget(IPC_PRIVATE, shm_size, IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR); 226 | if ( shmid == -1 ) { 227 | perror("shmget"); 228 | abort(); 229 | } 230 | 231 | p_shm_recv_buf = shmat(shmid, NULL, 0); 232 | shm_recv_buf_init(p_shm_recv_buf, BUF_SIZE); 233 | 234 | 235 | if (argc == 1) { 236 | strcpy(url, IMG_URL); 237 | } else { 238 | strcpy(url, argv[1]); 239 | } 240 | printf("%s: URL is %s\n", argv[0], url); 241 | 242 | cpid = fork(); 243 | 244 | if ( cpid == 0 ) { /* child proc download */ 245 | 246 | curl_global_init(CURL_GLOBAL_DEFAULT); 247 | 248 | /* init a curl session */ 249 | curl_handle = curl_easy_init(); 250 | 251 | if (curl_handle == NULL) { 252 | fprintf(stderr, "curl_easy_init: returned NULL\n"); 253 | return 1; 254 | } 255 | 256 | /* specify URL to get */ 257 | curl_easy_setopt(curl_handle, CURLOPT_URL, url); 258 | 259 | /* register write call back function to process received data */ 260 | curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, write_cb_curl); 261 | /* user defined data structure passed to the call back function */ 262 | curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)p_shm_recv_buf); 263 | 264 | /* register header call back function to process received header data */ 265 | curl_easy_setopt(curl_handle, CURLOPT_HEADERFUNCTION, header_cb_curl); 266 | /* user defined data structure passed to the call back function */ 267 | curl_easy_setopt(curl_handle, CURLOPT_HEADERDATA, (void *)p_shm_recv_buf); 268 | 269 | /* some servers requires a user-agent field */ 270 | curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0"); 271 | 272 | 273 | /* get it! */ 274 | res = curl_easy_perform(curl_handle); 275 | 276 | if( res != CURLE_OK) { 277 | fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); 278 | } else { 279 | printf("%lu bytes received in memory %p, seq=%d.\n", \ 280 | p_shm_recv_buf->size, p_shm_recv_buf->buf, p_shm_recv_buf->seq); 281 | 282 | } 283 | /* cleaning up */ 284 | curl_easy_cleanup(curl_handle); 285 | curl_global_cleanup(); 286 | shmdt(p_shm_recv_buf); 287 | } else if ( cpid > 0 ) { /* parent proc */ 288 | int state; 289 | waitpid(cpid, &state, 0); 290 | sprintf(fname, "./output_%d_%d.png", p_shm_recv_buf->seq, pid); 291 | write_file(fname, p_shm_recv_buf->buf, p_shm_recv_buf->size); 292 | shmdt(p_shm_recv_buf); 293 | shmctl(shmid, IPC_RMID, NULL); 294 | } else { 295 | perror("fork"); 296 | abort(); 297 | } 298 | 299 | 300 | return 0; 301 | } 302 | -------------------------------------------------------------------------------- /manual/lab5_aio.tex: -------------------------------------------------------------------------------- 1 | \chapter{Asynchronous I/O with cURL} 2 | 3 | \section{Objectives} 4 | The purpose of this lab is to design and implement a single-threaded web crawler. In the previous lab, we designed and implemented a multi-threaded concurrent web crawler by using blocking I/O with cURL in each thread. Another solution to making the program concurrent is to use non-blocking, asynchronous I/O. The cURL multi interface enables multiple simultaneous transfers in the same thread. 5 | 6 | 7 | After this lab, you will be able to 8 | \begin{itemize} 9 | \item design and implement a single-threaded concurrent program by using asynchronous I/O 10 | \item gain experience with the cURL multi-interface 11 | \end{itemize} 12 | 13 | \section{Starter Files} 14 | As with all the previous labs, the starter files are on GitHub. The lab5/starter directory contains the following sub-directories where we have example code to help you get started: 15 | 16 | \begin{itemize} 17 | \item \verb+curl_multi+ has example code to show how to use the curl multi interface API 18 | \item \verb+tools+ has a shell script to compute statistics from timing data 19 | \end{itemize} 20 | The file lab5\_eceubunt1.csv is the template that you will need for submitting timing results (see Section \ref{sec:lab5:postlab}). 21 | 22 | \section{Pre-lab Preparation} 23 | Build and run the starter code to see what it does. You should work through the provided starter code to understand how it works. 24 | Read the documentation on the curl multi interface at the following URLs: 25 | \begin{itemize} 26 | \item \url{https://curl.haxx.se/libcurl/c/libcurl-multi.html} 27 | \item \url{https://ec.haxx.se/libcurl-drive-multi.html} 28 | \end{itemize} 29 | 30 | \section{Lab Assignment} 31 | \subsection{Problem Statement} 32 | We are still solving the PNG URLs searching problem defined in lab4. Instead of creating a multi-threaded web crawler, we will create a single-threaded concurrent web crawler by using non-blocking I/O to enable simultaneous transfers. You will need to use the curl multi API. 33 | 34 | This time, the solution should {\em not} use pthreads. Instead, it should keep multiple concurrent connections to servers open. We will create a single-threaded web crawler named \verb+findpng3+ to search the web starting from a given seed URL and find all the URLs that link to PNG images. 35 | 36 | \subsection{The findpng3 command} 37 | The expected behaviour of the \verb+findpng3+ command is given in the following manual page. 38 | \subsubsection{Man page of findpng3} 39 | \label{sec:findpng3_manpage} 40 | \subsubsection*{NAME} 41 | \begin{itemize} 42 | \item[]{\bf findpng3} - search for PNG file URLs on the web using a single thread 43 | \end{itemize} 44 | \subsubsection*{SYNOPSIS} 45 | \begin{itemize} 46 | \item[]{\bf findpng3} [OPTION]... SEED\_URL 47 | \end{itemize} 48 | \subsubsection*{DESCRIPTION} 49 | \begin{itemize} 50 | \item[]Start from the SEED\_URL and search for PNG file URLs on the world wide web and write the search results to a plain text file named \code{png\_urls.txt} in the current working directory. Output the execution time in seconds to the standard output. 51 | \item[] {\bf -t}=NUM 52 | \begin{itemize} 53 | \item[] keep a maximum of NUM concurrent connections\footnote{There are two implementation options when you launch up to NUM transfer requests. One is to launch up to NUM transfer requests in a batch, wait for all of them to complete, and then move to the next group of requests. The other is immediate replacement of the individual handle. We recommend the second approach, but either one is fine.} to servers open when crawling the web. When this option is not specified, assumes a single connection. 54 | \end{itemize} 55 | \item[] {\bf -m}=NUM 56 | \begin{itemize} 57 | \item[] find up to NUM unique PNG URLs on the web. It is possible that the number of search results is less than NUM. When this option is not specified, assumes NUM=50. 58 | \end{itemize} 59 | \item[] {\bf -v}=LOGFILE 60 | \begin{itemize} 61 | \item[] log the URLs visited by the crawler, one URL per line in LOGFILE. 62 | \end{itemize} 63 | \end{itemize} 64 | \subsubsection*{OUTPUT FORMAT} 65 | \begin{itemize} 66 | \item[]The time to execute the program is written to the standard output. It will look like the following: 67 | \begin{verbatim} 68 | findpng3 execution time: S seconds 69 | \end{verbatim} 70 | The search result is a list of PNG URLs, one URL per line saved in a file named \code{png\_urls.txt}. The order of listing the search results is not specified. If the search result is empty, then create an empty search result file. 71 | \end{itemize} 72 | \subsubsection*{EXAMPLES} 73 | \begin{verbatim} 74 | findpng3 -t 10 -m 20 -v log.txt http://ece252-1.uwaterloo.ca/lab4 75 | \end{verbatim} 76 | \begin{itemize} 77 | \item[]Find up to 20 PNG URLs starting from \url{http://ece252-1.uwaterloo.ca/lab4} by keeping a maximum of 10 concurrent connections open to servers. 78 | The output on the standard output will look like the following: 79 | \begin{verbatim} 80 | findpng3 execution time: 10.123456 seconds 81 | \end{verbatim} 82 | The first two lines in the \code{png\_urls.txt} file might look like the following: 83 | \begin{verbatim} 84 | http://ece252-2.uwaterloo.ca:2540/img?q=tyfoighidfyseoid== 85 | http://ece252-1.uwaterloo.ca:2541/img?q=kjvjkjxsroutqpqkgh 86 | \end{verbatim} 87 | An empty search result will generate \code{an empty png\_urls.txt} file. 88 | 89 | The first two lines in the \code{log.txt} file may look like the following: 90 | \begin{verbatim} 91 | http://ece252-1.uwaterloo.ca/lab4 92 | http://ece252-1.uwaterloo.ca/~yqhuang/lab4/index.html 93 | \end{verbatim} 94 | \end{itemize} 95 | 96 | \iffalse 97 | \subsection{Bonus Features} 98 | \label{sec:findpng3_bonus} 99 | For each valid PNG image segment the lab server sends, it comes with a sequence number in the HTTP header (see \ref{sec:lab2_problem_statement}). You do not need this sequence number if you are only interested in searching valid PNG links. If you want to go a step further to concatenate the received valid PNG segments, then you will need their sequence numbers. Add an extra option of \code{-o=FILENAME} to the \code{findpng3} command to concatenate in memory all PNG image segments found in the order of their sequence numbers and output the concatenated image from memory to FILENAME. 100 | \subsubsection*{EXAMPLE} 101 | \begin{verbatim} 102 | findpng3 -t 10 -m 50 -v log.txt -o output.png \ 103 | http://ece252-1.uwaterloo.ca/lab4 104 | \end{verbatim} 105 | \begin{itemize} 106 | \item[]Find up to 50 PNG URLs starting from \url{http://ece252-1.uwaterloo.ca/lab4} by keeping maximum 10 concurrent connections open to servers. 107 | Concatenate the found image segments in the order of the sequence numbers and output the concatenated image to \code{output.png}. 108 | Output the search results to \code{png\_urls.txt} file, one url per line. Output all the visited URLs by the crawler to \code{log.txt} file, one url per line. The execution time (in seconds) of the program is output to the standard output. 109 | \end{itemize} 110 | 111 | 112 | \subsection{Programming Tips} 113 | You will need a number of lists to keep track of different sets of URLs. One list is for the URLs frontier, which contains to-be-visited URLs. One list is for recording all the URLs that have been visited. Another list is for the PNG URLs that have been found. To crawl the web using multiple threads, these lists are shared between threads. Hence you need to synchronize them. Some lists can only be accessed by one thread both when reading and writing. Some lists may be accessed by multiple threads when reading, but only one thread when writing. 114 | 115 | Another subtle difficulty is to know when to terminate the program. The program should terminate either when there are no more URLs in the URLs frontier or the user specified number of PNG URLs have been found. You may need some shared counters to keep track of information such as how many PNG URLs have been found and how many threads are waiting for a new URL. 116 | 117 | If an URL has been visited already, then we do not want to visit it again. So a search of visited-URLs list is needed. Hashing will make the search very effective and you may consider using a hash table to represent this already-visited list. The glibc has hash table API (\code{man hsearch(3)}). 118 | \fi 119 | \section{Deliverables} 120 | \subsection{Pre-lab Deliverables} 121 | There is no pre-lab deliverable for this lab. 122 | 123 | \subsection{Post-lab Deliverables} 124 | \label{sec:lab5:postlab} 125 | Put the following items under a directory named lab5: 126 | \begin{enumerate} 127 | \item All the source code and a Makefile. The Makefile default target is the \verb+findpng3+ executable file. That is, the command \verb+make+ should generate the \verb+findpng3+ executable file. We also expect that the command \verb+make clean+ will remove the object code and the default target. That is, the \verb+.o+ files and the executable file should be removed. 128 | \item A timing result .csv file named lab5\_hostname.csv 129 | which contains the timing results by running the findpng3 on a server whose name is hostname. For example, \verb+lab5_eceubuntu1.csv+ means findpng3 was executed on the server eceubuntu1 and the file contains the timing results. 130 | The first line of the file is the header of the timing result table. The rest of the rows are the command line argument values and the timing results. The columns of the .csv file from left to right are the values of $T$ (the number of threads), $M$ (the number of unique PNG links to search for) and $TIME$ (the corresponding findpng3 average execution time). We have an example .csv file in the starter code folder named \verb+lab5_eceubuntu1.csv+ for illustration purpose. 131 | 132 | Run your findpng3 command on eceubuntu1. Record the average timing measurement data for the $(T, M)$ values shown in Table \ref{tb_timing_lab5} for a particular host. Note that for each given $(T, M)$ value in the table, you need to run the program $n$ times and compute the average time. We recommend $n=5$. 133 | \begin{table}[h] 134 | \begin{center} 135 | \begin{tabular}{|c|c|c|} 136 | \hline 137 | T & M & Time \\ \hline 138 | 139 | 1 & 1 & \\ \hline 140 | 1 & 10 & \\ \hline 141 | 1 & 20 & \\ \hline 142 | 1 & 30 & \\ \hline 143 | 1 & 40 & \\ \hline 144 | 1 & 50 & \\ \hline 145 | 1 & 100 & \\ \hline 146 | 10 & 1 & \\ \hline 147 | 10 & 10 & \\ \hline 148 | 10 & 20 & \\ \hline 149 | 10 & 30 & \\ \hline 150 | 10 & 40 & \\ \hline 151 | 10 & 50 & \\ \hline 152 | 10 & 100 & \\ \hline 153 | 20 & 1 & \\ \hline 154 | 20 & 10 & \\ \hline 155 | 20 & 20 & \\ \hline 156 | 20 & 30 & \\ \hline 157 | 20 & 40 & \\ \hline 158 | 20 & 50 & \\ \hline 159 | 20 & 100 & \\ \hline 160 | 161 | \end{tabular} 162 | \caption{Timing measurement data table for given $(T, M)$ values.} 163 | \label{tb_timing_lab5} 164 | \end{center} 165 | \end{table} 166 | \end{enumerate} 167 | Use the \verb+zip+ command to archive and compress the contents of the lab5 directory and name it \verb+lab5.zip+. We expect that the command \verb+unzip lab5.zip+ will produce a \verb+lab5+ sub-directory in the current working directory and under the \verb+lab5+ sub-directory we will find your source code, the Makefile and the lab5\_hostname.csv file. 168 | 169 | \section{Marking Rubric} 170 | The Rubric for marking is listed in Table \ref{tb_lab5_aio_rubric}. 171 | 172 | \begin{table}[ht] 173 | \begin{center} 174 | \begin{tabular}{|p{4cm}|p{10cm}|} 175 | \hline 176 | Points & Description \\ \hline 177 | 10 & Makefile correctly builds and cleans \verb+findpng3+\\ \hline 178 | 65 & Implementation of \verb+findpng3+ in Section \ref{sec:findpng3_manpage} \\ \hline 179 | 25 & Correct timing results in lab5\_hostname.csv file\\ \hline 180 | % \hline 181 | % Bonus Points & \\ \hline 182 | %50 & Implementation of the bonus feature in Section \ref{sec:findpng3_bonus} \\ \hline 183 | \end{tabular} 184 | \caption{Lab5 Marking Rubric} 185 | \label{tb_lab5_aio_rubric} 186 | \end{center} 187 | \end{table} 188 | 189 | %%% Local Variables: 190 | %%% mode: latex 191 | %%% TeX-master: "main_book" 192 | %%% End: 193 | -------------------------------------------------------------------------------- /manual/p1_policy.tex: -------------------------------------------------------------------------------- 1 | \chapter*{Lab Administration Policy } 2 | 3 | \section*{Group Lab Policy} 4 | 5 | \begin{itemize} 6 | \item {\bf Group Size.} All labs are done in groups of {\em two}. 7 | A size of three is only considered in a lab section that has 8 | an odd number of students, and only one group is allowed to have 9 | a size of three. All group of three requests are processed on 10 | a first-come, first-served basis. 11 | A group size of one is not permitted except if your group 12 | splits up. There is no workload reduction if you do 13 | the labs individually. 14 | Everyone in the group normally gets the same mark. 15 | The Learn system (\verb+http://learn.uwaterloo.ca+) 16 | is used to sign up for groups. 17 | %The Course Book System at URL\\ 18 | %\verb+ https://ecewo32.uwaterloo.ca/cgi-bin/WebObjects/CourseBook+\\ 19 | %is used to signup for groups and reserve lab demo times. 20 | {\em The lab group signup is due by 10:00pm on the Second Friday of 21 | the academic term}. Late group sign-up is not accepted and will 22 | result in losing the entire lab sign-up mark, which is \verb+2%+ 23 | of the total lab grade. Grace days do not apply to Group Signup. 24 | 25 | \item {\bf Group Split-up.} 26 | If you notice a workload imbalance in your group, try to solve it as soon as possible 27 | within your group. As a last resort, you can split up your group. 28 | Group split-up is only allowed once. You are allowed to join a one member group 29 | after the split-up. You are not allowed to split up the newly formed group. 30 | There is a one grace day deduction penalty to be applied to each member of the old group. 31 | A copy of the code and documentation that was completed before the group split-up 32 | will be given to each individual in the group. 33 | We highly recommend that everyone stays with their groups as much as possible, 34 | since the ability to do work as a team will be an important skill in your future career. 35 | Please choose your lab partners carefully. 36 | 37 | \item {\bf Group Split-up Deadline.} 38 | To split up your group starting from a particular lab, 39 | you need to notify the lab instructor in writing and 40 | sign the group split-up form (see Appendix). 41 | For Lab{\em n} ({\em n=1,2,3,4,5}), the group split-up form needs to 42 | be submitted to the lab instructor by 4:30pm on Thursday in the week that Lab{\em n} has 43 | scheduled lab sessions. 44 | If you are late to submit the split-up form, 45 | then you need to finish Lab{\em n} as a group and submit 46 | your split-up form during the week where Lab({\em n+1}) 47 | has scheduled sessions and split starting from Lab({\em n+1}). 48 | \end{itemize} 49 | 50 | \begin{table} 51 | \begin{center} 52 | \begin{tabular}{|p{4cm}|l|l|l|} 53 | \hline 54 | Deliverable & Weight & Lab Session Week & Post-Lab Deliverable Deadline \\ \hline 55 | Group Sign-up & \verb+2%+ & N/A & 22:00 Friday in Week 2 \\ \hline 56 | % % % % % The following is for Spring term 57 | LAB 1 & \verb+18%+ & Week 3 & 22:00 2 days after the lab session \\ \hline 58 | LAB 2 & \verb+20%+ & Week 5 & 22:00 2 days after the lab session \\ \hline 59 | LAB 3 & \verb+20%+ & Weeks 8 & 22:00 Sunday after the lab session \\ \hline 60 | LAB 4 & \verb+20%+ & Week 10 & 22:00 Sunday after the lab session \\ \hline 61 | LAB 5 & \verb+20%+ & Week 12 & 22:00 Sunday after the lab session \\ \hline 62 | % % % % % The following is for Fall term that starts on a Thursday!!!! 63 | %LAB1 & \verb+8%+ & Week 0 and 1 & 10:00pm Wednesday in Week 2 \\ \hline 64 | %LAB2 & \verb+30%+ & Weeks 2, 3, 4 and 5 & 10:00pm Wednesday in Week 6 \\ \hline 65 | %LAB3 & \verb+30%+ & Weeks 7 and 9 & 10:00pm Wednesday in Week 10 \\ \hline 66 | %LAB4 & \verb+30%+ & Week 11 & 10:00pm Wednesday in Week 12 \\ \hline 67 | %%LAB5 & \verb+30%+ & Week 11 & 10:00pm Tuesday in Week 12 \\ \hline 68 | %Deliverable & Weight & Due Date & File Name \\ \hline 69 | %Group Sign-up & & 04:30pm May. 09th & \\ \hline 70 | %LAB1 & \verb+2%+ & 11:59pm May. 13th & LAB1\_Gid.zip \\ \hline 71 | %LAB2 & \verb+2%+ & 11:59pm May. 27th & LAB2\_Gid.zip \\ \hline 72 | %LAB3 & \verb+6%+ & 11:59pm Jun. 26th & LAB3\_Gid.zip \\ \hline 73 | %LAB4 & \verb+4%+ & 11:59pm Jul. 08th & LAB4\_Gid.zip \\ \hline 74 | %LAB5 & \verb+6%+ & 11:59pm Jul. 22nd & LAB5\_Gid.zip \\ \hline 75 | \end{tabular} 76 | \caption{Project Deliverable Weight of the Lab Grade, Scheduled Lab Sessions and Deadlines.} 77 | \label{tb_deadline} 78 | \end{center} 79 | \end{table} 80 | \section*{Lab Assignments Grading and Deadline Policy} 81 | Labs are graded by lab TAs based on the rubric listed in each lab. The weight of each lab towards your final lab grade is listed in Table \ref{tb_deadline}. 82 | 83 | \begin{itemize} 84 | \item {\bf Lab Assignment Preparation and Due Dates.} 85 | Students are required to prepare for the lab well 86 | before they come to the schedule lab session. 87 | {\em Pre-lab deliverables for each lab are due by the scheduled lab session starting time}. 88 | During the scheduled lab session, we either provide 89 | in-lab help or conduct lab assignment evaluation 90 | or do both at the same time. 91 | 92 | %Post-lab deliverables are normally due on Wednesdays in the week after the scheduled lab session. 93 | The detailed deadlines of post-lab deliverables 94 | are displayed in Table \ref{tb_deadline}. Note that the reading/study week is not counted as a week in the table. 95 | %Please note that different lab sections have different deadlines. 96 | 97 | %Table \ref{tb_deadline} lists the Post-lab deliverable deadlines. 98 | %{\em Please be advised that lab sessions during the midterm week 99 | % are cancelled.} 100 | \item {\bf Lab Assignment Late Submissions.} 101 | Late submission is accepted within five days after the deadline of the lab. 102 | No late submission is accepted five days after the lab deadline. 103 | There are five grace days \footnote{Grace days are calendar days. Days in weekends are counted.} 104 | that can be used for some post-lab deliverables late submissions 105 | \footnote{A post-lab deliverable that does not accept a late submission 106 | will be clearly identified in the lab assignment description. 107 | Labs whose evaluation requires demonstrations do not accept late submissions 108 | of the code.}. 109 | A group split-up will consume one grace day. 110 | After all grace days are consumed, a \verb+10%+ per day late submission penalty will be applied. 111 | However, if it is five days after the lab deadline, no submission is accepted. 112 | %automatically get a grade of zero. 113 | 114 | %You will get a bonus mark of {\em N\%}of your entire lab mark, 115 | %where {\em N} is the number of grace days you do not use. 116 | %When you use up all your grace days, 117 | %a 10\% per day late penalty will be applied to a late submission. 118 | %Please be advised that to simplify the book-keeping, 119 | %late submission is counted in a unit of day rather than hour or minute. 120 | %An hour late submission is one day late, 121 | %so does a fifteen hour late submission. 122 | \item {\bf Lab Re-grading.} 123 | To initiate a re-grading process, contact the grading TA in charge first. The re-grading is a rigid process. The entire lab will be re-graded. Your new grades may be lower, unchanged or higher than the original grade received. If you are still not satisfied with the grades received after the re-grading, escalate your case to the lab instructor to request a review and the lab instructor will finalize the case. 124 | \end{itemize} 125 | \section*{Lab Repeating Policy} 126 | For a student who repeats the course, labs need to be re-done with a new lab partner. 127 | Simply turning in the old lab code is not allowed. 128 | We understand that the student may choose a similar route to the solution chosen last time 129 | the course was taken. However it should not be identical. Since the lab is being done for the second time, 130 | we expect that the student will improve upon the older solution. Also the new lab partner should be 131 | contributing equally, which will also lead to differences in the solutions. 132 | 133 | Note that the policy is course specific, and at the discretion of the course instructor and the lab instructor. 134 | 135 | \section*{Lab Assignments Solution Internet Policy} 136 | It is not permitted to post your lab assignment solution source code or lab report on the internet freely for the public to access. For example, it is not acceptable to host a public repository on GitHub that contains your lab assignment solutions. A warning with instructions to take the lab assignment solutions off the internet will be sent out upon the first offence. If no action is taken by the offender within twenty-four hours, then a lab grade of zero will automatically be assigned to the offender. 137 | 138 | \section*{Seeking Help Outside Scheduled Lab Hours} 139 | \begin{itemize} 140 | \item{\bf Discussion Forum.} 141 | We recommend that students use the Piazza discussion forum to ask the teaching team questions instead of sending individual emails to the teaching staff. 142 | For questions related to the current lab project, our target response time is one business day 143 | \footnote{Our past experiences show that the number of questions spike when deadline is close.The teaching staff will not be able to guarantee one business day response time when workload is above average, though we always try our best to provide a timely response.}. 144 | {\em There is no guarantee on the response time to questions about labs other than the current one}. 145 | \item{\bf Office Hours.} 146 | The Learn system calendar gives the office hour details. 147 | \item{\bf Appointments.} 148 | Students can also make appointments with the lab teaching staff if their problems are not resolved by the discussion forum or during office hours. The appointment booking is by email. 149 | 150 | To make the appointment efficient and effective, when requesting an appointment, 151 | please specify three preferred times and roughly how long 152 | the appointment needs to be. On average, an appointment is fifteen minutes per project group. 153 | In your email that requests the appointment, please also summarize the main questions to be asked. 154 | If a question requires teaching staff to look at a code fragment, please bring a laptop with the necessary development software installed. 155 | 156 | Please note that teaching staff will not debug a student's program for them. Debugging is part of the exercise of completing a programming assignment. Teaching staff will be able to demonstrate how to use the debugger and provide case-specific debugging tips. Teaching staff will not give a direct solution to a lab assignment. Guidances and hints will be provided to help students to find the solution by themselves. 157 | 158 | \end{itemize} 159 | %\begin{table} 160 | %\begin{center} 161 | %\begin{tabular}{|l|l|p{5cm}|l|} 162 | %\hline 163 | %Time (even weeks only) & Location & Name & email ID \\ \hline 164 | %TBA & DC-2631 & Yiqing (Irene) Huang & yqhuang\\ \hline 165 | %TBA & E5-5122 & Anas Abognah & aabognah \\ \hline 166 | %TBA 10:30-11:30 & E5-4121 & Jean-Christophe Petkovich & j2petkovich\\ \hline 167 | %\end{tabular} 168 | %\caption{Bi-weekly Office Hour Schedule} 169 | %\label{tb_office_hour} 170 | %\end{center} 171 | %\end{table} 172 | 173 | \section*{Lab Facility After Hours Access Policy} 174 | After hour access to the lab will be given to the class 175 | when we start to use the Keil boards in lab. 176 | However, please be advised that after hours access is a privilege. 177 | Students are required to keep the lab equipment and furniture 178 | in good condition in order to maintain this privilege. 179 | 180 | No food or drink is allowed in the lab. 181 | Please be aware that you may be sharing the lab with other classes. 182 | When resources become too tight, cooperation is required 183 | such as taking turns using the stations in the lab. 184 | 185 | %%% Local Variables: 186 | %%% mode: latex 187 | %%% TeX-master: "main_book" 188 | %%% End: 189 | --------------------------------------------------------------------------------