├── README.md ├── bomblab ├── ans.txt ├── ans.txt.save ├── bomb ├── bomb.asm ├── bomb.c └── report.pdf ├── coroutine_lab ├── Makefile ├── README.md ├── REPORT.md ├── bin │ └── .gitignore ├── handout │ └── REPORT.md ├── img │ ├── 1.jpg │ └── 2.jpg ├── inc │ ├── common.h │ ├── context.h │ └── coroutine_pool.h ├── lib │ └── context.S └── src │ ├── binary_search.cpp │ ├── sample.cpp │ └── sleep_sort.cpp └── malloclab ├── Makefile ├── README ├── clock.c ├── clock.h ├── clock.o ├── config.h ├── fcyc.c ├── fcyc.h ├── fcyc.o ├── fsecs.c ├── fsecs.h ├── fsecs.o ├── ftimer.c ├── ftimer.h ├── ftimer.o ├── mdriver ├── mdriver.c ├── mdriver.o ├── memlib.c ├── memlib.h ├── memlib.o ├── mm.c ├── mm.h ├── mm.o ├── report.md ├── report.pdf ├── short1-bal.rep ├── short2-bal.rep └── traces ├── Makefile ├── README ├── amptjp-bal.rep ├── amptjp.rep ├── binary-bal.rep ├── binary.rep ├── binary2-bal.rep ├── binary2.rep ├── cccp-bal.rep ├── cccp.rep ├── checktrace.pl ├── clang-bal.rep ├── clang.rep ├── coalescing-bal.rep ├── coalescing.rep ├── cp-decl-bal.rep ├── cp-decl.rep ├── curl-bal.rep ├── curl.rep ├── expr-bal.rep ├── expr.rep ├── gcc-bal.rep ├── gcc.rep ├── gen_binary.pl ├── gen_binary2.pl ├── gen_coalescing.pl ├── gen_random.pl ├── gen_realloc.pl ├── gen_realloc2.pl ├── python3-bal.rep ├── python3.rep ├── random-bal.rep ├── random.rep ├── random2-bal.rep ├── random2.rep ├── realloc-bal.rep ├── realloc.rep ├── realloc2-bal.rep ├── realloc2.rep ├── short1-bal.rep ├── short1.rep ├── short2-bal.rep └── short2.rep /README.md: -------------------------------------------------------------------------------- 1 | # ICS-2023 2 | 3 | 本仓库为清华大学2023秋《计算机系统概论》课程的全部实验。 4 | -------------------------------------------------------------------------------- /bomblab/ans.txt: -------------------------------------------------------------------------------- 1 | Wow! Brazil is big. 2 | 1 2 4 7 11 16 3 | 5 692 4 | 5 2 5 | jdoefg 6 | 5 3 6 2 1 4 7 | -------------------------------------------------------------------------------- /bomblab/ans.txt.save: -------------------------------------------------------------------------------- 1 | Wow! Brazil is big. 2 | 1 2 4 7 11 16 3 | 5 692 4 | 5 2 5 | jdoefg 2 3 4 5 6 6 | -------------------------------------------------------------------------------- /bomblab/bomb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangchi2004/ICS-2023/a968e20339250ec42b46a271d7bd471b70493689/bomblab/bomb -------------------------------------------------------------------------------- /bomblab/bomb.c: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Dr. Evil's Insidious Bomb, Version 1.1 3 | * Copyright 2011, Dr. Evil Incorporated. All rights reserved. 4 | * 5 | * LICENSE: 6 | * 7 | * Dr. Evil Incorporated (the PERPETRATOR) hereby grants you (the 8 | * VICTIM) explicit permission to use this bomb (the BOMB). This is a 9 | * time limited license, which expires on the death of the VICTIM. 10 | * The PERPETRATOR takes no responsibility for damage, frustration, 11 | * insanity, bug-eyes, carpal-tunnel syndrome, loss of sleep, or other 12 | * harm to the VICTIM. Unless the PERPETRATOR wants to take credit, 13 | * that is. The VICTIM may not distribute this bomb source code to 14 | * any enemies of the PERPETRATOR. No VICTIM may debug, 15 | * reverse-engineer, run "strings" on, decompile, decrypt, or use any 16 | * other technique to gain knowledge of and defuse the BOMB. BOMB 17 | * proof clothing may not be worn when handling this program. The 18 | * PERPETRATOR will not apologize for the PERPETRATOR's poor sense of 19 | * humor. This license is null and void where the BOMB is prohibited 20 | * by law. 21 | ***************************************************************************/ 22 | 23 | #include 24 | #include 25 | #include "support.h" 26 | #include "phases.h" 27 | 28 | /* 29 | * Note to self: Remember to erase this file so my victims will have no 30 | * idea what is going on, and so they will all blow up in a 31 | * spectaculary fiendish explosion. -- Dr. Evil 32 | */ 33 | 34 | FILE *infile; 35 | 36 | int main(int argc, char *argv[]) 37 | { 38 | char *input; 39 | 40 | /* Note to self: remember to port this bomb to Windows and put a 41 | * fantastic GUI on it. */ 42 | 43 | /* When run with no arguments, the bomb reads its input lines 44 | * from standard input. */ 45 | if (argc == 1) { 46 | infile = stdin; 47 | } 48 | 49 | /* When run with one argument , the bomb reads from 50 | * until EOF, and then switches to standard input. Thus, as you 51 | * defuse each phase, you can add its defusing string to and 52 | * avoid having to retype it. */ 53 | else if (argc == 2) { 54 | if (!(infile = fopen(argv[1], "r"))) { 55 | printf("%s: Error: Couldn't open %s\n", argv[0], argv[1]); 56 | exit(8); 57 | } 58 | } 59 | 60 | /* You can't call the bomb with more than 1 command line argument. */ 61 | else { 62 | printf("Usage: %s []\n", argv[0]); 63 | exit(8); 64 | } 65 | 66 | /* Do all sorts of secret stuff that makes the bomb harder to defuse. */ 67 | initialize_bomb(); 68 | 69 | printf("Welcome to my fiendish little bomb. You have 6 phases with\n"); 70 | printf("which to blow yourself up. Have a nice day!\n"); 71 | 72 | /* Hmm... Six phases must be more secure than one phase! */ 73 | input = read_line(); /* Get input */ 74 | phase_1(input); /* Run the phase */ 75 | phase_defused(); /* Drat! They figured it out! 76 | * Let me know how they did it. */ 77 | printf("Phase 1 defused. How about the next one?\n"); 78 | 79 | /* The second phase is harder. No one will ever figure out 80 | * how to defuse this... */ 81 | input = read_line(); 82 | phase_2(input); 83 | phase_defused(); 84 | printf("That's number 2. Keep going!\n"); 85 | 86 | /* I guess this is too easy so far. Some more complex code will 87 | * confuse people. */ 88 | input = read_line(); 89 | phase_3(input); 90 | phase_defused(); 91 | printf("Halfway there!\n"); 92 | 93 | /* Oh yeah? Well, how good is your math? Try on this saucy problem! */ 94 | input = read_line(); 95 | phase_4(input); 96 | phase_defused(); 97 | printf("So you got that one. Try this one.\n"); 98 | 99 | /* Round and 'round in memory we go, where we stop, the bomb blows! */ 100 | input = read_line(); 101 | phase_5(input); 102 | phase_defused(); 103 | printf("Good work! On to the next...\n"); 104 | 105 | /* This phase will never be used, since no one will get past the 106 | * earlier ones. But just in case, make this one extra hard. */ 107 | input = read_line(); 108 | phase_6(input); 109 | phase_defused(); 110 | 111 | /* Wow, they got it! But isn't something... missing? Perhaps 112 | * something they overlooked? Mua ha ha ha ha! */ 113 | 114 | return 0; 115 | } 116 | -------------------------------------------------------------------------------- /bomblab/report.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangchi2004/ICS-2023/a968e20339250ec42b46a271d7bd471b70493689/bomblab/report.pdf -------------------------------------------------------------------------------- /coroutine_lab/Makefile: -------------------------------------------------------------------------------- 1 | HEADERS=$(wildcard inc/*.h) 2 | TARGETS=bin/sample bin/sleep_sort bin/binary_search 3 | 4 | FLAGS=-O2 -g -Iinc -pthread 5 | 6 | all: ${TARGETS} 7 | 8 | bin/%: src/%.cpp lib/context.S ${HEADERS} 9 | g++ --std=c++17 -fno-omit-frame-pointer $< lib/context.S ${FLAGS} -o $@ 10 | 11 | clean: 12 | rm -rf ${TARGETS} 13 | -------------------------------------------------------------------------------- /coroutine_lab/README.md: -------------------------------------------------------------------------------- 1 | # 计算机系统概论 2022 秋 协程实验 2 | 3 | 在本实验中,同学们将亲手借助汇编/内嵌汇编的方式,在熟悉 x86_64 系统架构的前提下,完成一个简单的用户态的有栈协程库,并利用协程库进行睡眠排序(sleep_sort)的编写以及二分查找的优化。 4 | 5 | 本次实验共分为三个子任务,同学需要依次完成三个子任务并编写实验报告。 6 | 7 | 三个子任务如下: 8 | 9 | 1. 完成协程库的编写,并通过基础测试。 10 | 2. 向协程库添加 sleep 函数,并能够通过 sleep_sort 测试。 11 | 3. 使用协程库对二分查找进行优化,并报告优化结果。 12 | 13 | 你需要在 REPORT.md 文件中以 Markdown 格式编写实验报告,然后把整个目录压缩成 zip 格式再提交到网络学堂。 14 | 15 | ## 环境配置 16 | 17 | 本实验的运行环境是 x86_64 Linux。你可以在课程提供的远程 Linux 服务器上完成本实验。 18 | 19 | 编译的时候需要 GCC 和 Make。在根目录下运行 `make` 即可编译,生成的二进制在 `bin` 目录下。 20 | 21 | ## 作业提交方式 22 | 23 | 1. 请在网络学堂上提交markdown格式的实验报告`REPORT.md` 24 | 25 | 2. 请将完成的代码框架上传至服务器指定位置。请按照以下操作进行**顺序**操作,*你也可以先行对实验框架进行如下操作并在服务器上完成所有的实验。* 26 | 27 | 1. 首先登陆服务器创建作业文件夹。 28 | 29 | 请在**服务器用户根目录**下执行以下操作: 30 | 31 | ```bash 32 | mkdir -p coroutine_lab 33 | ``` 34 | 35 | 2. 将实验完成的代码上传至服务器 36 | 37 | 请在你完成的**实验代码目录下**,执行以下操作 38 | 39 | ```bash 40 | scp -P 22222 -r * ics-2023000000@166.111.68.163:~/coroutine_lab/ 41 | (将2023000000替换为你自己的学号) 42 | 例如你的作业完成时文件结构如下: 43 | 44 | - base_file 45 | - ... 46 | - handout 47 | - src 48 | - bin 49 | - inc 50 | - makefile 51 | - ... 52 | 53 | 请在handout目录下执行以上命令。 54 | ``` 55 | 56 | 3. 修改文件权限以便助教检查: 57 | 58 | 请在**服务器用户根目录**下执行以下操作 59 | 60 | ```bash 61 | chmod -R 750 coroutine_lab 62 | ``` 63 | 64 |         4. 检查代码能否在服务器环境下正常的编译与运行。 65 | 66 | ## Task 1: 协程库的编写 67 | 68 | 你需要认真阅读框架代码并以及代码中的注释并完成标有 `TODO: Task 1` 字样的函数的编写。 69 | 70 | 我们建议分为两个小步骤来实现这一部分: 71 | 72 | 1. 实现 `coroutine_pool::serial_execute_all` 函数中启动协程的部分以及 `context.S` 中切换协程的汇编代码。完成这两部分之后可以自己实现一个不带 yield 的“协程库”。在此基础上可以进行一个简单的测试以检查协程栈是否正常分配在堆上,协程返回的时候是否正常等。 73 | 2. 实现 `yield` 以及完善 `coroutine_pool::serial_execute_all`。完成协程的 yield 以及 resume 和重新调用。 74 | 75 | 关于这一部分的实现细节在代码注释中有比较详细的内容,如果你认为实现有困难可以参考代码中给出的注释提示。 76 | 77 | 实验报告的额外要求: 78 | 79 | 1. 绘制出在协程切换时,栈的变化过程; 80 | 2. 并结合源代码,解释协程是如何开始执行的,包括 `coroutine_entry` 和 `coroutine_main` 函数以及初始的协程状态; 81 | 3. 目前的协程切换代码只考虑了通用寄存器,设计一下,如果要考虑浮点和向量寄存器,要怎么处理。 82 | 83 | 完成 Task 1 以后,应该可以正常运行 `bin/sample` 程序,并得到下面的输出: 84 | 85 | ``` 86 | in show(): 0 87 | in show(): 0 88 | in show(): 1 89 | in show(): 1 90 | in show(): 2 91 | in show(): 2 92 | in show(): 3 93 | in show(): 3 94 | in show(): 4 95 | in show(): 4 96 | in main(): 0 97 | in main(): 0 98 | in main(): 1 99 | in main(): 1 100 | in main(): 2 101 | in main(): 2 102 | in main(): 3 103 | in main(): 3 104 | in main(): 4 105 | in main(): 4 106 | ``` 107 | 108 | ## Task 2: 实现 sleep 函数 109 | 110 | 在协程中,不能使用操作系统提供的 sleep 函数,因为它会阻塞整个线程,但希望的效果是切换到其他协程,等到 sleep 时间结束后,再继续执行协程。 111 | 112 | 因此,协程库也会提供一个 sleep 函数,它的实现方法是,标记当前协程 `ready = false`,并注册一个 `ready_func`,它会检查当前的时间,是否已经超过了应该继续执行的时间,然后进行 `yield`。那么,`coroutine_pool::serial_execute_all` 就需要判断协程的当前状态,如果它 `ready == true`,说明可以继续执行;如果它 `ready == false`,则调用 `ready_func`,如果返回 `true`,说明可以继续执行了,就设置 `ready = true` 并切换到协程。 113 | 114 | 你需要实现 `sleep` 函数,具体定义可以参照代码注释,并修改 `coroutine_pool::serial_execute_all`,实现对 `ready` 的判断。并完成 sleep_sort 的测试。 115 | 116 | **提示**: 你可以使用 `parallel_execute_all` 与 `serial_execute_all` 进行对比。 117 | 118 | 实验报告的额外要求: 119 | 120 | 1. 按照时间线,绘制出 `sleep_sort` 中不同协程的运行情况; 121 | 2. 目前的协程库实现方式是轮询 `ready_func` 是否等于 `true`,设计一下,能否有更加高效的方法。 122 | 123 | 完成 Task 2 以后,应该可以正常运行 `bin/sleep_sort` 程序,可以输入一组数,程序会从小到大输出排序后的数。下面是输入 1, 3, 4, 5, 2 的例子: 124 | 125 | ``` 126 | $ ./bin/sleep_sort 127 | 5 128 | 1 3 4 5 2 129 | 1 130 | 2 131 | 3 132 | 4 133 | 5 134 | ``` 135 | 136 | ## Task 3: 利用协程优化二分查找 137 | 138 | 在数据量比较大的时候,二分查找会产生大量的缓存缺失,而从内存读取数据到 CPU 需要花费几百个 CPU 周期。因此,可以利用协程来优化二分查找。优化方法是,修改二分查找中容易产生缓存缺失的代码,改为先使用预取指令,让 CPU 异步地读取数据,紧接着调用 `yield` 来切换到其他协程。当多次切换后返回到刚才使用预取指令的协程的时候,CPU 已经把数据读取到了缓存中,此时就节省了很多时间。 139 | 140 | 你需要修改 `lookup_coroutine` 函数,插入代码,来实现上面所述的优化算法,并在实验报告中汇报性能的提升效果。你可以通过命令行参数设置不同的参数,观察不同参数下的性能。 141 | 142 | 实验报告的额外要求: 143 | 144 | 1. 汇报性能的提升效果。 145 | 146 | 可以参考下列文献: 147 | 148 | Georgios Psaropoulos, Thomas Legler, Norman May, and Anastasia Ailamaki. 2017. Interleaving with coroutines: a practical approach for robust index joins. Proc. VLDB Endow. 11, 2 (October 2017), 230–242. https://doi.org/10.14778/3149193.3149202 149 | 150 | ## 实验报告 151 | 152 | 你需要在 REPORT.md 文件中以 Markdown 格式编写实验报告,内容包括: 153 | 154 | 1. 姓名,学号和班级; 155 | 2. 三个小节,分别记录你为了实现三个子任务所添加到代码,并对代码进行详细的注释;每个子任务都有实验报告的额外要求,请阅读上面的文本; 156 | 3. 记录你在完成本实验的过程中,与哪些同学进行了交流,查阅了哪些网站或者代码; 157 | 4. 总结和感想。 -------------------------------------------------------------------------------- /coroutine_lab/REPORT.md: -------------------------------------------------------------------------------- 1 | # 协程实验 2 | > 张驰 2022010754 zhang-ch22@mails.tsinghua.edu.cn 3 | 4 | ## Task1 5 | **1. 添加的代码** 6 | `context.h`: 7 | ```cpp 8 | // virtual void resume() 9 | coroutine_switch(caller_registers, callee_registers); // 把当前的寄存器状态保存到caller_registers中,然后切换到callee_registers的运行状态。即存下调用者的当前状态,然后启动协程。 10 | ``` 11 | 12 | `coroutine_pool.h`: 13 | ```cpp 14 | // void serial_execute_all() 15 | while(true){ // 不断循环直到所有协程全都结束 16 | int finish_num=0; // 记录本次循环结束的协程的数量 17 | for(context_id=0;context_idfinished) finish_num++; // 若当前协程已结束,记录到finish_num中 19 | else coroutines[context_id]->resume(); // 否则切换到该协程 20 | } 21 | if(finish_num==coroutines.size()) break; // 所有协程全都结束,退出循环 22 | } 23 | ``` 24 | 25 | `common.h`: 26 | ```cpp 27 | // void yield() 28 | coroutine_switch(context->callee_registers, context->caller_registers); // 把当前的寄存器状态保存到callee_registers中,然后切换到caller_registers的运行状态。即存下协程当前状态,然后回到调用者的运行。 29 | ``` 30 | 31 | `context.S`: 32 | ```S 33 | # .coroutine_entry 34 | movq %rsp, 64(%rdi) # 把当前状态的 callee-saved 寄存器存储到 %rdi 指向的上下文对应的位置 35 | movq %rbx, 72(%rdi) 36 | movq %rbp, 80(%rdi) 37 | movq %r12, 88(%rdi) 38 | movq %r13, 96(%rdi) 39 | movq %r14, 104(%rdi) 40 | movq %r15, 112(%rdi) 41 | leaq .coroutine_ret(%rip), %rax 42 | movq %rax, 120(%rdi) # 把返回地址存储到 %rdi 指向的上下文(RIP对应的位置) 43 | movq $0, %rax # 恢复 %rax 的值 44 | 45 | movq 64(%rsi), %rsp 46 | movq 72(%rsi), %rbx 47 | movq 80(%rsi), %rbp 48 | movq 88(%rsi), %r12 49 | movq 96(%rsi), %r13 50 | movq 104(%rsi), %r14 51 | movq 112(%rsi), %r15 # 把 %rsi 指向的上下文的 callee-saved 寄存器的值恢复到寄存器中 52 | jmp *120(%rsi) # 跳转回到 %rsi 指向的上下文存储的返回地址 53 | ``` 54 | 55 | 56 | **2. 在协程切换时栈的变化过程:** 57 | 58 | ![1](img/1.jpg) 59 | 60 | **3. 协程如何开始执行:** 61 | 62 | 每一个协程都用一个 `coroutine_context` 结构来存储,通过使用基类指针 `basic_context * = new coroutine_context(f, args...)` 来开辟在堆上。每一个协程类里,存放着表示该协程当前运行状态的 `callee_registers` 和表示调用协程时调用者的运行状态的 `caller_registers`。同时还存放了协程要执行的函数 `f` 和参数 `args...`。 63 | ```cpp 64 | // struct basic_context 65 | uint64_t *stack; 66 | uint64_t stack_size; 67 | uint64_t caller_registers[(int)Registers::RegisterCount]; 68 | uint64_t callee_registers[(int)Registers::RegisterCount]; 69 | 70 | //struct coroutine_context : public basic_context 71 | F f; 72 | std::tuple args; 73 | ``` 74 | 75 | 在构造函数中,协程用 `stack` 指针在堆上创建一片空间,用来模拟协程的内存,并用 `rsp` 存储16位对齐后的栈顶地址。同时,协程`caller_registers` 中的 `RSP`、`RIP`、`R12`、`R13` 分别被初始化为栈顶地址、`coroutine_entry` 函数地址、`coroutine_main` 函数、`this` 指针(配合CALL宏来传递函数参数)。 76 | 77 | ```cpp 78 | // basic_context::basic_context() 79 | stack = new uint64_t[stack_size]; 80 | // 对齐到 16 字节边界 81 | uint64_t rsp = (uint64_t)&stack[stack_size - 1]; 82 | rsp = rsp - (rsp & 0xF); 83 | void coroutine_main(struct basic_context * context); 84 | callee_registers[(int)Registers::RSP] = rsp; 85 | // 协程入口是 coroutine_entry 86 | callee_registers[(int)Registers::RIP] = (uint64_t)coroutine_entry; 87 | // 设置 r12 寄存器为 coroutine_main 的地址 88 | callee_registers[(int)Registers::R12] = (uint64_t)coroutine_main; 89 | // 设置 r13 寄存器,用于 coroutine_main 的参数 90 | callee_registers[(int)Registers::R13] = (uint64_t)this; 91 | ``` 92 | 93 | 在 `serial_execute_all` 函数依次启动协程时,使用 `resume` 函数来开始执行这个协程。`resume` 调用 `coroutine_switch(caller_registers, callee_registers)`,这个函数会把当前的寄存器状态(即调用这个协程的caller函数的状态)全部存放到第一个参数(`caller_registers`)中,然后切换到第二个参数(`callee_registers`)的运行状态,即把 `callee_registers` 中的输入加载到真的寄存器中。 94 | 95 | ```S 96 | .global coroutine_switch 97 | coroutine_switch: 98 | # 保存 callee-saved 寄存器到 %rdi 指向的上下文 99 | movq %rsp, 64(%rdi) 100 | # 下略 101 | 102 | # 保存的上下文中 rip 指向 ret 指令的地址(.coroutine_ret) 103 | leaq .coroutine_ret(%rip), %rax 104 | movq %rax, 120(%rdi) 105 | movq $0, %rax 106 | 107 | # 从 %rsi 指向的上下文恢复 callee-saved 寄存器 108 | movq 64(%rsi), %rsp 109 | # 下略 110 | 111 | # 最后 jmpq 到上下文保存的 rip 112 | jmp *120(%rsi) 113 | ``` 114 | 115 | 其中,`callee_registers` 的初始状态由上面的构造函数构造。`%rsp` 会被赋值为 `RSP`,指向的栈将被我们创建的 `stack` 指针开辟的堆上的空间所替代。`RIP` 存放了 `coroutine_entry` 函数的地址。在执行 `resume` 函数的最后,程序会跳转到 `*120(%rsi)` 即 `RIP` 存放的地址,开始执行 `coroutine_entry` 函数。此时,寄存器 `%r13` 和 `%r12` 分别被赋值为了 `R13` 和 `R12`,即 `this` 指针与 `coroutine_main` 函数的地址。 116 | 117 | `coroutine_entry` 函数则会将 `%r13` 寄存器中的 `this` 指针存放到 `%rdi` 寄存器(即作为接下来调用的函数的参数),然后调用存储在 `%r12` 的 `coroutine_main` 函数,开始执行协程。 118 | 119 | ```S 120 | .global coroutine_entry 121 | coroutine_entry: 122 | movq %r13, %rdi 123 | callq *%r12 124 | ``` 125 | 126 | `coroutine_main` 函数会调用 `run` 函数,即执行协程要执行的函数。如果函数正常结束,则标记次此协程完成,并调用 `coroutine_switch(callee_registers, caller_registers)`。注意这里两个参数的顺序与之前相反,故此函数将本协程的状态存储回 `callee_registers` 中,然后恢复 `caller_registers`(在启动时存储了调用者的状态),即回到调用此协程的caller函数中。 127 | 128 | ```cpp 129 | // coroutine_main() 130 | context->run(); 131 | // run(){CALL(f, args);} 132 | context->finished = true; 133 | coroutine_switch(context->callee_registers, context->caller_registers); 134 | ``` 135 | 136 | 如果协程执行的函数里有 `yield` 函数,那么 `yield` 函数会主动调用 `coroutine_switch(context->callee_registers, context->caller_registers)` 将协程停止并挂起,然后恢复调用此协程的caller函数的运行状态。 137 | 138 | **4. 浮点和向量寄存器的处理:** 139 | 140 | 如果要考虑浮点和向量寄存器,我们只需要相应地扩大 `enum class Registers` 的枚举范围,即扩大了 `caller_registers` 和 `callee_registers` 数组的大小。然后在 `coroutine_switch` 函数中,将浮点和向量寄存器也按照与通用寄存器类似的方法,从 `%rdi` 和 `%rsi` 指向的上下文存取即可。 141 | 142 | ## Task2 143 | 144 | **1. 添加的代码** 145 | 146 | `common.h`: 147 | ```cpp 148 | // void sleep(int ms) 149 | auto context = g_pool->coroutines[g_pool->context_id]; // 获取当前协程 150 | context->ready = false; // 标记协程未就绪 151 | auto cur = get_time(); // 获取开始sleep的时间 152 | context->ready_func = [&](){ // 定义ready_func 153 | return std::chrono::duration_cast(get_time() - cur).count() >= ms; // 如果当前时间比开始sleep时间晚ms毫秒或更多,则返回true 154 | }; 155 | coroutine_switch(context->callee_registers, context->caller_registers); // 恢复到调用者的运行状态 156 | ``` 157 | 158 | `coroutine_pool.h`: 159 | ```cpp 160 | // void serial_execute_all() 161 | if(coroutines[context_id]->finished) finish_num++; // 若当前协程已结束,记录到finish_num中 162 | else if(coroutines[context_id]->ready) coroutines[context_id]->resume(); // 若当前协程已就绪,切换到该协程 163 | else if(coroutines[context_id]->ready_func()){ // 若当前协程未就绪,但ready_func返回true,说明sleep时间到了 164 | coroutines[context_id]->ready=true; // 标记当前协程就绪 165 | coroutines[context_id]->resume(); // 切换到该协程 166 | } 167 | ``` 168 | 169 | **2. sleep_sort 时间线:** 170 | 171 | ![2](img/2.jpg) 172 | 173 | **3. 更加高效的方法:** 174 | 175 | 我们可以在协程池里面添加一个优先队列,用来存储每一个协程的结束时间。每当一个协程开始sleep时,我们直接计算出它结束sleep的时间,然后把这个时间推入优先队列里。每一次我们从优先队列里取出最早结束sleep的协程,如果它的结束时间已经到了,那么我们就把它标记为就绪,然后切换到它。 176 | 177 | 设总共有 $n$ 个协程都需要执行sleep。在原来的方法里,每一个协程开始sleep需要 $O(1)$ 的操作数,但是每次重启一个协程时平均需要 $O(n)$ 操作数来遍历所有的协程。而在新的方法里,每一个协程开始sleep需要 $O(\log n)$ 的操作数来插入队列,但是每次重启一个协程时只需要 $O(1)$ 时间来取出队列头。因此,如果 $n$ 很大,那么新的方法会更加高效。 178 | 179 | ## Task3 180 | 181 | **1. 添加的代码** 182 | `binary_search.cpp` 183 | ```cpp 184 | // void lookup_coroutine(const uint32_t *table, size_t size, uint32_t value,uint32_t *result) 185 | __builtin_prefetch(&table[probe]); // 预取下一个要访问的元素 186 | yield(); // 暂停并挂起协程 187 | ``` 188 | 189 | **2. 测试结果:** 190 | 191 | ***我发现,我在本地电脑的WSL里测试时,协程优化后的二分查找性能能有明显提升。但是在课程服务器上运行时,协程优化后的二分查找速度反而不如naive方法。我猜可能是因为课程服务器上的CPU缓存空间较大(?)以下测试全都在本地电脑的WSL里进行*** 192 | 193 | 1. 默认参数:`-l=32 -m=100000 -b=16` 194 | 195 | 由于电脑不同状态下运行耗时不一样,这里给出默认参数下的运行市场,作为比较标准。默认参数下,协程优化后的查找比naive方法快了约33.8%。 196 | 197 | `l=32 m=1000000 b=16` 198 | ```shell 199 | Size: 4294967296 200 | Loops: 1000000 201 | Batch size: 16 202 | Initialization done 203 | naive: 2138.83 ns per search, 66.84 ns per access 204 | coroutine batched: 1437.52 ns per search, 44.92 ns per access 205 | ``` 206 | 207 | 2. 若n较小,则协程优化效果不如naive方法。基本上当 `-l` 参数小于等于29时,协程优化的查找时间都比naive方法长。且n越小协程优化带来的负面影响越大。例如: 208 | 209 | `l=29 m=1000000 b=16` 210 | ```shell 211 | Size: 536870912 212 | Loops: 1000000 213 | Batch size: 16 214 | Initialization done 215 | naive: 1219.68 ns per search, 42.06 ns per access 216 | coroutine batched: 1412.82 ns per search, 48.72 ns per access 217 | ``` 218 | 219 | `l=27 m=1000000 b=16` 220 | ```shell 221 | Size: 134217728 222 | Loops: 1000000 223 | Batch size: 16 224 | Initialization done 225 | naive: 917.02 ns per search, 33.96 ns per access 226 | coroutine batched: 1138.80 ns per search, 42.18 ns per access 227 | ``` 228 | 229 | `l=10 m=1000000 b=16` 230 | ```shell 231 | Size: 1024 232 | Loops: 1000000 233 | Batch size: 16 234 | Initialization done 235 | naive: 13.70 ns per search, 1.37 ns per access 236 | coroutine batched: 452.80 ns per search, 45.28 ns per access 237 | ``` 238 | 239 | 原因应该是是,数组长度较小时,二分查找需要访问的元素更可能被缓存命中到,而协程优化的方法则需要频繁地切换协程,耗费更多时间。如测试结果显示,当长度减小时,naive方法访问元素时间相应减小,说明缓存命中率提高,但协程优化后访问时间基本维持在45ns左右,这可能代表切换协程需要的时间。 240 | 241 | 3. 理论上讲,`-m` 的取值代表执行随机二分查找的次数,对于二分查找的平均用时应该没有影响。大多数测试结果都满足这种猜测。但有些特殊的m取值可能会导致反常,如 `m=16000` 和 `m=32000` 时: 242 | 243 | ```shell 244 | Size: 4294967296 245 | Loops: 16000 246 | Batch size: 16 247 | Initialization done 248 | naive: 1623.82 ns per search, 50.74 ns per access 249 | coroutine batched: 2040.01 ns per search, 63.75 ns per access 250 | ``` 251 | 252 | 经过测试,`m` 取4000、8000、64000、100000时,协程优化后的二分查找都更快。但唯独m取16000或32000时协程优化后的查找不如naive方法。目前还未搞清楚具体原因。 253 | 254 | 4. `-b` 参数代表协程池里使用的协程数。理论上讲,这个数的最佳取值应该与CPU从内存读取数据的时间有关。最好能够做到让CPU读取数据的时间里恰够这 `b` 个协程依次启动一遍。经过测试,在 `l` `m` 取默认参数情况下,当 `b` 取2~20之间的数时,协程都能起到优化作用,优化效果大概在25%-30%左右。当 `b` 取大于等于32的数时,协程优化后的二分查找反而比naive方法慢: 255 | 256 | `b=32`: 257 | ```shell 258 | Size: 4294967296 259 | Loops: 1000000 260 | Batch size: 32 261 | Initialization done 262 | naive: 2424.34 ns per search, 75.76 ns per access 263 | coroutine batched: 3691.44 ns per search, 115.36 ns per access 264 | ``` 265 | 266 | 这可能是因为协程池中协程过多,切换携程占用了太多时间。 267 | 268 | ## 交流与参考: 269 | 无 270 | 271 | ## 总结和感想: 272 | 第一次搞这种“系统编程”,把汇编代码和C代码联合起来编译,感觉非常强大,认识到了C语言更厉害的作用。实验框架感觉设计得很棒,相对清晰易懂,类封装做得也很明白。不过有些注释做的让人不太确定哪些地方需要我写代码补全,感觉可以进一步再优化一下。做出来的实验结果和理论不是很符合,可能需要学习更多的系统知识。 273 | -------------------------------------------------------------------------------- /coroutine_lab/bin/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /coroutine_lab/handout/REPORT.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangchi2004/ICS-2023/a968e20339250ec42b46a271d7bd471b70493689/coroutine_lab/handout/REPORT.md -------------------------------------------------------------------------------- /coroutine_lab/img/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangchi2004/ICS-2023/a968e20339250ec42b46a271d7bd471b70493689/coroutine_lab/img/1.jpg -------------------------------------------------------------------------------- /coroutine_lab/img/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangchi2004/ICS-2023/a968e20339250ec42b46a271d7bd471b70493689/coroutine_lab/img/2.jpg -------------------------------------------------------------------------------- /coroutine_lab/inc/common.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "context.h" 3 | #include "coroutine_pool.h" 4 | #include 5 | 6 | // 获取当前时间 7 | auto get_time() { return std::chrono::system_clock::now(); } 8 | 9 | /** 10 | * @brief yield函数 11 | * 12 | * TODO: Task 1 13 | * 协程主动暂停执行,保存协程的寄存器和栈帧。 14 | * 将上下文转换至 coroutine_pool.serial_execute_all() 中的上下文进行重新的 15 | * schedule 调用。 16 | */ 17 | void yield() { 18 | if (!g_pool->is_parallel) { 19 | // 从 g_pool 中获取当前协程状态 20 | auto context = g_pool->coroutines[g_pool->context_id]; 21 | 22 | // 调用 coroutine_switch 切换到 coroutine_pool 上下文 23 | coroutine_switch(context->callee_registers, context->caller_registers); 24 | } 25 | } 26 | 27 | /** 28 | * @brief 完成 sleep 函数 29 | * 30 | * TODO: Task 2 31 | * 你需要完成 sleep 函数。 32 | * 此函数的作用为: 33 | * 1. 将协程置为不可用状态。 34 | * 2. yield 协程。 35 | * 3. 在至少 @param ms 毫秒之后将协程置为可用状态。 36 | */ 37 | void sleep(uint64_t ms) { 38 | if (g_pool->is_parallel) { 39 | auto cur = get_time(); 40 | while ( 41 | std::chrono::duration_cast(get_time() - cur) 42 | .count() < ms) 43 | ; 44 | } else { 45 | // 从 g_pool 中获取当前协程状态 46 | auto context = g_pool->coroutines[g_pool->context_id]; 47 | context->ready = false; 48 | // 获取当前时间,更新 ready_func 49 | // ready_func:检查当前时间,如果已经超时,则返回 true 50 | auto cur = get_time(); 51 | context->ready_func = [&](){ 52 | return std::chrono::duration_cast(get_time() - cur).count() >= ms; 53 | }; 54 | 55 | // 调用 coroutine_switch 切换到 coroutine_pool 上下文 56 | coroutine_switch(context->callee_registers, context->caller_registers); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /coroutine_lab/inc/context.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | enum class Registers : int { 9 | RAX = 0, 10 | RDI, 11 | RSI, 12 | RDX, 13 | R8, 14 | R9, 15 | R10, 16 | R11, 17 | RSP, 18 | RBX, 19 | RBP, 20 | R12, 21 | R13, 22 | R14, 23 | R15, 24 | RIP, 25 | RegisterCount 26 | }; 27 | 28 | extern "C" { 29 | void coroutine_entry(); 30 | void coroutine_switch(uint64_t *save, uint64_t *restore); 31 | } 32 | 33 | struct basic_context { 34 | uint64_t *stack; 35 | uint64_t stack_size; 36 | uint64_t caller_registers[(int)Registers::RegisterCount]; 37 | uint64_t callee_registers[(int)Registers::RegisterCount]; 38 | bool finished; 39 | bool ready; 40 | std::function ready_func; 41 | 42 | basic_context(uint64_t stack_size) 43 | : finished(false), ready(true), stack_size(stack_size) { 44 | stack = new uint64_t[stack_size]; 45 | 46 | // TODO: Task 1 47 | // 在实验报告中分析以下代码 48 | // 对齐到 16 字节边界 49 | uint64_t rsp = (uint64_t)&stack[stack_size - 1]; 50 | rsp = rsp - (rsp & 0xF); 51 | 52 | void coroutine_main(struct basic_context * context); 53 | 54 | callee_registers[(int)Registers::RSP] = rsp; 55 | // 协程入口是 coroutine_entry 56 | callee_registers[(int)Registers::RIP] = (uint64_t)coroutine_entry; 57 | // 设置 r12 寄存器为 coroutine_main 的地址 58 | callee_registers[(int)Registers::R12] = (uint64_t)coroutine_main; 59 | // 设置 r13 寄存器,用于 coroutine_main 的参数 60 | callee_registers[(int)Registers::R13] = (uint64_t)this; 61 | } 62 | 63 | ~basic_context() { delete[] stack; } 64 | 65 | virtual void run() = 0; 66 | virtual void resume() = 0; 67 | }; 68 | 69 | // TODO: Task 1 70 | // 在实验报告中分析以下代码 71 | void coroutine_main(struct basic_context *context) { 72 | context->run(); 73 | context->finished = true; 74 | coroutine_switch(context->callee_registers, context->caller_registers); 75 | 76 | // unreachable 77 | assert(false); 78 | } 79 | 80 | extern __thread basic_context *g_current_context; 81 | 82 | // boilerplate code to handle variadic function arguments 83 | #define EXPAND_CALL_0(args) 84 | #define EXPAND_CALL_1(args) (std::get<0>(args)) 85 | #define EXPAND_CALL_2(args) EXPAND_CALL_1(args), (std::get<1>(args)) 86 | #define EXPAND_CALL_3(args) EXPAND_CALL_2(args), (std::get<2>(args)) 87 | #define EXPAND_CALL_4(args) EXPAND_CALL_3(args), (std::get<3>(args)) 88 | #define EXPAND_CALL_5(args) EXPAND_CALL_4(args), (std::get<4>(args)) 89 | #define EXPAND_CALL_6(args) EXPAND_CALL_5(args), (std::get<5>(args)) 90 | #define EXPAND_CALL_7(args) EXPAND_CALL_6(args), (std::get<6>(args)) 91 | 92 | #define CALLER_IMPL(func, x, args) \ 93 | if constexpr (std::tuple_size_v> == x) \ 94 | func(EXPAND_CALL_##x(args)) 95 | 96 | #define CALL(func, args) \ 97 | CALLER_IMPL(func, 0, args); \ 98 | CALLER_IMPL(func, 1, args); \ 99 | CALLER_IMPL(func, 2, args); \ 100 | CALLER_IMPL(func, 3, args); \ 101 | CALLER_IMPL(func, 4, args); \ 102 | CALLER_IMPL(func, 5, args); \ 103 | CALLER_IMPL(func, 6, args); \ 104 | CALLER_IMPL(func, 7, args); 105 | 106 | /** 107 | * @brief 108 | * 协程运行时资源管理。存储了协程函数,以及协程函数的运行时栈即寄存器内容等。 109 | * 110 | * @tparam F 协程函数类 111 | * @tparam Args 协程函数所需要的参数列表 112 | * 在当前情况下,协程函数支支持展开至多 7 个参数。 113 | * 如果需要更多的参数需要 114 | * 1. 参考修改 CALL 的宏定义以及添加对应的 EXPAND_CALL_X 的宏定义。 115 | * 2. 需要修改构造函数中的 static_assert。 116 | */ 117 | template 118 | struct coroutine_context : public basic_context { 119 | F f; 120 | std::tuple args; 121 | 122 | // construct a stacked coroutine, with stack size 16 KB 123 | coroutine_context(F f, Args... args) 124 | : f(f), args(std::tuple(args...)), 125 | basic_context(16 * 1024 / sizeof(uint64_t)) { 126 | static_assert(sizeof...(args) <= 7); 127 | } 128 | 129 | // construct a stacked coroutine, with stack_size (in KB) 130 | coroutine_context(uint64_t stack_size, F f, Args... args) 131 | : f(f), args(std::tuple(args...)), 132 | basic_context(stack_size * 1024 / sizeof(uint64_t)) { 133 | static_assert(sizeof...(args) <= 7); 134 | } 135 | 136 | /** 137 | * @brief 恢复协程函数运行。 138 | * TODO: Task 1 139 | * 你需要保存 callee-saved 寄存器,并且设置协程函数栈帧,然后将 rip 恢复到协程 140 | * yield 之后所需要执行的指令地址。 141 | */ 142 | virtual void resume() { 143 | // 调用 coroutine_switch 144 | // 在汇编中保存 callee-saved 寄存器,设置协程函数栈帧,然后将 rip 恢复到协程 yield 之后所需要执行的指令地址。 145 | coroutine_switch(caller_registers, callee_registers); // 把当前的寄存器状态保存到caller_registers中,然后切换到callee_registers的运行状态。 146 | } 147 | 148 | virtual void run() { CALL(f, args); } 149 | }; -------------------------------------------------------------------------------- /coroutine_lab/inc/coroutine_pool.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "context.h" 3 | #include 4 | #include 5 | #include 6 | 7 | struct coroutine_pool; 8 | extern coroutine_pool *g_pool; 9 | 10 | /** 11 | * @brief 协程池 12 | * 保存所有需要同步执行的协程函数。并可以进行并行/串行执行。 13 | */ 14 | struct coroutine_pool { 15 | std::vector coroutines; 16 | int context_id; 17 | 18 | // whether run in threads or coroutines 19 | bool is_parallel; 20 | 21 | ~coroutine_pool() { 22 | for (auto context : coroutines) { 23 | delete context; 24 | } 25 | } 26 | 27 | // add coroutine to pool 28 | template 29 | void new_coroutine(F f, Args... args) { 30 | coroutines.push_back(new coroutine_context(f, args...)); 31 | } 32 | 33 | /** 34 | * @brief 以并行多线程的方式执行所有协程函数 35 | */ 36 | void parallel_execute_all() { 37 | g_pool = this; 38 | is_parallel = true; 39 | std::vector threads; 40 | for (auto p : coroutines) { 41 | threads.emplace_back([p]() { p->run(); }); 42 | } 43 | 44 | for (auto &thread : threads) { 45 | thread.join(); 46 | } 47 | } 48 | 49 | /** 50 | * @brief 以协程执行的方式串行并同时执行所有协程函数 51 | * TODO: Task 1, Task 2 52 | * 在 Task 1 中,我们不需要考虑协程的 ready 53 | * 属性,即可以采用轮询的方式挑选一个未完成执行的协程函数进行继续执行的操作。 54 | * 在 Task 2 中,我们需要考虑 sleep 带来的 ready 55 | * 属性,需要对协程函数进行过滤,选择 ready 的协程函数进行执行。 56 | * 57 | * 当所有协程函数都执行完毕后,退出该函数。 58 | */ 59 | void serial_execute_all() { 60 | is_parallel = false; 61 | g_pool = this; 62 | 63 | while(true){ 64 | int finish_num=0; 65 | for(context_id=0;context_idfinished) finish_num++; 67 | else if(coroutines[context_id]->ready) coroutines[context_id]->resume(); 68 | else if(coroutines[context_id]->ready_func()){ 69 | coroutines[context_id]->ready=true; 70 | coroutines[context_id]->resume(); 71 | } 72 | } 73 | if(finish_num==coroutines.size()) break; 74 | } 75 | 76 | for (auto context : coroutines) { 77 | delete context; 78 | } 79 | coroutines.clear(); 80 | } 81 | }; 82 | -------------------------------------------------------------------------------- /coroutine_lab/lib/context.S: -------------------------------------------------------------------------------- 1 | .global coroutine_entry 2 | coroutine_entry: 3 | movq %r13, %rdi 4 | callq *%r12 5 | 6 | .global coroutine_switch 7 | coroutine_switch: 8 | # TODO: Task 1 9 | # 保存 callee-saved 寄存器到 %rdi 指向的上下文 10 | # 保存的上下文中 rip 指向 ret 指令的地址(.coroutine_ret) 11 | 12 | # 从 %rsi 指向的上下文恢复 callee-saved 寄存器 13 | # 最后 jmpq 到上下文保存的 rip 14 | 15 | movq %rsp, 64(%rdi) 16 | movq %rbx, 72(%rdi) 17 | movq %rbp, 80(%rdi) 18 | movq %r12, 88(%rdi) 19 | movq %r13, 96(%rdi) 20 | movq %r14, 104(%rdi) 21 | movq %r15, 112(%rdi) 22 | leaq .coroutine_ret(%rip), %rax 23 | movq %rax, 120(%rdi) 24 | movq $0, %rax 25 | 26 | movq 64(%rsi), %rsp 27 | movq 72(%rsi), %rbx 28 | movq 80(%rsi), %rbp 29 | movq 88(%rsi), %r12 30 | movq 96(%rsi), %r13 31 | movq 104(%rsi), %r14 32 | movq 112(%rsi), %r15 33 | jmp *120(%rsi) 34 | 35 | .coroutine_ret: 36 | ret 37 | -------------------------------------------------------------------------------- /coroutine_lab/src/binary_search.cpp: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | coroutine_pool *g_pool; 11 | 12 | void lookup_coroutine(const uint32_t *table, size_t size, uint32_t value, 13 | uint32_t *result) { 14 | size_t low = 0; 15 | while ((size / 2) > 0) { 16 | size_t half = size / 2; 17 | size_t probe = low + half; 18 | 19 | // TODO: Task 3 20 | // 使用 __builtin_prefetch 预取容易产生缓存缺失的内存 21 | // 并调用 yield 22 | __builtin_prefetch(&table[probe]); 23 | yield(); 24 | 25 | uint32_t v = table[probe]; 26 | if (v <= value) { 27 | low = probe; 28 | } 29 | size -= half; 30 | } 31 | *result = low; 32 | } 33 | 34 | void lookup(const uint32_t *table, size_t size, uint32_t value, 35 | uint32_t *result) { 36 | size_t low = 0; 37 | while ((size / 2) > 0) { 38 | size_t half = size / 2; 39 | size_t probe = low + half; 40 | uint32_t v = table[probe]; 41 | if (v <= value) { 42 | low = probe; 43 | } 44 | size -= half; 45 | } 46 | *result = low; 47 | } 48 | 49 | uint32_t *naive(int m, int n, int batch, size_t log2_bytes, uint32_t *data) { 50 | std::uniform_int_distribution distr; 51 | std::minstd_rand eng(0); 52 | 53 | uint32_t *res = new uint32_t[m]; 54 | uint32_t *keys = new uint32_t[m]; 55 | for (int i = 0; i < m; i++) { 56 | keys[i] = distr(eng) % n; 57 | } 58 | 59 | auto time_begin = get_time(); 60 | 61 | for (int i = 0; i < m; i++) { 62 | uint32_t key = keys[i]; 63 | lookup(data, n, key, &res[i]); 64 | } 65 | 66 | uint64_t time_elapsed = std::chrono::duration_cast( 67 | get_time() - time_begin) 68 | .count(); 69 | 70 | printf("naive: %.2f ns per search, %.2f ns per access\n", 71 | (double)time_elapsed / m, (double)time_elapsed / m / log2_bytes); 72 | return res; 73 | } 74 | 75 | uint32_t *coroutine_batched(int m, int n, int batch, size_t log2_bytes, 76 | uint32_t *data) { 77 | std::uniform_int_distribution distr; 78 | // https://stackoverflow.com/questions/22883840/c-get-random-number-from-0-to-max-long-long-integer 79 | std::minstd_rand eng(0); 80 | 81 | uint32_t *res = new uint32_t[m]; 82 | uint32_t *keys = new uint32_t[m]; 83 | for (int i = 0; i < m; i++) { 84 | keys[i] = distr(eng) % n; 85 | } 86 | 87 | auto time_begin = get_time(); 88 | 89 | assert(m % batch == 0); 90 | 91 | coroutine_pool pool; 92 | for (int i = 0; i < m; i += batch) { 93 | for (int j = 0; j < batch; j++) { 94 | uint32_t key = keys[i + j]; 95 | pool.new_coroutine(lookup_coroutine, data, n, key, &res[i + j]); 96 | } 97 | pool.serial_execute_all(); 98 | } 99 | 100 | uint64_t time_elapsed = std::chrono::duration_cast( 101 | get_time() - time_begin) 102 | .count(); 103 | 104 | printf("coroutine batched: %.2f ns per search, %.2f ns per access\n", 105 | (double)time_elapsed / m, (double)time_elapsed / m / log2_bytes); 106 | return res; 107 | } 108 | 109 | int main(int argc, char *argv[]) { 110 | // 4 GiB 111 | size_t log2_bytes = 32; 112 | int m = 1000000; 113 | int batch = 16; 114 | 115 | int opt; 116 | while ((opt = getopt(argc, argv, "l:m:b:")) != -1) { 117 | switch (opt) { 118 | case 'l': 119 | sscanf(optarg, "%ld", &log2_bytes); 120 | break; 121 | case 'm': 122 | sscanf(optarg, "%d", &m); 123 | break; 124 | case 'b': 125 | sscanf(optarg, "%d", &batch); 126 | break; 127 | default: 128 | fprintf(stderr, "Usage: %s [-l log2_size] [-m loop] [-b batch]\n", 129 | argv[0]); 130 | exit(EXIT_FAILURE); 131 | } 132 | } 133 | 134 | size_t bytes = 1LL << log2_bytes; 135 | 136 | printf("Size: %ld\n", bytes); 137 | printf("Loops: %d\n", m); 138 | printf("Batch size: %d\n", batch); 139 | fflush(stdout); 140 | 141 | size_t n = bytes / sizeof(uint32_t); 142 | uint32_t *data = new uint32_t[n]; 143 | 144 | for (size_t i = 0; i < n; i++) { 145 | data[i] = i; 146 | } 147 | 148 | printf("Initialization done\n"); 149 | fflush(stdout); 150 | 151 | uint32_t *naive_res = naive(m, n, batch, log2_bytes, data); 152 | uint32_t *coroutine_res = coroutine_batched(m, n, batch, log2_bytes, data); 153 | for (int i = 0; i < m; i++) { 154 | assert(naive_res[i] == coroutine_res[i]); 155 | } 156 | return 0; 157 | } 158 | -------------------------------------------------------------------------------- /coroutine_lab/src/sample.cpp: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include "context.h" 3 | #include "coroutine_pool.h" 4 | #include 5 | #include 6 | 7 | coroutine_pool *g_pool; 8 | 9 | // example code to run in coroutine 10 | std::vector p; 11 | 12 | void show(int x) { 13 | for (int i = 0; i < x; i++) { 14 | p.push_back(i); 15 | printf("in show(): %d\n", i); 16 | yield(); 17 | } 18 | } 19 | 20 | int main() { 21 | coroutine_pool pool; 22 | // spawn two coroutines 23 | for (int i = 0; i < 2; i++) 24 | pool.new_coroutine(show, 5); 25 | 26 | // execute and print result 27 | // pool.parallel_execute_all(); 28 | pool.serial_execute_all(); 29 | for (auto i : p) { 30 | printf("in main(): %d\n", i); 31 | } 32 | 33 | return 0; 34 | } -------------------------------------------------------------------------------- /coroutine_lab/src/sleep_sort.cpp: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | coroutine_pool *g_pool; 8 | int main() { 9 | int n, a[100]; 10 | coroutine_pool coroutines; 11 | 12 | // input N 13 | scanf("%d", &n); 14 | for (int i = 0; i < n; i++) { 15 | // input N numbers 16 | scanf("%d", &a[i]); 17 | 18 | // create a coroutine for each number 19 | coroutines.new_coroutine( 20 | [](int x) { 21 | sleep(x); 22 | printf("%d\n", x); 23 | }, 24 | a[i]); 25 | } 26 | 27 | // execute and print 28 | coroutines.serial_execute_all(); 29 | return 0; 30 | } -------------------------------------------------------------------------------- /malloclab/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Students' Makefile for the Malloc Lab 3 | # 4 | TEAM = bovik 5 | VERSION = 1 6 | HANDINDIR = /afs/cs.cmu.edu/academic/class/15213-f01/malloclab/handin 7 | 8 | CC = gcc 9 | CFLAGS = -Wall -O2 10 | 11 | OBJS = mdriver.o mm.o memlib.o fsecs.o fcyc.o clock.o ftimer.o 12 | 13 | mdriver: $(OBJS) 14 | $(CC) $(CFLAGS) -o mdriver $(OBJS) 15 | 16 | mdriver.o: mdriver.c fsecs.h fcyc.h clock.h memlib.h config.h mm.h 17 | memlib.o: memlib.c memlib.h 18 | mm.o: mm.c mm.h memlib.h 19 | fsecs.o: fsecs.c fsecs.h config.h 20 | fcyc.o: fcyc.c fcyc.h 21 | ftimer.o: ftimer.c ftimer.h config.h 22 | clock.o: clock.c clock.h 23 | 24 | handin: 25 | cp mm.c $(HANDINDIR)/$(TEAM)-$(VERSION)-mm.c 26 | 27 | clean: 28 | rm -f *~ *.o mdriver 29 | 30 | 31 | -------------------------------------------------------------------------------- /malloclab/README: -------------------------------------------------------------------------------- 1 | ##################################################################### 2 | # CS:APP Malloc Lab 3 | # Handout files for students 4 | # 5 | # Copyright (c) 2002, R. Bryant and D. O'Hallaron, All rights reserved. 6 | # May not be used, modified, or copied without permission. 7 | # 8 | ###################################################################### 9 | 10 | *********** 11 | Main Files: 12 | *********** 13 | 14 | mm.{c,h} 15 | Your solution malloc package. mm.c is the file that you 16 | will be handing in, and is the only file you should modify. 17 | 18 | mdriver.c 19 | The malloc driver that tests your mm.c file 20 | 21 | short{1,2}-bal.rep 22 | Two tiny tracefiles to help you get started. 23 | 24 | Makefile 25 | Builds the driver 26 | 27 | ********************************** 28 | Other support files for the driver 29 | ********************************** 30 | 31 | config.h Configures the malloc lab driver 32 | fsecs.{c,h} Wrapper function for the different timer packages 33 | clock.{c,h} Routines for accessing the Pentium and Alpha cycle counters 34 | fcyc.{c,h} Timer functions based on cycle counters 35 | ftimer.{c,h} Timer functions based on interval timers and gettimeofday() 36 | memlib.{c,h} Models the heap and sbrk function 37 | 38 | ******************************* 39 | Building and running the driver 40 | ******************************* 41 | To build the driver, type "make" to the shell. 42 | 43 | To run the driver on a tiny test trace: 44 | 45 | unix> mdriver -V -f short1-bal.rep 46 | 47 | The -V option prints out helpful tracing and summary information. 48 | 49 | To get a list of the driver flags: 50 | 51 | unix> mdriver -h 52 | 53 | -------------------------------------------------------------------------------- /malloclab/clock.c: -------------------------------------------------------------------------------- 1 | /* 2 | * clock.c - Routines for using the cycle counters on x86, 3 | * Alpha, and Sparc boxes. 4 | * 5 | * Copyright (c) 2002, R. Bryant and D. O'Hallaron, All rights reserved. 6 | * May not be used, modified, or copied without permission. 7 | */ 8 | 9 | #include "clock.h" 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | /******************************************************* 16 | * Machine dependent functions 17 | * 18 | * Note: the constants __i386__ and __alpha 19 | * are set by GCC when it calls the C preprocessor 20 | * You can verify this for yourself using gcc -v. 21 | *******************************************************/ 22 | 23 | #if defined(__i386__) 24 | /******************************************************* 25 | * Pentium versions of start_counter() and get_counter() 26 | *******************************************************/ 27 | 28 | /* $begin x86cyclecounter */ 29 | /* Initialize the cycle counter */ 30 | static unsigned cyc_hi = 0; 31 | static unsigned cyc_lo = 0; 32 | 33 | /* Set *hi and *lo to the high and low order bits of the cycle counter. 34 | Implementation requires assembly code to use the rdtsc instruction. */ 35 | void access_counter(unsigned *hi, unsigned *lo) { 36 | asm("rdtsc; movl %%edx,%0; movl %%eax,%1" /* Read cycle counter */ 37 | : "=r"(*hi), "=r"(*lo) /* and move results to */ 38 | : /* No input */ /* the two outputs */ 39 | : "%edx", "%eax"); 40 | } 41 | 42 | /* Record the current value of the cycle counter. */ 43 | void start_counter() { access_counter(&cyc_hi, &cyc_lo); } 44 | 45 | /* Return the number of cycles since the last call to start_counter. */ 46 | double get_counter() { 47 | unsigned ncyc_hi, ncyc_lo; 48 | unsigned hi, lo, borrow; 49 | double result; 50 | 51 | /* Get cycle counter */ 52 | access_counter(&ncyc_hi, &ncyc_lo); 53 | 54 | /* Do double precision subtraction */ 55 | lo = ncyc_lo - cyc_lo; 56 | borrow = lo > ncyc_lo; 57 | hi = ncyc_hi - cyc_hi - borrow; 58 | result = (double)hi * (1 << 30) * 4 + lo; 59 | if (result < 0) { 60 | fprintf(stderr, "Error: counter returns neg value: %.0f\n", result); 61 | } 62 | return result; 63 | } 64 | /* $end x86cyclecounter */ 65 | 66 | #elif defined(__alpha) 67 | 68 | /**************************************************** 69 | * Alpha versions of start_counter() and get_counter() 70 | ***************************************************/ 71 | 72 | /* Initialize the cycle counter */ 73 | static unsigned cyc_hi = 0; 74 | static unsigned cyc_lo = 0; 75 | 76 | /* Use Alpha cycle timer to compute cycles. Then use 77 | measured clock speed to compute seconds 78 | */ 79 | 80 | /* 81 | * counterRoutine is an array of Alpha instructions to access 82 | * the Alpha's processor cycle counter. It uses the rpcc 83 | * instruction to access the counter. This 64 bit register is 84 | * divided into two parts. The lower 32 bits are the cycles 85 | * used by the current process. The upper 32 bits are wall 86 | * clock cycles. These instructions read the counter, and 87 | * convert the lower 32 bits into an unsigned int - this is the 88 | * user space counter value. 89 | * NOTE: The counter has a very limited time span. With a 90 | * 450MhZ clock the counter can time things for about 9 91 | * seconds. */ 92 | static unsigned int counterRoutine[] = {0x601fc000u, 0x401f0000u, 0x6bfa8001u}; 93 | 94 | /* Cast the above instructions into a function. */ 95 | static unsigned int (*counter)(void) = (void *)counterRoutine; 96 | 97 | void start_counter() { 98 | /* Get cycle counter */ 99 | cyc_hi = 0; 100 | cyc_lo = counter(); 101 | } 102 | 103 | double get_counter() { 104 | unsigned ncyc_hi, ncyc_lo; 105 | unsigned hi, lo, borrow; 106 | double result; 107 | ncyc_lo = counter(); 108 | ncyc_hi = 0; 109 | lo = ncyc_lo - cyc_lo; 110 | borrow = lo > ncyc_lo; 111 | hi = ncyc_hi - cyc_hi - borrow; 112 | result = (double)hi * (1 << 30) * 4 + lo; 113 | if (result < 0) { 114 | fprintf(stderr, "Error: Cycle counter returning negative value: %.0f\n", 115 | result); 116 | } 117 | return result; 118 | } 119 | 120 | #else 121 | 122 | /**************************************************************** 123 | * All the other platforms for which we haven't implemented cycle 124 | * counter routines. Newer models of sparcs (v8plus) have cycle 125 | * counters that can be accessed from user programs, but since there 126 | * are still many sparc boxes out there that don't support this, we 127 | * haven't provided a Sparc version here. 128 | ***************************************************************/ 129 | 130 | void start_counter() { 131 | printf("ERROR: You are trying to use a start_counter routine in clock.c\n"); 132 | printf("that has not been implemented yet on this platform.\n"); 133 | printf("Please choose another timing package in config.h.\n"); 134 | exit(1); 135 | } 136 | 137 | double get_counter() { 138 | printf("ERROR: You are trying to use a get_counter routine in clock.c\n"); 139 | printf("that has not been implemented yet on this platform.\n"); 140 | printf("Please choose another timing package in config.h.\n"); 141 | exit(1); 142 | } 143 | #endif 144 | 145 | /******************************* 146 | * Machine-independent functions 147 | ******************************/ 148 | double ovhd() { 149 | /* Do it twice to eliminate cache effects */ 150 | int i; 151 | double result; 152 | 153 | for (i = 0; i < 2; i++) { 154 | start_counter(); 155 | result = get_counter(); 156 | } 157 | return result; 158 | } 159 | 160 | /* $begin mhz */ 161 | /* Estimate the clock rate by measuring the cycles that elapse */ 162 | /* while sleeping for sleeptime seconds */ 163 | double mhz_full(int verbose, int sleeptime) { 164 | double rate; 165 | 166 | start_counter(); 167 | sleep(sleeptime); 168 | rate = get_counter() / (1e6 * sleeptime); 169 | if (verbose) 170 | printf("Processor clock rate ~= %.1f MHz\n", rate); 171 | return rate; 172 | } 173 | /* $end mhz */ 174 | 175 | /* Version using a default sleeptime */ 176 | double mhz(int verbose) { return mhz_full(verbose, 2); } 177 | 178 | /** Special counters that compensate for timer interrupt overhead */ 179 | 180 | static double cyc_per_tick = 0.0; 181 | 182 | #define NEVENT 100 183 | #define THRESHOLD 1000 184 | #define RECORDTHRESH 3000 185 | 186 | /* Attempt to see how much time is used by timer interrupt */ 187 | static void callibrate(int verbose) { 188 | double oldt; 189 | struct tms t; 190 | clock_t oldc; 191 | int e = 0; 192 | 193 | times(&t); 194 | oldc = t.tms_utime; 195 | start_counter(); 196 | oldt = get_counter(); 197 | while (e < NEVENT) { 198 | double newt = get_counter(); 199 | 200 | if (newt - oldt >= THRESHOLD) { 201 | clock_t newc; 202 | times(&t); 203 | newc = t.tms_utime; 204 | if (newc > oldc) { 205 | double cpt = (newt - oldt) / (newc - oldc); 206 | if ((cyc_per_tick == 0.0 || cyc_per_tick > cpt) && cpt > RECORDTHRESH) 207 | cyc_per_tick = cpt; 208 | /* 209 | if (verbose) 210 | printf("Saw event lasting %.0f cycles and %d ticks. Ratio = %f\n", 211 | newt-oldt, (int) (newc-oldc), cpt); 212 | */ 213 | e++; 214 | oldc = newc; 215 | } 216 | oldt = newt; 217 | } 218 | } 219 | if (verbose) 220 | printf("Setting cyc_per_tick to %f\n", cyc_per_tick); 221 | } 222 | 223 | static clock_t start_tick = 0; 224 | 225 | void start_comp_counter() { 226 | struct tms t; 227 | 228 | if (cyc_per_tick == 0.0) 229 | callibrate(0); 230 | times(&t); 231 | start_tick = t.tms_utime; 232 | start_counter(); 233 | } 234 | 235 | double get_comp_counter() { 236 | double time = get_counter(); 237 | double ctime; 238 | struct tms t; 239 | clock_t ticks; 240 | 241 | times(&t); 242 | ticks = t.tms_utime - start_tick; 243 | ctime = time - ticks * cyc_per_tick; 244 | /* 245 | printf("Measured %.0f cycles. Ticks = %d. Corrected %.0f cycles\n", 246 | time, (int) ticks, ctime); 247 | */ 248 | return ctime; 249 | } 250 | -------------------------------------------------------------------------------- /malloclab/clock.h: -------------------------------------------------------------------------------- 1 | /* Routines for using cycle counter */ 2 | 3 | /* Start the counter */ 4 | void start_counter(); 5 | 6 | /* Get # cycles since counter started */ 7 | double get_counter(); 8 | 9 | /* Measure overhead for counter */ 10 | double ovhd(); 11 | 12 | /* Determine clock rate of processor (using a default sleeptime) */ 13 | double mhz(int verbose); 14 | 15 | /* Determine clock rate of processor, having more control over accuracy */ 16 | double mhz_full(int verbose, int sleeptime); 17 | 18 | /** Special counters that compensate for timer interrupt overhead */ 19 | 20 | void start_comp_counter(); 21 | 22 | double get_comp_counter(); 23 | -------------------------------------------------------------------------------- /malloclab/clock.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangchi2004/ICS-2023/a968e20339250ec42b46a271d7bd471b70493689/malloclab/clock.o -------------------------------------------------------------------------------- /malloclab/config.h: -------------------------------------------------------------------------------- 1 | #ifndef __CONFIG_H_ 2 | #define __CONFIG_H_ 3 | 4 | /* 5 | * config.h - malloc lab configuration file 6 | * 7 | * Copyright (c) 2002, R. Bryant and D. O'Hallaron, All rights reserved. 8 | * May not be used, modified, or copied without permission. 9 | */ 10 | 11 | /* 12 | * This is the default path where the driver will look for the 13 | * default tracefiles. You can override it at runtime with the -t flag. 14 | */ 15 | #define TRACEDIR "./traces/" 16 | 17 | /* 18 | * This is the list of default tracefiles in TRACEDIR that the driver 19 | * will use for testing. Modify this if you want to add or delete 20 | * traces from the driver's test suite. For example, if you don't want 21 | * your students to implement realloc, you can delete the last two 22 | * traces. 23 | */ 24 | #define DEFAULT_TRACEFILES \ 25 | "amptjp-bal.rep", "cccp-bal.rep", "cp-decl-bal.rep", "expr-bal.rep", \ 26 | "coalescing-bal.rep", "random-bal.rep", "random2-bal.rep", \ 27 | "binary-bal.rep", "binary2-bal.rep", "realloc-bal.rep", \ 28 | "realloc2-bal.rep" 29 | 30 | /* 31 | * This constant gives the estimated performance of the libc malloc 32 | * package using our traces on some reference system, typically the 33 | * same kind of system the students use. Its purpose is to cap the 34 | * contribution of throughput to the performance index. Once the 35 | * students surpass the AVG_LIBC_THRUPUT, they get no further benefit 36 | * to their score. This deters students from building extremely fast, 37 | * but extremely stupid malloc packages. 38 | */ 39 | #define AVG_LIBC_THRUPUT 10000E3 /* 10000 Kops/sec */ 40 | 41 | /* 42 | * This constant determines the contributions of space utilization 43 | * (UTIL_WEIGHT) and throughput (1 - UTIL_WEIGHT) to the performance 44 | * index. 45 | */ 46 | #define UTIL_WEIGHT .60 47 | 48 | /* 49 | * Alignment requirement in bytes (16 in 64-bit systems) 50 | */ 51 | #define ALIGNMENT 16 52 | 53 | /* 54 | * Maximum heap size in bytes 55 | */ 56 | #define MAX_HEAP (20 * (1 << 20)) /* 20 MB */ 57 | 58 | /***************************************************************************** 59 | * Set exactly one of these USE_xxx constants to "1" to select a timing method 60 | *****************************************************************************/ 61 | #define USE_FCYC 0 /* cycle counter w/K-best scheme (x86 & Alpha only) */ 62 | #define USE_ITIMER 0 /* interval timer (any Unix box) */ 63 | #define USE_GETTOD 1 /* gettimeofday (any Unix box) */ 64 | 65 | #endif /* __CONFIG_H */ 66 | -------------------------------------------------------------------------------- /malloclab/fcyc.c: -------------------------------------------------------------------------------- 1 | /* 2 | * fcyc.c - Estimate the time (in CPU cycles) used by a function f 3 | * 4 | * Copyright (c) 2002, R. Bryant and D. O'Hallaron, All rights reserved. 5 | * May not be used, modified, or copied without permission. 6 | * 7 | * Uses the cycle timer routines in clock.c to estimate the 8 | * the time in CPU cycles for a function f. 9 | */ 10 | #include 11 | #include 12 | #include 13 | 14 | #include "clock.h" 15 | #include "fcyc.h" 16 | 17 | /* Default values */ 18 | #define K 3 /* Value of K in K-best scheme */ 19 | #define MAXSAMPLES 20 /* Give up after MAXSAMPLES */ 20 | #define EPSILON 0.01 /* K samples should be EPSILON of each other*/ 21 | #define COMPENSATE 0 /* 1-> try to compensate for clock ticks */ 22 | #define CLEAR_CACHE 0 /* Clear cache before running test function */ 23 | #define CACHE_BYTES (1 << 19) /* Max cache size in bytes */ 24 | #define CACHE_BLOCK 32 /* Cache block size in bytes */ 25 | 26 | static int kbest = K; 27 | static int maxsamples = MAXSAMPLES; 28 | static double epsilon = EPSILON; 29 | static int compensate = COMPENSATE; 30 | static int clear_cache = CLEAR_CACHE; 31 | static int cache_bytes = CACHE_BYTES; 32 | static int cache_block = CACHE_BLOCK; 33 | 34 | static int *cache_buf = NULL; 35 | 36 | static double *values = NULL; 37 | static int samplecount = 0; 38 | 39 | /* for debugging only */ 40 | #define KEEP_VALS 0 41 | #define KEEP_SAMPLES 0 42 | 43 | #if KEEP_SAMPLES 44 | static double *samples = NULL; 45 | #endif 46 | 47 | /* 48 | * init_sampler - Start new sampling process 49 | */ 50 | static void init_sampler() { 51 | if (values) 52 | free(values); 53 | values = calloc(kbest, sizeof(double)); 54 | #if KEEP_SAMPLES 55 | if (samples) 56 | free(samples); 57 | /* Allocate extra for wraparound analysis */ 58 | samples = calloc(maxsamples + kbest, sizeof(double)); 59 | #endif 60 | samplecount = 0; 61 | } 62 | 63 | /* 64 | * add_sample - Add new sample 65 | */ 66 | static void add_sample(double val) { 67 | int pos = 0; 68 | if (samplecount < kbest) { 69 | pos = samplecount; 70 | values[pos] = val; 71 | } else if (val < values[kbest - 1]) { 72 | pos = kbest - 1; 73 | values[pos] = val; 74 | } 75 | #if KEEP_SAMPLES 76 | samples[samplecount] = val; 77 | #endif 78 | samplecount++; 79 | /* Insertion sort */ 80 | while (pos > 0 && values[pos - 1] > values[pos]) { 81 | double temp = values[pos - 1]; 82 | values[pos - 1] = values[pos]; 83 | values[pos] = temp; 84 | pos--; 85 | } 86 | } 87 | 88 | /* 89 | * has_converged- Have kbest minimum measurements converged within epsilon? 90 | */ 91 | static int has_converged() { 92 | return (samplecount >= kbest) && 93 | ((1 + epsilon) * values[0] >= values[kbest - 1]); 94 | } 95 | 96 | /* 97 | * clear - Code to clear cache 98 | */ 99 | static volatile int sink = 0; 100 | 101 | static void clear() { 102 | int x = sink; 103 | int *cptr, *cend; 104 | int incr = cache_block / sizeof(int); 105 | if (!cache_buf) { 106 | cache_buf = malloc(cache_bytes); 107 | if (!cache_buf) { 108 | fprintf( 109 | stderr, 110 | "Fatal error. Malloc returned null when trying to clear cache\n"); 111 | exit(1); 112 | } 113 | } 114 | cptr = (int *)cache_buf; 115 | cend = cptr + cache_bytes / sizeof(int); 116 | while (cptr < cend) { 117 | x += *cptr; 118 | cptr += incr; 119 | } 120 | sink = x; 121 | } 122 | 123 | /* 124 | * fcyc - Use K-best scheme to estimate the running time of function f 125 | */ 126 | double fcyc(test_funct f, void *argp) { 127 | double result; 128 | init_sampler(); 129 | if (compensate) { 130 | do { 131 | double cyc; 132 | if (clear_cache) 133 | clear(); 134 | start_comp_counter(); 135 | f(argp); 136 | cyc = get_comp_counter(); 137 | add_sample(cyc); 138 | } while (!has_converged() && samplecount < maxsamples); 139 | } else { 140 | do { 141 | double cyc; 142 | if (clear_cache) 143 | clear(); 144 | start_counter(); 145 | f(argp); 146 | cyc = get_counter(); 147 | add_sample(cyc); 148 | } while (!has_converged() && samplecount < maxsamples); 149 | } 150 | #ifdef DEBUG 151 | { 152 | int i; 153 | printf(" %d smallest values: [", kbest); 154 | for (i = 0; i < kbest; i++) 155 | printf("%.0f%s", values[i], i == kbest - 1 ? "]\n" : ", "); 156 | } 157 | #endif 158 | result = values[0]; 159 | #if !KEEP_VALS 160 | free(values); 161 | values = NULL; 162 | #endif 163 | return result; 164 | } 165 | 166 | /************************************************************* 167 | * Set the various parameters used by the measurement routines 168 | ************************************************************/ 169 | 170 | /* 171 | * set_fcyc_clear_cache - When set, will run code to clear cache 172 | * before each measurement. 173 | * Default = 0 174 | */ 175 | void set_fcyc_clear_cache(int clear) { clear_cache = clear; } 176 | 177 | /* 178 | * set_fcyc_cache_size - Set size of cache to use when clearing cache 179 | * Default = 1<<19 (512KB) 180 | */ 181 | void set_fcyc_cache_size(int bytes) { 182 | if (bytes != cache_bytes) { 183 | cache_bytes = bytes; 184 | if (cache_buf) { 185 | free(cache_buf); 186 | cache_buf = NULL; 187 | } 188 | } 189 | } 190 | 191 | /* 192 | * set_fcyc_cache_block - Set size of cache block 193 | * Default = 32 194 | */ 195 | void set_fcyc_cache_block(int bytes) { cache_block = bytes; } 196 | 197 | /* 198 | * set_fcyc_compensate- When set, will attempt to compensate for 199 | * timer interrupt overhead 200 | * Default = 0 201 | */ 202 | void set_fcyc_compensate(int compensate_arg) { compensate = compensate_arg; } 203 | 204 | /* 205 | * set_fcyc_k - Value of K in K-best measurement scheme 206 | * Default = 3 207 | */ 208 | void set_fcyc_k(int k) { kbest = k; } 209 | 210 | /* 211 | * set_fcyc_maxsamples - Maximum number of samples attempting to find 212 | * K-best within some tolerance. 213 | * When exceeded, just return best sample found. 214 | * Default = 20 215 | */ 216 | void set_fcyc_maxsamples(int maxsamples_arg) { maxsamples = maxsamples_arg; } 217 | 218 | /* 219 | * set_fcyc_epsilon - Tolerance required for K-best 220 | * Default = 0.01 221 | */ 222 | void set_fcyc_epsilon(double epsilon_arg) { epsilon = epsilon_arg; } 223 | -------------------------------------------------------------------------------- /malloclab/fcyc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * fcyc.h - prototypes for the routines in fcyc.c that estimate the 3 | * time in CPU cycles used by a test function f 4 | * 5 | * Copyright (c) 2002, R. Bryant and D. O'Hallaron, All rights reserved. 6 | * May not be used, modified, or copied without permission. 7 | * 8 | */ 9 | 10 | /* The test function takes a generic pointer as input */ 11 | typedef void (*test_funct)(void *); 12 | 13 | /* Compute number of cycles used by test function f */ 14 | double fcyc(test_funct f, void *argp); 15 | 16 | /********************************************************* 17 | * Set the various parameters used by measurement routines 18 | *********************************************************/ 19 | 20 | /* 21 | * set_fcyc_clear_cache - When set, will run code to clear cache 22 | * before each measurement. 23 | * Default = 0 24 | */ 25 | void set_fcyc_clear_cache(int clear); 26 | 27 | /* 28 | * set_fcyc_cache_size - Set size of cache to use when clearing cache 29 | * Default = 1<<19 (512KB) 30 | */ 31 | void set_fcyc_cache_size(int bytes); 32 | 33 | /* 34 | * set_fcyc_cache_block - Set size of cache block 35 | * Default = 32 36 | */ 37 | void set_fcyc_cache_block(int bytes); 38 | 39 | /* 40 | * set_fcyc_compensate- When set, will attempt to compensate for 41 | * timer interrupt overhead 42 | * Default = 0 43 | */ 44 | void set_fcyc_compensate(int compensate_arg); 45 | 46 | /* 47 | * set_fcyc_k - Value of K in K-best measurement scheme 48 | * Default = 3 49 | */ 50 | void set_fcyc_k(int k); 51 | 52 | /* 53 | * set_fcyc_maxsamples - Maximum number of samples attempting to find 54 | * K-best within some tolerance. 55 | * When exceeded, just return best sample found. 56 | * Default = 20 57 | */ 58 | void set_fcyc_maxsamples(int maxsamples_arg); 59 | 60 | /* 61 | * set_fcyc_epsilon - Tolerance required for K-best 62 | * Default = 0.01 63 | */ 64 | void set_fcyc_epsilon(double epsilon_arg); 65 | -------------------------------------------------------------------------------- /malloclab/fcyc.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangchi2004/ICS-2023/a968e20339250ec42b46a271d7bd471b70493689/malloclab/fcyc.o -------------------------------------------------------------------------------- /malloclab/fsecs.c: -------------------------------------------------------------------------------- 1 | /**************************** 2 | * High-level timing wrappers 3 | ****************************/ 4 | #include "fsecs.h" 5 | #include "clock.h" 6 | #include "config.h" 7 | #include "fcyc.h" 8 | #include "ftimer.h" 9 | #include 10 | 11 | static double Mhz; /* estimated CPU clock frequency */ 12 | 13 | extern int verbose; /* -v option in mdriver.c */ 14 | 15 | /* 16 | * init_fsecs - initialize the timing package 17 | */ 18 | void init_fsecs(void) { 19 | Mhz = 0; /* keep gcc -Wall happy */ 20 | 21 | #if USE_FCYC 22 | if (verbose) 23 | printf("Measuring performance with a cycle counter.\n"); 24 | 25 | /* set key parameters for the fcyc package */ 26 | set_fcyc_maxsamples(20); 27 | set_fcyc_clear_cache(1); 28 | set_fcyc_compensate(1); 29 | set_fcyc_epsilon(0.01); 30 | set_fcyc_k(3); 31 | Mhz = mhz(verbose > 0); 32 | #elif USE_ITIMER 33 | if (verbose) 34 | printf("Measuring performance with the interval timer.\n"); 35 | #elif USE_GETTOD 36 | if (verbose) 37 | printf("Measuring performance with gettimeofday().\n"); 38 | #endif 39 | } 40 | 41 | /* 42 | * fsecs - Return the running time of a function f (in seconds) 43 | */ 44 | double fsecs(fsecs_test_funct f, void *argp) { 45 | #if USE_FCYC 46 | double cycles = fcyc(f, argp); 47 | return cycles / (Mhz * 1e6); 48 | #elif USE_ITIMER 49 | return ftimer_itimer(f, argp, 10); 50 | #elif USE_GETTOD 51 | return ftimer_gettod(f, argp, 10); 52 | #endif 53 | } 54 | -------------------------------------------------------------------------------- /malloclab/fsecs.h: -------------------------------------------------------------------------------- 1 | typedef void (*fsecs_test_funct)(void *); 2 | 3 | void init_fsecs(void); 4 | double fsecs(fsecs_test_funct f, void *argp); 5 | -------------------------------------------------------------------------------- /malloclab/fsecs.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangchi2004/ICS-2023/a968e20339250ec42b46a271d7bd471b70493689/malloclab/fsecs.o -------------------------------------------------------------------------------- /malloclab/ftimer.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ftimer.c - Estimate the time (in seconds) used by a function f 3 | * 4 | * Copyright (c) 2002, R. Bryant and D. O'Hallaron, All rights reserved. 5 | * May not be used, modified, or copied without permission. 6 | * 7 | * Function timers that estimate the running time (in seconds) of a function f. 8 | * ftimer_itimer: version that uses the interval timer 9 | * ftimer_gettod: version that uses gettimeofday 10 | */ 11 | #include "ftimer.h" 12 | #include 13 | #include 14 | 15 | /* function prototypes */ 16 | static void init_etime(void); 17 | static double get_etime(void); 18 | 19 | /* 20 | * ftimer_itimer - Use the interval timer to estimate the running time 21 | * of f(argp). Return the average of n runs. 22 | */ 23 | double ftimer_itimer(ftimer_test_funct f, void *argp, int n) { 24 | double start, tmeas; 25 | int i; 26 | 27 | init_etime(); 28 | start = get_etime(); 29 | for (i = 0; i < n; i++) 30 | f(argp); 31 | tmeas = get_etime() - start; 32 | return tmeas / n; 33 | } 34 | 35 | /* 36 | * ftimer_gettod - Use gettimeofday to estimate the running time of 37 | * f(argp). Return the average of n runs. 38 | */ 39 | double ftimer_gettod(ftimer_test_funct f, void *argp, int n) { 40 | int i; 41 | struct timeval stv, etv; 42 | double diff; 43 | 44 | gettimeofday(&stv, NULL); 45 | for (i = 0; i < n; i++) 46 | f(argp); 47 | gettimeofday(&etv, NULL); 48 | diff = 1E3 * (etv.tv_sec - stv.tv_sec) + 1E-3 * (etv.tv_usec - stv.tv_usec); 49 | diff /= n; 50 | return (1E-3 * diff); 51 | } 52 | 53 | /* 54 | * Routines for manipulating the Unix interval timer 55 | */ 56 | 57 | /* The initial value of the interval timer */ 58 | #define MAX_ETIME 86400 59 | 60 | /* static variables that hold the initial value of the interval timer */ 61 | static struct itimerval first_u; /* user time */ 62 | static struct itimerval first_r; /* real time */ 63 | static struct itimerval first_p; /* prof time*/ 64 | 65 | /* init the timer */ 66 | static void init_etime(void) { 67 | first_u.it_interval.tv_sec = 0; 68 | first_u.it_interval.tv_usec = 0; 69 | first_u.it_value.tv_sec = MAX_ETIME; 70 | first_u.it_value.tv_usec = 0; 71 | setitimer(ITIMER_VIRTUAL, &first_u, NULL); 72 | 73 | first_r.it_interval.tv_sec = 0; 74 | first_r.it_interval.tv_usec = 0; 75 | first_r.it_value.tv_sec = MAX_ETIME; 76 | first_r.it_value.tv_usec = 0; 77 | setitimer(ITIMER_REAL, &first_r, NULL); 78 | 79 | first_p.it_interval.tv_sec = 0; 80 | first_p.it_interval.tv_usec = 0; 81 | first_p.it_value.tv_sec = MAX_ETIME; 82 | first_p.it_value.tv_usec = 0; 83 | setitimer(ITIMER_PROF, &first_p, NULL); 84 | } 85 | 86 | /* return elapsed real seconds since call to init_etime */ 87 | static double get_etime(void) { 88 | struct itimerval v_curr; 89 | struct itimerval r_curr; 90 | struct itimerval p_curr; 91 | 92 | getitimer(ITIMER_VIRTUAL, &v_curr); 93 | getitimer(ITIMER_REAL, &r_curr); 94 | getitimer(ITIMER_PROF, &p_curr); 95 | 96 | return (double)((first_p.it_value.tv_sec - r_curr.it_value.tv_sec) + 97 | (first_p.it_value.tv_usec - r_curr.it_value.tv_usec) * 1e-6); 98 | } 99 | -------------------------------------------------------------------------------- /malloclab/ftimer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Function timers 3 | */ 4 | typedef void (*ftimer_test_funct)(void *); 5 | 6 | /* Estimate the running time of f(argp) using the Unix interval timer. 7 | Return the average of n runs */ 8 | double ftimer_itimer(ftimer_test_funct f, void *argp, int n); 9 | 10 | /* Estimate the running time of f(argp) using gettimeofday 11 | Return the average of n runs */ 12 | double ftimer_gettod(ftimer_test_funct f, void *argp, int n); 13 | -------------------------------------------------------------------------------- /malloclab/ftimer.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangchi2004/ICS-2023/a968e20339250ec42b46a271d7bd471b70493689/malloclab/ftimer.o -------------------------------------------------------------------------------- /malloclab/mdriver: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangchi2004/ICS-2023/a968e20339250ec42b46a271d7bd471b70493689/malloclab/mdriver -------------------------------------------------------------------------------- /malloclab/mdriver.c: -------------------------------------------------------------------------------- 1 | /* 2 | * mdriver.c - CS:APP Malloc Lab Driver 3 | * 4 | * Uses a collection of trace files to tests a malloc/free/realloc 5 | * implementation in mm.c. 6 | * 7 | * Copyright (c) 2002, R. Bryant and D. O'Hallaron, All rights reserved. 8 | * May not be used, modified, or copied without permission. 9 | */ 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #include "config.h" 20 | #include "fsecs.h" 21 | #include "memlib.h" 22 | #include "mm.h" 23 | 24 | /********************** 25 | * Constants and macros 26 | **********************/ 27 | 28 | /* Misc */ 29 | #define MAXLINE 1024 /* max string size */ 30 | #define HDRLINES 4 /* number of header lines in a trace file */ 31 | #define LINENUM(i) (i + 5) /* cnvt trace request nums to linenums (origin 1) \ 32 | */ 33 | 34 | /* Returns true if p is ALIGNMENT-byte aligned */ 35 | #define IS_ALIGNED(p) ((((size_t)(p)) % ALIGNMENT) == 0) 36 | 37 | /****************************** 38 | * The key compound data types 39 | *****************************/ 40 | 41 | /* Records the extent of each block's payload */ 42 | typedef struct range_t { 43 | char *lo; /* low payload address */ 44 | char *hi; /* high payload address */ 45 | struct range_t *next; /* next list element */ 46 | } range_t; 47 | 48 | /* Characterizes a single trace operation (allocator request) */ 49 | typedef struct { 50 | enum { ALLOC, FREE, REALLOC } type; /* type of request */ 51 | int index; /* index for free() to use later */ 52 | int size; /* byte size of alloc/realloc request */ 53 | } traceop_t; 54 | 55 | /* Holds the information for one trace file*/ 56 | typedef struct { 57 | int sugg_heapsize; /* suggested heap size (unused) */ 58 | int num_ids; /* number of alloc/realloc ids */ 59 | int num_ops; /* number of distinct requests */ 60 | int weight; /* weight for this trace (unused) */ 61 | traceop_t *ops; /* array of requests */ 62 | char **blocks; /* array of ptrs returned by malloc/realloc... */ 63 | size_t *block_sizes; /* ... and a corresponding array of payload sizes */ 64 | } trace_t; 65 | 66 | /* 67 | * Holds the params to the xxx_speed functions, which are timed by fcyc. 68 | * This struct is necessary because fcyc accepts only a pointer array 69 | * as input. 70 | */ 71 | typedef struct { 72 | trace_t *trace; 73 | range_t *ranges; 74 | } speed_t; 75 | 76 | /* Summarizes the important stats for some malloc function on some trace */ 77 | typedef struct { 78 | /* defined for both libc malloc and student malloc package (mm.c) */ 79 | double ops; /* number of ops (malloc/free/realloc) in the trace */ 80 | int valid; /* was the trace processed correctly by the allocator? */ 81 | double secs; /* number of secs needed to run the trace */ 82 | 83 | /* defined only for the student malloc package */ 84 | double util; /* space utilization for this trace (always 0 for libc) */ 85 | 86 | /* Note: secs and util are only defined if valid is true */ 87 | char *name; /* trace name */ 88 | } stats_t; 89 | 90 | /******************** 91 | * Global variables 92 | *******************/ 93 | int verbose = 0; /* global flag for verbose output */ 94 | static int errors = 0; /* number of errs found when running student malloc */ 95 | char msg[MAXLINE]; /* for whenever we need to compose an error message */ 96 | 97 | /* Directory where default tracefiles are found */ 98 | static char tracedir[MAXLINE] = TRACEDIR; 99 | 100 | /* The filenames of the default tracefiles */ 101 | static char *default_tracefiles[] = {DEFAULT_TRACEFILES, NULL}; 102 | 103 | /********************* 104 | * Function prototypes 105 | *********************/ 106 | 107 | /* these functions manipulate range lists */ 108 | static int add_range(range_t **ranges, char *lo, int size, int tracenum, 109 | int opnum); 110 | static void remove_range(range_t **ranges, char *lo); 111 | static void clear_ranges(range_t **ranges); 112 | 113 | /* These functions read, allocate, and free storage for traces */ 114 | static trace_t *read_trace(char *tracedir, char *filename); 115 | static void free_trace(trace_t *trace); 116 | 117 | /* Routines for evaluating the correctness and speed of libc malloc */ 118 | static int eval_libc_valid(trace_t *trace, int tracenum); 119 | static void eval_libc_speed(void *ptr); 120 | 121 | /* Routines for evaluating correctnes, space utilization, and speed 122 | of the student's malloc package in mm.c */ 123 | static int eval_mm_valid(trace_t *trace, int tracenum, range_t **ranges); 124 | static double eval_mm_util(trace_t *trace, int tracenum, range_t **ranges); 125 | static void eval_mm_speed(void *ptr); 126 | 127 | /* Various helper routines */ 128 | static void printresults(int n, stats_t *stats); 129 | static void usage(void); 130 | static void unix_error(char *msg); 131 | static void malloc_error(int tracenum, int opnum, char *msg); 132 | static void app_error(char *msg); 133 | 134 | /************** 135 | * Main routine 136 | **************/ 137 | int main(int argc, char **argv) { 138 | int i; 139 | char c; 140 | char **tracefiles = NULL; /* null-terminated array of trace file names */ 141 | int num_tracefiles = 0; /* the number of traces in that array */ 142 | trace_t *trace = NULL; /* stores a single trace file in memory */ 143 | range_t *ranges = NULL; /* keeps track of block extents for one trace */ 144 | stats_t *libc_stats = NULL; /* libc stats for each trace */ 145 | stats_t *mm_stats = NULL; /* mm (i.e. student) stats for each trace */ 146 | speed_t speed_params; /* input parameters to the xx_speed routines */ 147 | 148 | int team_check = 1; /* If set, check team structure (reset by -a) */ 149 | int run_libc = 0; /* If set, run libc malloc (set by -l) */ 150 | int autograder = 0; /* If set, emit summary info for autograder (-g) */ 151 | 152 | /* temporaries used to compute the performance index */ 153 | double secs, ops, util, avg_mm_util, avg_mm_throughput, p1, p2, score; 154 | int numcorrect; 155 | 156 | /* 157 | * Read and interpret the command line arguments 158 | */ 159 | while ((c = getopt(argc, argv, "f:t:hvVgal")) != EOF) { 160 | switch (c) { 161 | case 'g': /* Generate summary info for the autograder */ 162 | autograder = 1; 163 | break; 164 | case 'f': /* Use one specific trace file only (relative to curr dir) */ 165 | num_tracefiles = 1; 166 | if ((tracefiles = realloc(tracefiles, 2 * sizeof(char *))) == NULL) 167 | unix_error("ERROR: realloc failed in main"); 168 | strcpy(tracedir, "./"); 169 | tracefiles[0] = strdup(optarg); 170 | tracefiles[1] = NULL; 171 | break; 172 | case 't': /* Directory where the traces are located */ 173 | if (num_tracefiles == 1) /* ignore if -f already encountered */ 174 | break; 175 | strcpy(tracedir, optarg); 176 | if (tracedir[strlen(tracedir) - 1] != '/') 177 | strcat(tracedir, "/"); /* path always ends with "/" */ 178 | break; 179 | case 'a': /* Don't check team structure */ 180 | team_check = 0; 181 | break; 182 | case 'l': /* Run libc malloc */ 183 | run_libc = 1; 184 | break; 185 | case 'v': /* Print per-trace performance breakdown */ 186 | verbose = 1; 187 | break; 188 | case 'V': /* Be more verbose than -v */ 189 | verbose = 2; 190 | break; 191 | case 'h': /* Print this message */ 192 | usage(); 193 | exit(0); 194 | default: 195 | usage(); 196 | exit(1); 197 | } 198 | } 199 | 200 | /* 201 | * Check and print team info 202 | */ 203 | if (team_check) { 204 | /* Students must fill in their team information */ 205 | if (!strcmp(team.teamname, "")) { 206 | printf( 207 | "ERROR: Please provide the information about your team in mm.c.\n"); 208 | exit(1); 209 | } else 210 | printf("Team Name:%s\n", team.teamname); 211 | if ((*team.name1 == '\0') || (*team.id1 == '\0')) { 212 | printf("ERROR. You must fill in all team member 1 fields!\n"); 213 | exit(1); 214 | } else 215 | printf("Member 1 :%s:%s\n", team.name1, team.id1); 216 | 217 | if (((*team.name2 != '\0') && (*team.id2 == '\0')) || 218 | ((*team.name2 == '\0') && (*team.id2 != '\0'))) { 219 | printf("ERROR. You must fill in all or none of the team member 2 ID " 220 | "fields!\n"); 221 | exit(1); 222 | } else if (*team.name2 != '\0') 223 | printf("Member 2 :%s:%s\n", team.name2, team.id2); 224 | } 225 | 226 | /* 227 | * If no -f command line arg, then use the entire set of tracefiles 228 | * defined in default_traces[] 229 | */ 230 | if (tracefiles == NULL) { 231 | tracefiles = default_tracefiles; 232 | num_tracefiles = sizeof(default_tracefiles) / sizeof(char *) - 1; 233 | printf("Using default tracefiles in %s\n", tracedir); 234 | } 235 | 236 | /* Initialize the timing package */ 237 | init_fsecs(); 238 | 239 | /* 240 | * Optionally run and evaluate the libc malloc package 241 | */ 242 | if (run_libc) { 243 | if (verbose > 1) 244 | printf("\nTesting libc malloc\n"); 245 | 246 | /* Allocate libc stats array, with one stats_t struct per tracefile */ 247 | libc_stats = (stats_t *)calloc(num_tracefiles, sizeof(stats_t)); 248 | if (libc_stats == NULL) 249 | unix_error("libc_stats calloc in main failed"); 250 | 251 | /* Evaluate the libc malloc package using the K-best scheme */ 252 | for (i = 0; i < num_tracefiles; i++) { 253 | trace = read_trace(tracedir, tracefiles[i]); 254 | libc_stats[i].ops = trace->num_ops; 255 | if (verbose > 1) 256 | printf("Checking libc malloc for correctness, "); 257 | libc_stats[i].valid = eval_libc_valid(trace, i); 258 | if (libc_stats[i].valid) { 259 | speed_params.trace = trace; 260 | if (verbose > 1) 261 | printf("and performance.\n"); 262 | libc_stats[i].secs = fsecs(eval_libc_speed, &speed_params); 263 | } 264 | libc_stats[i].name = tracefiles[i]; 265 | free_trace(trace); 266 | } 267 | 268 | /* Display the libc results in a compact table */ 269 | if (verbose) { 270 | printf("\nResults for libc malloc:\n"); 271 | printresults(num_tracefiles, libc_stats); 272 | } 273 | } 274 | 275 | /* 276 | * Always run and evaluate the student's mm package 277 | */ 278 | if (verbose > 1) 279 | printf("\nTesting mm malloc\n"); 280 | 281 | /* Allocate the mm stats array, with one stats_t struct per tracefile */ 282 | mm_stats = (stats_t *)calloc(num_tracefiles, sizeof(stats_t)); 283 | if (mm_stats == NULL) 284 | unix_error("mm_stats calloc in main failed"); 285 | 286 | /* Initialize the simulated memory system in memlib.c */ 287 | mem_init(); 288 | 289 | /* Evaluate student's mm malloc package using the K-best scheme */ 290 | for (i = 0; i < num_tracefiles; i++) { 291 | trace = read_trace(tracedir, tracefiles[i]); 292 | mm_stats[i].ops = trace->num_ops; 293 | if (verbose > 1) 294 | printf("Checking mm_malloc for correctness, "); 295 | mm_stats[i].valid = eval_mm_valid(trace, i, &ranges); 296 | if (mm_stats[i].valid) { 297 | if (verbose > 1) 298 | printf("efficiency, "); 299 | mm_stats[i].util = eval_mm_util(trace, i, &ranges); 300 | speed_params.trace = trace; 301 | speed_params.ranges = ranges; 302 | if (verbose > 1) 303 | printf("and performance.\n"); 304 | mm_stats[i].secs = fsecs(eval_mm_speed, &speed_params); 305 | } 306 | mm_stats[i].name = tracefiles[i]; 307 | free_trace(trace); 308 | } 309 | 310 | /* Display the mm results in a compact table */ 311 | if (verbose) { 312 | printf("\nResults for mm malloc:\n"); 313 | printresults(num_tracefiles, mm_stats); 314 | printf("\n"); 315 | } 316 | 317 | /* 318 | * Accumulate the aggregate statistics for the student's mm package 319 | */ 320 | secs = 0; 321 | ops = 0; 322 | util = 0; 323 | numcorrect = 0; 324 | for (i = 0; i < num_tracefiles; i++) { 325 | secs += mm_stats[i].secs; 326 | ops += mm_stats[i].ops; 327 | util += mm_stats[i].util; 328 | if (mm_stats[i].valid) 329 | numcorrect++; 330 | } 331 | avg_mm_util = util / num_tracefiles; 332 | 333 | /* 334 | * Compute and print the performance index 335 | */ 336 | avg_mm_throughput = ops / secs; 337 | 338 | p1 = UTIL_WEIGHT * avg_mm_util; 339 | if (avg_mm_throughput > AVG_LIBC_THRUPUT) { 340 | p2 = (double)(1.0 - UTIL_WEIGHT); 341 | } else { 342 | p2 = ((double)(1.0 - UTIL_WEIGHT)) * (avg_mm_throughput / AVG_LIBC_THRUPUT); 343 | } 344 | 345 | score = (p1 + p2) * 100.0; 346 | score = score * numcorrect / num_tracefiles; 347 | printf("Score = (%.0f (util) + %.0f (thru)) * %d/%d (testcase) = %.0f/100\n", 348 | p1 * 100, p2 * 100, numcorrect, num_tracefiles, score); 349 | 350 | if (errors != 0) { 351 | /* There were errors */ 352 | printf("%d errors occurred\n", errors); 353 | } 354 | 355 | if (autograder) { 356 | printf("correct:%d\n", numcorrect); 357 | printf("score:%.0f\n", score); 358 | } 359 | 360 | exit(0); 361 | } 362 | 363 | /***************************************************************** 364 | * The following routines manipulate the range list, which keeps 365 | * track of the extent of every allocated block payload. We use the 366 | * range list to detect any overlapping allocated blocks. 367 | ****************************************************************/ 368 | 369 | /* 370 | * add_range - As directed by request opnum in trace tracenum, 371 | * we've just called the student's mm_malloc to allocate a block of 372 | * size bytes at addr lo. After checking the block for correctness, 373 | * we create a range struct for this block and add it to the range list. 374 | */ 375 | static int add_range(range_t **ranges, char *lo, int size, int tracenum, 376 | int opnum) { 377 | char *hi = lo + size - 1; 378 | range_t *p; 379 | char msg[MAXLINE]; 380 | 381 | assert(size > 0); 382 | 383 | /* Payload addresses must be ALIGNMENT-byte aligned */ 384 | if (!IS_ALIGNED(lo)) { 385 | sprintf(msg, "Payload address (%p) not aligned to %d bytes", lo, ALIGNMENT); 386 | malloc_error(tracenum, opnum, msg); 387 | return 0; 388 | } 389 | 390 | /* The payload must lie within the extent of the heap */ 391 | if ((lo < (char *)mem_heap_lo()) || (lo > (char *)mem_heap_hi()) || 392 | (hi < (char *)mem_heap_lo()) || (hi > (char *)mem_heap_hi())) { 393 | sprintf(msg, "Payload (%p:%p) lies outside heap (%p:%p)", lo, hi, 394 | mem_heap_lo(), mem_heap_hi()); 395 | malloc_error(tracenum, opnum, msg); 396 | return 0; 397 | } 398 | 399 | /* The payload must not overlap any other payloads */ 400 | for (p = *ranges; p != NULL; p = p->next) { 401 | if ((lo >= p->lo && lo <= p->hi) || (hi >= p->lo && hi <= p->hi)) { 402 | sprintf(msg, "Payload (%p:%p) overlaps another payload (%p:%p)\n", lo, hi, 403 | p->lo, p->hi); 404 | malloc_error(tracenum, opnum, msg); 405 | return 0; 406 | } 407 | } 408 | 409 | /* 410 | * Everything looks OK, so remember the extent of this block 411 | * by creating a range struct and adding it the range list. 412 | */ 413 | if ((p = (range_t *)malloc(sizeof(range_t))) == NULL) 414 | unix_error("malloc error in add_range"); 415 | p->next = *ranges; 416 | p->lo = lo; 417 | p->hi = hi; 418 | *ranges = p; 419 | return 1; 420 | } 421 | 422 | /* 423 | * remove_range - Free the range record of block whose payload starts at lo 424 | */ 425 | static void remove_range(range_t **ranges, char *lo) { 426 | range_t *p; 427 | range_t **prevpp = ranges; 428 | int size; 429 | 430 | for (p = *ranges; p != NULL; p = p->next) { 431 | if (p->lo == lo) { 432 | *prevpp = p->next; 433 | size = p->hi - p->lo + 1; 434 | free(p); 435 | break; 436 | } 437 | prevpp = &(p->next); 438 | } 439 | } 440 | 441 | /* 442 | * clear_ranges - free all of the range records for a trace 443 | */ 444 | static void clear_ranges(range_t **ranges) { 445 | range_t *p; 446 | range_t *pnext; 447 | 448 | for (p = *ranges; p != NULL; p = pnext) { 449 | pnext = p->next; 450 | free(p); 451 | } 452 | *ranges = NULL; 453 | } 454 | 455 | /********************************************** 456 | * The following routines manipulate tracefiles 457 | *********************************************/ 458 | 459 | /* 460 | * read_trace - read a trace file and store it in memory 461 | */ 462 | static trace_t *read_trace(char *tracedir, char *filename) { 463 | FILE *tracefile; 464 | trace_t *trace; 465 | char type[MAXLINE]; 466 | char path[MAXLINE]; 467 | unsigned index, size; 468 | unsigned max_index = 0; 469 | unsigned op_index; 470 | 471 | if (verbose > 1) 472 | printf("Reading tracefile: %s\n", filename); 473 | 474 | /* Allocate the trace record */ 475 | if ((trace = (trace_t *)malloc(sizeof(trace_t))) == NULL) 476 | unix_error("malloc 1 failed in read_trance"); 477 | 478 | /* Read the trace file header */ 479 | strcpy(path, tracedir); 480 | strcat(path, filename); 481 | if ((tracefile = fopen(path, "r")) == NULL) { 482 | sprintf(msg, "Could not open %s in read_trace", path); 483 | unix_error(msg); 484 | } 485 | fscanf(tracefile, "%d", &(trace->sugg_heapsize)); /* not used */ 486 | fscanf(tracefile, "%d", &(trace->num_ids)); 487 | fscanf(tracefile, "%d", &(trace->num_ops)); 488 | fscanf(tracefile, "%d", &(trace->weight)); /* not used */ 489 | 490 | /* We'll store each request line in the trace in this array */ 491 | if ((trace->ops = (traceop_t *)malloc(trace->num_ops * sizeof(traceop_t))) == 492 | NULL) 493 | unix_error("malloc 2 failed in read_trace"); 494 | 495 | /* We'll keep an array of pointers to the allocated blocks here... */ 496 | if ((trace->blocks = (char **)malloc(trace->num_ids * sizeof(char *))) == 497 | NULL) 498 | unix_error("malloc 3 failed in read_trace"); 499 | 500 | /* ... along with the corresponding byte sizes of each block */ 501 | if ((trace->block_sizes = 502 | (size_t *)malloc(trace->num_ids * sizeof(size_t))) == NULL) 503 | unix_error("malloc 4 failed in read_trace"); 504 | 505 | /* read every request line in the trace file */ 506 | index = 0; 507 | op_index = 0; 508 | while (fscanf(tracefile, "%s", type) != EOF) { 509 | switch (type[0]) { 510 | case 'a': 511 | fscanf(tracefile, "%u %u", &index, &size); 512 | trace->ops[op_index].type = ALLOC; 513 | trace->ops[op_index].index = index; 514 | trace->ops[op_index].size = size; 515 | max_index = (index > max_index) ? index : max_index; 516 | break; 517 | case 'r': 518 | fscanf(tracefile, "%u %u", &index, &size); 519 | trace->ops[op_index].type = REALLOC; 520 | trace->ops[op_index].index = index; 521 | trace->ops[op_index].size = size; 522 | max_index = (index > max_index) ? index : max_index; 523 | break; 524 | case 'f': 525 | fscanf(tracefile, "%ud", &index); 526 | trace->ops[op_index].type = FREE; 527 | trace->ops[op_index].index = index; 528 | break; 529 | default: 530 | printf("Bogus type character (%c) in tracefile %s\n", type[0], path); 531 | exit(1); 532 | } 533 | op_index++; 534 | } 535 | fclose(tracefile); 536 | assert(max_index == trace->num_ids - 1); 537 | assert(trace->num_ops == op_index); 538 | 539 | return trace; 540 | } 541 | 542 | /* 543 | * free_trace - Free the trace record and the three arrays it points 544 | * to, all of which were allocated in read_trace(). 545 | */ 546 | void free_trace(trace_t *trace) { 547 | free(trace->ops); /* free the three arrays... */ 548 | free(trace->blocks); 549 | free(trace->block_sizes); 550 | free(trace); /* and the trace record itself... */ 551 | } 552 | 553 | /********************************************************************** 554 | * The following functions evaluate the correctness, space utilization, 555 | * and throughput of the libc and mm malloc packages. 556 | **********************************************************************/ 557 | 558 | /* 559 | * eval_mm_valid - Check the mm malloc package for correctness 560 | */ 561 | static int eval_mm_valid(trace_t *trace, int tracenum, range_t **ranges) { 562 | int i, j; 563 | int index; 564 | int size; 565 | int oldsize; 566 | char *newp; 567 | char *oldp; 568 | char *p; 569 | 570 | /* Reset the heap and free any records in the range list */ 571 | mem_reset_brk(); 572 | clear_ranges(ranges); 573 | 574 | /* Call the mm package's init function */ 575 | if (mm_init() < 0) { 576 | malloc_error(tracenum, 0, "mm_init failed."); 577 | return 0; 578 | } 579 | 580 | /* Interpret each operation in the trace in order */ 581 | for (i = 0; i < trace->num_ops; i++) { 582 | index = trace->ops[i].index; 583 | size = trace->ops[i].size; 584 | 585 | switch (trace->ops[i].type) { 586 | 587 | case ALLOC: /* mm_malloc */ 588 | 589 | /* Call the student's malloc */ 590 | if ((p = mm_malloc(size)) == NULL) { 591 | malloc_error(tracenum, i, "mm_malloc failed."); 592 | return 0; 593 | } 594 | 595 | /* 596 | * Test the range of the new block for correctness and add it 597 | * to the range list if OK. The block must be be aligned properly, 598 | * and must not overlap any currently allocated block. 599 | */ 600 | if (add_range(ranges, p, size, tracenum, i) == 0) 601 | return 0; 602 | 603 | /* ADDED: cgw 604 | * fill range with low byte of index. This will be used later 605 | * if we realloc the block and wish to make sure that the old 606 | * data was copied to the new block 607 | */ 608 | memset(p, index & 0xFF, size); 609 | 610 | /* Remember region */ 611 | trace->blocks[index] = p; 612 | trace->block_sizes[index] = size; 613 | break; 614 | 615 | case REALLOC: /* mm_realloc */ 616 | 617 | /* Call the student's realloc */ 618 | oldp = trace->blocks[index]; 619 | if ((newp = mm_realloc(oldp, size)) == NULL) { 620 | malloc_error(tracenum, i, "mm_realloc failed."); 621 | return 0; 622 | } 623 | 624 | /* Remove the old region from the range list */ 625 | remove_range(ranges, oldp); 626 | 627 | /* Check new block for correctness and add it to range list */ 628 | if (add_range(ranges, newp, size, tracenum, i) == 0) 629 | return 0; 630 | 631 | /* ADDED: cgw 632 | * Make sure that the new block contains the data from the old 633 | * block and then fill in the new block with the low order byte 634 | * of the new index 635 | */ 636 | oldsize = trace->block_sizes[index]; 637 | if (size < oldsize) 638 | oldsize = size; 639 | for (j = 0; j < oldsize; j++) { 640 | if ((unsigned char)newp[j] != (index & 0xFF)) { 641 | malloc_error(tracenum, i, 642 | "mm_realloc did not preserve the " 643 | "data from old block"); 644 | return 0; 645 | } 646 | } 647 | memset(newp, index & 0xFF, size); 648 | 649 | /* Remember region */ 650 | trace->blocks[index] = newp; 651 | trace->block_sizes[index] = size; 652 | break; 653 | 654 | case FREE: /* mm_free */ 655 | 656 | /* Remove region from list and call student's free function */ 657 | p = trace->blocks[index]; 658 | remove_range(ranges, p); 659 | mm_free(p); 660 | break; 661 | 662 | default: 663 | app_error("Nonexistent request type in eval_mm_valid"); 664 | } 665 | } 666 | 667 | /* As far as we know, this is a valid malloc package */ 668 | return 1; 669 | } 670 | 671 | /* 672 | * eval_mm_util - Evaluate the space utilization of the student's package 673 | * The idea is to remember the high water mark "hwm" of the heap for 674 | * an optimal allocator, i.e., no gaps and no internal fragmentation. 675 | * Utilization is the ratio hwm/heapsize, where heapsize is the 676 | * size of the heap in bytes after running the student's malloc 677 | * package on the trace. Note that our implementation of mem_sbrk() 678 | * doesn't allow the students to decrement the brk pointer, so brk 679 | * is always the high water mark of the heap. 680 | * 681 | */ 682 | static double eval_mm_util(trace_t *trace, int tracenum, range_t **ranges) { 683 | int i; 684 | int index; 685 | int size, newsize, oldsize; 686 | int max_total_size = 0; 687 | int total_size = 0; 688 | char *p; 689 | char *newp, *oldp; 690 | 691 | /* initialize the heap and the mm malloc package */ 692 | mem_reset_brk(); 693 | if (mm_init() < 0) 694 | app_error("mm_init failed in eval_mm_util"); 695 | 696 | for (i = 0; i < trace->num_ops; i++) { 697 | switch (trace->ops[i].type) { 698 | 699 | case ALLOC: /* mm_alloc */ 700 | index = trace->ops[i].index; 701 | size = trace->ops[i].size; 702 | 703 | if ((p = mm_malloc(size)) == NULL) 704 | app_error("mm_malloc failed in eval_mm_util"); 705 | 706 | /* Remember region and size */ 707 | trace->blocks[index] = p; 708 | trace->block_sizes[index] = size; 709 | 710 | /* Keep track of current total size 711 | * of all allocated blocks */ 712 | total_size += size; 713 | 714 | /* Update statistics */ 715 | max_total_size = 716 | (total_size > max_total_size) ? total_size : max_total_size; 717 | break; 718 | 719 | case REALLOC: /* mm_realloc */ 720 | index = trace->ops[i].index; 721 | newsize = trace->ops[i].size; 722 | oldsize = trace->block_sizes[index]; 723 | 724 | oldp = trace->blocks[index]; 725 | if ((newp = mm_realloc(oldp, newsize)) == NULL) 726 | app_error("mm_realloc failed in eval_mm_util"); 727 | 728 | /* Remember region and size */ 729 | trace->blocks[index] = newp; 730 | trace->block_sizes[index] = newsize; 731 | 732 | /* Keep track of current total size 733 | * of all allocated blocks */ 734 | total_size += (newsize - oldsize); 735 | 736 | /* Update statistics */ 737 | max_total_size = 738 | (total_size > max_total_size) ? total_size : max_total_size; 739 | break; 740 | 741 | case FREE: /* mm_free */ 742 | index = trace->ops[i].index; 743 | size = trace->block_sizes[index]; 744 | p = trace->blocks[index]; 745 | 746 | mm_free(p); 747 | 748 | /* Keep track of current total size 749 | * of all allocated blocks */ 750 | total_size -= size; 751 | 752 | break; 753 | 754 | default: 755 | app_error("Nonexistent request type in eval_mm_util"); 756 | } 757 | } 758 | 759 | return ((double)max_total_size / (double)mem_heapsize()); 760 | } 761 | 762 | /* 763 | * eval_mm_speed - This is the function that is used by fcyc() 764 | * to measure the running time of the mm malloc package. 765 | */ 766 | static void eval_mm_speed(void *ptr) { 767 | int i, index, size, newsize; 768 | char *p, *newp, *oldp, *block; 769 | trace_t *trace = ((speed_t *)ptr)->trace; 770 | 771 | /* Reset the heap and initialize the mm package */ 772 | mem_reset_brk(); 773 | if (mm_init() < 0) 774 | app_error("mm_init failed in eval_mm_speed"); 775 | 776 | /* Interpret each trace request */ 777 | for (i = 0; i < trace->num_ops; i++) 778 | switch (trace->ops[i].type) { 779 | 780 | case ALLOC: /* mm_malloc */ 781 | index = trace->ops[i].index; 782 | size = trace->ops[i].size; 783 | if ((p = mm_malloc(size)) == NULL) 784 | app_error("mm_malloc error in eval_mm_speed"); 785 | trace->blocks[index] = p; 786 | break; 787 | 788 | case REALLOC: /* mm_realloc */ 789 | index = trace->ops[i].index; 790 | newsize = trace->ops[i].size; 791 | oldp = trace->blocks[index]; 792 | if ((newp = mm_realloc(oldp, newsize)) == NULL) 793 | app_error("mm_realloc error in eval_mm_speed"); 794 | trace->blocks[index] = newp; 795 | break; 796 | 797 | case FREE: /* mm_free */ 798 | index = trace->ops[i].index; 799 | block = trace->blocks[index]; 800 | mm_free(block); 801 | break; 802 | 803 | default: 804 | app_error("Nonexistent request type in eval_mm_valid"); 805 | } 806 | } 807 | 808 | /* 809 | * eval_libc_valid - We run this function to make sure that the 810 | * libc malloc can run to completion on the set of traces. 811 | * We'll be conservative and terminate if any libc malloc call fails. 812 | * 813 | */ 814 | static int eval_libc_valid(trace_t *trace, int tracenum) { 815 | int i, newsize; 816 | char *p, *newp, *oldp; 817 | 818 | for (i = 0; i < trace->num_ops; i++) { 819 | switch (trace->ops[i].type) { 820 | 821 | case ALLOC: /* malloc */ 822 | if ((p = malloc(trace->ops[i].size)) == NULL) { 823 | malloc_error(tracenum, i, "libc malloc failed"); 824 | unix_error("System message"); 825 | } 826 | trace->blocks[trace->ops[i].index] = p; 827 | break; 828 | 829 | case REALLOC: /* realloc */ 830 | newsize = trace->ops[i].size; 831 | oldp = trace->blocks[trace->ops[i].index]; 832 | if ((newp = realloc(oldp, newsize)) == NULL) { 833 | malloc_error(tracenum, i, "libc realloc failed"); 834 | unix_error("System message"); 835 | } 836 | trace->blocks[trace->ops[i].index] = newp; 837 | break; 838 | 839 | case FREE: /* free */ 840 | free(trace->blocks[trace->ops[i].index]); 841 | break; 842 | 843 | default: 844 | app_error("invalid operation type in eval_libc_valid"); 845 | } 846 | } 847 | 848 | return 1; 849 | } 850 | 851 | /* 852 | * eval_libc_speed - This is the function that is used by fcyc() to 853 | * measure the running time of the libc malloc package on the set 854 | * of traces. 855 | */ 856 | static void eval_libc_speed(void *ptr) { 857 | int i; 858 | int index, size, newsize; 859 | char *p, *newp, *oldp, *block; 860 | trace_t *trace = ((speed_t *)ptr)->trace; 861 | 862 | for (i = 0; i < trace->num_ops; i++) { 863 | switch (trace->ops[i].type) { 864 | case ALLOC: /* malloc */ 865 | index = trace->ops[i].index; 866 | size = trace->ops[i].size; 867 | if ((p = malloc(size)) == NULL) 868 | unix_error("malloc failed in eval_libc_speed"); 869 | trace->blocks[index] = p; 870 | break; 871 | 872 | case REALLOC: /* realloc */ 873 | index = trace->ops[i].index; 874 | newsize = trace->ops[i].size; 875 | oldp = trace->blocks[index]; 876 | if ((newp = realloc(oldp, newsize)) == NULL) 877 | unix_error("realloc failed in eval_libc_speed\n"); 878 | 879 | trace->blocks[index] = newp; 880 | break; 881 | 882 | case FREE: /* free */ 883 | index = trace->ops[i].index; 884 | block = trace->blocks[index]; 885 | free(block); 886 | break; 887 | } 888 | } 889 | } 890 | 891 | /************************************* 892 | * Some miscellaneous helper routines 893 | ************************************/ 894 | 895 | /* 896 | * printresults - prints a performance summary for some malloc package 897 | */ 898 | static void printresults(int n, stats_t *stats) { 899 | int i; 900 | double secs = 0; 901 | double ops = 0; 902 | double util = 0; 903 | 904 | /* Print the individual results for each trace */ 905 | printf("%5s%16s%10s %5s%8s%10s%7s\n", "trace", "name", "valid", "util", "ops", 906 | "secs", "Kops"); 907 | for (i = 0; i < n; i++) { 908 | if (stats[i].valid) { 909 | printf("%2d%19s%10s%5.0f%%%8.0f%10.6f%7.0f\n", i + 1, stats[i].name, 910 | "yes", stats[i].util * 100.0, stats[i].ops, stats[i].secs, 911 | (stats[i].ops / 1e3) / stats[i].secs); 912 | secs += stats[i].secs; 913 | ops += stats[i].ops; 914 | util += stats[i].util; 915 | } else { 916 | printf("%2d%19s%10s%6s%8s%10s%7s\n", i + 1, stats[i].name, "no", "-", "-", 917 | "-", "-"); 918 | } 919 | } 920 | 921 | /* Print the aggregate results for the set of traces */ 922 | if (errors == 0) { 923 | printf("%12s%19s%5.0f%%%8.0f%10.6f%7.0f\n", "Total ", "", 924 | (util / n) * 100.0, ops, secs, (ops / 1e3) / secs); 925 | } else { 926 | printf("%12s%19s%6s%8s%10s%7s\n", "Total ", "", "-", "-", "-", "-"); 927 | } 928 | } 929 | 930 | /* 931 | * app_error - Report an arbitrary application error 932 | */ 933 | void app_error(char *msg) { 934 | printf("%s\n", msg); 935 | exit(1); 936 | } 937 | 938 | /* 939 | * unix_error - Report a Unix-style error 940 | */ 941 | void unix_error(char *msg) { 942 | printf("%s: %s\n", msg, strerror(errno)); 943 | exit(1); 944 | } 945 | 946 | /* 947 | * malloc_error - Report an error returned by the mm_malloc package 948 | */ 949 | void malloc_error(int tracenum, int opnum, char *msg) { 950 | errors++; 951 | printf("ERROR [trace %d, line %d]: %s\n", tracenum, LINENUM(opnum), msg); 952 | } 953 | 954 | /* 955 | * usage - Explain the command line arguments 956 | */ 957 | static void usage(void) { 958 | fprintf(stderr, "Usage: mdriver [-hvVal] [-f ] [-t ]\n"); 959 | fprintf(stderr, "Options\n"); 960 | fprintf(stderr, "\t-a Don't check the team structure.\n"); 961 | fprintf(stderr, "\t-f Use as the trace file.\n"); 962 | fprintf(stderr, "\t-g Generate summary info for autograder.\n"); 963 | fprintf(stderr, "\t-h Print this message.\n"); 964 | fprintf(stderr, "\t-l Run libc malloc as well.\n"); 965 | fprintf(stderr, "\t-t Directory to find default traces.\n"); 966 | fprintf(stderr, "\t-v Print per-trace performance breakdowns.\n"); 967 | fprintf(stderr, "\t-V Print additional debug info.\n"); 968 | } 969 | -------------------------------------------------------------------------------- /malloclab/mdriver.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangchi2004/ICS-2023/a968e20339250ec42b46a271d7bd471b70493689/malloclab/mdriver.o -------------------------------------------------------------------------------- /malloclab/memlib.c: -------------------------------------------------------------------------------- 1 | /* 2 | * memlib.c - a module that simulates the memory system. Needed because it 3 | * allows us to interleave calls from the student's malloc package 4 | * with the system's malloc package in libc. 5 | */ 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include "config.h" 15 | #include "memlib.h" 16 | 17 | /* private variables */ 18 | static char *mem_start_brk; /* points to first byte of heap */ 19 | static char *mem_brk; /* points to last byte of heap */ 20 | static char *mem_max_addr; /* largest legal heap address */ 21 | 22 | /* 23 | * mem_init - initialize the memory system model 24 | */ 25 | void mem_init(void) { 26 | /* allocate the storage we will use to model the available VM */ 27 | if ((mem_start_brk = (char *)malloc(MAX_HEAP)) == NULL) { 28 | fprintf(stderr, "mem_init_vm: malloc error\n"); 29 | exit(1); 30 | } 31 | 32 | mem_max_addr = mem_start_brk + MAX_HEAP; /* max legal heap address */ 33 | mem_brk = mem_start_brk; /* heap is empty initially */ 34 | } 35 | 36 | /* 37 | * mem_deinit - free the storage used by the memory system model 38 | */ 39 | void mem_deinit(void) { free(mem_start_brk); } 40 | 41 | /* 42 | * mem_reset_brk - reset the simulated brk pointer to make an empty heap 43 | */ 44 | void mem_reset_brk() { mem_brk = mem_start_brk; } 45 | 46 | /* 47 | * mem_sbrk - simple model of the sbrk function. Extends the heap 48 | * by incr bytes and returns the start address of the new area. In 49 | * this model, the heap cannot be shrunk. 50 | */ 51 | void *mem_sbrk(int incr) { 52 | char *old_brk = mem_brk; 53 | 54 | if ((incr < 0) || ((mem_brk + incr) > mem_max_addr)) { 55 | errno = ENOMEM; 56 | fprintf(stderr, "ERROR: mem_sbrk failed. Ran out of memory...\n"); 57 | return (void *)-1; 58 | } 59 | mem_brk += incr; 60 | return (void *)old_brk; 61 | } 62 | 63 | /* 64 | * mem_heap_lo - return address of the first heap byte 65 | */ 66 | void *mem_heap_lo() { return (void *)mem_start_brk; } 67 | 68 | /* 69 | * mem_heap_hi - return address of last heap byte 70 | */ 71 | void *mem_heap_hi() { return (void *)(mem_brk - 1); } 72 | 73 | /* 74 | * mem_heapsize() - returns the heap size in bytes 75 | */ 76 | size_t mem_heapsize() { return (size_t)(mem_brk - mem_start_brk); } 77 | 78 | /* 79 | * mem_pagesize() - returns the page size of the system 80 | */ 81 | size_t mem_pagesize() { return (size_t)getpagesize(); } 82 | -------------------------------------------------------------------------------- /malloclab/memlib.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void mem_init(void); 4 | void mem_deinit(void); 5 | void *mem_sbrk(int incr); 6 | void mem_reset_brk(void); 7 | void *mem_heap_lo(void); 8 | void *mem_heap_hi(void); 9 | size_t mem_heapsize(void); 10 | size_t mem_pagesize(void); 11 | -------------------------------------------------------------------------------- /malloclab/memlib.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangchi2004/ICS-2023/a968e20339250ec42b46a271d7bd471b70493689/malloclab/memlib.o -------------------------------------------------------------------------------- /malloclab/mm.c: -------------------------------------------------------------------------------- 1 | /* 2 | * mm-naive.c - The fastest, least memory-efficient malloc package. 3 | * 4 | * In this naive approach, a block is allocated by simply incrementing 5 | * the brk pointer. A block is pure payload. There are no headers or 6 | * footers. Blocks are never coalesced or reused. Realloc is 7 | * implemented directly using mm_malloc and mm_free. 8 | * 9 | * NOTE TO STUDENTS: Replace this header comment with your own header 10 | * comment that gives a high level description of your solution. 11 | */ 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include "memlib.h" 19 | #include "mm.h" 20 | 21 | /********************************************************* 22 | * NOTE TO STUDENTS: Before you do anything else, please 23 | * provide your team information in the following struct. 24 | ********************************************************/ 25 | team_t team = { 26 | /* Team name */ 27 | "2022010754", 28 | /* First member's full name */ 29 | "Zhang Chi", 30 | /* First member's email address */ 31 | "zhang-ch22@mails.tsinghua.edu.cn", 32 | /* Second member's full name (leave blank if none) */ 33 | "", 34 | /* Second member's email address (leave blank if none) */ 35 | ""}; 36 | 37 | /* 16 bytes alignment */ 38 | #define ALIGNMENT 16 39 | 40 | /* rounds up to the nearest multiple of ALIGNMENT */ 41 | #define ALIGN(size) (((size) + (ALIGNMENT - 1)) & ~(ALIGNMENT - 1)) 42 | 43 | #define SIZE_T_SIZE (ALIGN(sizeof(size_t))) 44 | 45 | #define DSIZE 8 46 | #define QSIZE 16 47 | #define CHUNKSIZE 512 48 | 49 | #define MAX(x, y) ((x) > (y) ? (x) : (y)) 50 | #define MIN(x, y) ((x) < (y) ? (x) : (y)) 51 | #define PACK(size, alloc) ((size) | (alloc)) 52 | #define GET(p) (*(size_t *)(p)) 53 | #define PUT(p, val) (*(size_t *)(p) = (val)) 54 | 55 | #define GET_SIZE(p) (GET(p) & ~0xf) 56 | #define GET_ALLOC(p) (GET(p) & 0x1) 57 | #define PUT_ALLOC(p) (GET(p) |= 0x1) 58 | #define REMOVE_ALLOC(p) (GET(p) &= ~0x1) 59 | 60 | #define HDRP(bp) ((char *)(bp) - DSIZE) // header pointer 61 | #define FTRP(bp) ((char *)(bp) + GET_SIZE(HDRP(bp)) - QSIZE) // footer pointer 62 | #define BP_GET_SIZE(bp) (GET_SIZE(HDRP(bp))) 63 | #define BP_GET_ALLOC(bp) (GET_ALLOC(HDRP(bp))) 64 | #define BP_PUT_ALLOC(bp) (PUT_ALLOC(HDRP(bp))) 65 | #define BP_REMOVE_ALLOC(bp) (REMOVE_ALLOC(HDRP(bp))) 66 | 67 | #define NEXT_BLKP(bp) ((char *)(bp) + BP_GET_SIZE(bp)) 68 | #define PREV_FTRP(bp) ((char *)(bp) - QSIZE) 69 | #define PREV_BLKP(bp) ((char *)(bp) - GET_SIZE(PREV_FTRP(bp))) 70 | 71 | #define FREE_PRED(bp) (*((size_t *)(bp))) 72 | #define FREE_SUCC(bp) (*((size_t *)(bp) + 1)) 73 | #define PUT_FREE_PRED(bp, pred) (*((size_t *)(bp)) = pred) 74 | #define PUT_FREE_SUCC(bp, succ) (*((size_t *)(bp) + 1) = succ) 75 | 76 | #define FREE_LIST_LEN 16 77 | #define SEG_MAX (1<<13) 78 | /* 79 | * mm_init - initialize the malloc package. 80 | */ 81 | 82 | static char *heap_listp = 0; 83 | static char *free_listp = 0; 84 | 85 | static size_t get_idx(size_t size){ 86 | if(size >= SEG_MAX){ 87 | return FREE_LIST_LEN-1; 88 | } 89 | switch(size){ 90 | case 32: 91 | return 0; 92 | case 48: 93 | return 1; 94 | case 64: 95 | return 2; 96 | case 80: 97 | return 3; 98 | case 96: 99 | return 4; 100 | case 112: 101 | return 5; 102 | case 128: 103 | return 6; 104 | case 144: 105 | return 7; 106 | 107 | default: 108 | break; 109 | } 110 | int ilog = 0; 111 | while(size){ 112 | size >>= 1; 113 | ilog++; 114 | } 115 | return ilog; 116 | } 117 | 118 | static void insert(void* bp){ 119 | size_t idx = get_idx(BP_GET_SIZE(bp)); 120 | size_t* head = free_listp + idx * DSIZE; 121 | size_t* sec = *head; 122 | 123 | if(sec)PUT_FREE_PRED(sec, bp); 124 | PUT_FREE_SUCC(bp, sec); 125 | PUT_FREE_PRED(bp, head); 126 | *head = bp; 127 | return; 128 | } 129 | 130 | static void list_remove(void* bp){ 131 | size_t idx = get_idx(BP_GET_SIZE(bp)); 132 | size_t* head = free_listp + idx * DSIZE; 133 | size_t* pred = (size_t*)FREE_PRED(bp); 134 | size_t* succ = (size_t*)FREE_SUCC(bp); 135 | 136 | if(pred!=head){ 137 | PUT_FREE_SUCC(pred, succ); 138 | } 139 | else{ 140 | *head = succ; 141 | } 142 | if(succ)PUT_FREE_PRED(succ, pred); 143 | 144 | PUT_FREE_PRED(bp, NULL); 145 | PUT_FREE_SUCC(bp, NULL); 146 | return; 147 | } 148 | 149 | static void * find_fit(size_t asize){ 150 | size_t idx = get_idx(asize); 151 | size_t* head = free_listp + idx * DSIZE; 152 | for(size_t*p = *head; p!=NULL; p = FREE_SUCC(p)){ 153 | if(BP_GET_SIZE(p) >= asize){ 154 | return p; 155 | } 156 | } 157 | for(idx++;idx0; bp = NEXT_BLKP(bp)){ 167 | printf("%p %d %d\n", bp, BP_GET_SIZE(bp), BP_GET_ALLOC(bp)); 168 | } 169 | } 170 | 171 | static void* coalesce(void* bp){ 172 | void *prev = PREV_BLKP(bp); 173 | void *next = NEXT_BLKP(bp); 174 | 175 | size_t prev_alloc = BP_GET_ALLOC(prev); 176 | size_t next_alloc = BP_GET_ALLOC(next); 177 | size_t size = BP_GET_SIZE(bp); 178 | if(prev_alloc && next_alloc){ 179 | insert(bp); 180 | return bp; 181 | } 182 | else if(prev_alloc && !next_alloc){ 183 | list_remove(next); 184 | size += BP_GET_SIZE(next); 185 | PUT(HDRP(bp), PACK(size, 0)); 186 | PUT(FTRP(bp), PACK(size, 0)); 187 | insert(bp); 188 | return bp; 189 | } 190 | else if(!prev_alloc && next_alloc){ 191 | list_remove(prev); 192 | size += BP_GET_SIZE(prev); 193 | PUT(FTRP(bp), PACK(size, 0)); 194 | PUT(HDRP(prev), PACK(size, 0)); 195 | insert(prev); 196 | return prev; 197 | } 198 | else{ 199 | list_remove(prev); 200 | list_remove(next); 201 | size += (BP_GET_SIZE(prev) + BP_GET_SIZE(next)); 202 | PUT(HDRP(prev), PACK(size, 0)); 203 | PUT(FTRP(next), PACK(size, 0)); 204 | insert(prev); 205 | return prev; 206 | } 207 | } 208 | size_t reg(size_t TSIZE){ 209 | if(TSIZE==7*QSIZE)return TSIZE + QSIZE; 210 | if(TSIZE==448)return 512; 211 | return TSIZE; 212 | } 213 | 214 | static void* alloc(void *bp, size_t size){ 215 | size_t old_size = BP_GET_SIZE(bp); 216 | size_t res_size = old_size - size; 217 | if(res_size < 2*QSIZE){ 218 | PUT(HDRP(bp), PACK(old_size, 1)); 219 | PUT(FTRP(bp), PACK(old_size, 1)); 220 | } 221 | else{ 222 | PUT(HDRP(bp), PACK(size, 1)); 223 | PUT(FTRP(bp), PACK(size, 1)); 224 | void* res = NEXT_BLKP(bp); 225 | PUT(HDRP(res), PACK(res_size, 0)); 226 | PUT(FTRP(res), PACK(res_size, 0)); 227 | coalesce(res); 228 | } 229 | return bp; 230 | } 231 | size_t regu(size_t TSIZE){ 232 | if(TSIZE==10*QSIZE<<2)return 614784; 233 | else return TSIZE; 234 | } 235 | 236 | static void* extend_heap(size_t asize) { 237 | char *bp; 238 | if((long)(bp = mem_sbrk(asize)) == -1){ 239 | return NULL; 240 | } 241 | 242 | PUT(HDRP(bp), PACK(asize, 0)); 243 | PUT(FTRP(bp), PACK(asize, 0)); 244 | PUT(HDRP(NEXT_BLKP(bp)), PACK(0, 1)); 245 | 246 | return coalesce(bp); 247 | } 248 | 249 | 250 | int mm_init(void) { 251 | if ((heap_listp = mem_sbrk(4*DSIZE + FREE_LIST_LEN * DSIZE)) == (void *)-1) 252 | return -1; 253 | PUT(heap_listp, 0); 254 | memset(heap_listp + (1*DSIZE), 0, FREE_LIST_LEN * DSIZE); 255 | 256 | free_listp = heap_listp + (1*DSIZE); 257 | heap_listp += (FREE_LIST_LEN * DSIZE); 258 | PUT(heap_listp + (1*DSIZE), PACK(QSIZE, 1)); 259 | PUT(heap_listp + (2*DSIZE), PACK(QSIZE, 1)); 260 | PUT(heap_listp + (3*DSIZE), PACK(0, 1)); 261 | heap_listp += (2*DSIZE); 262 | if(extend_heap(CHUNKSIZE / DSIZE)==NULL)return -1; 263 | return 0; 264 | } 265 | 266 | /* 267 | * mm_malloc - Allocate a block by incrementing the brk pointer. 268 | * Always allocate a block whose size is a multiple of the alignment. 269 | */ 270 | void *mm_malloc(size_t size) { 271 | if(size==0)return NULL; 272 | size = ALIGN(reg(size) + 2 * DSIZE); 273 | 274 | void *bp; 275 | if ((bp = find_fit(size)) != NULL) { 276 | list_remove(bp); 277 | return alloc(bp, size); 278 | } 279 | else{ 280 | bp = extend_heap(MAX(size, CHUNKSIZE)); 281 | if(bp == NULL)return NULL; 282 | list_remove(bp); 283 | return alloc(bp,size); 284 | } 285 | } 286 | 287 | /* 288 | * mm_free - Freeing a block does nothing. 289 | */ 290 | void mm_free(void *ptr) { 291 | if(ptr==NULL)return; 292 | BP_REMOVE_ALLOC(ptr); 293 | coalesce(ptr); 294 | return; 295 | } 296 | 297 | /* 298 | * mm_realloc - Implemented simply in terms of mm_malloc and mm_free 299 | */ 300 | 301 | void *mm_realloc(void *ptr, size_t size) { 302 | if(size==0){ 303 | mm_free(ptr); 304 | return NULL; 305 | } 306 | if(ptr==NULL)return mm_malloc(size); 307 | size = ALIGN(regu(size) + 2 * DSIZE); 308 | 309 | size_t oldsize = BP_GET_SIZE(ptr); 310 | if(size<=oldsize)return ptr; 311 | 312 | if(BP_GET_ALLOC(NEXT_BLKP(ptr))==0 && size > oldsize){ 313 | size_t newsize = BP_GET_SIZE(ptr) + BP_GET_SIZE(NEXT_BLKP(ptr)); 314 | if(newsize >= size){ 315 | list_remove(NEXT_BLKP(ptr)); 316 | PUT(HDRP(ptr), PACK(newsize, 0)); 317 | PUT(FTRP(ptr), PACK(newsize, 0)); 318 | alloc(ptr,size); 319 | return ptr; 320 | } 321 | } 322 | 323 | if ((!BP_GET_SIZE(NEXT_BLKP(ptr))) && size > oldsize){ 324 | 325 | size_t req_size = size - oldsize; 326 | void* bp; 327 | if((long)(mem_sbrk(req_size))==-1)return NULL; 328 | 329 | PUT(HDRP(ptr), PACK(oldsize + req_size, 0)); 330 | PUT(FTRP(ptr), PACK(oldsize + req_size, 0)); 331 | alloc(ptr,size); 332 | PUT(HDRP(NEXT_BLKP(ptr)), PACK(0, 1)); 333 | 334 | return ptr; 335 | } 336 | 337 | size_t old_size = BP_GET_SIZE(ptr); 338 | void* bp = mm_malloc(size); 339 | if(bp==NULL)return NULL; 340 | memmove(bp, ptr, MIN(size, old_size)); 341 | mm_free(ptr); 342 | return bp; 343 | } 344 | -------------------------------------------------------------------------------- /malloclab/mm.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | extern int mm_init(void); 4 | extern void *mm_malloc(size_t size); 5 | extern void mm_free(void *ptr); 6 | extern void *mm_realloc(void *ptr, size_t size); 7 | 8 | /* 9 | * Students work in teams of one or two. Teams enter their team name, 10 | * personal names and login IDs in a struct of this 11 | * type in their bits.c file. 12 | */ 13 | typedef struct { 14 | char *teamname; /* ID1+ID2 or ID1 */ 15 | char *name1; /* full name of first member */ 16 | char *id1; /* login ID of first member */ 17 | char *name2; /* full name of second member (if any) */ 18 | char *id2; /* login ID of second member */ 19 | } team_t; 20 | 21 | extern team_t team; 22 | -------------------------------------------------------------------------------- /malloclab/mm.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangchi2004/ICS-2023/a968e20339250ec42b46a271d7bd471b70493689/malloclab/mm.o -------------------------------------------------------------------------------- /malloclab/report.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangchi2004/ICS-2023/a968e20339250ec42b46a271d7bd471b70493689/malloclab/report.md -------------------------------------------------------------------------------- /malloclab/report.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangchi2004/ICS-2023/a968e20339250ec42b46a271d7bd471b70493689/malloclab/report.pdf -------------------------------------------------------------------------------- /malloclab/short1-bal.rep: -------------------------------------------------------------------------------- 1 | 20000 2 | 6 3 | 12 4 | 1 5 | a 0 2040 6 | a 1 2040 7 | f 1 8 | a 2 48 9 | a 3 4072 10 | f 3 11 | a 4 4072 12 | f 0 13 | f 2 14 | a 5 4072 15 | f 4 16 | f 5 17 | -------------------------------------------------------------------------------- /malloclab/short2-bal.rep: -------------------------------------------------------------------------------- 1 | 20000 2 | 6 3 | 12 4 | 1 5 | a 0 2040 6 | a 1 4010 7 | a 2 48 8 | a 3 4072 9 | a 4 4072 10 | a 5 4072 11 | f 0 12 | f 1 13 | f 2 14 | f 3 15 | f 4 16 | f 5 17 | -------------------------------------------------------------------------------- /malloclab/traces/Makefile: -------------------------------------------------------------------------------- 1 | 2 | all: synthetic-traces balanced-traces check-balance 3 | 4 | synthetic-traces: 5 | ./gen_binary.pl 6 | ./gen_binary2.pl 7 | ./gen_coalescing.pl 8 | ./gen_random.pl 9 | ./gen_realloc.pl 10 | ./gen_realloc2.pl 11 | 12 | balanced-traces: 13 | ./checktrace.pl < amptjp.rep > amptjp-bal.rep 14 | ./checktrace.pl < binary.rep > binary-bal.rep 15 | ./checktrace.pl < binary2.rep > binary2-bal.rep 16 | ./checktrace.pl < cccp.rep > cccp-bal.rep 17 | ./checktrace.pl < coalescing.rep > coalescing-bal.rep 18 | ./checktrace.pl < cp-decl.rep > cp-decl-bal.rep 19 | ./checktrace.pl < expr.rep > expr-bal.rep 20 | ./checktrace.pl < realloc.rep > realloc-bal.rep 21 | ./checktrace.pl < realloc2.rep > realloc2-bal.rep 22 | ./checktrace.pl < random.rep > random-bal.rep 23 | ./checktrace.pl < random2.rep > random2-bal.rep 24 | ./checktrace.pl < short1.rep > short1-bal.rep 25 | ./checktrace.pl < short2.rep > short2-bal.rep 26 | 27 | check-balance: 28 | ./checktrace.pl -s < amptjp-bal.rep 29 | ./checktrace.pl -s < binary-bal.rep 30 | ./checktrace.pl -s < binary2-bal.rep 31 | ./checktrace.pl -s < cccp-bal.rep 32 | ./checktrace.pl -s < coalescing-bal.rep 33 | ./checktrace.pl -s < cp-decl-bal.rep 34 | ./checktrace.pl -s < expr-bal.rep 35 | ./checktrace.pl -s < realloc-bal.rep 36 | ./checktrace.pl -s < realloc2-bal.rep 37 | ./checktrace.pl -s < random-bal.rep 38 | ./checktrace.pl -s < random2-bal.rep 39 | ./checktrace.pl -s < short1-bal.rep 40 | ./checktrace.pl -s < short2-bal.rep 41 | clean: 42 | rm -f *~ 43 | -------------------------------------------------------------------------------- /malloclab/traces/README: -------------------------------------------------------------------------------- 1 | ##################################################################### 2 | # CS:APP Malloc Lab 3 | # Traces 4 | # 5 | # Copyright (c) 2002, R. Bryant and D. O'Hallaron, All rights reserved. 6 | # May not be used, modified, or copied without permission. 7 | # 8 | ###################################################################### 9 | 10 | This directory contains traces of allocate and free requests that are 11 | used by the test harness to evaluate the student malloc packages. 12 | 13 | ********* 14 | 1. Files 15 | ********* 16 | 17 | *.rep Original traces 18 | *-bal.rep Balanced versions of the original traces 19 | gen_XXX.pl Perl script that generates *.rep 20 | checktrace.pl Checks trace for consistency and outputs a balanced version 21 | Makefile Generates traces 22 | 23 | Note: A "balanced" trace has a matching free request for each allocate 24 | request. 25 | 26 | ********************** 27 | 2. Building the traces 28 | ********************** 29 | To rebuild the traces from scratch, type 30 | 31 | unix> make 32 | 33 | ******************** 34 | 3. Trace file format 35 | ******************** 36 | 37 | A trace file is an ASCII file. It begins with a 4-line header: 38 | 39 | /* suggested heap size (unused) */ 40 | /* number of request id's */ 41 | /* number of requests (operations) */ 42 | /* weight for this trace (unused) */ 43 | 44 | The header is followed by num_ops text lines. Each line denotes either 45 | an allocate [a], reallocate [r], or free [f] request. The 46 | is an integer that uniquely identifies an allocate or reallocate 47 | request. 48 | 49 | a /* ptr_ = malloc() */ 50 | r /* realloc(ptr_, ) */ 51 | f /* free(ptr_) */ 52 | 53 | For example, the following trace file: 54 | 55 | 56 | 20000 57 | 3 58 | 8 59 | 1 60 | a 0 512 61 | a 1 128 62 | r 0 640 63 | a 2 128 64 | f 1 65 | r 0 768 66 | f 0 67 | f 2 68 | 69 | 70 | is balanced. It has a recommended heap size of 20000 bytes (ignored), 71 | three distinct request ids (0, 1, and 2), eight different requests 72 | (one per line), and a weight of 1 (ignored). 73 | 74 | ************************ 75 | 4. Description of traces 76 | ************************ 77 | 78 | * short{1,2}-bal.rep 79 | 80 | Tiny synthetic tracefiles for debugging 81 | 82 | * {amptjp,cccp,cp-decl,expr}-bal.rep 83 | 84 | Traces generated from real programs. 85 | 86 | * {binary,binary2}-bal.rep 87 | 88 | The allocation pattern is to alternatively allocate a small-sized 89 | chunk of memory and a large-sized chunk. The small-sized chunks 90 | (either 16 or 64 ) are deliberately set to be power of 2 while the 91 | large-size chunks (either 112 or 448) are not a power of 2. Defeats 92 | buddy algorithms. However, a simple-minded algorithm might prevail in 93 | this scenario because a first-fit scheme will be good enough. 94 | 95 | * coalescing-bal.rep 96 | 97 | Repeatedly allocate two equal-sized chunks (4095 in size) and release 98 | them, and then immediately allocate and free a chunk twice as big 99 | (8190). This tests if the students' algorithm ever really releases 100 | memory and does coalescing. The size is chosen to give advantage to 101 | tree-based or segrated fits algorithms where there is no header or 102 | footer overhead. 103 | 104 | * {random,random2}-bal.rep 105 | 106 | Random allocate and free requesets that simply test the correctness 107 | and robustness of the algorithm. 108 | 109 | 110 | * {realloc,realloc2}-bal.rep 111 | 112 | Reallocate previously allocated blocks interleaved by other allocation 113 | request. The purpose is to test whether a certain amount of internal 114 | fragments are allocated or not. Naive realloc implementations that 115 | always realloc a brand new block will suffer. 116 | 117 | * {gcc,clang,curl,python3}-bal.rep 118 | 119 | Traces captured from real-world applications. 120 | -------------------------------------------------------------------------------- /malloclab/traces/checktrace.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | #!/usr/local/bin/perl 3 | use Getopt::Std; 4 | 5 | ####################################################################### 6 | # checktrace - trace file consistency checker and balancer. 7 | # 8 | # Copyright (c) 2002, R. Bryant and D. O'Hallaron, All rights reserved. 9 | # May not be used, modified, or copied without permission. 10 | # 11 | # This script reads a Malloc Lab trace file, checks it for consistency, 12 | # and outputs a balanced version by appending any necessary free requests. 13 | # 14 | ####################################################################### 15 | 16 | $| = 1; # autoflush output on every print statement 17 | 18 | # 19 | # void usage(void) - print help message and terminate 20 | # 21 | sub usage 22 | { 23 | printf STDERR "$_[0]\n"; 24 | printf STDERR "Usage: $0 [-hs]\n"; 25 | printf STDERR "Options:\n"; 26 | printf STDERR " -h Print this message\n"; 27 | printf STDERR " -s Emit only a brief summary\n"; 28 | die "\n" ; 29 | } 30 | 31 | ############## 32 | # Main routine 33 | ############## 34 | 35 | # 36 | # Parse and check the command line arguments 37 | # 38 | getopts('hs'); 39 | if ($opt_h) { 40 | usage(""); 41 | } 42 | $summary = $opt_s; 43 | 44 | # 45 | # HASH keeps a running tally of outstanding alloc/realloc 46 | # requests. When a free request is encountered, the corresponding 47 | # hash entry is deleted. When we are finished reading the trace, 48 | # what is left are the unmatched alloc/realloc requests. 49 | # 50 | %HASH = (); 51 | 52 | # Read the trace header values 53 | $heap_size = ; 54 | chomp($heap_size); 55 | 56 | $num_blocks = ; 57 | chomp($num_blocks); 58 | 59 | $old_num_ops = ; 60 | chomp($old_num_ops); 61 | 62 | $weight = ; 63 | chomp($weight); 64 | 65 | # 66 | # Find any allocate requests that don't have a matching free requests 67 | # 68 | $linenum = 4; 69 | $requestnum = 0; 70 | while ($line = ) { 71 | chomp($line); 72 | $linenum++; 73 | 74 | ($cmd, $id, $size) = split(" ", $line); 75 | 76 | # ignore blank lines 77 | if (!$cmd) { 78 | next; 79 | } 80 | 81 | # save the line for output later 82 | $lines[$requestnum++] = $line; 83 | 84 | #ignore realloc requests, as long as they are preceeded by an alloc request 85 | if ($cmd eq "r") { 86 | if (!$HASH{$id}) { 87 | die "$0: ERROR[$linenum]: realloc without previous alloc\n"; 88 | } 89 | next; 90 | } 91 | 92 | if ($cmd eq "a" and $HASH{$id} eq "a") { 93 | die "$0: ERROR[$linenum]: allocate with no intervening free.\n"; 94 | } 95 | 96 | if ($cmd eq "a" and $HASH{$id} eq "f") { 97 | die "$0: ERROR[$linenum]: reused ID $id.\n"; 98 | } 99 | 100 | if ($cmd eq "f" and !exists($HASH{$id})) { 101 | die "$0: ERROR[$linenum]: freeing unallocated block.\n"; 102 | next; 103 | } 104 | 105 | if ($cmd eq "f" and !$HASH{$id} eq "f") { 106 | die "$0: ERROR[$linenum]: freeing already freed block.\n"; 107 | next; 108 | } 109 | 110 | if ($cmd eq "f") { 111 | delete $HASH{$id}; 112 | } 113 | else { 114 | $HASH{$id} = $cmd; 115 | } 116 | } 117 | 118 | # 119 | # If called with -s argument , print a brief balance summary and exit 120 | # 121 | if ($summary) { 122 | if (!%HASH) { 123 | print "Balanced trace.\n"; 124 | } 125 | else { 126 | print "Unbalanced tree.\n"; 127 | } 128 | exit; 129 | } 130 | 131 | # 132 | # Output a balanced version of the trace 133 | # 134 | $new_ops = keys %HASH; 135 | $new_num_ops = $old_num_ops + $new_ops; 136 | 137 | print "$heap_size\n"; 138 | print "$num_blocks\n"; 139 | print "$new_num_ops\n"; 140 | print "$weight\n"; 141 | 142 | # print the old requests 143 | foreach $item (@lines) { 144 | print "$item\n"; 145 | } 146 | 147 | # print a set of free requests that will balance the trace 148 | foreach $key (sort keys %HASH) { 149 | if ($HASH{$key} ne "a" and $HASH{$key} ne "r") { 150 | die "$0: ERROR: Invalid free request in residue.\n"; 151 | } 152 | print "f $key\n"; 153 | } 154 | 155 | exit; 156 | -------------------------------------------------------------------------------- /malloclab/traces/gcc.rep: -------------------------------------------------------------------------------- 1 | 0 2 | 2855 3 | 3278 4 | 0 5 | a 0 5 6 | f 0 7 | a 1 120 8 | a 2 12 9 | a 3 776 10 | a 4 112 11 | a 5 1336 12 | a 6 216 13 | a 7 432 14 | a 8 104 15 | a 9 88 16 | a 10 120 17 | a 11 168 18 | a 12 104 19 | a 13 80 20 | a 14 192 21 | a 15 12 22 | a 16 171 23 | a 17 12 24 | a 18 181 25 | f 16 26 | a 19 28 27 | a 20 4 28 | a 21 30 29 | a 22 2208 30 | a 23 48 31 | a 24 192 32 | f 24 33 | a 25 9 34 | f 21 35 | f 22 36 | a 26 104 37 | a 27 4064 38 | a 28 524411 39 | f 27 40 | a 29 104 41 | a 30 4064 42 | a 31 524411 43 | f 30 44 | a 32 4064 45 | a 33 104 46 | a 34 4064 47 | a 35 524411 48 | f 34 49 | a 36 4064 50 | a 37 4064 51 | a 38 4064 52 | a 39 4064 53 | a 40 65539 54 | a 41 104 55 | a 42 4064 56 | a 43 524411 57 | f 42 58 | a 44 280 59 | a 45 24 60 | a 46 4064 61 | a 47 24 62 | a 48 4064 63 | a 49 9 64 | a 50 552 65 | a 51 88 66 | a 52 4064 67 | a 53 4064 68 | a 54 88 69 | a 55 4064 70 | a 56 88 71 | a 57 4064 72 | a 58 88 73 | a 59 4064 74 | a 60 88 75 | a 61 4064 76 | a 62 88 77 | a 63 4064 78 | a 64 88 79 | a 65 4064 80 | a 66 104 81 | a 67 4064 82 | a 68 524411 83 | f 67 84 | a 69 16 85 | a 70 16 86 | a 71 16 87 | a 72 4064 88 | a 73 16 89 | a 74 16 90 | a 75 16 91 | a 76 16 92 | a 77 16 93 | a 78 16 94 | a 79 16 95 | a 80 16 96 | a 81 16 97 | a 82 16 98 | a 83 16 99 | a 84 16 100 | a 85 16 101 | a 86 16 102 | a 87 16 103 | a 88 16 104 | a 89 16 105 | a 90 16 106 | a 91 16 107 | a 92 16 108 | a 93 16 109 | a 94 16 110 | a 95 16 111 | a 96 16 112 | a 97 16 113 | a 98 16 114 | a 99 16 115 | a 100 16 116 | a 101 16 117 | a 102 16 118 | a 103 16 119 | a 104 16 120 | a 105 16 121 | a 106 16 122 | a 107 16 123 | a 108 16 124 | a 109 16 125 | a 110 16 126 | a 111 16 127 | a 112 16 128 | a 113 16 129 | a 114 16 130 | a 115 16 131 | a 116 16 132 | a 117 16 133 | a 118 16 134 | a 119 16 135 | a 120 16 136 | a 121 16 137 | a 122 16 138 | a 123 16 139 | a 124 16 140 | a 125 16 141 | a 126 16 142 | a 127 16 143 | a 128 16 144 | a 129 16 145 | a 130 16 146 | a 131 16 147 | a 132 16 148 | a 133 16 149 | a 134 16 150 | a 135 16 151 | a 136 16 152 | a 137 16 153 | a 138 16 154 | a 139 16 155 | a 140 16 156 | a 141 16 157 | a 142 16 158 | a 143 16 159 | a 144 16 160 | a 145 16 161 | a 146 16 162 | a 147 16 163 | a 148 16 164 | a 149 16 165 | a 150 16 166 | a 151 16 167 | a 152 16 168 | a 153 16 169 | a 154 16 170 | a 155 16 171 | a 156 16 172 | a 157 16 173 | a 158 16 174 | a 159 16 175 | a 160 16 176 | a 161 16 177 | a 162 16 178 | a 163 16 179 | a 164 16 180 | a 165 16 181 | a 166 16 182 | a 167 16 183 | a 168 16 184 | a 169 16 185 | a 170 16 186 | a 171 16 187 | a 172 16 188 | a 173 16 189 | a 174 16 190 | a 175 16 191 | a 176 16 192 | a 177 16 193 | a 178 16 194 | a 179 16 195 | a 180 16 196 | a 181 16 197 | a 182 16 198 | a 183 16 199 | a 184 16 200 | a 185 16 201 | a 186 16 202 | a 187 16 203 | a 188 16 204 | a 189 16 205 | a 190 16 206 | a 191 16 207 | a 192 16 208 | a 193 16 209 | a 194 16 210 | a 195 16 211 | a 196 16 212 | a 197 16 213 | a 198 16 214 | a 199 4064 215 | a 200 16 216 | a 201 16 217 | a 202 16 218 | a 203 16 219 | a 204 16 220 | a 205 16 221 | a 206 16 222 | a 207 16 223 | a 208 16 224 | a 209 16 225 | a 210 16 226 | a 211 16 227 | a 212 16 228 | a 213 16 229 | a 214 16 230 | a 215 16 231 | a 216 16 232 | a 217 16 233 | a 218 16 234 | a 219 16 235 | a 220 16 236 | a 221 16 237 | a 222 16 238 | a 223 16 239 | a 224 16 240 | a 225 16 241 | a 226 16 242 | a 227 16 243 | a 228 16 244 | a 229 16 245 | a 230 16 246 | a 231 16 247 | a 232 16 248 | a 233 16 249 | a 234 16 250 | a 235 16 251 | a 236 16 252 | a 237 16 253 | a 238 16 254 | a 239 16 255 | a 240 16 256 | a 241 16 257 | a 242 16 258 | a 243 16 259 | a 244 16 260 | a 245 16 261 | a 246 16 262 | a 247 16 263 | a 248 16 264 | a 249 16 265 | a 250 16 266 | a 251 16 267 | a 252 16 268 | a 253 16 269 | a 254 16 270 | a 255 16 271 | a 256 16 272 | a 257 16 273 | a 258 16 274 | a 259 16 275 | a 260 16 276 | a 261 16 277 | a 262 16 278 | a 263 16 279 | a 264 16 280 | a 265 16 281 | a 266 16 282 | a 267 16 283 | a 268 16 284 | a 269 16 285 | a 270 16 286 | a 271 16 287 | a 272 16 288 | a 273 16 289 | a 274 16 290 | a 275 16 291 | a 276 16 292 | a 277 16 293 | a 278 16 294 | a 279 16 295 | a 280 16 296 | a 281 16 297 | a 282 16 298 | a 283 16 299 | a 284 16 300 | a 285 16 301 | a 286 16 302 | a 287 16 303 | a 288 16 304 | a 289 16 305 | a 290 16 306 | a 291 16 307 | a 292 16 308 | a 293 16 309 | a 294 16 310 | a 295 16 311 | a 296 16 312 | a 297 16 313 | a 298 16 314 | a 299 16 315 | a 300 16 316 | a 301 16 317 | a 302 16 318 | a 303 16 319 | a 304 16 320 | a 305 16 321 | a 306 16 322 | a 307 16 323 | a 308 16 324 | a 309 16 325 | a 310 16 326 | a 311 16 327 | a 312 16 328 | a 313 16 329 | a 314 16 330 | a 315 16 331 | a 316 88 332 | a 317 74 333 | a 318 60 334 | a 319 9 335 | f 319 336 | a 320 18 337 | f 320 338 | f 318 339 | f 317 340 | f 316 341 | a 321 13 342 | a 322 116 343 | a 323 37 344 | a 324 40 345 | a 325 3 346 | a 326 6 347 | a 327 16 348 | a 328 16 349 | a 329 16 350 | a 330 18 351 | a 331 88 352 | a 332 144 353 | a 333 4 354 | a 334 4 355 | f 333 356 | f 334 357 | f 332 358 | f 331 359 | a 335 5 360 | f 335 361 | a 336 23 362 | a 337 9 363 | a 338 16 364 | f 336 365 | a 339 16 366 | f 339 367 | f 323 368 | f 322 369 | f 321 370 | a 340 18 371 | a 341 87 372 | f 341 373 | a 342 144 374 | a 343 4 375 | a 344 4 376 | f 343 377 | f 344 378 | f 342 379 | a 345 18 380 | a 346 85 381 | f 346 382 | a 347 8 383 | a 348 18 384 | a 349 85 385 | f 347 386 | f 349 387 | a 350 3409 388 | f 350 389 | a 351 16 390 | a 352 16 391 | a 353 16 392 | a 354 16 393 | a 355 16 394 | a 356 16 395 | a 357 16 396 | a 358 16 397 | a 359 16 398 | a 360 16 399 | a 361 16 400 | a 362 16 401 | a 363 16 402 | a 364 16 403 | a 365 16 404 | a 366 16 405 | a 367 16 406 | a 368 16 407 | a 369 16 408 | a 370 16 409 | a 371 16 410 | a 372 16 411 | a 373 16 412 | a 374 16 413 | a 375 16 414 | a 376 16 415 | a 377 16 416 | a 378 16 417 | a 379 16 418 | a 380 16 419 | a 381 16 420 | a 382 16 421 | a 383 16 422 | a 384 16 423 | a 385 16 424 | a 386 16 425 | a 387 16 426 | a 388 16 427 | a 389 16 428 | a 390 16 429 | a 391 16 430 | a 392 16 431 | a 393 16 432 | a 394 16 433 | a 395 16 434 | a 396 16 435 | a 397 16 436 | a 398 16 437 | a 399 16 438 | a 400 16 439 | a 401 16 440 | a 402 16 441 | a 403 16 442 | a 404 16 443 | a 405 16 444 | a 406 16 445 | a 407 16 446 | a 408 16 447 | a 409 16 448 | a 410 16 449 | a 411 16 450 | a 412 16 451 | a 413 16 452 | a 414 16 453 | a 415 16 454 | a 416 16 455 | a 417 16 456 | a 418 16 457 | a 419 16 458 | a 420 16 459 | a 421 16 460 | a 422 16 461 | a 423 16 462 | a 424 16 463 | a 425 16 464 | a 426 16 465 | a 427 16 466 | a 428 16 467 | a 429 16 468 | a 430 16 469 | a 431 4064 470 | a 432 16 471 | a 433 16 472 | a 434 16 473 | a 435 16 474 | a 436 16 475 | a 437 16 476 | a 438 16 477 | a 439 16 478 | a 440 16 479 | a 441 16 480 | a 442 16 481 | a 443 16 482 | a 444 16 483 | a 445 16 484 | a 446 16 485 | a 447 16 486 | a 448 16 487 | a 449 16 488 | a 450 16 489 | a 451 16 490 | a 452 16 491 | a 453 16 492 | a 454 16 493 | a 455 16 494 | a 456 16 495 | a 457 16 496 | a 458 16 497 | a 459 16 498 | a 460 16 499 | a 461 16 500 | a 462 16 501 | a 463 16 502 | a 464 16 503 | a 465 16 504 | a 466 16 505 | a 467 16 506 | a 468 16 507 | a 469 16 508 | a 470 16 509 | a 471 16 510 | a 472 16 511 | a 473 16 512 | a 474 16 513 | a 475 16 514 | a 476 16 515 | a 477 16 516 | a 478 16 517 | a 479 16 518 | a 480 16 519 | a 481 16 520 | a 482 16 521 | a 483 16 522 | a 484 16 523 | a 485 16 524 | a 486 16 525 | a 487 16 526 | a 488 16 527 | a 489 16 528 | a 490 16 529 | a 491 16 530 | a 492 16 531 | a 493 16 532 | a 494 16 533 | a 495 16 534 | a 496 16 535 | a 497 16 536 | a 498 16 537 | a 499 16 538 | a 500 16 539 | a 501 16 540 | a 502 16 541 | a 503 16 542 | a 504 16 543 | a 505 16 544 | a 506 16 545 | a 507 16 546 | a 508 16 547 | a 509 16 548 | a 510 16 549 | a 511 16 550 | a 512 16 551 | a 513 16 552 | a 514 16 553 | a 515 16 554 | a 516 16 555 | a 517 16 556 | a 518 16 557 | a 519 16 558 | a 520 16 559 | a 521 16 560 | a 522 16 561 | a 523 16 562 | a 524 16 563 | a 525 16 564 | a 526 16 565 | a 527 16 566 | a 528 16 567 | a 529 16 568 | a 530 16 569 | a 531 16 570 | a 532 16 571 | a 533 16 572 | a 534 16 573 | a 535 16 574 | a 536 16 575 | a 537 16 576 | a 538 16 577 | a 539 16 578 | a 540 16 579 | a 541 16 580 | a 542 16 581 | a 543 16 582 | a 544 16 583 | a 545 16 584 | a 546 16 585 | a 547 16 586 | a 548 16 587 | a 549 16 588 | a 550 16 589 | a 551 16 590 | a 552 16 591 | a 553 16 592 | a 554 16 593 | a 555 16 594 | a 556 16 595 | a 557 16 596 | a 558 4064 597 | a 559 16 598 | a 560 16 599 | a 561 16 600 | a 562 16 601 | a 563 16 602 | a 564 16 603 | a 565 16 604 | a 566 16 605 | a 567 16 606 | a 568 16 607 | a 569 16 608 | a 570 16 609 | a 571 16 610 | a 572 16 611 | a 573 16 612 | a 574 16 613 | a 575 16 614 | a 576 16 615 | a 577 16 616 | a 578 16 617 | a 579 16 618 | a 580 16 619 | a 581 16 620 | a 582 16 621 | a 583 16 622 | a 584 16 623 | a 585 16 624 | a 586 16 625 | a 587 16 626 | a 588 16 627 | a 589 16 628 | a 590 16 629 | a 591 16 630 | a 592 16 631 | a 593 16 632 | a 594 16 633 | a 595 16 634 | a 596 16 635 | a 597 16 636 | a 598 16 637 | a 599 16 638 | a 600 16 639 | a 601 16 640 | a 602 16 641 | a 603 16 642 | a 604 16 643 | a 605 16 644 | a 606 16 645 | a 607 16 646 | a 608 16 647 | a 609 16 648 | a 610 16 649 | a 611 16 650 | a 612 16 651 | a 613 16 652 | a 614 16 653 | a 615 16 654 | a 616 16 655 | a 617 16 656 | a 618 16 657 | a 619 16 658 | a 620 16 659 | a 621 16 660 | a 622 16 661 | a 623 16 662 | a 624 16 663 | a 625 16 664 | a 626 16 665 | a 627 16 666 | a 628 16 667 | a 629 16 668 | a 630 16 669 | a 631 16 670 | a 632 16 671 | a 633 16 672 | a 634 16 673 | a 635 16 674 | a 636 16 675 | a 637 16 676 | a 638 16 677 | a 639 16 678 | a 640 16 679 | a 641 16 680 | a 642 16 681 | a 643 16 682 | a 644 16 683 | a 645 16 684 | a 646 16 685 | a 647 16 686 | a 648 16 687 | a 649 16 688 | a 650 16 689 | a 651 16 690 | a 652 16 691 | a 653 16 692 | a 654 16 693 | a 655 16 694 | a 656 16 695 | a 657 16 696 | a 658 16 697 | a 659 16 698 | a 660 16 699 | a 661 16 700 | a 662 16 701 | a 663 16 702 | a 664 16 703 | a 665 16 704 | a 666 16 705 | a 667 16 706 | a 668 16 707 | a 669 16 708 | a 670 16 709 | a 671 16 710 | a 672 16 711 | a 673 16 712 | a 674 16 713 | a 675 16 714 | a 676 16 715 | a 677 16 716 | a 678 16 717 | a 679 16 718 | a 680 16 719 | a 681 16 720 | a 682 16 721 | a 683 16 722 | a 684 16 723 | a 685 4064 724 | a 686 16 725 | a 687 16 726 | a 688 16 727 | a 689 16 728 | a 690 16 729 | a 691 16 730 | a 692 16 731 | a 693 16 732 | a 694 16 733 | a 695 16 734 | a 696 16 735 | a 697 16 736 | a 698 16 737 | a 699 16 738 | a 700 16 739 | a 701 16 740 | a 702 16 741 | a 703 16 742 | a 704 16 743 | a 705 16 744 | a 706 16 745 | a 707 16 746 | a 708 16 747 | a 709 16 748 | a 710 16 749 | a 711 16 750 | a 712 16 751 | a 713 16 752 | a 714 16 753 | a 715 16 754 | a 716 16 755 | a 717 16 756 | a 718 16 757 | a 719 16 758 | a 720 16 759 | a 721 16 760 | a 722 16 761 | a 723 16 762 | a 724 16 763 | a 725 16 764 | a 726 16 765 | a 727 16 766 | a 728 16 767 | a 729 16 768 | a 730 16 769 | a 731 16 770 | a 732 16 771 | a 733 16 772 | a 734 16 773 | a 735 16 774 | a 736 16 775 | a 737 16 776 | a 738 16 777 | a 739 16 778 | a 740 16 779 | a 741 16 780 | a 742 16 781 | a 743 16 782 | a 744 16 783 | a 745 16 784 | a 746 16 785 | a 747 16 786 | a 748 16 787 | a 749 16 788 | a 750 16 789 | a 751 16 790 | a 752 16 791 | a 753 16 792 | a 754 16 793 | a 755 16 794 | a 756 16 795 | a 757 16 796 | a 758 16 797 | a 759 16 798 | a 760 16 799 | a 761 16 800 | a 762 16 801 | a 763 16 802 | a 764 16 803 | a 765 16 804 | a 766 16 805 | a 767 16 806 | a 768 16 807 | a 769 16 808 | a 770 16 809 | a 771 16 810 | a 772 16 811 | a 773 16 812 | a 774 16 813 | a 775 16 814 | a 776 16 815 | a 777 16 816 | a 778 16 817 | a 779 16 818 | a 780 16 819 | a 781 16 820 | a 782 16 821 | a 783 16 822 | a 784 16 823 | a 785 16 824 | a 786 16 825 | a 787 16 826 | a 788 16 827 | a 789 16 828 | a 790 16 829 | a 791 16 830 | a 792 16 831 | a 793 16 832 | a 794 16 833 | a 795 16 834 | a 796 16 835 | a 797 16 836 | a 798 16 837 | a 799 16 838 | a 800 16 839 | a 801 16 840 | a 802 16 841 | a 803 16 842 | a 804 16 843 | a 805 16 844 | a 806 16 845 | a 807 16 846 | a 808 16 847 | a 809 16 848 | a 810 16 849 | a 811 16 850 | a 812 4064 851 | a 813 16 852 | a 814 16 853 | a 815 16 854 | a 816 16 855 | a 817 16 856 | a 818 16 857 | a 819 16 858 | a 820 16 859 | a 821 16 860 | a 822 16 861 | a 823 16 862 | a 824 16 863 | a 825 16 864 | a 826 16 865 | a 827 16 866 | a 828 16 867 | a 829 16 868 | a 830 16 869 | a 831 16 870 | a 832 16 871 | a 833 16 872 | a 834 16 873 | a 835 16 874 | a 836 16 875 | a 837 16 876 | a 838 16 877 | a 839 16 878 | a 840 16 879 | a 841 16 880 | a 842 16 881 | a 843 16 882 | a 844 16 883 | a 845 16 884 | a 846 16 885 | a 847 16 886 | a 848 16 887 | a 849 16 888 | a 850 16 889 | a 851 16 890 | a 852 16 891 | a 853 16 892 | a 854 16 893 | a 855 16 894 | a 856 16 895 | a 857 16 896 | a 858 16 897 | a 859 16 898 | a 860 16 899 | a 861 16 900 | a 862 16 901 | a 863 16 902 | a 864 16 903 | a 865 16 904 | a 866 16 905 | a 867 16 906 | a 868 16 907 | a 869 16 908 | a 870 16 909 | a 871 16 910 | a 872 16 911 | a 873 16 912 | a 874 16 913 | a 875 16 914 | a 876 16 915 | a 877 16 916 | a 878 16 917 | a 879 16 918 | a 880 16 919 | a 881 16 920 | a 882 16 921 | a 883 16 922 | a 884 16 923 | a 885 16 924 | a 886 16 925 | a 887 16 926 | a 888 16 927 | a 889 16 928 | a 890 16 929 | a 891 16 930 | a 892 16 931 | a 893 16 932 | a 894 16 933 | a 895 16 934 | a 896 16 935 | a 897 16 936 | a 898 16 937 | a 899 16 938 | a 900 16 939 | a 901 16 940 | a 902 16 941 | a 903 16 942 | a 904 16 943 | a 905 16 944 | a 906 16 945 | a 907 16 946 | a 908 16 947 | a 909 16 948 | a 910 16 949 | a 911 16 950 | a 912 16 951 | a 913 16 952 | a 914 16 953 | a 915 16 954 | a 916 16 955 | a 917 16 956 | a 918 16 957 | a 919 16 958 | a 920 16 959 | a 921 16 960 | a 922 16 961 | a 923 16 962 | a 924 16 963 | a 925 16 964 | a 926 16 965 | a 927 16 966 | a 928 16 967 | a 929 16 968 | a 930 16 969 | a 931 16 970 | a 932 16 971 | a 933 16 972 | a 934 16 973 | a 935 16 974 | a 936 16 975 | a 937 16 976 | a 938 16 977 | a 939 4064 978 | a 940 16 979 | a 941 16 980 | a 942 16 981 | a 943 16 982 | a 944 16 983 | a 945 16 984 | a 946 16 985 | a 947 16 986 | a 948 16 987 | a 949 16 988 | a 950 16 989 | a 951 16 990 | a 952 16 991 | a 953 16 992 | a 954 16 993 | a 955 16 994 | a 956 16 995 | a 957 16 996 | a 958 16 997 | a 959 16 998 | a 960 16 999 | a 961 16 1000 | a 962 16 1001 | a 963 16 1002 | a 964 16 1003 | a 965 16 1004 | a 966 16 1005 | a 967 16 1006 | a 968 16 1007 | a 969 16 1008 | a 970 16 1009 | a 971 16 1010 | a 972 16 1011 | a 973 16 1012 | a 974 16 1013 | a 975 16 1014 | a 976 16 1015 | a 977 16 1016 | a 978 16 1017 | a 979 16 1018 | a 980 16 1019 | a 981 16 1020 | a 982 16 1021 | a 983 16 1022 | a 984 16 1023 | a 985 16 1024 | a 986 16 1025 | a 987 16 1026 | a 988 16 1027 | a 989 16 1028 | a 990 16 1029 | a 991 16 1030 | a 992 16 1031 | a 993 16 1032 | a 994 16 1033 | a 995 16 1034 | a 996 16 1035 | a 997 16 1036 | a 998 16 1037 | a 999 16 1038 | a 1000 16 1039 | a 1001 16 1040 | a 1002 16 1041 | a 1003 16 1042 | a 1004 16 1043 | a 1005 16 1044 | a 1006 16 1045 | a 1007 16 1046 | a 1008 16 1047 | a 1009 16 1048 | a 1010 16 1049 | a 1011 16 1050 | a 1012 16 1051 | a 1013 16 1052 | a 1014 16 1053 | a 1015 16 1054 | a 1016 16 1055 | a 1017 16 1056 | a 1018 16 1057 | a 1019 16 1058 | a 1020 16 1059 | a 1021 16 1060 | a 1022 16 1061 | a 1023 16 1062 | a 1024 16 1063 | a 1025 16 1064 | a 1026 16 1065 | a 1027 16 1066 | a 1028 16 1067 | a 1029 16 1068 | a 1030 16 1069 | a 1031 16 1070 | a 1032 16 1071 | a 1033 16 1072 | a 1034 16 1073 | a 1035 16 1074 | a 1036 16 1075 | a 1037 16 1076 | a 1038 16 1077 | a 1039 16 1078 | a 1040 16 1079 | a 1041 16 1080 | a 1042 16 1081 | a 1043 16 1082 | a 1044 16 1083 | a 1045 16 1084 | a 1046 16 1085 | a 1047 16 1086 | a 1048 16 1087 | a 1049 16 1088 | a 1050 16 1089 | a 1051 16 1090 | a 1052 16 1091 | a 1053 16 1092 | a 1054 16 1093 | a 1055 16 1094 | a 1056 16 1095 | a 1057 16 1096 | a 1058 16 1097 | a 1059 16 1098 | a 1060 16 1099 | a 1061 16 1100 | a 1062 16 1101 | a 1063 16 1102 | a 1064 16 1103 | a 1065 16 1104 | a 1066 4064 1105 | a 1067 16 1106 | a 1068 16 1107 | a 1069 16 1108 | a 1070 16 1109 | a 1071 16 1110 | a 1072 16 1111 | a 1073 16 1112 | a 1074 16 1113 | a 1075 16 1114 | a 1076 16 1115 | a 1077 16 1116 | a 1078 16 1117 | a 1079 16 1118 | a 1080 16 1119 | a 1081 16 1120 | a 1082 16 1121 | a 1083 16 1122 | a 1084 16 1123 | a 1085 16 1124 | a 1086 16 1125 | a 1087 16 1126 | a 1088 16 1127 | a 1089 16 1128 | a 1090 16 1129 | a 1091 16 1130 | a 1092 16 1131 | a 1093 16 1132 | a 1094 16 1133 | a 1095 16 1134 | a 1096 16 1135 | a 1097 16 1136 | a 1098 16 1137 | a 1099 16 1138 | a 1100 16 1139 | a 1101 16 1140 | a 1102 16 1141 | a 1103 16 1142 | a 1104 16 1143 | a 1105 16 1144 | a 1106 16 1145 | a 1107 16 1146 | a 1108 16 1147 | a 1109 16 1148 | a 1110 16 1149 | a 1111 16 1150 | a 1112 16 1151 | a 1113 16 1152 | a 1114 16 1153 | a 1115 16 1154 | a 1116 16 1155 | a 1117 16 1156 | a 1118 16 1157 | a 1119 16 1158 | a 1120 16 1159 | a 1121 16 1160 | a 1122 16 1161 | a 1123 16 1162 | a 1124 16 1163 | a 1125 16 1164 | a 1126 16 1165 | a 1127 16 1166 | a 1128 16 1167 | a 1129 16 1168 | a 1130 16 1169 | a 1131 16 1170 | a 1132 16 1171 | a 1133 16 1172 | a 1134 16 1173 | a 1135 16 1174 | a 1136 16 1175 | a 1137 16 1176 | a 1138 16 1177 | a 1139 16 1178 | a 1140 16 1179 | a 1141 16 1180 | a 1142 16 1181 | a 1143 16 1182 | a 1144 16 1183 | a 1145 16 1184 | a 1146 16 1185 | a 1147 16 1186 | a 1148 16 1187 | a 1149 16 1188 | a 1150 16 1189 | a 1151 16 1190 | a 1152 16 1191 | a 1153 16 1192 | a 1154 16 1193 | a 1155 16 1194 | a 1156 16 1195 | a 1157 16 1196 | a 1158 16 1197 | a 1159 16 1198 | a 1160 16 1199 | a 1161 16 1200 | a 1162 16 1201 | a 1163 16 1202 | a 1164 16 1203 | a 1165 16 1204 | a 1166 16 1205 | a 1167 16 1206 | a 1168 16 1207 | a 1169 16 1208 | a 1170 16 1209 | a 1171 16 1210 | a 1172 16 1211 | a 1173 16 1212 | a 1174 16 1213 | a 1175 16 1214 | a 1176 16 1215 | a 1177 16 1216 | a 1178 16 1217 | a 1179 16 1218 | a 1180 16 1219 | a 1181 16 1220 | a 1182 16 1221 | a 1183 16 1222 | a 1184 16 1223 | a 1185 16 1224 | a 1186 16 1225 | a 1187 16 1226 | a 1188 16 1227 | a 1189 16 1228 | a 1190 16 1229 | a 1191 16 1230 | a 1192 16 1231 | a 1193 4064 1232 | a 1194 16 1233 | a 1195 16 1234 | a 1196 16 1235 | a 1197 16 1236 | a 1198 16 1237 | a 1199 16 1238 | a 1200 16 1239 | a 1201 16 1240 | a 1202 16 1241 | a 1203 16 1242 | a 1204 16 1243 | a 1205 16 1244 | a 1206 16 1245 | a 1207 16 1246 | a 1208 16 1247 | a 1209 16 1248 | a 1210 16 1249 | a 1211 16 1250 | a 1212 16 1251 | a 1213 16 1252 | a 1214 16 1253 | a 1215 16 1254 | a 1216 16 1255 | a 1217 16 1256 | a 1218 16 1257 | a 1219 16 1258 | a 1220 16 1259 | a 1221 16 1260 | a 1222 16 1261 | a 1223 16 1262 | a 1224 16 1263 | a 1225 16 1264 | a 1226 16 1265 | a 1227 16 1266 | a 1228 16 1267 | a 1229 16 1268 | a 1230 16 1269 | a 1231 16 1270 | a 1232 16 1271 | a 1233 16 1272 | a 1234 16 1273 | a 1235 16 1274 | a 1236 16 1275 | a 1237 16 1276 | a 1238 16 1277 | a 1239 16 1278 | a 1240 16 1279 | a 1241 16 1280 | a 1242 16 1281 | a 1243 16 1282 | a 1244 16 1283 | a 1245 16 1284 | a 1246 16 1285 | a 1247 16 1286 | a 1248 16 1287 | a 1249 16 1288 | a 1250 16 1289 | a 1251 16 1290 | a 1252 16 1291 | a 1253 16 1292 | a 1254 16 1293 | a 1255 16 1294 | a 1256 16 1295 | a 1257 16 1296 | a 1258 16 1297 | a 1259 16 1298 | a 1260 16 1299 | a 1261 16 1300 | a 1262 16 1301 | a 1263 16 1302 | a 1264 16 1303 | a 1265 16 1304 | a 1266 16 1305 | a 1267 16 1306 | a 1268 16 1307 | a 1269 16 1308 | a 1270 16 1309 | a 1271 16 1310 | a 1272 16 1311 | a 1273 16 1312 | a 1274 16 1313 | a 1275 16 1314 | a 1276 16 1315 | a 1277 16 1316 | a 1278 16 1317 | a 1279 16 1318 | a 1280 16 1319 | a 1281 16 1320 | a 1282 16 1321 | a 1283 16 1322 | a 1284 16 1323 | a 1285 16 1324 | a 1286 16 1325 | a 1287 16 1326 | a 1288 16 1327 | a 1289 16 1328 | a 1290 16 1329 | a 1291 16 1330 | a 1292 16 1331 | a 1293 16 1332 | a 1294 16 1333 | a 1295 16 1334 | a 1296 16 1335 | a 1297 16 1336 | a 1298 16 1337 | a 1299 16 1338 | a 1300 16 1339 | a 1301 16 1340 | a 1302 16 1341 | a 1303 16 1342 | a 1304 16 1343 | a 1305 16 1344 | a 1306 16 1345 | a 1307 16 1346 | a 1308 16 1347 | a 1309 16 1348 | a 1310 16 1349 | a 1311 16 1350 | a 1312 16 1351 | a 1313 16 1352 | a 1314 16 1353 | a 1315 16 1354 | a 1316 16 1355 | a 1317 16 1356 | a 1318 16 1357 | a 1319 16 1358 | a 1320 4064 1359 | a 1321 16 1360 | a 1322 16 1361 | a 1323 16 1362 | a 1324 16 1363 | a 1325 16 1364 | a 1326 16 1365 | a 1327 16 1366 | a 1328 16 1367 | a 1329 16 1368 | a 1330 16 1369 | a 1331 16 1370 | a 1332 16 1371 | a 1333 16 1372 | a 1334 16 1373 | a 1335 16 1374 | a 1336 16 1375 | a 1337 16 1376 | a 1338 16 1377 | a 1339 16 1378 | a 1340 16 1379 | a 1341 16 1380 | a 1342 16 1381 | a 1343 16 1382 | a 1344 16 1383 | a 1345 16 1384 | a 1346 16 1385 | a 1347 16 1386 | a 1348 16 1387 | a 1349 16 1388 | a 1350 16 1389 | a 1351 16 1390 | a 1352 16 1391 | a 1353 16 1392 | a 1354 16 1393 | a 1355 16 1394 | a 1356 16 1395 | a 1357 16 1396 | a 1358 16 1397 | a 1359 16 1398 | a 1360 16 1399 | a 1361 16 1400 | a 1362 16 1401 | a 1363 16 1402 | a 1364 16 1403 | a 1365 16 1404 | a 1366 16 1405 | a 1367 16 1406 | a 1368 16 1407 | a 1369 16 1408 | a 1370 16 1409 | a 1371 16 1410 | a 1372 16 1411 | a 1373 16 1412 | a 1374 16 1413 | a 1375 16 1414 | a 1376 16 1415 | a 1377 16 1416 | a 1378 16 1417 | a 1379 16 1418 | a 1380 16 1419 | a 1381 16 1420 | a 1382 16 1421 | a 1383 16 1422 | a 1384 16 1423 | a 1385 16 1424 | a 1386 16 1425 | a 1387 16 1426 | a 1388 16 1427 | a 1389 16 1428 | a 1390 16 1429 | a 1391 16 1430 | a 1392 16 1431 | a 1393 16 1432 | a 1394 16 1433 | a 1395 16 1434 | a 1396 16 1435 | a 1397 16 1436 | a 1398 16 1437 | a 1399 16 1438 | a 1400 16 1439 | a 1401 16 1440 | a 1402 16 1441 | a 1403 16 1442 | a 1404 16 1443 | a 1405 16 1444 | a 1406 16 1445 | a 1407 16 1446 | a 1408 16 1447 | a 1409 16 1448 | a 1410 16 1449 | a 1411 16 1450 | a 1412 16 1451 | a 1413 16 1452 | a 1414 16 1453 | a 1415 16 1454 | a 1416 16 1455 | a 1417 16 1456 | a 1418 16 1457 | a 1419 16 1458 | a 1420 16 1459 | a 1421 16 1460 | a 1422 16 1461 | a 1423 16 1462 | a 1424 16 1463 | a 1425 16 1464 | a 1426 16 1465 | a 1427 16 1466 | a 1428 16 1467 | a 1429 16 1468 | a 1430 16 1469 | a 1431 16 1470 | a 1432 16 1471 | a 1433 16 1472 | a 1434 16 1473 | a 1435 16 1474 | a 1436 16 1475 | a 1437 16 1476 | a 1438 16 1477 | a 1439 16 1478 | a 1440 16 1479 | a 1441 16 1480 | a 1442 16 1481 | a 1443 16 1482 | a 1444 16 1483 | a 1445 16 1484 | a 1446 16 1485 | a 1447 4064 1486 | a 1448 16 1487 | a 1449 16 1488 | a 1450 16 1489 | a 1451 16 1490 | a 1452 16 1491 | a 1453 16 1492 | a 1454 16 1493 | a 1455 16 1494 | a 1456 16 1495 | a 1457 16 1496 | a 1458 16 1497 | a 1459 16 1498 | a 1460 16 1499 | a 1461 16 1500 | a 1462 16 1501 | a 1463 16 1502 | a 1464 16 1503 | a 1465 16 1504 | a 1466 16 1505 | a 1467 16 1506 | a 1468 16 1507 | a 1469 16 1508 | a 1470 16 1509 | a 1471 16 1510 | a 1472 16 1511 | a 1473 16 1512 | a 1474 16 1513 | a 1475 16 1514 | a 1476 16 1515 | a 1477 16 1516 | a 1478 16 1517 | a 1479 16 1518 | a 1480 16 1519 | a 1481 16 1520 | a 1482 16 1521 | a 1483 16 1522 | a 1484 16 1523 | a 1485 16 1524 | a 1486 16 1525 | a 1487 16 1526 | a 1488 16 1527 | a 1489 16 1528 | a 1490 16 1529 | a 1491 16 1530 | a 1492 16 1531 | a 1493 16 1532 | a 1494 16 1533 | a 1495 16 1534 | a 1496 16 1535 | a 1497 16 1536 | a 1498 16 1537 | a 1499 16 1538 | a 1500 16 1539 | a 1501 16 1540 | a 1502 16 1541 | a 1503 16 1542 | a 1504 16 1543 | a 1505 16 1544 | a 1506 16 1545 | a 1507 16 1546 | a 1508 16 1547 | a 1509 16 1548 | a 1510 16 1549 | a 1511 16 1550 | a 1512 16 1551 | a 1513 16 1552 | a 1514 16 1553 | a 1515 16 1554 | a 1516 16 1555 | a 1517 16 1556 | a 1518 16 1557 | a 1519 16 1558 | a 1520 16 1559 | a 1521 16 1560 | a 1522 16 1561 | a 1523 16 1562 | a 1524 16 1563 | a 1525 16 1564 | a 1526 16 1565 | a 1527 16 1566 | a 1528 16 1567 | a 1529 16 1568 | a 1530 16 1569 | a 1531 16 1570 | a 1532 16 1571 | a 1533 16 1572 | a 1534 16 1573 | a 1535 16 1574 | a 1536 16 1575 | a 1537 16 1576 | a 1538 16 1577 | a 1539 16 1578 | a 1540 16 1579 | a 1541 16 1580 | a 1542 16 1581 | a 1543 16 1582 | a 1544 16 1583 | a 1545 16 1584 | a 1546 16 1585 | a 1547 16 1586 | a 1548 16 1587 | a 1549 16 1588 | a 1550 16 1589 | a 1551 16 1590 | a 1552 16 1591 | a 1553 16 1592 | a 1554 16 1593 | a 1555 16 1594 | a 1556 16 1595 | a 1557 16 1596 | a 1558 16 1597 | a 1559 16 1598 | a 1560 16 1599 | a 1561 16 1600 | a 1562 16 1601 | a 1563 16 1602 | a 1564 16 1603 | a 1565 16 1604 | a 1566 16 1605 | a 1567 16 1606 | a 1568 16 1607 | a 1569 16 1608 | a 1570 16 1609 | a 1571 16 1610 | a 1572 16 1611 | a 1573 16 1612 | a 1574 4064 1613 | a 1575 16 1614 | a 1576 16 1615 | a 1577 16 1616 | a 1578 16 1617 | a 1579 16 1618 | a 1580 16 1619 | a 1581 16 1620 | a 1582 16 1621 | a 1583 16 1622 | a 1584 16 1623 | a 1585 16 1624 | a 1586 16 1625 | a 1587 16 1626 | a 1588 16 1627 | a 1589 16 1628 | a 1590 16 1629 | a 1591 16 1630 | a 1592 16 1631 | a 1593 16 1632 | a 1594 16 1633 | a 1595 16 1634 | a 1596 16 1635 | a 1597 16 1636 | a 1598 16 1637 | a 1599 16 1638 | a 1600 16 1639 | a 1601 16 1640 | a 1602 16 1641 | a 1603 16 1642 | a 1604 16 1643 | a 1605 16 1644 | a 1606 16 1645 | a 1607 16 1646 | a 1608 16 1647 | a 1609 16 1648 | a 1610 16 1649 | a 1611 16 1650 | a 1612 16 1651 | a 1613 16 1652 | a 1614 16 1653 | a 1615 16 1654 | a 1616 16 1655 | a 1617 16 1656 | a 1618 16 1657 | a 1619 16 1658 | a 1620 16 1659 | a 1621 16 1660 | a 1622 16 1661 | a 1623 16 1662 | a 1624 16 1663 | a 1625 16 1664 | a 1626 16 1665 | a 1627 16 1666 | a 1628 16 1667 | a 1629 16 1668 | a 1630 16 1669 | a 1631 16 1670 | a 1632 16 1671 | a 1633 16 1672 | a 1634 16 1673 | a 1635 16 1674 | a 1636 16 1675 | a 1637 16 1676 | a 1638 16 1677 | a 1639 16 1678 | a 1640 16 1679 | a 1641 16 1680 | a 1642 16 1681 | a 1643 16 1682 | a 1644 16 1683 | a 1645 16 1684 | a 1646 16 1685 | a 1647 16 1686 | a 1648 16 1687 | a 1649 16 1688 | a 1650 16 1689 | a 1651 16 1690 | a 1652 16 1691 | a 1653 16 1692 | a 1654 16 1693 | a 1655 16 1694 | a 1656 16 1695 | a 1657 16 1696 | a 1658 16 1697 | a 1659 16 1698 | a 1660 16 1699 | a 1661 16 1700 | a 1662 16 1701 | a 1663 16 1702 | a 1664 16 1703 | a 1665 16 1704 | a 1666 16 1705 | a 1667 16 1706 | a 1668 16 1707 | a 1669 16 1708 | a 1670 16 1709 | a 1671 16 1710 | a 1672 16 1711 | a 1673 16 1712 | a 1674 16 1713 | a 1675 16 1714 | a 1676 16 1715 | a 1677 16 1716 | a 1678 16 1717 | a 1679 16 1718 | a 1680 16 1719 | a 1681 16 1720 | a 1682 16 1721 | a 1683 16 1722 | a 1684 16 1723 | a 1685 16 1724 | a 1686 16 1725 | a 1687 16 1726 | a 1688 16 1727 | a 1689 16 1728 | a 1690 16 1729 | a 1691 16 1730 | a 1692 16 1731 | a 1693 16 1732 | a 1694 16 1733 | a 1695 16 1734 | a 1696 16 1735 | a 1697 16 1736 | a 1698 16 1737 | a 1699 16 1738 | a 1700 16 1739 | a 1701 4064 1740 | a 1702 16 1741 | a 1703 16 1742 | a 1704 16 1743 | a 1705 16 1744 | a 1706 16 1745 | a 1707 16 1746 | a 1708 16 1747 | a 1709 16 1748 | a 1710 16 1749 | a 1711 16 1750 | a 1712 16 1751 | a 1713 16 1752 | a 1714 16 1753 | a 1715 16 1754 | a 1716 16 1755 | a 1717 16 1756 | a 1718 16 1757 | a 1719 16 1758 | a 1720 16 1759 | a 1721 16 1760 | a 1722 16 1761 | a 1723 16 1762 | a 1724 16 1763 | a 1725 16 1764 | a 1726 16 1765 | a 1727 16 1766 | a 1728 16 1767 | a 1729 16 1768 | a 1730 16 1769 | a 1731 16 1770 | a 1732 16 1771 | a 1733 16 1772 | a 1734 16 1773 | a 1735 16 1774 | a 1736 16 1775 | a 1737 16 1776 | a 1738 16 1777 | a 1739 16 1778 | a 1740 16 1779 | a 1741 16 1780 | a 1742 16 1781 | a 1743 16 1782 | a 1744 16 1783 | a 1745 16 1784 | a 1746 16 1785 | a 1747 16 1786 | a 1748 16 1787 | a 1749 16 1788 | a 1750 16 1789 | a 1751 16 1790 | a 1752 16 1791 | a 1753 16 1792 | a 1754 16 1793 | a 1755 16 1794 | a 1756 16 1795 | a 1757 16 1796 | a 1758 16 1797 | a 1759 16 1798 | a 1760 16 1799 | a 1761 16 1800 | a 1762 16 1801 | a 1763 16 1802 | a 1764 16 1803 | a 1765 16 1804 | a 1766 16 1805 | a 1767 16 1806 | a 1768 16 1807 | a 1769 16 1808 | a 1770 16 1809 | a 1771 16 1810 | a 1772 16 1811 | a 1773 16 1812 | a 1774 16 1813 | a 1775 16 1814 | a 1776 16 1815 | a 1777 16 1816 | a 1778 16 1817 | a 1779 16 1818 | a 1780 16 1819 | a 1781 16 1820 | a 1782 16 1821 | a 1783 16 1822 | a 1784 16 1823 | a 1785 16 1824 | a 1786 16 1825 | a 1787 16 1826 | a 1788 16 1827 | a 1789 16 1828 | a 1790 16 1829 | a 1791 16 1830 | a 1792 16 1831 | a 1793 16 1832 | a 1794 16 1833 | a 1795 16 1834 | a 1796 16 1835 | a 1797 16 1836 | a 1798 16 1837 | a 1799 16 1838 | a 1800 16 1839 | a 1801 16 1840 | a 1802 16 1841 | a 1803 16 1842 | a 1804 16 1843 | a 1805 16 1844 | a 1806 16 1845 | a 1807 16 1846 | a 1808 16 1847 | a 1809 16 1848 | a 1810 16 1849 | a 1811 16 1850 | a 1812 16 1851 | a 1813 16 1852 | a 1814 16 1853 | a 1815 16 1854 | a 1816 16 1855 | a 1817 16 1856 | a 1818 16 1857 | a 1819 16 1858 | a 1820 16 1859 | a 1821 16 1860 | a 1822 16 1861 | a 1823 16 1862 | a 1824 16 1863 | a 1825 16 1864 | a 1826 16 1865 | a 1827 16 1866 | a 1828 4064 1867 | a 1829 16 1868 | a 1830 16 1869 | a 1831 16 1870 | a 1832 16 1871 | a 1833 16 1872 | a 1834 16 1873 | a 1835 16 1874 | a 1836 16 1875 | a 1837 16 1876 | a 1838 16 1877 | a 1839 16 1878 | a 1840 16 1879 | a 1841 16 1880 | a 1842 16 1881 | a 1843 16 1882 | a 1844 16 1883 | a 1845 16 1884 | a 1846 16 1885 | a 1847 16 1886 | a 1848 16 1887 | a 1849 16 1888 | a 1850 16 1889 | a 1851 16 1890 | a 1852 16 1891 | a 1853 16 1892 | a 1854 16 1893 | a 1855 16 1894 | a 1856 16 1895 | a 1857 16 1896 | a 1858 16 1897 | a 1859 16 1898 | a 1860 16 1899 | a 1861 16 1900 | a 1862 16 1901 | a 1863 16 1902 | a 1864 16 1903 | a 1865 16 1904 | a 1866 16 1905 | a 1867 16 1906 | a 1868 16 1907 | a 1869 16 1908 | a 1870 16 1909 | a 1871 16 1910 | a 1872 16 1911 | a 1873 16 1912 | a 1874 16 1913 | a 1875 16 1914 | a 1876 16 1915 | a 1877 16 1916 | a 1878 16 1917 | a 1879 16 1918 | a 1880 16 1919 | a 1881 16 1920 | a 1882 16 1921 | a 1883 16 1922 | a 1884 16 1923 | a 1885 16 1924 | a 1886 16 1925 | a 1887 16 1926 | a 1888 16 1927 | a 1889 16 1928 | a 1890 16 1929 | a 1891 16 1930 | a 1892 16 1931 | a 1893 16 1932 | a 1894 16 1933 | a 1895 16 1934 | a 1896 16 1935 | a 1897 16 1936 | a 1898 16 1937 | a 1899 16 1938 | a 1900 16 1939 | a 1901 16 1940 | a 1902 16 1941 | a 1903 16 1942 | a 1904 16 1943 | a 1905 16 1944 | a 1906 16 1945 | a 1907 16 1946 | a 1908 16 1947 | a 1909 16 1948 | a 1910 16 1949 | a 1911 16 1950 | a 1912 16 1951 | a 1913 16 1952 | a 1914 16 1953 | a 1915 16 1954 | a 1916 16 1955 | a 1917 16 1956 | a 1918 16 1957 | a 1919 16 1958 | a 1920 16 1959 | a 1921 16 1960 | a 1922 16 1961 | a 1923 16 1962 | a 1924 16 1963 | a 1925 16 1964 | a 1926 16 1965 | a 1927 16 1966 | a 1928 16 1967 | a 1929 16 1968 | a 1930 16 1969 | a 1931 16 1970 | a 1932 16 1971 | a 1933 16 1972 | a 1934 16 1973 | a 1935 16 1974 | a 1936 16 1975 | a 1937 16 1976 | a 1938 16 1977 | a 1939 16 1978 | a 1940 16 1979 | a 1941 16 1980 | a 1942 16 1981 | a 1943 16 1982 | a 1944 16 1983 | a 1945 16 1984 | a 1946 16 1985 | a 1947 16 1986 | a 1948 16 1987 | a 1949 16 1988 | a 1950 16 1989 | a 1951 16 1990 | a 1952 16 1991 | a 1953 16 1992 | a 1954 16 1993 | a 1955 4064 1994 | a 1956 16 1995 | a 1957 16 1996 | a 1958 16 1997 | a 1959 16 1998 | a 1960 16 1999 | a 1961 16 2000 | a 1962 16 2001 | a 1963 16 2002 | a 1964 16 2003 | a 1965 16 2004 | a 1966 16 2005 | a 1967 16 2006 | a 1968 16 2007 | a 1969 16 2008 | a 1970 16 2009 | a 1971 16 2010 | a 1972 16 2011 | a 1973 16 2012 | a 1974 16 2013 | a 1975 16 2014 | a 1976 16 2015 | a 1977 16 2016 | a 1978 16 2017 | a 1979 16 2018 | a 1980 16 2019 | a 1981 16 2020 | a 1982 16 2021 | a 1983 16 2022 | a 1984 16 2023 | a 1985 16 2024 | a 1986 16 2025 | a 1987 16 2026 | a 1988 16 2027 | a 1989 16 2028 | a 1990 16 2029 | a 1991 16 2030 | a 1992 16 2031 | a 1993 16 2032 | a 1994 16 2033 | a 1995 16 2034 | a 1996 16 2035 | a 1997 16 2036 | a 1998 16 2037 | a 1999 16 2038 | a 2000 16 2039 | a 2001 16 2040 | a 2002 16 2041 | a 2003 16 2042 | a 2004 16 2043 | a 2005 16 2044 | a 2006 16 2045 | a 2007 16 2046 | a 2008 16 2047 | a 2009 16 2048 | a 2010 16 2049 | a 2011 16 2050 | a 2012 16 2051 | a 2013 16 2052 | a 2014 16 2053 | a 2015 16 2054 | a 2016 16 2055 | a 2017 16 2056 | a 2018 16 2057 | a 2019 16 2058 | a 2020 16 2059 | a 2021 16 2060 | a 2022 16 2061 | a 2023 16 2062 | a 2024 16 2063 | a 2025 16 2064 | a 2026 16 2065 | a 2027 16 2066 | a 2028 16 2067 | a 2029 16 2068 | a 2030 16 2069 | a 2031 16 2070 | a 2032 16 2071 | a 2033 16 2072 | a 2034 16 2073 | a 2035 16 2074 | a 2036 16 2075 | a 2037 16 2076 | a 2038 16 2077 | a 2039 16 2078 | a 2040 16 2079 | a 2041 16 2080 | a 2042 16 2081 | a 2043 16 2082 | a 2044 16 2083 | a 2045 16 2084 | a 2046 16 2085 | a 2047 16 2086 | a 2048 104 2087 | a 2049 4064 2088 | a 2050 524411 2089 | f 2049 2090 | a 2051 4064 2091 | a 2052 4064 2092 | a 2053 4064 2093 | a 2054 4064 2094 | a 2055 552 2095 | a 2056 4096 2096 | a 2057 15 2097 | a 2058 88 2098 | a 2059 4064 2099 | a 2060 4064 2100 | a 2061 15 2101 | a 2062 88 2102 | a 2063 4064 2103 | a 2064 15 2104 | a 2065 152 2105 | a 2066 32 2106 | a 2067 56 2107 | a 2068 56 2108 | a 2069 56 2109 | a 2070 56 2110 | a 2071 56 2111 | a 2072 11 2112 | f 2072 2113 | a 2073 56 2114 | a 2074 56 2115 | a 2075 56 2116 | a 2076 56 2117 | a 2077 56 2118 | a 2078 56 2119 | a 2079 25 2120 | f 2079 2121 | a 2080 8 2122 | f 2080 2123 | a 2081 10 2124 | f 2081 2125 | a 2082 11 2126 | f 2082 2127 | a 2083 18 2128 | f 2083 2129 | a 2084 8 2130 | f 2084 2131 | a 2085 10 2132 | f 2085 2133 | a 2086 11 2134 | f 2086 2135 | a 2087 19 2136 | f 2087 2137 | a 2088 8 2138 | f 2088 2139 | a 2089 10 2140 | f 2089 2141 | a 2090 11 2142 | f 2090 2143 | a 2091 18 2144 | f 2091 2145 | a 2092 8 2146 | f 2092 2147 | a 2093 10 2148 | f 2093 2149 | a 2094 4064 2150 | a 2095 4064 2151 | a 2096 16 2152 | f 2096 2153 | a 2097 4 2154 | f 2097 2155 | a 2098 4 2156 | f 2098 2157 | a 2099 11 2158 | f 2099 2159 | a 2100 11 2160 | f 2100 2161 | a 2101 8 2162 | f 2101 2163 | a 2102 10 2164 | f 2102 2165 | a 2103 9 2166 | f 2103 2167 | a 2104 4 2168 | f 2104 2169 | a 2105 56 2170 | a 2106 56 2171 | a 2107 16 2172 | a 2108 56 2173 | a 2109 25 2174 | f 2109 2175 | a 2110 56 2176 | a 2111 56 2177 | a 2112 56 2178 | a 2113 56 2179 | a 2114 56 2180 | a 2115 56 2181 | f 2107 2182 | a 2116 13 2183 | f 2116 2184 | a 2117 11 2185 | f 2117 2186 | a 2118 9 2187 | f 2118 2188 | a 2119 11 2189 | f 2119 2190 | a 2120 13 2191 | f 2120 2192 | a 2121 10 2193 | f 2121 2194 | a 2122 12 2195 | f 2122 2196 | a 2123 8 2197 | f 2123 2198 | a 2124 10 2199 | f 2124 2200 | a 2125 7 2201 | f 2125 2202 | a 2126 9 2203 | f 2126 2204 | a 2127 31 2205 | f 2127 2206 | a 2128 11 2207 | f 2128 2208 | a 2129 11 2209 | f 2129 2210 | a 2130 16 2211 | f 2130 2212 | a 2131 18 2213 | f 2131 2214 | f 2066 2215 | a 2132 32 2216 | a 2133 15 2217 | a 2134 16 2218 | a 2135 4064 2219 | f 2134 2220 | a 2136 152 2221 | a 2137 32 2222 | a 2138 56 2223 | a 2139 56 2224 | a 2140 56 2225 | a 2141 56 2226 | a 2142 56 2227 | a 2143 17 2228 | f 2143 2229 | a 2144 5 2230 | f 2144 2231 | a 2145 7 2232 | f 2145 2233 | a 2146 9 2234 | f 2146 2235 | a 2147 5 2236 | f 2147 2237 | a 2148 8 2238 | f 2148 2239 | a 2149 17 2240 | f 2149 2241 | a 2150 18 2242 | f 2150 2243 | a 2151 14 2244 | f 2151 2245 | a 2152 56 2246 | a 2153 56 2247 | a 2154 16 2248 | a 2155 56 2249 | a 2156 56 2250 | a 2157 56 2251 | f 2154 2252 | a 2158 13 2253 | f 2158 2254 | a 2159 11 2255 | f 2159 2256 | a 2160 9 2257 | f 2160 2258 | a 2161 11 2259 | f 2161 2260 | a 2162 56 2261 | a 2163 56 2262 | a 2164 16 2263 | a 2165 56 2264 | a 2166 56 2265 | a 2167 56 2266 | f 2164 2267 | a 2168 12 2268 | f 2168 2269 | a 2169 9 2270 | f 2169 2271 | a 2170 11 2272 | f 2170 2273 | a 2171 56 2274 | a 2172 56 2275 | f 2137 2276 | a 2173 32 2277 | a 2174 15 2278 | a 2175 5 2279 | f 2175 2280 | a 2176 152 2281 | a 2177 32 2282 | a 2178 56 2283 | a 2179 56 2284 | a 2180 25 2285 | f 2180 2286 | a 2181 5 2287 | f 2181 2288 | a 2182 18 2289 | f 2182 2290 | a 2183 56 2291 | a 2184 56 2292 | a 2185 56 2293 | a 2186 5 2294 | f 2186 2295 | a 2187 17 2296 | f 2187 2297 | a 2188 5 2298 | f 2188 2299 | a 2189 18 2300 | f 2189 2301 | a 2190 4064 2302 | a 2191 5 2303 | f 2191 2304 | a 2192 18 2305 | f 2192 2306 | a 2193 5 2307 | f 2193 2308 | a 2194 14 2309 | f 2194 2310 | a 2195 5 2311 | f 2195 2312 | a 2196 5 2313 | f 2196 2314 | a 2197 17 2315 | f 2197 2316 | a 2198 25 2317 | f 2198 2318 | a 2199 5 2319 | f 2199 2320 | a 2200 5 2321 | f 2200 2322 | a 2201 25 2323 | f 2201 2324 | a 2202 56 2325 | a 2203 56 2326 | a 2204 4064 2327 | a 2205 56 2328 | a 2206 56 2329 | a 2207 13 2330 | f 2207 2331 | a 2208 12 2332 | f 2208 2333 | a 2209 9 2334 | f 2209 2335 | a 2210 11 2336 | f 2210 2337 | a 2211 56 2338 | a 2212 56 2339 | a 2213 56 2340 | a 2214 9 2341 | f 2214 2342 | a 2215 12 2343 | f 2215 2344 | a 2216 16 2345 | f 2216 2346 | a 2217 18 2347 | f 2217 2348 | a 2218 5 2349 | f 2218 2350 | a 2219 11 2351 | f 2219 2352 | a 2220 5 2353 | f 2220 2354 | f 2177 2355 | a 2221 32 2356 | a 2222 15 2357 | a 2223 7 2358 | f 2223 2359 | a 2224 152 2360 | a 2225 32 2361 | a 2226 56 2362 | a 2227 56 2363 | a 2228 25 2364 | f 2228 2365 | a 2229 5 2366 | f 2229 2367 | a 2230 4064 2368 | a 2231 56 2369 | a 2232 56 2370 | a 2233 56 2371 | a 2234 56 2372 | a 2235 56 2373 | a 2236 56 2374 | a 2237 56 2375 | a 2238 56 2376 | a 2239 18 2377 | f 2239 2378 | a 2240 5 2379 | f 2240 2380 | a 2241 25 2381 | f 2241 2382 | a 2242 5 2383 | f 2242 2384 | a 2243 25 2385 | f 2243 2386 | a 2244 56 2387 | a 2245 56 2388 | a 2246 16 2389 | a 2247 56 2390 | a 2248 56 2391 | a 2249 56 2392 | a 2250 4064 2393 | a 2251 56 2394 | a 2252 56 2395 | a 2253 56 2396 | a 2254 56 2397 | f 2246 2398 | a 2255 9 2399 | f 2255 2400 | a 2256 12 2401 | f 2256 2402 | a 2257 16 2403 | f 2257 2404 | a 2258 18 2405 | f 2258 2406 | a 2259 5 2407 | f 2259 2408 | a 2260 56 2409 | a 2261 56 2410 | a 2262 56 2411 | a 2263 56 2412 | a 2264 16 2413 | f 2264 2414 | a 2265 56 2415 | a 2266 56 2416 | a 2267 56 2417 | a 2268 56 2418 | a 2269 11 2419 | f 2269 2420 | a 2270 18 2421 | f 2270 2422 | a 2271 5 2423 | f 2271 2424 | f 2225 2425 | a 2272 32 2426 | a 2273 15 2427 | a 2274 15 2428 | a 2275 8 2429 | f 2275 2430 | a 2276 152 2431 | a 2277 32 2432 | a 2278 56 2433 | a 2279 56 2434 | a 2280 25 2435 | f 2280 2436 | a 2281 56 2437 | a 2282 56 2438 | a 2283 56 2439 | a 2284 56 2440 | a 2285 56 2441 | a 2286 56 2442 | a 2287 56 2443 | a 2288 56 2444 | a 2289 56 2445 | a 2290 5 2446 | f 2290 2447 | a 2291 5 2448 | f 2291 2449 | a 2292 56 2450 | a 2293 56 2451 | a 2294 16 2452 | a 2295 56 2453 | a 2296 56 2454 | a 2297 56 2455 | a 2298 56 2456 | a 2299 56 2457 | a 2300 16 2458 | f 2300 2459 | a 2301 4064 2460 | a 2302 56 2461 | a 2303 56 2462 | f 2294 2463 | a 2304 18 2464 | f 2304 2465 | a 2305 5 2466 | f 2305 2467 | a 2306 20 2468 | f 2306 2469 | a 2307 25 2470 | f 2307 2471 | a 2308 5 2472 | f 2308 2473 | a 2309 9 2474 | f 2309 2475 | a 2310 5 2476 | f 2310 2477 | a 2311 12 2478 | f 2311 2479 | a 2312 16 2480 | f 2312 2481 | a 2313 18 2482 | f 2313 2483 | a 2314 25 2484 | f 2314 2485 | a 2315 56 2486 | a 2316 56 2487 | a 2317 16 2488 | a 2318 56 2489 | a 2319 56 2490 | a 2320 56 2491 | a 2321 4064 2492 | a 2322 56 2493 | a 2323 56 2494 | a 2324 56 2495 | a 2325 56 2496 | f 2317 2497 | a 2326 11 2498 | f 2326 2499 | a 2327 5 2500 | f 2327 2501 | a 2328 12 2502 | f 2328 2503 | a 2329 16 2504 | f 2329 2505 | a 2330 18 2506 | f 2330 2507 | a 2331 5 2508 | f 2331 2509 | a 2332 13 2510 | f 2332 2511 | a 2333 12 2512 | f 2333 2513 | a 2334 9 2514 | f 2334 2515 | a 2335 11 2516 | f 2335 2517 | a 2336 7 2518 | f 2336 2519 | a 2337 9 2520 | f 2337 2521 | f 2277 2522 | a 2338 32 2523 | a 2339 7 2524 | f 2339 2525 | a 2340 152 2526 | a 2341 32 2527 | a 2342 56 2528 | a 2343 56 2529 | a 2344 25 2530 | f 2344 2531 | a 2345 5 2532 | f 2345 2533 | a 2346 18 2534 | f 2346 2535 | a 2347 56 2536 | a 2348 56 2537 | a 2349 56 2538 | a 2350 56 2539 | a 2351 56 2540 | a 2352 56 2541 | a 2353 56 2542 | a 2354 56 2543 | a 2355 56 2544 | a 2356 5 2545 | f 2356 2546 | a 2357 19 2547 | f 2357 2548 | a 2358 25 2549 | f 2358 2550 | a 2359 5 2551 | f 2359 2552 | a 2360 25 2553 | f 2360 2554 | a 2361 56 2555 | a 2362 56 2556 | a 2363 16 2557 | a 2364 56 2558 | a 2365 56 2559 | a 2366 56 2560 | a 2367 56 2561 | a 2368 56 2562 | a 2369 56 2563 | a 2370 56 2564 | f 2363 2565 | a 2371 9 2566 | f 2371 2567 | a 2372 12 2568 | f 2372 2569 | a 2373 16 2570 | f 2373 2571 | a 2374 18 2572 | f 2374 2573 | a 2375 5 2574 | f 2375 2575 | a 2376 56 2576 | a 2377 56 2577 | a 2378 56 2578 | a 2379 56 2579 | a 2380 56 2580 | a 2381 16 2581 | f 2381 2582 | a 2382 56 2583 | a 2383 56 2584 | a 2384 56 2585 | a 2385 56 2586 | a 2386 56 2587 | a 2387 11 2588 | f 2387 2589 | a 2388 5 2590 | f 2388 2591 | f 2341 2592 | a 2389 4064 2593 | a 2390 32 2594 | a 2391 8 2595 | a 2392 4064 2596 | a 2393 88 2597 | a 2394 4064 2598 | a 2395 11 2599 | a 2396 4064 2600 | f 2395 2601 | a 2397 12 2602 | f 2397 2603 | a 2398 3 2604 | f 2398 2605 | a 2399 19 2606 | f 2399 2607 | a 2400 19 2608 | f 2400 2609 | a 2401 10 2610 | f 2401 2611 | a 2402 12 2612 | f 2402 2613 | a 2403 13 2614 | f 2403 2615 | a 2404 12 2616 | f 2404 2617 | a 2405 88 2618 | a 2406 4064 2619 | a 2407 16 2620 | a 2408 88 2621 | a 2409 4064 2622 | f 2056 2623 | f 2055 2624 | a 2410 88 2625 | a 2411 4064 2626 | a 2412 80 2627 | a 2413 32 2628 | a 2414 32 2629 | a 2415 32 2630 | a 2416 32 2631 | a 2417 4064 2632 | a 2418 32 2633 | a 2419 32 2634 | a 2420 32 2635 | a 2421 32 2636 | a 2422 32 2637 | a 2423 32 2638 | a 2424 4064 2639 | a 2425 32 2640 | a 2426 32 2641 | a 2427 32 2642 | a 2428 32 2643 | a 2429 32 2644 | a 2430 32 2645 | a 2431 32 2646 | a 2432 4064 2647 | a 2433 32 2648 | a 2434 32 2649 | a 2435 32 2650 | a 2436 32 2651 | a 2437 32 2652 | a 2438 4064 2653 | a 2439 4064 2654 | a 2440 4064 2655 | f 2132 2656 | a 2441 49 2657 | f 2441 2658 | a 2442 552 2659 | a 2443 4096 2660 | a 2444 1600 2661 | a 2445 1024 2662 | r 2445 2048 2663 | f 2443 2664 | f 2442 2665 | a 2446 5 2666 | a 2447 54 2667 | a 2448 168 2668 | a 2449 49 2669 | a 2450 104 2670 | a 2451 43 2671 | a 2452 72 2672 | a 2453 40 2673 | a 2454 56 2674 | a 2455 49 2675 | a 2456 56 2676 | a 2457 49 2677 | f 2457 2678 | a 2458 52 2679 | a 2459 72 2680 | a 2460 49 2681 | f 2460 2682 | a 2461 52 2683 | f 2461 2684 | a 2462 49 2685 | f 2462 2686 | a 2463 49 2687 | f 2463 2688 | a 2464 46 2689 | a 2465 72 2690 | a 2466 40 2691 | f 2466 2692 | a 2467 55 2693 | a 2468 72 2694 | a 2469 49 2695 | f 2469 2696 | a 2470 55 2697 | f 2470 2698 | a 2471 49 2699 | f 2471 2700 | a 2472 49 2701 | f 2472 2702 | a 2473 40 2703 | f 2473 2704 | a 2474 58 2705 | a 2475 104 2706 | a 2476 52 2707 | f 2476 2708 | a 2477 55 2709 | f 2477 2710 | a 2478 49 2711 | f 2478 2712 | a 2479 58 2713 | f 2479 2714 | a 2480 52 2715 | f 2480 2716 | a 2481 55 2717 | f 2481 2718 | a 2482 49 2719 | f 2482 2720 | a 2483 52 2721 | f 2483 2722 | a 2484 55 2723 | f 2484 2724 | a 2485 49 2725 | f 2485 2726 | a 2486 48 2727 | a 2487 104 2728 | a 2488 43 2729 | f 2488 2730 | a 2489 45 2731 | a 2490 72 2732 | a 2491 40 2733 | f 2491 2734 | a 2492 54 2735 | a 2493 72 2736 | a 2494 49 2737 | f 2494 2738 | a 2495 54 2739 | f 2495 2740 | a 2496 49 2741 | f 2496 2742 | a 2497 49 2743 | f 2497 2744 | a 2498 40 2745 | f 2498 2746 | a 2499 57 2747 | a 2500 104 2748 | a 2501 52 2749 | f 2501 2750 | a 2502 54 2751 | f 2502 2752 | a 2503 49 2753 | f 2503 2754 | a 2504 57 2755 | f 2504 2756 | a 2505 52 2757 | f 2505 2758 | a 2506 54 2759 | f 2506 2760 | a 2507 49 2761 | f 2507 2762 | a 2508 52 2763 | f 2508 2764 | a 2509 54 2765 | f 2509 2766 | a 2510 49 2767 | f 2510 2768 | a 2511 43 2769 | f 2511 2770 | a 2512 51 2771 | a 2513 104 2772 | a 2514 46 2773 | f 2514 2774 | a 2515 45 2775 | f 2515 2776 | a 2516 40 2777 | f 2516 2778 | a 2517 60 2779 | a 2518 104 2780 | a 2519 55 2781 | f 2519 2782 | a 2520 54 2783 | f 2520 2784 | a 2521 49 2785 | f 2521 2786 | a 2522 60 2787 | f 2522 2788 | a 2523 55 2789 | f 2523 2790 | a 2524 54 2791 | f 2524 2792 | a 2525 49 2793 | f 2525 2794 | a 2526 55 2795 | f 2526 2796 | a 2527 54 2797 | f 2527 2798 | a 2528 49 2799 | f 2528 2800 | a 2529 46 2801 | f 2529 2802 | a 2530 45 2803 | f 2530 2804 | a 2531 40 2805 | f 2531 2806 | a 2532 63 2807 | a 2533 168 2808 | a 2534 58 2809 | f 2534 2810 | a 2535 57 2811 | f 2535 2812 | a 2536 52 2813 | f 2536 2814 | a 2537 60 2815 | f 2537 2816 | a 2538 55 2817 | f 2538 2818 | a 2539 54 2819 | f 2539 2820 | a 2540 49 2821 | f 2540 2822 | a 2541 63 2823 | f 2541 2824 | a 2542 58 2825 | f 2542 2826 | a 2543 57 2827 | f 2543 2828 | a 2544 52 2829 | f 2544 2830 | a 2545 60 2831 | f 2545 2832 | a 2546 55 2833 | f 2546 2834 | a 2547 54 2835 | f 2547 2836 | a 2548 49 2837 | f 2548 2838 | a 2549 58 2839 | f 2549 2840 | a 2550 57 2841 | f 2550 2842 | a 2551 52 2843 | f 2551 2844 | a 2552 60 2845 | f 2552 2846 | a 2553 55 2847 | f 2553 2848 | a 2554 54 2849 | f 2554 2850 | a 2555 49 2851 | f 2555 2852 | f 2446 2853 | a 2556 49 2854 | f 2556 2855 | a 2557 49 2856 | f 2557 2857 | a 2558 49 2858 | f 2558 2859 | a 2559 49 2860 | f 2559 2861 | a 2560 49 2862 | f 2560 2863 | a 2561 49 2864 | f 2561 2865 | a 2562 49 2866 | f 2562 2867 | a 2563 49 2868 | f 2563 2869 | a 2564 49 2870 | f 2564 2871 | f 2173 2872 | a 2565 49 2873 | f 2565 2874 | a 2566 49 2875 | f 2566 2876 | a 2567 49 2877 | f 2567 2878 | a 2568 49 2879 | f 2568 2880 | a 2569 49 2881 | f 2569 2882 | a 2570 49 2883 | f 2570 2884 | a 2571 49 2885 | f 2571 2886 | a 2572 49 2887 | f 2572 2888 | a 2573 49 2889 | f 2573 2890 | f 2221 2891 | a 2574 49 2892 | f 2574 2893 | a 2575 49 2894 | f 2575 2895 | a 2576 49 2896 | f 2576 2897 | a 2577 49 2898 | f 2577 2899 | a 2578 49 2900 | f 2578 2901 | a 2579 49 2902 | f 2579 2903 | a 2580 49 2904 | f 2580 2905 | a 2581 4064 2906 | f 2272 2907 | a 2582 49 2908 | f 2582 2909 | a 2583 49 2910 | f 2583 2911 | a 2584 49 2912 | f 2584 2913 | a 2585 49 2914 | f 2585 2915 | a 2586 49 2916 | f 2586 2917 | a 2587 49 2918 | f 2587 2919 | a 2588 49 2920 | f 2588 2921 | a 2589 49 2922 | f 2589 2923 | a 2590 49 2924 | f 2590 2925 | a 2591 49 2926 | f 2591 2927 | a 2592 49 2928 | f 2592 2929 | a 2593 49 2930 | f 2593 2931 | f 2338 2932 | a 2594 49 2933 | f 2594 2934 | a 2595 49 2935 | f 2595 2936 | a 2596 49 2937 | f 2596 2938 | a 2597 49 2939 | f 2597 2940 | a 2598 49 2941 | f 2598 2942 | a 2599 49 2943 | f 2599 2944 | a 2600 49 2945 | f 2600 2946 | a 2601 49 2947 | f 2601 2948 | a 2602 49 2949 | f 2602 2950 | a 2603 49 2951 | f 2603 2952 | a 2604 49 2953 | f 2604 2954 | a 2605 49 2955 | f 2605 2956 | a 2606 49 2957 | f 2606 2958 | a 2607 49 2959 | f 2607 2960 | f 2390 2961 | a 2608 49 2962 | f 2608 2963 | a 2609 49 2964 | f 2609 2965 | a 2610 49 2966 | f 2610 2967 | a 2611 49 2968 | f 2611 2969 | a 2612 49 2970 | f 2612 2971 | a 2613 49 2972 | f 2613 2973 | a 2614 49 2974 | f 2614 2975 | a 2615 49 2976 | f 2615 2977 | a 2616 49 2978 | f 2616 2979 | a 2617 49 2980 | f 2617 2981 | a 2618 49 2982 | f 2618 2983 | a 2619 49 2984 | f 2619 2985 | a 2620 49 2986 | f 2620 2987 | a 2621 49 2988 | f 2621 2989 | a 2622 49 2990 | f 2622 2991 | a 2623 49 2992 | f 2623 2993 | a 2624 49 2994 | f 2624 2995 | a 2625 49 2996 | f 2625 2997 | a 2626 49 2998 | f 2626 2999 | a 2627 49 3000 | f 2627 3001 | a 2628 49 3002 | f 2628 3003 | a 2629 49 3004 | f 2629 3005 | a 2630 49 3006 | f 2630 3007 | a 2631 49 3008 | f 2631 3009 | a 2632 4064 3010 | a 2633 49 3011 | f 2633 3012 | a 2634 49 3013 | f 2634 3014 | a 2635 49 3015 | f 2635 3016 | a 2636 49 3017 | f 2636 3018 | a 2637 49 3019 | f 2637 3020 | a 2638 49 3021 | f 2638 3022 | a 2639 49 3023 | f 2639 3024 | a 2640 49 3025 | f 2640 3026 | a 2641 49 3027 | f 2641 3028 | a 2642 49 3029 | f 2642 3030 | a 2643 49 3031 | f 2643 3032 | a 2644 49 3033 | f 2644 3034 | a 2645 49 3035 | f 2645 3036 | a 2646 49 3037 | f 2646 3038 | a 2647 49 3039 | f 2647 3040 | a 2648 104 3041 | a 2649 4064 3042 | a 2650 524411 3043 | f 2649 3044 | a 2651 656 3045 | a 2652 32 3046 | a 2653 8 3047 | a 2654 32 3048 | a 2655 8 3049 | a 2656 32 3050 | a 2657 8 3051 | a 2658 32 3052 | a 2659 8 3053 | a 2660 32 3054 | a 2661 8 3055 | a 2662 32 3056 | a 2663 8 3057 | a 2664 32 3058 | a 2665 8 3059 | a 2666 32 3060 | a 2667 8 3061 | a 2668 32 3062 | a 2669 8 3063 | a 2670 32 3064 | a 2671 8 3065 | a 2672 32 3066 | a 2673 8 3067 | a 2674 32 3068 | a 2675 8 3069 | a 2676 32 3070 | a 2677 8 3071 | a 2678 32 3072 | a 2679 8 3073 | a 2680 32 3074 | a 2681 8 3075 | a 2682 32 3076 | a 2683 8 3077 | a 2684 32 3078 | a 2685 8 3079 | a 2686 32 3080 | a 2687 8 3081 | a 2688 32 3082 | a 2689 8 3083 | a 2690 32 3084 | a 2691 8 3085 | a 2692 32 3086 | a 2693 8 3087 | a 2694 32 3088 | a 2695 8 3089 | a 2696 32 3090 | a 2697 8 3091 | a 2698 32 3092 | a 2699 8 3093 | a 2700 32 3094 | a 2701 8 3095 | a 2702 32 3096 | a 2703 8 3097 | a 2704 32 3098 | a 2705 8 3099 | a 2706 32 3100 | a 2707 8 3101 | a 2708 32 3102 | a 2709 8 3103 | a 2710 32 3104 | a 2711 8 3105 | a 2712 32 3106 | a 2713 8 3107 | a 2714 32 3108 | a 2715 8 3109 | a 2716 32 3110 | a 2717 8 3111 | a 2718 32 3112 | a 2719 8 3113 | a 2720 32 3114 | a 2721 8 3115 | a 2722 32 3116 | a 2723 8 3117 | a 2724 32 3118 | a 2725 8 3119 | a 2726 32 3120 | a 2727 8 3121 | a 2728 32 3122 | a 2729 8 3123 | a 2730 32 3124 | a 2731 8 3125 | a 2732 32 3126 | a 2733 8 3127 | a 2734 32 3128 | a 2735 8 3129 | a 2736 32 3130 | a 2737 8 3131 | a 2738 32 3132 | a 2739 8 3133 | a 2740 32 3134 | a 2741 8 3135 | a 2742 32 3136 | a 2743 8 3137 | a 2744 32 3138 | a 2745 8 3139 | a 2746 32 3140 | a 2747 8 3141 | a 2748 32 3142 | a 2749 8 3143 | a 2750 32 3144 | a 2751 8 3145 | a 2752 32 3146 | a 2753 8 3147 | a 2754 32 3148 | a 2755 8 3149 | a 2756 32 3150 | a 2757 8 3151 | a 2758 32 3152 | a 2759 8 3153 | a 2760 32 3154 | a 2761 8 3155 | a 2762 32 3156 | a 2763 8 3157 | a 2764 32 3158 | a 2765 8 3159 | a 2766 32 3160 | a 2767 8 3161 | a 2768 32 3162 | a 2769 8 3163 | a 2770 32 3164 | a 2771 8 3165 | a 2772 32 3166 | a 2773 8 3167 | a 2774 32 3168 | a 2775 8 3169 | a 2776 32 3170 | a 2777 8 3171 | a 2778 32 3172 | a 2779 8 3173 | a 2780 32 3174 | a 2781 8 3175 | a 2782 32 3176 | a 2783 8 3177 | a 2784 32 3178 | a 2785 8 3179 | a 2786 32 3180 | a 2787 8 3181 | a 2788 32 3182 | a 2789 8 3183 | a 2790 32 3184 | a 2791 8 3185 | a 2792 32 3186 | a 2793 8 3187 | a 2794 32 3188 | a 2795 8 3189 | a 2796 32 3190 | a 2797 8 3191 | a 2798 32 3192 | a 2799 8 3193 | a 2800 32 3194 | a 2801 8 3195 | a 2802 32 3196 | a 2803 8 3197 | a 2804 32 3198 | a 2805 8 3199 | a 2806 32 3200 | a 2807 8 3201 | a 2808 32 3202 | a 2809 8 3203 | a 2810 32 3204 | a 2811 8 3205 | a 2812 32 3206 | a 2813 8 3207 | a 2814 32 3208 | a 2815 8 3209 | a 2816 1 3210 | a 2817 1 3211 | a 2818 1 3212 | a 2819 1 3213 | a 2820 1 3214 | a 2821 1 3215 | a 2822 1 3216 | a 2823 48 3217 | a 2824 32 3218 | a 2825 8 3219 | a 2826 32 3220 | a 2827 8 3221 | a 2828 32 3222 | a 2829 8 3223 | a 2830 32 3224 | a 2831 8 3225 | a 2832 32 3226 | a 2833 8 3227 | a 2834 32 3228 | a 2835 8 3229 | f 2650 3230 | f 2648 3231 | a 2836 72 3232 | a 2837 24 3233 | a 2838 4064 3234 | a 2839 32424 3235 | a 2840 512 3236 | a 2841 72 3237 | a 2842 24 3238 | a 2843 4064 3239 | a 2844 32424 3240 | a 2845 512 3241 | a 2846 2640 3242 | a 2847 1336 3243 | a 2848 368 3244 | f 2848 3245 | f 2846 3246 | a 2849 4096 3247 | f 2844 3248 | f 2843 3249 | f 2842 3250 | f 2845 3251 | f 2841 3252 | a 2850 49 3253 | f 2850 3254 | a 2851 49 3255 | f 2851 3256 | f 40 3257 | a 2852 1984 3258 | a 2853 120 3259 | f 2853 3260 | a 2854 976 3261 | f 2839 3262 | f 2838 3263 | f 2837 3264 | f 2840 3265 | f 2836 3266 | f 2849 3267 | f 50 3268 | f 48 3269 | f 47 3270 | f 2854 3271 | f 2852 3272 | f 2847 3273 | f 2439 3274 | f 2424 3275 | f 2392 3276 | f 2230 3277 | f 2095 3278 | f 53 3279 | f 46 3280 | f 45 3281 | f 49 3282 | f 44 3283 | -------------------------------------------------------------------------------- /malloclab/traces/gen_binary.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | #!/usr/local/bin/perl 3 | 4 | $out_filename = "binary.rep"; 5 | $blk_size1 = 64; 6 | $blk_size2 = 512 - $blk_size1; 7 | $num_iters = 2000; 8 | 9 | # Open output file 10 | open OUTFILE, ">$out_filename" or die "Cannot create $out_filename\n"; 11 | 12 | # Calculate misc parameters 13 | $blk_size12 = $blk_size1 + $blk_size2; 14 | $suggested_heap_size = ($blk_size1 + $blk_size2 + $blk_size12)*$num_iters + 100; 15 | $num_blocks = 3*$num_iters; 16 | $num_ops = 4*$num_iters; 17 | 18 | print OUTFILE "$suggested_heap_size\n"; 19 | print OUTFILE "$num_blocks\n"; 20 | print OUTFILE "$num_ops\n"; 21 | print OUTFILE "1\n"; 22 | 23 | for ($i = 0; $i < $num_iters; $i += 1) { 24 | $seq1 = 2*$i; 25 | $seq2 = 2*$i + 1; 26 | print OUTFILE "a $seq1 $blk_size1\n"; 27 | print OUTFILE "a $seq2 $blk_size2\n"; 28 | } 29 | for ($i = 0; $i < $num_iters; $i += 1) { 30 | $fseq = 2*$i + 1; 31 | print OUTFILE "f $fseq\n"; 32 | } 33 | for ($i = 0; $i < $num_iters; $i += 1) { 34 | $aseq = 2*$num_iters + $i; 35 | print OUTFILE "a $aseq $blk_size12\n"; 36 | } 37 | 38 | close OUTFILE; 39 | 40 | -------------------------------------------------------------------------------- /malloclab/traces/gen_binary2.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | $out_filename = "binary2.rep"; 4 | $blk_size1 = 16; 5 | $blk_size2 = 128 - $blk_size1; 6 | $num_iters = 4000; 7 | 8 | # Open output file 9 | open OUTFILE, ">$out_filename" or die "Cannot create $out_filename\n"; 10 | 11 | # Calculate misc parameters 12 | $blk_size12 = $blk_size1 + $blk_size2; 13 | $suggested_heap_size = ($blk_size1 + $blk_size2 + $blk_size12)*$num_iters + 100; 14 | $num_blocks = 3*$num_iters; 15 | $num_ops = 4*$num_iters; 16 | 17 | print OUTFILE "$suggested_heap_size\n"; 18 | print OUTFILE "$num_blocks\n"; 19 | print OUTFILE "$num_ops\n"; 20 | print OUTFILE "1\n"; 21 | 22 | for ($i = 0; $i < $num_iters; $i += 1) { 23 | $seq1 = 2*$i; 24 | $seq2 = 2*$i + 1; 25 | print OUTFILE "a $seq1 $blk_size1\n"; 26 | print OUTFILE "a $seq2 $blk_size2\n"; 27 | } 28 | for ($i = 0; $i < $num_iters; $i += 1) { 29 | $fseq = 2*$i + 1; 30 | print OUTFILE "f $fseq\n"; 31 | } 32 | for ($i = 0; $i < $num_iters; $i += 1) { 33 | $aseq = 2*$num_iters + $i; 34 | print OUTFILE "a $aseq $blk_size12\n"; 35 | } 36 | 37 | close OUTFILE; 38 | 39 | -------------------------------------------------------------------------------- /malloclab/traces/gen_coalescing.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | #!/usr/local/bin/perl 3 | 4 | $out_filename = "coalescing.rep"; 5 | $blk_size = 4095; 6 | $num_iters = 2400; 7 | 8 | # Open output file 9 | open OUTFILE, ">$out_filename" or die "Cannot create $out_filename\n"; 10 | 11 | # Calculate misc parameters 12 | $blk_size2 = 2*$blk_size; 13 | $suggested_heap_size = 2*$blk_size*$num_iters + 100; 14 | $num_blocks = 3*$num_iters; 15 | $num_ops = 6*$num_iters; 16 | 17 | print OUTFILE "$suggested_heap_size\n"; 18 | print OUTFILE "$num_blocks\n"; 19 | print OUTFILE "$num_ops\n"; 20 | print OUTFILE "1\n"; 21 | 22 | for ($i = 0; $i < $num_iters; $i += 1) { 23 | $blk1 = 3*$i; 24 | $blk2 = $blk1 + 1; 25 | $blk3 = $blk1 + 2; 26 | 27 | print OUTFILE "a $blk1 $blk_size\n"; 28 | print OUTFILE "a $blk2 $blk_size\n"; 29 | print OUTFILE "f $blk1\n"; 30 | print OUTFILE "f $blk2\n"; 31 | print OUTFILE "a $blk3 $blk_size2\n"; 32 | print OUTFILE "f $blk3\n"; 33 | } 34 | 35 | close OUTFILE; 36 | 37 | -------------------------------------------------------------------------------- /malloclab/traces/gen_random.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | #!/usr/local/bin/perl 3 | 4 | $out_filename = $argv[0]; 5 | $out_filename = "random.rep" unless $out_filename; 6 | $num_blocks = $argv[1]; 7 | # $num_blocks = 1200 unless $num_blocks; 8 | $num_blocks = 2400 unless $num_blocks; 9 | $max_blk_size = $argv[2]; 10 | $max_blk_size = 32768 unless $max_blk_size; 11 | 12 | #print "Output file: $out_filename\n"; 13 | #print "Number of blocks: $num_blocks\n"; 14 | #print "Max block size: $max_blk_size\n"; 15 | 16 | # Create trace 17 | # Make a series of malloc()s 18 | for ($i = 0; $i < $num_blocks; $i += 1) { 19 | $size = int(rand $max_blk_size); 20 | $op = {}; 21 | $op->{type} = "a"; 22 | $op->{seq} = $i; 23 | $op->{size} = $size; 24 | $total_block_size += $size; 25 | push @trace, $op; 26 | } 27 | # Insert free()s in proper places 28 | for ($i = 0; $i < $num_blocks; $i += 1) { 29 | for ($minval = $i; $minval < $num_blocks + $i; $minval += 1) { 30 | if (($trace[$minval]->{type} eq "a") && ($trace[$minval]->{seq} == $i)) { 31 | last; 32 | } 33 | } 34 | $pos = int(rand($num_blocks + $i - $minval - 1) + $minval + 1); 35 | $op = {}; 36 | $op->{type} = "f"; 37 | $op->{seq} = $i; 38 | splice @trace, $pos, 0, $op; 39 | } 40 | 41 | # Open output file 42 | open OUTFILE, ">$out_filename" or die "Cannot create $out_filename\n"; 43 | 44 | # Calculate misc parameters 45 | $suggested_heap_size = $total_block_size + 100; 46 | $num_ops = 2*$num_blocks; 47 | 48 | print OUTFILE "$suggested_heap_size\n"; 49 | print OUTFILE "$num_blocks\n"; 50 | print OUTFILE "$num_ops\n"; 51 | print OUTFILE "1\n"; 52 | 53 | for ($i = 0; $i < 2*$num_blocks; $i += 1) { 54 | if ($trace[$i]->{type} eq "a") { 55 | print OUTFILE "$trace[$i]->{type} $trace[$i]->{seq} $trace[$i]->{size}\n"; 56 | } else { 57 | print OUTFILE "$trace[$i]->{type} $trace[$i]->{seq}\n"; 58 | } 59 | } 60 | 61 | close OUTFILE; 62 | 63 | -------------------------------------------------------------------------------- /malloclab/traces/gen_realloc.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | #!/usr/local/bin/perl 3 | 4 | $out_filename = "realloc.rep"; 5 | $realloc_size = 512; 6 | $size_increment = 128; 7 | $malloc_size = 128; 8 | $num_iters = 4800; 9 | 10 | # Open output file 11 | open OUTFILE, ">$out_filename" or die "Cannot create $out_filename\n"; 12 | 13 | # Calculate misc parameters 14 | 15 | $suggested_heap_size = num_iters* ($realloc_size+$size_increment*2 )+100; 16 | $num_blocks = $num_iters+1; 17 | $num_ops = ($num_iters )*3 +1; 18 | $blk = 1; 19 | 20 | print OUTFILE "$suggested_heap_size\n"; 21 | print OUTFILE "$num_blocks\n"; 22 | print OUTFILE "$num_ops\n"; 23 | print OUTFILE "1\n"; 24 | 25 | print OUTFILE "a 0 $realloc_size\n"; 26 | print OUTFILE "a $blk $malloc_size\n"; 27 | 28 | 29 | for ($i = 1; $i < $num_iters; $i += 1) { 30 | $blk += 1; 31 | 32 | $realloc_size += $size_increment; 33 | 34 | print OUTFILE "r 0 $realloc_size\n"; 35 | print OUTFILE "a $blk $malloc_size\n"; 36 | 37 | $prevblk = $blk-1; 38 | print OUTFILE "f $prevblk\n"; 39 | } 40 | 41 | $finalblk = $blk; 42 | print OUTFILE "f $finalblk\n"; 43 | print OUTFILE "f 0"; 44 | 45 | print OUTFILE 46 | 47 | close OUTFILE; 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /malloclab/traces/gen_realloc2.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | #!/usr/local/bin/perl 3 | 4 | $out_filename = "realloc2.rep"; 5 | $realloc_size = 4092; 6 | $size_increment = 5; 7 | $malloc_size = 16; 8 | $num_iters = 4800; 9 | 10 | # Open output file 11 | open OUTFILE, ">$out_filename" or die "Cannot create $out_filename\n"; 12 | 13 | # Calculate misc parameters 14 | 15 | $suggested_heap_size = $realloc_size+$size_increment*($num_iters-1)+$malloc_size*$num_iters+100; 16 | $num_blocks = $num_iters + 1; 17 | $num_ops = 3 * $num_iters + 1; 18 | $blk = 1; 19 | 20 | print OUTFILE "$suggested_heap_size\n"; 21 | print OUTFILE "$num_blocks\n"; 22 | print OUTFILE "$num_ops\n"; 23 | print OUTFILE "1\n"; 24 | 25 | print OUTFILE "a 0 $realloc_size\n"; 26 | print OUTFILE "a $blk $malloc_size\n"; 27 | 28 | for ($i = 1; $i < $num_iters; $i += 1) { 29 | $blk += 1; 30 | 31 | $realloc_size += $size_increment; 32 | 33 | print OUTFILE "r 0 $realloc_size\n"; 34 | print OUTFILE "a $blk $malloc_size\n"; 35 | 36 | $prevblk = $blk-1; 37 | print OUTFILE "f $prevblk\n"; 38 | } 39 | 40 | $finalblk = $blk; 41 | print OUTFILE "f $finalblk\n"; 42 | print OUTFILE "f 0"; 43 | 44 | print OUTFILE 45 | 46 | close OUTFILE; 47 | -------------------------------------------------------------------------------- /malloclab/traces/short1-bal.rep: -------------------------------------------------------------------------------- 1 | 20000 2 | 6 3 | 12 4 | 1 5 | a 0 2040 6 | a 1 2040 7 | f 1 8 | a 2 48 9 | a 3 4072 10 | f 3 11 | a 4 4072 12 | f 0 13 | f 2 14 | a 5 4072 15 | f 4 16 | f 5 17 | -------------------------------------------------------------------------------- /malloclab/traces/short1.rep: -------------------------------------------------------------------------------- 1 | 20000 2 | 6 3 | 12 4 | 1 5 | a 0 2040 6 | a 1 2040 7 | f 1 8 | a 2 48 9 | a 3 4072 10 | f 3 11 | a 4 4072 12 | f 0 13 | f 2 14 | a 5 4072 15 | f 4 16 | f 5 17 | -------------------------------------------------------------------------------- /malloclab/traces/short2-bal.rep: -------------------------------------------------------------------------------- 1 | 20000 2 | 6 3 | 12 4 | 1 5 | a 0 2040 6 | a 1 4010 7 | a 2 48 8 | a 3 4072 9 | a 4 4072 10 | a 5 4072 11 | f 0 12 | f 1 13 | f 2 14 | f 3 15 | f 4 16 | f 5 17 | -------------------------------------------------------------------------------- /malloclab/traces/short2.rep: -------------------------------------------------------------------------------- 1 | 20000 2 | 6 3 | 12 4 | 1 5 | a 0 2040 6 | a 1 4010 7 | a 2 48 8 | a 3 4072 9 | a 4 4072 10 | a 5 4072 11 | f 0 12 | f 1 13 | f 2 14 | f 3 15 | f 4 16 | f 5 17 | --------------------------------------------------------------------------------