├── Makefile ├── README.md ├── doc └── Doxyfile ├── driver ├── mm_driver.o └── mm_util.o ├── reference └── mm_test ├── src ├── blocklist.c ├── blocklist.h ├── dataseg.c ├── dataseg.h ├── memmgr.c ├── memmgr.h ├── mm_test.c ├── nulldriver.c └── nulldriver.h └── tests ├── 100K.dmas ├── alloc.dmas ├── demo.dmas └── ls.dmas /Makefile: -------------------------------------------------------------------------------- 1 | #--------------------------------------------------------------------------------------------------- 2 | # System Programming Memory Lab Spring 2024 3 | # 4 | # Makefile 5 | # 6 | # GNU make driver 7 | # Author: Bernhard Egger 8 | # Change Log: 9 | # 2020/09/27 Bernhard Egger created 10 | # 2021/10/03 Bernhard Egger move deps and object files into separate directories 11 | # 12 | # License 13 | # Copyright (c) 2020-2023, Computer Systems and Platforms Laboratory, SNU 14 | # All rights reserved 15 | # 16 | # Redistribution and use in source and binary forms, with or without modification, are permitted 17 | # provided that the following conditions are met: 18 | # 19 | # - Redistributions of source code must retain the above copyright notice, this list of condi- 20 | # tions and the following disclaimer. 21 | # - Redistributions in binary form must reproduce the above copyright notice, this list of condi- 22 | # tions and the following disclaimer in the documentation and/or other materials provided with 23 | # the distribution. 24 | # 25 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 26 | # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 27 | # AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 28 | # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSE- 29 | # QUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 30 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31 | # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 32 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 33 | # DAMAGE. 34 | #--------------------------------------------------------------------------------------------------- 35 | 36 | 37 | #--------------------------------------------------------------------------------------------------- 38 | # Put your source and header files into the SRC_DIR (=src/) directory and make sure that SOURCES 39 | # includes ALL C source files required to compile your project. 40 | # 41 | SOURCES=memmgr.c dataseg.c blocklist.c nulldriver.c 42 | #--------------------------------------------------------------------------------------------------- 43 | 44 | 45 | #--- variable declarations 46 | 47 | # directories 48 | SRC_DIR=src 49 | OBJ_DIR=obj 50 | DEP_DIR=.deps 51 | DRV_DIR=driver 52 | 53 | # C compiler and compilation flags 54 | CC=gcc 55 | CFLAGS=-Wall -Wno-stringop-truncation -O2 -g 56 | LINKFLAGS=-lpthread -ldl -rdynamic 57 | DEPFLAGS=-MMD -MP -MT $@ -MF $(DEP_DIR)/$*.d 58 | 59 | # derived variables & constants 60 | DRV_OBJ=$(DRV_DIR)/mm_driver.o $(DRV_DIR)/mm_util.o 61 | TARGET_MAIN=mm_test.c 62 | TARGET_OBJ=$(TARGET_MAIN:%.c=$(OBJ_DIR)/%.o) 63 | OBJECTS=$(SOURCES:%.c=$(OBJ_DIR)/%.o) 64 | DEPS=$(SOURCES:%.c=$(DEP_DIR)/%.d) 65 | 66 | TARGET=mm_test 67 | DRIVER=mm_driver 68 | 69 | 70 | #--- rules 71 | .PHONY: doc clean mrproper 72 | 73 | all: $(TARGET) 74 | 75 | $(TARGET): $(TARGET_OBJ) $(OBJECTS) 76 | $(CC) $(CFLAGS) -o $@ $^ 77 | 78 | $(DRIVER): $(OBJECTS) $(DRV_OBJ) 79 | $(CC) $(CFLAGS) -o $@ $^ $(LINKFLAGS) 80 | 81 | $(OBJ_DIR)/%.o: $(SRC_DIR)/%.c | $(DEP_DIR) $(OBJ_DIR) 82 | $(CC) $(CFLAGS) $(DEPFLAGS) -o $@ -c $< 83 | 84 | $(DEP_DIR): 85 | @mkdir -p $(DEP_DIR) 86 | 87 | $(OBJ_DIR): 88 | @mkdir -p $(OBJ_DIR) 89 | 90 | -include $(DEPS) 91 | 92 | doc: $(SOURCES:%.c=$(SRC_DIR)/%.c) $(wildcard $(SOURCES:%.c=$(SRC_DIR)/%.h)) 93 | doxygen doc/Doxyfile 94 | 95 | clean: 96 | rm -rf $(OBJ_DIR) $(DEP_DIR) 97 | 98 | mrproper: clean 99 | rm -rf $(TARGET) $(DRIVER) doc/html 100 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Lab 3: Memory Lab 2 | 3 | In this lab, we implement our own dynamic memory manager. 4 | 5 | You will learn 6 | * how a dynamic memory manager works 7 | * how to implement a dynamic memory manager 8 | * how to work with macros in C 9 | * how to work with function pointers in C 10 | * how to debug code 11 | * that writing a dynamic memory manager is simple in theory and difficult in practice. 12 | 13 | 14 | ## Important Dates 15 | 16 | | Date | Description | 17 | |:--- |:--- | 18 | | Tuesday, April 9, 18:30 | Memory Lab hand-out | 19 | | Tuesday, April 16, 18:30 | Memory Lab session 1 | 20 | | Tuesday, April 23, 18:30 | Memory Lab session 2 | 21 | | Monday, April 29, 23:59 | Submission deadline | 22 | 23 | There are no separate deadlines for phases 1 and 2. At the end of the lab, both phases should be implemented. 24 | 25 | ## Logistics 26 | 27 | ### Hand-out 28 | 29 | You can **clone this repository** directly on your VM instance or local computer and get to work. If you want to keep your own repository, you should **keep the lab's visibility to private.** Otherwise, others would see your work. Read the instructions here carefully. Then clone the lab to your local computer and get to work. 30 | 31 | **Changing visibility** 32 | 33 | After cloning the repository, you should change the push remote URL to your own repository. 34 | 35 | 1. Create an empty repository that you're going to manage **(again, keep it private)** 36 | 2. Copy the url of that repository 37 | 3. On your terminal in the cloned directory, type `git remote set-url --push origin ` 38 | 4. Check with `git remote -v` if the push URL has changed to yours while the fetch URL remains the same (this repo) 39 | 40 | ### Submission 41 | 42 | You should upload your archive file(.tar) containing code (memmgr.c) and report (2024-12345.pdf) via eTL. To make an archive file, follow the example below on your own VM. 43 | ``` 44 | $ ls 45 | 2024-12345.pdf doc Makefile README.md driver src tests 46 | $ tar -cvf 2024-12345.tar src/memmgr.c 2024-12345.pdf 47 | src/memmgr.c 48 | 2024-12345.pdf 49 | $ file 2024-12345.tar 50 | 2024-12345.tar: POSIX tar archive (GNU) 51 | ``` 52 | 53 | * With VirtualBox : 54 | ``` 55 | scp -P 8888 sysprog@localhost: 56 | # example: scp -P 8888 sysprog@localhost:/home/sysporg/2024_spring_sysprog_Lab3/2024-12345.tar . 57 | ``` 58 | 59 | * With UTM : 60 | ``` 61 | scp sysprog@: 62 | # example: scp sysprog@192.168.4.4:/home/sysprog/2024_spring_sysprog_Lab3/2024-12345.tar . 63 | ``` 64 | 65 | ## Dynamic Memory Manager 66 | 67 | ### Overview 68 | 69 | The dynamic memory manager implemented in this lab provides the same API as the C standard library's memory manager: `malloc()`, `free()`, `calloc()`, and `realloc()`. In addition to these four functions, additional methods for initialization, logging, and debugging need to be implemented. 70 | The following table shows the API of our dynamic memory manager: 71 | 72 | | API function | libc | Description | 73 | |:--- |:--- |:--- | 74 | | `void* mm_malloc(size_t size)`| `malloc` | allocate a block of memory with a payload size of (at least) _size_ bytes | 75 | | `void mm_free(void *ptr)` | `free` | free a previously allocated block of memory | 76 | | `void* mm_calloc(size_t nelem, size_t size)` | `calloc` | allocate a block of memory with a payload size of (at least) _size_ bytes and initialize with zeroes | 77 | | `void* mm_realloc(void *ptr, size_t size)` | `realloc` | change the size of a previously allocated block _ptr_ to a new _size_. This operation may need to move the memory block to a different location. The original payload is preserved up to _min(old size, new size)_ | 78 | | `void mm_init(void)` | n/a | initialize dynamic memory manager | 79 | | `void mm_setloglevel(int level)` | similar to `mtrace()` | set the logging level of the allocator | 80 | | `void mm_check(void)` | simiar to `mcheck()` | check and dump the status of the heap | 81 | 82 | 83 | ### Operation 84 | 85 | Since libc's memory allocator is built into the standard C runtime, our memory manager cannot directly manipulate the heap of the process. Instead, we operate on a simulated heap. The simulated heap is controlled with the same two functions the kernel offers for that purpose: `sbrk()` and `getpagesize()`. 86 | 87 | The C runtime initializes the heap and the dynamic memory manager automatically whenever a process is started. For our memory manager, we have to do that manually, hence the `mm_init()` function. Similarly, the simulated heap has to be initialized before it can be used by calling `ds_allocate()`. 88 | 89 | The following diagram shows the organization and operation of our allocator: 90 | 91 | ``` 92 | File: mm_test.c 93 | +-------------------------------------------------+ 94 | | user-level process. After initializing the data | 95 | | segment and the heap, mm_malloc/free/calloc/ | 96 | | realloc can be used as in libc. | 97 | +-------------------------------------------------+ 98 | | | | 99 | 1. ds_allocate() | 3. sequence of mm_malloc(), 100 | | | mm_free(), mm_calloc(), 101 | | 2. mm_init() and mm_realloc() 102 | | | | 103 | | v v 104 | | +-----------------------------------------+ 105 | | | custom memory manager. Manages the heap | 106 | | +-----------------------------------------+ 107 | | File: memmgr.c | 108 | | ds_sbrk() 109 | | | 110 | v v 111 | +-------------------------------------------------+ 112 | | custom data segment implementation. Manages the | 113 | | data segment to be used by our allocator. | 114 | +-------------------------------------------------+ 115 | File: dataseg.c 116 | ``` 117 | 118 | ### Heap Organization 119 | 120 | Our memory manager is a 64-bit operator, i.e., one word in the allocator is 8 bytes long. The heap is conceptually organized into blocks. The minimal block size is 32 bytes. Each block must have a boundary tag (header/footer). In this lab, we plan to implement two approaches to free list management: implicit and explicit free list. 121 | 122 | The boundary tags comprise of the size of the block and an allocated bit. Since block sizes are a muliple of 32, the low 4 bits of the size are always 0. We use bit 0 to indicate the status of the block (1: allocated, 0: free). 123 | 124 | You are free to add special sentinel blocks at the start and end of the heap to simplify the operation of the allocator. 125 | 126 | 127 | ### API Specification 128 | 129 | ### mm_init() 130 | 131 | You can assume that `mm_init()` is called before any other operations on the heap are performed. The function needs to initialize the heap to its initial state. 132 | 133 | ### mm_malloc() 134 | 135 | The `void* mm_malloc(size_t size)` routine returns a pointer to an allocated payload block of at least 136 | _size_ bytes. The entire allocated block must lie within the heap region and must not overlap with 137 | any other block. 138 | 139 | ### mm_calloc() 140 | 141 | `void* mm_calloc(size_t nmemb, size_t size)` returns a pointer to an allocated payload block of at least 142 | _nmemb*size_ bytes that is initialized to zero. The same constraints as for `mm_malloc()` apply. 143 | 144 | ### mm_realloc() 145 | 146 | The `void* mm_realloc(void *ptr, size_t size)` routine returns a pointer to an allocated region of at least size bytes with the following constraints. 147 | 148 | * if `ptr` is NULL, the call is equivalent to `mm_malloc(size)`. 149 | * if `size` is equal to zero, the call is equivalent to `mm_free(ptr)`. 150 | * if `ptr` is not NULL, it must point to a valid allocated block. The call to `mm_realloc` changes 151 | the size of the memory block pointed to by `ptr` (the old block) to `size` bytes and returns the 152 | address of the new block. Notice that the address of the new block might be the same as the 153 | old block, or it might be different, depending on your implementation, the amount of internal 154 | fragmentation in the old block, and the size of the `realloc` request. 155 | The contents of the new block are the same as those of the old `ptr` block, up to the minimum of 156 | the old and new sizes. Everything else is uninitialized. For example, if the old block is 8 bytes 157 | and the new block is 12 bytes, then the first 8 bytes of the new block are identical to the first 8 158 | bytes of the old block and the last 4 bytes are uninitialized. 159 | * if `size` is smaller than the size of the memory block pointed to by `ptr`, the block should be split into a smaller allocated block and a new free block. 160 | * if `size` is larger than the size of the memory block pointed to by `ptr`, the following should be performed: First, check if the successor block is free and large enough when merged. If so, the memory manager should increase the block size and fix the remaining free block. If the successor block is neither free nor large enough to place the requested new size when merged, it should assign a new block by the allocation policy(best-fit) and copy the original contents. Afterwards, the original block must be freed. 161 | 162 | ### mm_free() 163 | 164 | The `void mm_free(void *ptr)` routine frees the block pointed to by `ptr` that was returned by an earlier call to 165 | `mm_malloc()`, `mm_calloc()`, or `mm_realloc()` and has not yet been freed. When when the callee tries to free a freed 166 | memory block, an error is printed. 167 | 168 | 169 | ### Free block management and policies 170 | 171 | In this lab, we will be implementing the allocation of requested blocks based on the best fit policy, utilizing both implicit and explicit free list management methods. Although multiple options are available when freeing allocated blocks using the explicit free list method, we will implement the LIFO policy. 172 | 173 | **Best fit** allocates memory by selecting the smallest available block that is large enough to fulfill the request, aiming to reduce fragmentation and optimize space utilization. 174 | 175 | **Implicit free list** utilizes the spaces within the memory itself to track free blocks, integrating allocation metadata directly within the memory being managed. 176 | 177 | **Explicit free list** manages free memory by creating a linked list of free blocks, where each block points to the next and previous block, facilitating precise and flexible memory allocation. 178 | 179 | 180 | ## Handout Overview 181 | 182 | The handout contains the following files and directories 183 | 184 | | File/Directory | Description | 185 | |:--- |:--- | 186 | | `doc/` | Doxygen instructions, configuration file, and auto-generated documentation. Run `make doc` to generate. | 187 | | `driver/` | Pre-compiled modules required to link your implementation to the `mm_driver` test program | 188 | | `reference/` | Reference implementation | 189 | | `src/` | Source code of the lab. You will modify memmgr.c/h, mm_test.c | 190 | | `tests/` | Test allocation/deallocation sequences to test your allocator | 191 | | `README.md` | this file | 192 | | `Makefile` | Makefile driver program | 193 | 194 | The files you will work on or modify are all located in the `src/` directory 195 | 196 | | File | Description | 197 | |:--- |:--- | 198 | | `blocklist.c/h` | Implementation of a list to manage allocated blocks for debugging/verification purposes. **Do not modify!** | 199 | | `datasec.c/h` | Implementation of the data segment. **Do not modify!** | 200 | | `nulldriver.c/h` | Implementation of an empty allocator that does nothing. Useful to measure overhead. **Do not modify!** | 201 | | `memmgr.c/h` | The dynamic memory manager. A skeleton is provided. Implement your solution by editing the C file. | 202 | | `mm_test.c` | A simple test program to test your implementation step-by-step. | 203 | 204 | ### Reference implementation 205 | 206 | The directory `reference` contains a simple test driver program. You can use it to understand how our allocator works but should not take the output literally. 207 | 208 | 209 | ## Phase 1 210 | 211 | Your task in phase 1 is to implement the basic functionalities of the dynamic memory allocator(`mm_malloc()`, `mm_free()`, and `mm_realloc()`) by using implicit free list. `mm_calloc()` will work without any modification if you implemented `mm_malloc()` and `mm_free()` correctly. 212 | 213 | 214 | ### Implementation 215 | 216 | The skeleton provides some global variables and macros that we think will be helpful, logging and panic functions, and skeletons for the individual `mm_X()` functions that are more or less complete. 217 | 218 | Start by working on `mm_init()`. Use the `mm_check()` function to inspect your heap. Once the initial heap looks good, proceed with the implementation of `mm_malloc()`, followed by `mm_free()`. 219 | 220 | Have a look at `mm_test.c` and modify the code in there to test different cases. Have a look at the documentation of `mm_setloglevel()`, `ds_setloglevel()`, and `mm_check()`; these functions will be very handy to understand what's going on and debug your code. 221 | 222 | 223 | ## Phase 2 224 | 225 | In phase 2, implement the functions to also support the explicit free list. Have a close look at your implementations of phase 1, and identify the points where the next and previous block pointers should be managed. As in phase 1, utilizing global variables and macros will ease the job. 226 | 227 | `mm_test` will show the next and previous block pointers of each free block when explicit free list mode is selected. Test your implementation, and make sure every free block is connected after any operation. 228 | 229 | You can now test your allocator with the test driver (`mm_driver`, see below.) 230 | 231 | 232 | ## Evaluation 233 | For the evaluation, we use a driver program that issues a series of memory allocation and deallocation requests to your implementation. The grading focuses on implementation completeness and correctness over performance. 234 | 235 | ### Grading 236 | We expect you to implement `mm_malloc()`, `mm_free()`, `mm_calloc()`, and `mm_realloc()`. 237 | We will test the correctness of your implementation and measure the heap utilization. Performance is only considered when testing your explicit free list implementation. Even then, the relative performance against your implicit free list implementation is considered, not the absolute performance. 238 | 239 | ### mm_driver 240 | The handout includes a test version of `mm_driver` in pre-compiled form in the `driver/` directory. You can build the driver and link it to your memory manager by running 241 | ```bash 242 | $ make mm_driver 243 | gcc -Wall -Wno-stringop-truncation -O2 -g -MMD -MP -o memmgr.o -c memmgr.c 244 | gcc -Wall -Wno-stringop-truncation -O2 -g -o mm_driver memmgr.o dataseg.o driver/blocklist.o driver/mm_driver.o 245 | ``` 246 | 247 | The `mm_driver` program takes as an input a script file that describes the test. We provide some simple tests in the directory `tests/`. The scripts should be self-explanatory. 248 | Use as follows: 249 | ```bash 250 | $ ./mm_driver tests/demo.dmas 251 | Processing 'tests/demo.dmas'... 252 | ------------------------------------------------------------ 253 | Configuration: 254 | script file: tests/demo.dmas 255 | 256 | configuration: 257 | implementation: memory manager 258 | mode: correctness 259 | freelist policy: implicit 260 | data segment size: 0x2000000 (33554432) 261 | 262 | Action: m 1 16 263 | Action: m 2 50 264 | ... 265 | Action: stop 266 | ------------------------------------------------------------ 267 | Statistics: 268 | Actions: 17 269 | malloc: 9 270 | calloc: 0 271 | realloc: 0 272 | free: 8 273 | 274 | Utilization: 275 | payload: 30 ( 48) bytes 276 | heap size: 10000 ( 65536) bytes 277 | utilization: 0.1% 278 | #sbrk(): 1 times 279 | 280 | Performance: 281 | total time: 0.018493 sec 282 | throughput: 0.92 kops/sec 283 | ------------------------------------------------------------ 284 | ``` 285 | 286 | You can test with other options. Use the following command to see the options: 287 | ```bash 288 | $ ./mm_driver --help 289 | ``` 290 | 291 | ## Hints 292 | 293 | ### Skeleton code 294 | The skeleton code is meant to help you get started. You can modify it in any way you see fit - or implement this lab completely from scratch. 295 | 296 | ### Allocator in the textbook 297 | The textbook contains an implementation of a simple allocator with a free list in chapter 9.9.12. 298 | It is quite similar to what you need to do here. Try by yourself first. If you are stuck, study the allocator from the book and apply your gained knowledge to your code. 299 | 300 | ### Final words 301 | 302 | Implementing a dynamic memory allocator is easy in theory and very difficult in practice. A tiny mistake may destroy your heap, and to make matters worse, you may not notice that error until a few `mm_malloc()` and `mm_free()` operations later. At the beginning, you may feel overwhelmed and have no idea how to approach this task. 303 | 304 | Do not despair - we will give detailed instructions during the lab sessions and provide individual help so that each of you can finish this lab. After completing this lab, you will understand dynamic memory allocation from both the user and the system perspective. 305 | 306 |
307 | 308 | **Happy coding!** 309 |
310 | -------------------------------------------------------------------------------- /driver/mm_driver.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SNU-ARC/2024_spring_sysprog_Lab3/11b0859290a1ea52b38c477d9cdeaa324199433d/driver/mm_driver.o -------------------------------------------------------------------------------- /driver/mm_util.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SNU-ARC/2024_spring_sysprog_Lab3/11b0859290a1ea52b38c477d9cdeaa324199433d/driver/mm_util.o -------------------------------------------------------------------------------- /reference/mm_test: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SNU-ARC/2024_spring_sysprog_Lab3/11b0859290a1ea52b38c477d9cdeaa324199433d/reference/mm_test -------------------------------------------------------------------------------- /src/blocklist.c: -------------------------------------------------------------------------------- 1 | //-------------------------------------------------------------------------------------------------- 2 | // System Programming Memory Lab Spring 2024 3 | // 4 | /// @file 5 | /// @brief block list management for dynamic memory manager test program 6 | /// @author Bernhard Egger 7 | /// @section changelog Change Log 8 | /// 2020/10/04 Bernhard Egger created 9 | /// 10 | /// @section license_section License 11 | /// Copyright (c) 2020-2023, Computer Systems and Platforms Laboratory, SNU 12 | /// All rights reserved. 13 | /// 14 | /// Redistribution and use in source and binary forms, with or without modification, are permitted 15 | /// provided that the following conditions are met: 16 | /// 17 | /// - Redistributions of source code must retain the above copyright notice, this list of condi- 18 | /// tions and the following disclaimer. 19 | /// - Redistributions in binary form must reproduce the above copyright notice, this list of condi- 20 | /// tions and the following disclaimer in the documentation and/or other materials provided with 21 | /// the distribution. 22 | /// 23 | /// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 24 | /// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 25 | /// AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 26 | /// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSE- 27 | /// QUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 | /// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 29 | /// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | /// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 31 | /// DAMAGE. 32 | //-------------------------------------------------------------------------------------------------- 33 | 34 | #include 35 | #include "blocklist.h" 36 | 37 | Block *head = NULL; 38 | Block *tail = NULL; 39 | 40 | void init_blocklist(void) 41 | { 42 | if (head != NULL) free_blocklist(); 43 | 44 | // 45 | // create head & tail sentinels 46 | // 47 | head = calloc(1, sizeof(Block)); 48 | tail = calloc(1, sizeof(Block)); 49 | 50 | head->next = tail; 51 | tail->prev = head; 52 | 53 | // We set 54 | // head->ptr = NULL 55 | // tail->ptr = (void*)-1 56 | // 57 | // This simplifies the search for a (valid) ptr since the invariant 58 | // head->ptr < ptr < tail->ptr 59 | // always holds. 60 | head->ptr = NULL; 61 | tail->ptr = (void*)-1; 62 | } 63 | 64 | void free_blocklist(void) 65 | { 66 | Block *b = head; 67 | while (b != NULL) { 68 | Block *next = b->next; 69 | free(b); 70 | b = next; 71 | } 72 | head = tail = NULL; 73 | } 74 | 75 | Block* insert_block(void *ptr, size_t size, int flags) 76 | { 77 | assert(head != NULL); 78 | assert((ptr != NULL) && (ptr != (void*)-1)); 79 | 80 | Block *b = calloc(1, sizeof(Block)); 81 | if (b != NULL) { 82 | b->ptr = ptr; 83 | b->size = size; 84 | b->flags = flags; 85 | 86 | Block *s = head; 87 | while (s->ptr <= ptr) s = s->next; 88 | 89 | b->next = s; 90 | b->prev = s->prev; 91 | s->prev = b; 92 | b->prev->next = b; 93 | } 94 | 95 | return b; 96 | } 97 | 98 | Block* find_block(void *ptr) 99 | { 100 | assert(head != NULL); 101 | assert((ptr != NULL) && (ptr != (void*)-1)); 102 | 103 | Block *b = head; 104 | while (b->ptr < ptr) b = b->next; 105 | 106 | return b->ptr == ptr ? b : NULL; 107 | } 108 | 109 | Block* find_block_by_index(size_t idx) 110 | { 111 | assert(head != NULL); 112 | 113 | Block *b = head->next; 114 | while ((b != tail) && (idx > 0)) { 115 | b = b->next; 116 | idx--; 117 | } 118 | 119 | return b != tail ? b : NULL; 120 | } 121 | 122 | int delete_block(void *ptr) 123 | { 124 | assert(head != NULL); 125 | assert((ptr != NULL) && (ptr != (void*)-1)); 126 | 127 | Block *b = find_block(ptr); 128 | if (b != NULL) { 129 | b->prev->next = b->next; 130 | b->next->prev = b->prev; 131 | free(b); 132 | } 133 | 134 | return b != NULL; 135 | } 136 | 137 | const Block* first_block(void) 138 | { 139 | return find_block_by_index(0); 140 | } 141 | 142 | const Block* next_block(const Block *b) 143 | { 144 | assert(head != NULL); 145 | assert(b != NULL); 146 | 147 | b = b->next; 148 | 149 | return b != tail ? b : NULL; 150 | } 151 | 152 | int iterate_blocks(int (*callback)(const Block *, size_t, void*), void *ptr) 153 | { 154 | assert(head != NULL); 155 | assert(callback != NULL); 156 | 157 | int res = 0; 158 | size_t idx = 0; 159 | Block *b = head->next; 160 | while ((b != tail) && (res == 0)) { 161 | res = callback(b, idx, ptr); 162 | b = b->next; 163 | idx++; 164 | } 165 | 166 | return res; 167 | } 168 | 169 | size_t num_blocks(void) 170 | { 171 | assert(head != NULL); 172 | 173 | size_t res = 0; 174 | Block *b = head->next; 175 | 176 | while (b != tail) { 177 | b = b->next; 178 | res++; 179 | } 180 | 181 | return res; 182 | } 183 | 184 | Block** get_block_array(void) 185 | { 186 | assert(head != NULL); 187 | 188 | size_t nblocks = num_blocks(); 189 | Block **res = (Block**)calloc(nblocks+1, sizeof(Block*)); 190 | 191 | if (res != NULL) { 192 | size_t idx = 0; 193 | Block *b = head->next; 194 | while ((b != tail) && (idx < nblocks)) { 195 | res[idx] = b; 196 | idx++; 197 | b = b->next; 198 | } 199 | assert(idx == nblocks); 200 | } 201 | 202 | return res; 203 | } 204 | -------------------------------------------------------------------------------- /src/blocklist.h: -------------------------------------------------------------------------------- 1 | //-------------------------------------------------------------------------------------------------- 2 | // System Programming Memory Lab Spring 2024 3 | // 4 | /// @file 5 | /// @brief block list management for dynamic memory manager test program 6 | /// @author Bernhard Egger 7 | /// @section changelog Change Log 8 | /// 2020/10/04 Bernhard Egger created 9 | /// 10 | /// @section license_section License 11 | /// Copyright (c) 2020-2023, Computer Systems and Platforms Laboratory, SNU 12 | /// All rights reserved. 13 | /// 14 | /// Redistribution and use in source and binary forms, with or without modification, are permitted 15 | /// provided that the following conditions are met: 16 | /// 17 | /// - Redistributions of source code must retain the above copyright notice, this list of condi- 18 | /// tions and the following disclaimer. 19 | /// - Redistributions in binary form must reproduce the above copyright notice, this list of condi- 20 | /// tions and the following disclaimer in the documentation and/or other materials provided with 21 | /// the distribution. 22 | /// 23 | /// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 24 | /// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 25 | /// AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 26 | /// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSE- 27 | /// QUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 | /// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 29 | /// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | /// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 31 | /// DAMAGE. 32 | //-------------------------------------------------------------------------------------------------- 33 | 34 | #ifndef __BLOCKLIST_H__ 35 | #define __BLOCKLIST_H__ 36 | 37 | #include 38 | 39 | /// @brief Block structure in doubly-linked list to hold information about a memory block 40 | typedef struct __block { 41 | struct __block *prev, *next; ///< prev/next pointers in linked list 42 | void *ptr; ///< pointer to memory block (payload) obtained by malloc() et al 43 | size_t size; ///< size of payload 44 | int flags; ///< flags 45 | } Block; 46 | 47 | /// @brief initialize blocklist 48 | void init_blocklist(void); 49 | 50 | /// @brief free entrie blocklist 51 | void free_blocklist(void); 52 | 53 | /// @brief insert a block into the blocklist 54 | /// @param ptr pointer to memory block obtained by malloc() and variants 55 | /// @param size block (payload) size 56 | /// @param flags block flags 57 | /// @retval Block* pointer to inserted Block structure 58 | /// @retval NULL on failure 59 | Block* insert_block(void *ptr, size_t size, int flags); 60 | 61 | /// @brief find a block in the blocklist by its payload pointer @a ptr 62 | /// @param ptr pointer to memory block 63 | /// @retval Block* pointer to Block structure containin @a ptr 64 | /// @retval NULL if no such Block exists 65 | Block* find_block(void *ptr); 66 | 67 | /// @brief find a block in the blocklist by its index in the list 68 | /// @param idx index 69 | /// @retval Block* pointer to @a idx-th Block structure 70 | /// @retval NULL if no such Block exists 71 | Block* find_block_by_index(size_t idx); 72 | 73 | /// @brief delete a block from the blockslist 74 | /// @param ptr pointer to memory block 75 | /// @retval 1 on success 76 | /// @retval 0 if no such Block exists 77 | int delete_block(void *ptr); 78 | 79 | /// @brief get the first block in the list 80 | /// @retval Block* pointer to first block 81 | /// @retval NULL if list is empty 82 | const Block* first_block(void); 83 | 84 | /// @brief get the next block after @a b 85 | /// @param b current block 86 | /// @retval Block* pointer to block following @a b 87 | /// @retval NULL if @a b is the last block in the list 88 | const Block* next_block(const Block *b); 89 | 90 | /// @brief iterate through blocklist and call @a callback for each element 91 | /// @param callback callback function. Iteration continues as long as @a callback returns 0. 92 | /// The iterator function receives a pointer to the block, the index of the 93 | /// block in the list, and the pointer @a ptr provided to iterate_blocks(). 94 | /// @param ptr pointer passed to callback 95 | /// @retval 0 if entire list has been iterated 96 | /// @retval otherwise: return value of last callback 97 | int iterate_blocks(int (*callback)(const Block *, size_t, void*), void *ptr); 98 | 99 | /// @brief get the number of blocks 100 | /// @retval size_t number of blocks in list 101 | size_t num_blocks(void); 102 | 103 | /// @brief obtain a copy of the list as an array 104 | /// @retval array of Blocks (ordered by ptr), terminated by a NULL entry 105 | Block** get_block_array(void); 106 | 107 | #endif // __BLOCKLIST_H__ 108 | 109 | 110 | 111 | -------------------------------------------------------------------------------- /src/dataseg.c: -------------------------------------------------------------------------------- 1 | //-------------------------------------------------------------------------------------------------- 2 | // System Programming Memory Lab Spring 2024 3 | // 4 | /// @file 5 | /// @brief simulated data segment 6 | /// @author Bernhard Egger 7 | /// @section changelog Change Log 8 | /// 2020/09/27 Bernhard Egger created 9 | /// 10 | /// @section license_section License 11 | /// Copyright (c) 2020-2023, Computer Systems and Platforms Laboratory, SNU 12 | /// All rights reserved. 13 | /// 14 | /// Redistribution and use in source and binary forms, with or without modification, are permitted 15 | /// provided that the following conditions are met: 16 | /// 17 | /// - Redistributions of source code must retain the above copyright notice, this list of condi- 18 | /// tions and the following disclaimer. 19 | /// - Redistributions in binary form must reproduce the above copyright notice, this list of condi- 20 | /// tions and the following disclaimer in the documentation and/or other materials provided with 21 | /// the distribution. 22 | /// 23 | /// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 24 | /// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 25 | /// AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 26 | /// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSE- 27 | /// QUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 | /// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 29 | /// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | /// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 31 | /// DAMAGE. 32 | //-------------------------------------------------------------------------------------------------- 33 | 34 | // 35 | // Simulated data segment 36 | // ====================== 37 | // This module implements a simulated data segment to be used by our dynamic memory allocator. 38 | // 39 | // Design: 40 | // ------- 41 | // The data segment encloses the heap area that is presented to the user. One memory page at the 42 | // beginning and another one at the end are always marked PROT_NONE to catch accidential accesses 43 | // outside the assigned heap area. 44 | // 45 | // In particular, only the area between ds_heap_start and ds_heap_brk is marked READ/WRITE, every- 46 | // thing else is marked PROT_NONE. This helps catching accesses beyond the brk pointer. 47 | // 48 | // 49 | // ds_start ds_heap_start ds_heap_brk ds_heap_end ds_end 50 | // | | | | | 51 | // v v v v v 52 | // +--------------+===================+--------------------------------------+ 53 | // | no access | read/write access | no access | no access | 54 | // +--------------+===================+--------------------------------------+ 55 | // <- one page -> <--- max_heap_size ---> <- one page -> 56 | // 57 | // 58 | // Operation: 59 | // ---------- 60 | // The data segment is allocated and initalized by calling ds_allocate(). Initially, the 61 | // start of the heap and the brk pointer both point to the beginning of the heap 62 | // (i.e., to ds_start + PAGESIZE). 63 | // 64 | // The heap size can be adjusted by calling ds_sbrk(). The memory protection flags are set 65 | // automatically whenever the ds_heap_brk pointer is adjusted. 66 | // 67 | // ds_heap_stat() can be used to retrieve information about the heap area. 68 | // 69 | // ds_release() releases all memory and resets all internal variables. A subsequent call to 70 | // ds_allocate() is supported and initializes a 'fresh' heap. 71 | // 72 | 73 | #include 74 | #include 75 | #include 76 | #include 77 | #include 78 | #include 79 | #include 80 | #include 81 | 82 | #include "dataseg.h" 83 | 84 | 85 | static void *ds_start = NULL; ///< start of the data segment 86 | static void *ds_end = NULL; ///< end of the data segment 87 | static void *ds_heap_start = NULL; ///< start of the user space heap 88 | static void *ds_heap_brk = NULL; ///< current logical end of the user space heap 89 | static void *ds_heap_end = NULL; ///< end of the user space heap 90 | static int PAGESIZE = 0; ///< (system) page size 91 | static int ds_initialized = 0; ///< initialized flag (yes: 1, otherwise 0) 92 | static int ds_loglevel = 0; ///< log level (0: off; 1: info; 2: verbose) 93 | static int ds_domprotect = 1; ///< mprotect() heap areas (0: off, 1: on) 94 | static ssize_t ds_num_sbrk = 0; ///< number of times ds_sbrk() was called with a non-zero 95 | ///< argument 96 | 97 | 98 | /// @brief print a log message if level <= ds_loglevel. The variadic argument is a printf format 99 | /// string followed by its parametrs 100 | #ifdef DEBUG 101 | #define LOG(level, ...) ds_log(level, __VA_ARGS__) 102 | 103 | /// @brief print a log message. Do not call directly; use LOG() instead 104 | /// @param level log level of message. 105 | /// @param ... variadic parameters for vprintf function (format string with optional parameters) 106 | static void ds_log(int level, ...) 107 | { 108 | if (level > ds_loglevel) return; 109 | 110 | va_list va; 111 | va_start(va, level); 112 | const char *fmt = va_arg(va, const char*); 113 | 114 | if (fmt != NULL) vfprintf(stdout, fmt, va); 115 | 116 | va_end(va); 117 | 118 | fprintf(stdout, "\n"); 119 | } 120 | 121 | #else 122 | #define LOG(level, ...) 123 | #endif 124 | 125 | void ds_allocate(size_t max_heap_size) 126 | { 127 | LOG(1, "ds_allocate(%lx)", max_heap_size); 128 | 129 | if (ds_start != NULL) ds_release(); 130 | 131 | PAGESIZE = getpagesize(); 132 | size_t ds_size = max_heap_size + 2*PAGESIZE; 133 | 134 | // allocate memory for the data segment 135 | LOG(2, " allocating %lx bytes of memory", ds_size); 136 | ds_start = mmap(NULL, ds_size, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_POPULATE, -1, 0); 137 | if (ds_start == (void*)-1) { 138 | fprintf(stderr, "ERROR: cannot map memory in %s: %s.\n", 139 | __func__, strerror(errno)); 140 | exit(EXIT_FAILURE); 141 | } 142 | 143 | // try to lock the memory in RAM. Print only a warning if we don't succeed. 144 | /* don't do this for now. Requires changing resource limits in VM. 145 | LOG(2, " locking memory in DRAM...", ds_size); 146 | if (mlock(ds_start, ds_size) < 0) { 147 | fprintf(stderr, "WARNING: cannot lock memory in %s: %s.\n", 148 | __func__, strerror(errno)); 149 | } 150 | */ 151 | 152 | // initalize pointers 153 | ds_end = ds_start + ds_size; 154 | ds_heap_start = ds_start + PAGESIZE; 155 | ds_heap_brk = ds_heap_start; 156 | ds_heap_end = ds_end - PAGESIZE; 157 | ds_initialized = 1; 158 | ds_num_sbrk = 0; 159 | 160 | LOG(2, " ds_start: %p\n" 161 | " ds_heap_start: %p\n" 162 | " ds_heap_brk: %p\n" 163 | " ds_heap_end: %p\n" 164 | " ds_end: %p\n" 165 | " PAGESIZE: %d\n", 166 | ds_start, ds_heap_start, ds_heap_brk, ds_heap_end, ds_end, PAGESIZE); 167 | } 168 | 169 | 170 | void ds_release(void) 171 | { 172 | LOG(1, "ds_release()"); 173 | 174 | if (ds_start != NULL) { 175 | // unlock & release memory. Ignore error message here. 176 | //munlock(ds_start, ds_end-ds_start); 177 | munmap(ds_start, ds_end-ds_start); 178 | } 179 | 180 | ds_start = ds_end = ds_heap_start = ds_heap_brk = ds_heap_end = NULL; 181 | PAGESIZE = 0; 182 | ds_initialized = 0; 183 | } 184 | 185 | 186 | void* ds_sbrk(intptr_t increment) 187 | { 188 | LOG(1, "ds_sbrk(%c0x%lx)", increment < 0 ? '-' : '+', labs(increment)); 189 | assert(ds_initialized); 190 | 191 | void *old_heap_brk = ds_heap_brk; 192 | 193 | if (increment != 0) { 194 | ds_heap_brk += increment; 195 | ds_num_sbrk++; 196 | 197 | if ((ds_heap_start <= ds_heap_brk) && (ds_heap_brk < ds_heap_end)) { 198 | if (ds_domprotect) { 199 | // adjust memory access permissions 200 | // since we are not forcing alignment of brk at PAGESIZE, we need to mark the invalid part 201 | // before allowing access to the permissible area because permissions are set on a page-level 202 | // basis 203 | LOG(2, " setting memory protection:\n" 204 | " READ/WRITE from %p to %p\n" 205 | " NO ACCESS from %p to %p\n", 206 | ds_heap_start, ds_heap_brk, ds_heap_brk, ds_end); 207 | 208 | void *aligned_brk = (void*)(((unsigned long)ds_heap_brk) / PAGESIZE * PAGESIZE); // round down 209 | 210 | if ((mprotect(aligned_brk, ds_end-aligned_brk, PROT_NONE) != 0) || 211 | (mprotect(ds_heap_start, ds_heap_brk-ds_heap_start, PROT_READ|PROT_WRITE) != 0)) 212 | { 213 | fprintf(stderr, "ERROR: cannot set memory protection flags in %s: %s.\n", 214 | __func__, strerror(errno)); 215 | exit(EXIT_FAILURE); 216 | } 217 | } 218 | } else { 219 | // ignore increment and signal an error if we ended up outside the simulated data segment 220 | LOG(1, " invalid increment (ended up outside valid data segment)"); 221 | errno = ENOMEM; 222 | ds_heap_brk = old_heap_brk; 223 | old_heap_brk = (void*)-1; 224 | } 225 | } 226 | 227 | return old_heap_brk; 228 | } 229 | 230 | 231 | int ds_getpagesize(void) 232 | { 233 | assert(ds_initialized); 234 | 235 | return PAGESIZE; 236 | } 237 | 238 | 239 | void ds_heap_stat(void **start, void **brk, void **end) 240 | { 241 | if (start) *start = ds_heap_start; 242 | if (brk) *brk = ds_heap_brk; 243 | if (end) *end = ds_heap_end; 244 | } 245 | 246 | 247 | ssize_t ds_getnsbrk(void) 248 | { 249 | return ds_num_sbrk; 250 | } 251 | 252 | void ds_setloglevel(int level) 253 | { 254 | ds_loglevel = level; 255 | } 256 | 257 | 258 | void ds_setmprotect(int active) 259 | { 260 | ds_domprotect = (active > 0); 261 | } 262 | 263 | 264 | -------------------------------------------------------------------------------- /src/dataseg.h: -------------------------------------------------------------------------------- 1 | //-------------------------------------------------------------------------------------------------- 2 | // System Programming Memory Lab Spring 2024 3 | // 4 | /// @file 5 | /// @brief simulated data segment 6 | /// @author Bernhard Egger 7 | /// @section changelog Change Log 8 | /// 2020/09/27 Bernhard Egger created 9 | /// 10 | /// @section license_section License 11 | /// Copyright (c) 2020-2023, Computer Systems and Platforms Laboratory, SNU 12 | /// All rights reserved. 13 | /// 14 | /// Redistribution and use in source and binary forms, with or without modification, are permitted 15 | /// provided that the following conditions are met: 16 | /// 17 | /// - Redistributions of source code must retain the above copyright notice, this list of condi- 18 | /// tions and the following disclaimer. 19 | /// - Redistributions in binary form must reproduce the above copyright notice, this list of condi- 20 | /// tions and the following disclaimer in the documentation and/or other materials provided with 21 | /// the distribution. 22 | /// 23 | /// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 24 | /// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 25 | /// AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 26 | /// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSE- 27 | /// QUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 | /// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 29 | /// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | /// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 31 | /// DAMAGE. 32 | //-------------------------------------------------------------------------------------------------- 33 | 34 | #ifndef __DATASEG_H__ 35 | #define __DATASEG_H__ 36 | 37 | #include 38 | 39 | /// @brief initialize simulated data segment. Allocates & locks memory pages in RAM to minimize 40 | /// performance variance. 41 | /// @param max_heap_size maximum possible size of heap data segment 42 | void ds_allocate(size_t max_heap_size); 43 | 44 | /// @brief release simulated data segment 45 | void ds_release(void); 46 | 47 | /// @brief sbrk() implementation on our simulated data segment. Operates exactly as the kernel's 48 | /// sbrk() function (see man sbrk) 49 | /// @param increment offset by which to increase/decrease current brk. 50 | /// @retval old brk on success. 51 | /// @retval (void*)-1 on error. errno is set to ENOMEM 52 | void* ds_sbrk(intptr_t increment); 53 | 54 | /// @brief retrieve pagesize of data segment 55 | /// @retval page size 56 | /// @retval 0 if not data segment not initialized) 57 | int ds_getpagesize(void); 58 | 59 | /// @brief retrieve statistics about our data segment. Returns start, end, and current brk address. 60 | /// @param[out] start starting address of user-space heap 61 | /// @param[out] brk current break pointer of user-space heap 62 | /// @param[out] end largest possible address of user-space heap 63 | /// @param[out] nsbrk number of times sbrk() was called with a non-zero argument 64 | void ds_heap_stat(void **start, void **brk, void **end); 65 | 66 | /// @brief retrieve the number of sbrk() was called with a non-zero argument 67 | /// @retval ssize_t number of sbrk() calls 68 | ssize_t ds_getnsbrk(void); 69 | 70 | /// @brief set log level 71 | /// @brief level log level (0: no logging, 1: info; 2: verbose) 72 | void ds_setloglevel(int level); 73 | 74 | /// @brief turn mprotect() on/off 75 | /// @brief active (1: mprotect() activated, 0: mprotect() not executed) 76 | void ds_setmprotect(int active); 77 | 78 | #endif // __DATSEG_H__ 79 | -------------------------------------------------------------------------------- /src/memmgr.c: -------------------------------------------------------------------------------- 1 | //-------------------------------------------------------------------------------------------------- 2 | // System Programming Memory Lab Spring 2024 3 | // 4 | /// @file 5 | /// @brief dynamic memory manager 6 | /// @author 7 | /// @studid 8 | //-------------------------------------------------------------------------------------------------- 9 | 10 | 11 | // Dynamic memory manager 12 | // ====================== 13 | // This module implements a custom dynamic memory manager. 14 | // 15 | // Heap organization: 16 | // ------------------ 17 | // The data segment for the heap is provided by the dataseg module. A 'word' in the heap is 18 | // eight bytes. 19 | // 20 | // Implicit free list: 21 | // ------------------- 22 | // - minimal block size: 32 bytes (header + footer + 2 data words) 23 | // - h,f: header/footer of free block 24 | // - H,F: header/footer of allocated block 25 | // 26 | // - state after initialization 27 | // 28 | // initial sentinel half-block end sentinel half-block 29 | // | | 30 | // ds_heap_start | heap_start heap_end ds_heap_brk 31 | // | | | | | 32 | // v v v v v 33 | // +---+---+-----------------------------------------+---+---+ 34 | // |???| F | h : : f | H |???| 35 | // +---+---+-----------------------------------------+---+---+ 36 | // ^ ^ 37 | // | | 38 | // 32-byte aligned 32-byte aligned 39 | // 40 | // - allocation policy: best fit 41 | // - block splitting: always at 32-byte boundaries 42 | // - immediate coalescing upon free 43 | // 44 | // Explicit free list: 45 | // ------------------- 46 | // - minimal block size: 32 bytes (header + footer + next + prev) 47 | // - h,f: header/footer of free block 48 | // - n,p: next/previous pointer 49 | // - H,F: header/footer of allocated block 50 | // 51 | // - state after initialization 52 | // 53 | // initial sentinel half-block end sentinel half-block 54 | // | | 55 | // ds_heap_start | heap_start heap_end ds_heap_brk 56 | // | | | | | 57 | // v v v v v 58 | // +---+---+-----------------------------------------+---+---+ 59 | // |???| F | h : n : p : : f | H |???| 60 | // +---+---+-----------------------------------------+---+---+ 61 | // ^ ^ 62 | // | | 63 | // 32-byte aligned 32-byte aligned 64 | // 65 | // - allocation policy: best fit 66 | // - block splitting: always at 32-byte boundaries 67 | // - immediate coalescing upon free 68 | // 69 | 70 | #define _GNU_SOURCE 71 | 72 | #include 73 | #include 74 | #include 75 | #include 76 | #include 77 | #include 78 | #include 79 | #include 80 | 81 | #include "dataseg.h" 82 | #include "memmgr.h" 83 | 84 | 85 | /// @name global variables 86 | /// @{ 87 | static void *ds_heap_start = NULL; ///< physical start of data segment 88 | static void *ds_heap_brk = NULL; ///< physical end of data segment 89 | static void *heap_start = NULL; ///< logical start of heap 90 | static void *heap_end = NULL; ///< logical end of heap 91 | static int PAGESIZE = 0; ///< memory system page size 92 | static void *(*get_free_block)(size_t) = NULL; ///< get free block for selected allocation policy 93 | static size_t CHUNKSIZE = 1<<16; ///< minimal data segment allocation unit 94 | static size_t SHRINKTHLD = 1<<14; ///< threshold to shrink heap 95 | static int mm_initialized = 0; ///< initialized flag (yes: 1, otherwise 0) 96 | static int mm_loglevel = 0; ///< log level (0: off; 1: info; 2: verbose) 97 | 98 | // Freelist 99 | static FreelistPolicy freelist_policy = 0; ///< free list management policy 100 | 101 | 102 | // 103 | // TODO: add more global variables as needed 104 | // 105 | /// @} 106 | 107 | /// @name Macro definitions 108 | /// @{ 109 | #define MAX(a, b) ((a) > (b) ? (a) : (b)) ///< MAX function 110 | 111 | #define TYPE unsigned long ///< word type of heap 112 | #define TYPE_SIZE sizeof(TYPE) ///< size of word type 113 | 114 | #define ALLOC 1 ///< block allocated flag 115 | #define FREE 0 ///< block free flag 116 | #define STATUS_MASK ((TYPE)(0x7)) ///< mask to retrieve flags from header/footer 117 | #define SIZE_MASK (~STATUS_MASK) ///< mask to retrieve size from header/footer 118 | 119 | #define BS 32 ///< minimal block size. Must be a power of 2 120 | #define BS_MASK (~(BS-1)) ///< alignment mask 121 | 122 | #define WORD(p) ((TYPE)(p)) ///< convert pointer to TYPE 123 | #define PTR(w) ((void*)(w)) ///< convert TYPE to void* 124 | 125 | #define PREV_PTR(p) ((p)-TYPE_SIZE) ///< get pointer to word preceeding p 126 | #define NEXT_PTR(p) ((p)+TYPE_SIZE) ///< get pointer to word succeeding p 127 | #define HDR2FTR(p) ((p)+GET_SIZE(p)-TYPE_SIZE) ///< get footer for given header 128 | #define FTR2HDR(p) ((p)-GET_SIZE(p)+TYPE_SIZE) ///< get header for given footer 129 | 130 | #define PACK(size,status) ((size) | (status)) ///< pack size & status into boundary tag 131 | #define SIZE(v) (v & SIZE_MASK) ///< extract size from boundary tag 132 | #define STATUS(v) (v & STATUS_MASK) ///< extract status from boundary tag 133 | 134 | #define PUT(p, v) (*(TYPE*)(p) = (TYPE)(v)) ///< write word v to *p 135 | #define GET(p) (*(TYPE*)(p)) ///< read word at *p 136 | #define GET_SIZE(p) (SIZE(GET(p))) ///< extract size from header/footer 137 | #define GET_STATUS(p) (STATUS(GET(p))) ///< extract status from header/footer 138 | 139 | 140 | // 141 | // TODO: add more macros as needed 142 | // 143 | /// @} 144 | 145 | 146 | /// @name Logging facilities 147 | /// @{ 148 | 149 | /// @brief print a log message if level <= mm_loglevel. The variadic argument is a printf format 150 | /// string followed by its parametrs 151 | #ifdef DEBUG 152 | #define LOG(level, ...) mm_log(level, __VA_ARGS__) 153 | 154 | /// @brief print a log message. Do not call directly; use LOG() instead 155 | /// @param level log level of message. 156 | /// @param ... variadic parameters for vprintf function (format string with optional parameters) 157 | static void mm_log(int level, ...) 158 | { 159 | if (level > mm_loglevel) return; 160 | 161 | va_list va; 162 | va_start(va, level); 163 | const char *fmt = va_arg(va, const char*); 164 | 165 | if (fmt != NULL) vfprintf(stdout, fmt, va); 166 | 167 | va_end(va); 168 | 169 | fprintf(stdout, "\n"); 170 | } 171 | 172 | #else 173 | #define LOG(level, ...) 174 | #endif 175 | 176 | /// @} 177 | 178 | 179 | /// @name Program termination facilities 180 | /// @{ 181 | 182 | /// @brief print error message and terminate process. The variadic argument is a printf format 183 | /// string followed by its parameters 184 | #define PANIC(...) mm_panic(__func__, __VA_ARGS__) 185 | 186 | /// @brief print error message and terminate process. Do not call directly, Use PANIC() instead. 187 | /// @param func function name 188 | /// @param ... variadic parameters for vprintf function (format string with optional parameters) 189 | static void mm_panic(const char *func, ...) 190 | { 191 | va_list va; 192 | va_start(va, func); 193 | const char *fmt = va_arg(va, const char*); 194 | 195 | fprintf(stderr, "PANIC in %s%s", func, fmt ? ": " : "."); 196 | if (fmt != NULL) vfprintf(stderr, fmt, va); 197 | 198 | va_end(va); 199 | 200 | fprintf(stderr, "\n"); 201 | 202 | exit(EXIT_FAILURE); 203 | } 204 | /// @} 205 | 206 | 207 | static void* bf_get_free_block_implicit(size_t size); 208 | static void* bf_get_free_block_explicit(size_t size); 209 | 210 | void mm_init(FreelistPolicy fp) 211 | { 212 | LOG(1, "mm_init()"); 213 | 214 | // 215 | // set free list policy 216 | // 217 | freelist_policy = fp; 218 | switch (freelist_policy) 219 | { 220 | case fp_Implicit: 221 | get_free_block = bf_get_free_block_implicit; 222 | break; 223 | 224 | case fp_Explicit: 225 | get_free_block = bf_get_free_block_explicit; 226 | break; 227 | 228 | default: 229 | PANIC("Non supported freelist policy."); 230 | break; 231 | } 232 | 233 | // 234 | // retrieve heap status and perform a few initial sanity checks 235 | // 236 | ds_heap_stat(&ds_heap_start, &ds_heap_brk, NULL); 237 | PAGESIZE = ds_getpagesize(); 238 | 239 | LOG(2, " ds_heap_start: %p\n" 240 | " ds_heap_brk: %p\n" 241 | " PAGESIZE: %d\n", 242 | ds_heap_start, ds_heap_brk, PAGESIZE); 243 | 244 | if (ds_heap_start == NULL) PANIC("Data segment not initialized."); 245 | if (ds_heap_start != ds_heap_brk) PANIC("Heap not clean."); 246 | if (PAGESIZE == 0) PANIC("Reported pagesize == 0."); 247 | 248 | // 249 | // initialize heap 250 | // 251 | // TODO 252 | 253 | // 254 | // heap is initialized 255 | // 256 | mm_initialized = 1; 257 | } 258 | 259 | 260 | /// @brief find and return a free block of at least @a size bytes (best fit) 261 | /// @param size size of block (including header & footer tags), in bytes 262 | /// @retval void* pointer to header of large enough free block 263 | /// @retval NULL if no free block of the requested size is avilable 264 | static void* bf_get_free_block_implicit(size_t size) 265 | { 266 | LOG(1, "bf_get_free_block_implicit(0x%lx (%lu))", size, size); 267 | 268 | assert(mm_initialized); 269 | 270 | // 271 | // TODO 272 | // 273 | 274 | return NULL; 275 | } 276 | 277 | 278 | /// @brief find and return a free block of at least @a size bytes (best fit) 279 | /// @param size size of block (including header & footer tags), in bytes 280 | /// @retval void* pointer to header of large enough free block 281 | /// @retval NULL if no free block of the requested size is avilable 282 | static void* bf_get_free_block_explicit(size_t size) 283 | { 284 | LOG(1, "bf_get_free_block_explicit(0x%lx (%lu))", size, size); 285 | 286 | assert(mm_initialized); 287 | 288 | // 289 | // TODO 290 | // 291 | 292 | return NULL; 293 | } 294 | 295 | 296 | void* mm_malloc(size_t size) 297 | { 298 | LOG(1, "mm_malloc(0x%lx (%lu))", size, size); 299 | 300 | assert(mm_initialized); 301 | 302 | // 303 | // TODO 304 | // 305 | 306 | return NULL; 307 | } 308 | 309 | 310 | void* mm_calloc(size_t nmemb, size_t size) 311 | { 312 | LOG(1, "mm_calloc(0x%lx, 0x%lx (%lu))", nmemb, size, size); 313 | 314 | assert(mm_initialized); 315 | 316 | // 317 | // calloc is simply malloc() followed by memset() 318 | // 319 | void *payload = mm_malloc(nmemb * size); 320 | 321 | if (payload != NULL) memset(payload, 0, nmemb * size); 322 | 323 | return payload; 324 | } 325 | 326 | 327 | void* mm_realloc(void *ptr, size_t size) 328 | { 329 | LOG(1, "mm_realloc(%p, 0x%lx (%lu))", ptr, size, size); 330 | 331 | assert(mm_initialized); 332 | 333 | // 334 | // TODO 335 | // 336 | 337 | return NULL; 338 | } 339 | 340 | 341 | void mm_free(void *ptr) 342 | { 343 | LOG(1, "mm_free(%p)", ptr); 344 | 345 | assert(mm_initialized); 346 | 347 | // 348 | // TODO 349 | // 350 | 351 | } 352 | 353 | 354 | void mm_setloglevel(int level) 355 | { 356 | mm_loglevel = level; 357 | } 358 | 359 | 360 | void mm_check(void) 361 | { 362 | assert(mm_initialized); 363 | 364 | void *p; 365 | 366 | char *fpstr; 367 | if (freelist_policy == fp_Implicit) fpstr = "Implicit"; 368 | else if (freelist_policy == fp_Explicit) fpstr = "Explicit"; 369 | else fpstr = "invalid"; 370 | 371 | printf("----------------------------------------- mm_check ----------------------------------------------\n"); 372 | printf(" ds_heap_start: %p\n", ds_heap_start); 373 | printf(" ds_heap_brk: %p\n", ds_heap_brk); 374 | printf(" heap_start: %p\n", heap_start); 375 | printf(" heap_end: %p\n", heap_end); 376 | printf(" free list policy: %s\n", fpstr); 377 | 378 | printf("\n"); 379 | p = PREV_PTR(heap_start); 380 | printf(" initial sentinel: %p: size: %6lx (%7ld), status: %s\n", 381 | p, GET_SIZE(p), GET_SIZE(p), GET_STATUS(p) == ALLOC ? "allocated" : "free"); 382 | p = heap_end; 383 | printf(" end sentinel: %p: size: %6lx (%7ld), status: %s\n", 384 | p, GET_SIZE(p), GET_SIZE(p), GET_STATUS(p) == ALLOC ? "allocated" : "free"); 385 | printf("\n"); 386 | 387 | if(freelist_policy == fp_Implicit){ 388 | printf(" %-14s %8s %10s %10s %8s %s\n", "address", "offset", "size (hex)", "size (dec)", "payload", "status"); 389 | } 390 | else if(freelist_policy == fp_Explicit){ 391 | printf(" %-14s %8s %10s %10s %8s %-14s %-14s %s\n", "address", "offset", "size (hex)", "size (dec)", "payload", "next", "prev", "status"); 392 | } 393 | 394 | long errors = 0; 395 | p = heap_start; 396 | while (p < heap_end) { 397 | char *ofs_str, *size_str; 398 | 399 | TYPE hdr = GET(p); 400 | TYPE size = SIZE(hdr); 401 | TYPE status = STATUS(hdr); 402 | 403 | void *next = NEXT_LIST_GET(p); 404 | void *prev = PREV_LIST_GET(p); 405 | 406 | if (asprintf(&ofs_str, "0x%lx", p-heap_start) < 0) ofs_str = NULL; 407 | if (asprintf(&size_str, "0x%lx", size) < 0) size_str = NULL; 408 | 409 | if(freelist_policy == fp_Implicit){ 410 | printf(" %p %8s %10s %10ld %8ld %s\n", 411 | p, ofs_str, size_str, size, size-2*TYPE_SIZE, status == ALLOC ? "allocated" : "free"); 412 | } 413 | else if(freelist_policy == fp_Explicit){ 414 | printf(" %p %8s %10s %10ld %8ld %-14p %-14p %s\n", 415 | p, ofs_str, size_str, size, size-2*TYPE_SIZE, 416 | status == ALLOC ? NULL : next, status == ALLOC ? NULL : prev, 417 | status == ALLOC ? "allocated" : "free"); 418 | } 419 | 420 | free(ofs_str); 421 | free(size_str); 422 | 423 | void *fp = p + size - TYPE_SIZE; 424 | TYPE ftr = GET(fp); 425 | TYPE fsize = SIZE(ftr); 426 | TYPE fstatus = STATUS(ftr); 427 | 428 | if ((size != fsize) || (status != fstatus)) { 429 | errors++; 430 | printf(" --> ERROR: footer at %p with different properties: size: %lx, status: %lx\n", 431 | fp, fsize, fstatus); 432 | mm_panic("mm_check"); 433 | } 434 | 435 | p = p + size; 436 | if (size == 0) { 437 | printf(" WARNING: size 0 detected, aborting traversal.\n"); 438 | break; 439 | } 440 | } 441 | 442 | printf("\n"); 443 | if ((p == heap_end) && (errors == 0)) printf(" Block structure coherent.\n"); 444 | printf("-------------------------------------------------------------------------------------------------\n"); 445 | } 446 | 447 | 448 | -------------------------------------------------------------------------------- /src/memmgr.h: -------------------------------------------------------------------------------- 1 | //-------------------------------------------------------------------------------------------------- 2 | // System Programming Memory Lab Spring 2024 3 | // 4 | /// @file 5 | /// @brief dynamic memory manager 6 | /// @author Bernhard Egger 7 | /// @section changelog Change Log 8 | /// 2020/09/27 Bernhard Egger created 9 | /// 10 | /// @section license_section License 11 | /// Copyright (c) 2020-2023, Computer Systems and Platforms Laboratory, SNU 12 | /// All rights reserved. 13 | /// 14 | /// Redistribution and use in source and binary forms, with or without modification, are permitted 15 | /// provided that the following conditions are met: 16 | /// 17 | /// - Redistributions of source code must retain the above copyright notice, this list of condi- 18 | /// tions and the following disclaimer. 19 | /// - Redistributions in binary form must reproduce the above copyright notice, this list of condi- 20 | /// tions and the following disclaimer in the documentation and/or other materials provided with 21 | /// the distribution. 22 | /// 23 | /// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 24 | /// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 25 | /// AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 26 | /// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSE- 27 | /// QUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 | /// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 29 | /// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | /// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 31 | /// DAMAGE. 32 | //-------------------------------------------------------------------------------------------------- 33 | 34 | #ifndef __MEMMGR_H__ 35 | #define __MEMMGR_H__ 36 | 37 | #include 38 | 39 | // !! Remove allocation policy !! 40 | 41 | /// @brief supported free list managing policies 42 | typedef enum { 43 | fp_Implicit, ///< Implicit list management 44 | fp_Explicit, ///< Explicit list management 45 | } FreelistPolicy; 46 | 47 | /// @brief initialize heap. Must be called before any of the other functions can be used. 48 | void mm_init(FreelistPolicy ap); 49 | 50 | /// @brief allocate a block of memory of @a size bytes 51 | /// @param size requested size in bytes 52 | /// @retval void* pointer to first byte of memory on success 53 | /// @retval NULL if memory allocation failed 54 | void* mm_malloc(size_t size); 55 | 56 | /// @brief allocate a block of memory of @a nelem * @a size bytes initialized with zeroes. 57 | /// @param nelem number of elements 58 | /// @param size size of one element in bytes 59 | /// @retval void* pointer to first byte of zeroed memory on success 60 | /// @retval NULL if memory allocation failed 61 | void* mm_calloc(size_t nelem, size_t size); 62 | 63 | /// @brief re-allocate a block of memory to change its size to @a size bytes. 64 | /// @param ptr previously allocated block or NULL 65 | /// @param size requested new size in bytes 66 | /// @retval void* pointer to first byte of re-allocated memory on success 67 | /// @retval NULL if memory allocation failed 68 | void* mm_realloc(void *ptr, size_t size); 69 | 70 | /// @brief free a previously allocated block of memory 71 | /// @param ptr pointer to allocated memory obtained by calling mm_malloc, mm_calloc, or mm_realloc 72 | void mm_free(void *ptr); 73 | 74 | /// @brief set log level 75 | /// @brief level log level (0: no logging, 1: info; 2: verbose) 76 | void mm_setloglevel(int level); 77 | 78 | /// @brief dump heap and perform some sanity checks 79 | void mm_check(void); 80 | 81 | #endif // __MEMMGR_H__ 82 | -------------------------------------------------------------------------------- /src/mm_test.c: -------------------------------------------------------------------------------- 1 | //-------------------------------------------------------------------------------------------------- 2 | // System Programming Memory Lab Spring 2024 3 | // 4 | /// @file 5 | /// @brief dynamic memory manager test program 6 | /// @author Bernhard Egger 7 | /// @section changelog Change Log 8 | /// 2020/09/27 Bernhard Egger created 9 | /// 10 | /// @section license_section License 11 | /// Copyright (c) 2020-2023, Computer Systems and Platforms Laboratory, SNU 12 | /// All rights reserved. 13 | /// 14 | /// Redistribution and use in source and binary forms, with or without modification, are permitted 15 | /// provided that the following conditions are met: 16 | /// 17 | /// - Redistributions of source code must retain the above copyright notice, this list of condi- 18 | /// tions and the following disclaimer. 19 | /// - Redistributions in binary form must reproduce the above copyright notice, this list of condi- 20 | /// tions and the following disclaimer in the documentation and/or other materials provided with 21 | /// the distribution. 22 | /// 23 | /// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 24 | /// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 25 | /// AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 26 | /// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSE- 27 | /// QUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 | /// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 29 | /// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | /// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 31 | /// DAMAGE. 32 | //-------------------------------------------------------------------------------------------------- 33 | 34 | 35 | #include 36 | #include 37 | #include 38 | 39 | #include "dataseg.h" 40 | #include "memmgr.h" 41 | #include "blocklist.h" 42 | 43 | #define ALLOC 1 44 | #define FREE 0 45 | 46 | void enter(void) 47 | { 48 | printf("Press enter to continue.\n"); 49 | getchar(); 50 | } 51 | 52 | void do_malloc(void) 53 | { 54 | printf("(1) enter payload size(s) to malloc: "); 55 | 56 | char *str = NULL; 57 | size_t lstr = 0; 58 | 59 | if (getline(&str, &lstr, stdin) > 0) { 60 | int pos = 0, bread; 61 | size_t bytes; 62 | while (sscanf(&str[pos], "%lu%n", &bytes, &bread) == 1) { 63 | printf(" allocating %lu bytes\n", bytes); 64 | void *ptr = mm_malloc(bytes); 65 | if (ptr != NULL) insert_block(ptr, bytes, 1); 66 | pos += bread; 67 | } 68 | } 69 | 70 | if (str != NULL) free(str); 71 | } 72 | 73 | void do_free(void) 74 | { 75 | printf("(2) Block list\n"); 76 | 77 | Block **block = get_block_array(); 78 | size_t nblocks = 0; 79 | while (block[nblocks] != NULL) { 80 | Block *b = block[nblocks]; 81 | printf(" [%3lu] %p: size: %6lx (%7ld), status: %s\n", 82 | nblocks, b->ptr, b->size, b->size, 83 | b->flags == ALLOC ? "allocated" : "free"); 84 | nblocks++; 85 | } 86 | printf("\nEnter index/indices of blocks to free: "); 87 | 88 | char *str = NULL; 89 | size_t lstr = 0; 90 | 91 | if (getline(&str, &lstr, stdin) > 0) { 92 | int pos = 0, bread; 93 | size_t index; 94 | while (sscanf(&str[pos], "%lu%n", &index, &bread) == 1) { 95 | printf(" freeing %lu-th block\n", index); 96 | if (index < nblocks) { 97 | Block *b = block[index]; 98 | mm_free(b->ptr); 99 | delete_block(b->ptr); 100 | } else { 101 | printf(" --> no such block\n"); 102 | } 103 | pos += bread; 104 | } 105 | } 106 | 107 | free(block); 108 | } 109 | 110 | void do_setloglevel(void) 111 | { 112 | } 113 | 114 | int main(int argc, char *argv[]) 115 | { 116 | void *ptr[100]; 117 | unsigned int idx = 0; 118 | unsigned debug = 0; 119 | 120 | init_blocklist(); 121 | 122 | ds_setloglevel(0); 123 | mm_setloglevel(0); 124 | 125 | // !! Add freelist policy selection !! 126 | char *line = NULL; 127 | size_t llen = 0; 128 | char c = '\0'; 129 | 130 | FreelistPolicy fp = fp_Implicit; 131 | 132 | do { 133 | printf("-----------------------------------\n" 134 | " Select freelist policy.\n" 135 | "(i) implicit list\n" 136 | "(e) explicit list\n" 137 | "(q) quit\n" 138 | "Your selection: "); 139 | fflush(stdout); 140 | 141 | if (getline(&line, &llen, stdin) > 0) { 142 | c = line[0]; 143 | switch (c) { 144 | case 'i': fp = fp_Implicit; break; 145 | case 'e': fp = fp_Explicit; break; 146 | case 'q': return EXIT_SUCCESS; 147 | default: if (c > ' ') printf("Invalid selection.\n"); 148 | } 149 | } else { 150 | printf("Error reading character.\n"); 151 | } 152 | } while (c != 'i' && c != 'e'); 153 | 154 | printf("\n\n\n----------------------------------------\n" 155 | " Initializing heap...\n" 156 | "\n\n"); 157 | ds_allocate(32*1024*1024); 158 | 159 | // !! replace to freelist policy !! 160 | mm_init(fp); 161 | mm_check(); 162 | 163 | printf("\n\n\n----------------------------------------\n" 164 | " Testing mm_malloc()...\n" 165 | "\n\n"); 166 | 167 | mm_setloglevel(2); 168 | 169 | do { 170 | printf("-----------------------------------\n" 171 | "(m) malloc\n" 172 | "(f) free\n" 173 | "(c) check heap\n" 174 | "(l) set log level\n" 175 | "(q) quit\n" 176 | "Your selection: "); 177 | fflush(stdout); 178 | 179 | if (getline(&line, &llen, stdin) > 0) { 180 | c = line[0]; 181 | switch (c) { 182 | case 'm': do_malloc(); break; 183 | case 'f': do_free(); break; 184 | case 'c': mm_check(); break; 185 | case 'l': do_setloglevel(); break; 186 | case 'q': break; 187 | default: if (c > ' ') printf("Invalid selection.\n"); 188 | } 189 | } else { 190 | printf("Error reading character.\n"); 191 | } 192 | } while (c != 'q'); 193 | 194 | if (line != NULL) free(line); 195 | 196 | return EXIT_SUCCESS; 197 | 198 | 199 | 200 | debug = 1; 201 | ds_setloglevel(0); 202 | mm_setloglevel(0); 203 | 204 | enter(); ptr[idx++] = mm_malloc(1); if (debug) mm_check(); 205 | enter(); ptr[idx++] = mm_malloc(15); if (debug) mm_check(); 206 | enter(); ptr[idx++] = mm_malloc(16); if (debug) mm_check(); 207 | enter(); ptr[idx++] = mm_malloc(17); if (debug) mm_check(); 208 | enter(); ptr[idx++] = mm_malloc(31); if (debug) mm_check(); 209 | enter(); ptr[idx++] = mm_malloc(32); if (debug) mm_check(); 210 | enter(); ptr[idx++] = mm_malloc(33); if (debug) mm_check(); 211 | enter(); ptr[idx++] = mm_malloc(47); if (debug) mm_check(); 212 | enter(); ptr[idx++] = mm_malloc(48); if (debug) mm_check(); 213 | enter(); ptr[idx++] = mm_malloc(49); if (debug) mm_check(); 214 | enter(); ptr[idx++] = mm_malloc(100); if (debug) mm_check(); 215 | enter(); ptr[idx++] = mm_malloc(200); if (debug) mm_check(); 216 | enter(); ptr[idx++] = mm_malloc(400); if (debug) mm_check(); 217 | enter(); ptr[idx++] = mm_malloc(1024); if (debug) mm_check(); 218 | enter(); ptr[idx++] = mm_malloc(0x1000); if (debug) mm_check(); 219 | enter(); ptr[idx++] = mm_malloc(0x2000); if (debug) mm_check(); 220 | enter(); ptr[idx++] = mm_malloc(0x4000); if (debug) mm_check(); 221 | enter(); ptr[idx++] = mm_malloc(0x8000); if (debug) mm_check(); 222 | enter(); ptr[idx++] = mm_malloc(0x10000); if (debug) mm_check(); 223 | 224 | printf("\n\n\n----------------------------------------\n" 225 | " Testing mm_free()...\n" 226 | "\n\n"); 227 | debug = 1; 228 | ds_setloglevel(0); 229 | mm_setloglevel(0); 230 | 231 | enter(); mm_free(ptr[0]); if (debug) mm_check(); 232 | enter(); mm_free(ptr[1]); if (debug) mm_check(); 233 | enter(); mm_free(ptr[3]); if (debug) mm_check(); 234 | enter(); mm_free(ptr[2]); if (debug) mm_check(); 235 | enter(); mm_free(ptr[7]); if (debug) mm_check(); 236 | enter(); mm_free(ptr[6]); if (debug) mm_check(); 237 | enter(); mm_free(ptr[5]); if (debug) mm_check(); 238 | enter(); mm_free(ptr[4]); if (debug) mm_check(); 239 | enter(); mm_free(ptr[10]); if (debug) mm_check(); 240 | 241 | 242 | 243 | printf("\n\n\n----------------------------------------\n" 244 | " Testing mm_realloc()...\n" 245 | "\n\n"); 246 | debug = 1; 247 | ds_setloglevel(0); 248 | mm_setloglevel(2); 249 | 250 | enter(); mm_realloc(ptr[9], 50); if (debug) mm_check(); 251 | enter(); mm_realloc(ptr[9], 60); if (debug) mm_check(); 252 | enter(); mm_realloc(ptr[9], 48); if (debug) mm_check(); 253 | enter(); mm_realloc(ptr[9], 220); if (debug) mm_check(); 254 | 255 | 256 | return EXIT_SUCCESS; 257 | } 258 | 259 | 260 | -------------------------------------------------------------------------------- /src/nulldriver.c: -------------------------------------------------------------------------------- 1 | //-------------------------------------------------------------------------------------------------- 2 | // System Programming Memory Lab Spring 2024 3 | // 4 | /// @file 5 | /// @brief null driver (empty malloc interfaces to measure overhead of framework) 6 | /// @author Bernhard Egger 7 | /// @section changelog Change Log 8 | /// 2020/10/04 Bernhard Egger created 9 | /// 10 | /// @section license_section License 11 | /// Copyright (c) 2020-2023, Computer Systems and Platforms Laboratory, SNU 12 | /// All rights reserved. 13 | /// 14 | /// Redistribution and use in source and binary forms, with or without modification, are permitted 15 | /// provided that the following conditions are met: 16 | /// 17 | /// - Redistributions of source code must retain the above copyright notice, this list of condi- 18 | /// tions and the following disclaimer. 19 | /// - Redistributions in binary form must reproduce the above copyright notice, this list of condi- 20 | /// tions and the following disclaimer in the documentation and/or other materials provided with 21 | /// the distribution. 22 | /// 23 | /// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 24 | /// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 25 | /// AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 26 | /// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSE- 27 | /// QUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 | /// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 29 | /// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | /// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 31 | /// DAMAGE. 32 | //-------------------------------------------------------------------------------------------------- 33 | 34 | #include "nulldriver.h" 35 | 36 | void* null_malloc(size_t size) 37 | { 38 | return (void*)(long)-1; 39 | } 40 | 41 | void* null_calloc(size_t nmemb, size_t size) 42 | { 43 | return (void*)(long)-1; 44 | } 45 | 46 | void* null_realloc(void *ptr, size_t size) 47 | { 48 | return (void*)(long)-1; 49 | } 50 | 51 | void null_free(void *ptr) 52 | { 53 | } 54 | 55 | void null_stat(size_t *size, ssize_t *num_sbrk) 56 | { 57 | if (size) *size = 0; 58 | if (num_sbrk) *num_sbrk = -1; 59 | } 60 | -------------------------------------------------------------------------------- /src/nulldriver.h: -------------------------------------------------------------------------------- 1 | //-------------------------------------------------------------------------------------------------- 2 | // System Programming Memory Lab Spring 2024 3 | // 4 | /// @file 5 | /// @brief null driver (empty malloc interfaces to measure overhead of framework) 6 | /// @author Bernhard Egger 7 | /// @section changelog Change Log 8 | /// 2020/10/04 Bernhard Egger created 9 | /// 10 | /// @section license_section License 11 | /// Copyright (c) 2020-2023, Computer Systems and Platforms Laboratory, SNU 12 | /// All rights reserved. 13 | /// 14 | /// Redistribution and use in source and binary forms, with or without modification, are permitted 15 | /// provided that the following conditions are met: 16 | /// 17 | /// - Redistributions of source code must retain the above copyright notice, this list of condi- 18 | /// tions and the following disclaimer. 19 | /// - Redistributions in binary form must reproduce the above copyright notice, this list of condi- 20 | /// tions and the following disclaimer in the documentation and/or other materials provided with 21 | /// the distribution. 22 | /// 23 | /// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 24 | /// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 25 | /// AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 26 | /// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSE- 27 | /// QUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 | /// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 29 | /// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | /// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 31 | /// DAMAGE. 32 | //-------------------------------------------------------------------------------------------------- 33 | 34 | #ifndef __NULLDRIVER_H__ 35 | #define __NULLDRIVER_H__ 36 | 37 | #include 38 | 39 | /// @brief null malloc. Returns (void*)-1 40 | /// @param size size of payload 41 | /// @retval (void*)-1 42 | void* null_malloc(size_t size); 43 | 44 | 45 | /// @brief null calloc. Returns (void*)-1 46 | /// @param nmemb number of members 47 | /// @param size size of one member 48 | /// @retval (void*)-1 49 | void* null_calloc(size_t nmemb, size_t size); 50 | 51 | 52 | /// @brief null realloc. Returns (void*)-1 53 | /// @param size size of payload 54 | /// @retval (void*)-1 55 | void* null_realloc(void *ptr, size_t size); 56 | 57 | 58 | /// @brief null free. Does nothing. 59 | /// @param ptr pointer to free 60 | void null_free(void *ptr); 61 | 62 | 63 | /// @brief null statistics. Returns 0 for both @a size and @a num_sbrk 64 | /// @param size heap size. Set to 0 if not NULL 65 | /// @param num_sbrk number of sbrk invocations. Set to -1 if not NULL 66 | void null_stat(size_t *size, ssize_t *num_sbrk); 67 | 68 | #endif // __NULLDRIVER_H__ 69 | -------------------------------------------------------------------------------- /tests/alloc.dmas: -------------------------------------------------------------------------------- 1 | # 2 | # 2048 allocations 3 | # 4 | 5 | dataseg 0x4000000 6 | heap implicit 7 | 8 | mode performance 9 | 10 | log ds 1 11 | log mm 1 12 | 13 | start 14 | m 0 25743 15 | m 1 10099 16 | m 2 2796 17 | m 3 13450 18 | m 4 954 19 | m 5 18556 20 | m 6 28680 21 | m 7 22098 22 | m 8 19364 23 | m 9 11596 24 | m 10 29048 25 | m 11 15846 26 | m 12 32014 27 | m 13 19861 28 | m 14 3777 29 | m 15 13996 30 | m 16 27077 31 | m 17 8460 32 | m 18 12203 33 | m 19 2396 34 | m 20 6631 35 | m 21 12635 36 | m 22 454 37 | m 23 4513 38 | m 24 24916 39 | m 25 626 40 | m 26 9264 41 | m 27 29897 42 | m 28 19198 43 | m 29 4033 44 | m 30 20288 45 | m 31 3020 46 | m 32 8689 47 | m 33 32008 48 | m 34 12313 49 | m 35 20648 50 | m 36 26843 51 | m 37 2198 52 | m 38 16889 53 | m 39 17377 54 | m 40 10279 55 | m 41 14180 56 | m 42 14270 57 | m 43 21354 58 | m 44 29105 59 | m 45 20119 60 | m 46 13453 61 | m 47 18840 62 | m 48 16895 63 | m 49 25286 64 | m 50 28590 65 | m 51 5812 66 | m 52 16891 67 | m 53 32701 68 | m 54 26407 69 | m 55 18520 70 | m 56 11234 71 | m 57 9670 72 | m 58 32463 73 | m 59 19942 74 | m 60 27451 75 | m 61 31266 76 | m 62 28384 77 | m 63 20161 78 | m 64 29761 79 | m 65 4029 80 | m 66 20183 81 | m 67 11062 82 | m 68 9992 83 | m 69 5973 84 | m 70 30720 85 | m 71 30526 86 | m 72 16857 87 | m 73 8142 88 | m 74 6679 89 | m 75 6886 90 | m 76 1293 91 | m 77 7053 92 | m 78 22948 93 | m 79 24482 94 | m 80 3782 95 | m 81 6586 96 | m 82 12123 97 | m 83 6085 98 | m 84 11885 99 | m 85 5465 100 | m 86 8189 101 | m 87 8775 102 | m 88 32731 103 | m 89 4094 104 | m 90 5224 105 | m 91 16709 106 | m 92 15375 107 | m 93 15306 108 | m 94 28682 109 | m 95 12124 110 | m 96 21940 111 | m 97 18183 112 | m 98 23272 113 | m 99 27383 114 | m 100 2277 115 | m 101 30527 116 | m 102 20031 117 | m 103 9557 118 | m 104 10843 119 | m 105 30239 120 | m 106 3262 121 | m 107 8948 122 | m 108 31836 123 | m 109 1826 124 | m 110 25134 125 | m 111 29326 126 | m 112 31954 127 | m 113 70 128 | m 114 7235 129 | m 115 2156 130 | m 116 30951 131 | m 117 12029 132 | m 118 26699 133 | m 119 13284 134 | m 120 22771 135 | m 121 26748 136 | m 122 22712 137 | m 123 21396 138 | m 124 20945 139 | m 125 12533 140 | m 126 22189 141 | m 127 11547 142 | m 128 31446 143 | m 129 12801 144 | m 130 29279 145 | m 131 18599 146 | m 132 21372 147 | m 133 551 148 | m 134 23318 149 | m 135 12816 150 | m 136 19170 151 | m 137 27135 152 | m 138 4558 153 | m 139 4860 154 | m 140 27419 155 | m 141 22665 156 | m 142 18857 157 | m 143 886 158 | m 144 19286 159 | m 145 11500 160 | m 146 25885 161 | m 147 8 162 | m 148 18275 163 | m 149 13944 164 | m 150 858 165 | m 151 9184 166 | m 152 19628 167 | m 153 17663 168 | m 154 18788 169 | m 155 29637 170 | m 156 9824 171 | m 157 6947 172 | m 158 19180 173 | m 159 22364 174 | m 160 5315 175 | m 161 5645 176 | m 162 17811 177 | m 163 16275 178 | m 164 28090 179 | m 165 2026 180 | m 166 8338 181 | m 167 25478 182 | m 168 6870 183 | m 169 4894 184 | m 170 10318 185 | m 171 15860 186 | m 172 27105 187 | m 173 18167 188 | m 174 983 189 | m 175 21936 190 | m 176 15514 191 | m 177 14622 192 | m 178 2182 193 | m 179 10322 194 | m 180 9444 195 | m 181 3340 196 | m 182 16178 197 | m 183 6104 198 | m 184 31716 199 | m 185 30006 200 | m 186 19483 201 | m 187 2323 202 | m 188 27398 203 | m 189 3500 204 | m 190 14823 205 | m 191 1001 206 | m 192 26101 207 | m 193 27590 208 | m 194 12222 209 | m 195 27867 210 | m 196 15311 211 | m 197 16099 212 | m 198 17477 213 | m 199 17253 214 | m 200 21455 215 | m 201 26973 216 | m 202 1261 217 | m 203 31709 218 | m 204 28100 219 | m 205 27244 220 | m 206 2150 221 | m 207 26798 222 | m 208 14492 223 | m 209 13805 224 | m 210 5698 225 | m 211 25899 226 | m 212 32566 227 | m 213 26359 228 | m 214 1710 229 | m 215 18793 230 | m 216 11608 231 | m 217 32610 232 | m 218 9134 233 | m 219 10889 234 | m 220 13685 235 | m 221 10773 236 | m 222 32242 237 | m 223 13746 238 | m 224 16352 239 | m 225 18290 240 | m 226 3772 241 | m 227 30422 242 | m 228 29106 243 | m 229 29575 244 | m 230 19773 245 | m 231 328 246 | m 232 10548 247 | m 233 16319 248 | m 234 18172 249 | m 235 27968 250 | m 236 9640 251 | m 237 22752 252 | m 238 24151 253 | m 239 14329 254 | m 240 25648 255 | m 241 15739 256 | m 242 25169 257 | m 243 29473 258 | m 244 15498 259 | m 245 8041 260 | m 246 23640 261 | m 247 9848 262 | m 248 19073 263 | m 249 2729 264 | m 250 32315 265 | m 251 22064 266 | m 252 9496 267 | m 253 29296 268 | m 254 12528 269 | m 255 31228 270 | m 256 15346 271 | m 257 12870 272 | m 258 6705 273 | m 259 15405 274 | m 260 18604 275 | m 261 21118 276 | m 262 28159 277 | m 263 9649 278 | m 264 3147 279 | m 265 15824 280 | m 266 16181 281 | m 267 23174 282 | m 268 16237 283 | m 269 7589 284 | m 270 27086 285 | m 271 30302 286 | m 272 16009 287 | m 273 18656 288 | m 274 10026 289 | m 275 25457 290 | m 276 9017 291 | m 277 3333 292 | m 278 22055 293 | m 279 10877 294 | m 280 2390 295 | m 281 380 296 | m 282 11473 297 | m 283 434 298 | m 284 22593 299 | m 285 9406 300 | m 286 29214 301 | m 287 17105 302 | m 288 17018 303 | m 289 6432 304 | m 290 12198 305 | m 291 16602 306 | m 292 22059 307 | m 293 16722 308 | m 294 5549 309 | m 295 14463 310 | m 296 18652 311 | m 297 29928 312 | m 298 18692 313 | m 299 20922 314 | m 300 13696 315 | m 301 6695 316 | m 302 175 317 | m 303 25593 318 | m 304 6744 319 | m 305 18682 320 | m 306 14413 321 | m 307 31731 322 | m 308 12827 323 | m 309 16050 324 | m 310 9000 325 | m 311 14488 326 | m 312 12189 327 | m 313 8754 328 | m 314 1572 329 | m 315 12259 330 | m 316 25193 331 | m 317 891 332 | m 318 1142 333 | m 319 32305 334 | m 320 19330 335 | m 321 26652 336 | m 322 2632 337 | m 323 9157 338 | m 324 23423 339 | m 325 11336 340 | m 326 19571 341 | m 327 18442 342 | m 328 14229 343 | m 329 11811 344 | m 330 10062 345 | m 331 12518 346 | m 332 1151 347 | m 333 17768 348 | m 334 21431 349 | m 335 12669 350 | m 336 12782 351 | m 337 10093 352 | m 338 1009 353 | m 339 30204 354 | m 340 3104 355 | m 341 12526 356 | m 342 24526 357 | m 343 24590 358 | m 344 22571 359 | m 345 9179 360 | m 346 10818 361 | m 347 32680 362 | m 348 3332 363 | m 349 4866 364 | m 350 4693 365 | m 351 12511 366 | m 352 14587 367 | m 353 5204 368 | m 354 16146 369 | m 355 18714 370 | m 356 1910 371 | m 357 23896 372 | m 358 21802 373 | m 359 22155 374 | m 360 27308 375 | m 361 24605 376 | m 362 11322 377 | m 363 15092 378 | m 364 28985 379 | m 365 1738 380 | m 366 15668 381 | m 367 16994 382 | m 368 28810 383 | m 369 32456 384 | m 370 12590 385 | m 371 27770 386 | m 372 20601 387 | m 373 16897 388 | m 374 29709 389 | m 375 11501 390 | m 376 10014 391 | m 377 16350 392 | m 378 12123 393 | m 379 1577 394 | m 380 30421 395 | m 381 20487 396 | m 382 5917 397 | m 383 7201 398 | m 384 22819 399 | m 385 2641 400 | m 386 23517 401 | m 387 15699 402 | m 388 18616 403 | m 389 16403 404 | m 390 17546 405 | m 391 32742 406 | m 392 29224 407 | m 393 22917 408 | m 394 19032 409 | m 395 966 410 | m 396 24096 411 | m 397 15875 412 | m 398 17195 413 | m 399 29106 414 | m 400 28398 415 | m 401 23378 416 | m 402 851 417 | m 403 21599 418 | m 404 18469 419 | m 405 10254 420 | m 406 28563 421 | m 407 20522 422 | m 408 1459 423 | m 409 18414 424 | m 410 25535 425 | m 411 4658 426 | m 412 16987 427 | m 413 1558 428 | m 414 14978 429 | m 415 20295 430 | m 416 32721 431 | m 417 12421 432 | m 418 1288 433 | m 419 23244 434 | m 420 13277 435 | m 421 414 436 | m 422 22334 437 | m 423 21491 438 | m 424 4648 439 | m 425 8268 440 | m 426 24320 441 | m 427 10694 442 | m 428 17685 443 | m 429 1265 444 | m 430 6134 445 | m 431 10373 446 | m 432 23684 447 | m 433 31122 448 | m 434 30884 449 | m 435 5659 450 | m 436 1286 451 | m 437 26649 452 | m 438 28003 453 | m 439 7395 454 | m 440 2493 455 | m 441 30744 456 | m 442 6254 457 | m 443 27261 458 | m 444 14666 459 | m 445 19827 460 | m 446 30864 461 | m 447 19161 462 | m 448 2957 463 | m 449 3549 464 | m 450 11613 465 | m 451 26424 466 | m 452 12753 467 | m 453 8285 468 | m 454 20569 469 | m 455 8353 470 | m 456 22471 471 | m 457 24626 472 | m 458 11390 473 | m 459 15353 474 | m 460 30604 475 | m 461 3527 476 | m 462 6890 477 | m 463 32537 478 | m 464 27407 479 | m 465 10564 480 | m 466 18742 481 | m 467 475 482 | m 468 23844 483 | m 469 32389 484 | m 470 29236 485 | m 471 26915 486 | m 472 3990 487 | m 473 21937 488 | m 474 23290 489 | m 475 30640 490 | m 476 17405 491 | m 477 16525 492 | m 478 28062 493 | m 479 12530 494 | m 480 32131 495 | m 481 23666 496 | m 482 19449 497 | m 483 22076 498 | m 484 4737 499 | m 485 26677 500 | m 486 12038 501 | m 487 13184 502 | m 488 16910 503 | m 489 19655 504 | m 490 12720 505 | m 491 8729 506 | m 492 9907 507 | m 493 20996 508 | m 494 15630 509 | m 495 26656 510 | m 496 15831 511 | m 497 7272 512 | m 498 4169 513 | m 499 11716 514 | m 500 19592 515 | m 501 3226 516 | m 502 25888 517 | m 503 10900 518 | m 504 26667 519 | m 505 6121 520 | m 506 17758 521 | m 507 20981 522 | m 508 21260 523 | m 509 16665 524 | m 510 28197 525 | m 511 22386 526 | m 512 9431 527 | m 513 12212 528 | m 514 2206 529 | m 515 28998 530 | m 516 25802 531 | m 517 19266 532 | m 518 25030 533 | m 519 10162 534 | m 520 13496 535 | m 521 16680 536 | m 522 20010 537 | m 523 13920 538 | m 524 25224 539 | m 525 23297 540 | m 526 22434 541 | m 527 20571 542 | m 528 7737 543 | m 529 27569 544 | m 530 16449 545 | m 531 7600 546 | m 532 18436 547 | m 533 9341 548 | m 534 6070 549 | m 535 27444 550 | m 536 24312 551 | m 537 5051 552 | m 538 24407 553 | m 539 27569 554 | m 540 26275 555 | m 541 3352 556 | m 542 19023 557 | m 543 15233 558 | m 544 5307 559 | m 545 8479 560 | m 546 8402 561 | m 547 28041 562 | m 548 32330 563 | m 549 19650 564 | m 550 22412 565 | m 551 17714 566 | m 552 583 567 | m 553 3122 568 | m 554 17842 569 | m 555 23648 570 | m 556 11307 571 | m 557 26600 572 | m 558 18261 573 | m 559 21626 574 | m 560 21596 575 | m 561 7768 576 | m 562 21556 577 | m 563 25217 578 | m 564 14055 579 | m 565 32695 580 | m 566 32108 581 | m 567 23488 582 | m 568 18765 583 | m 569 25481 584 | m 570 19716 585 | m 571 28015 586 | m 572 17836 587 | m 573 12203 588 | m 574 13314 589 | m 575 9573 590 | m 576 17255 591 | m 577 19155 592 | m 578 5573 593 | m 579 23881 594 | m 580 29380 595 | m 581 8820 596 | m 582 9095 597 | m 583 6594 598 | m 584 11158 599 | m 585 8250 600 | m 586 20015 601 | m 587 4529 602 | m 588 1719 603 | m 589 27256 604 | m 590 4719 605 | m 591 18407 606 | m 592 19824 607 | m 593 8415 608 | m 594 18946 609 | m 595 31954 610 | m 596 17182 611 | m 597 27487 612 | m 598 11825 613 | m 599 11600 614 | m 600 30384 615 | m 601 11681 616 | m 602 10865 617 | m 603 130 618 | m 604 25255 619 | m 605 22670 620 | m 606 27890 621 | m 607 8837 622 | m 608 31067 623 | m 609 1632 624 | m 610 17025 625 | m 611 24998 626 | m 612 23618 627 | m 613 30122 628 | m 614 1380 629 | m 615 30593 630 | m 616 16321 631 | m 617 7783 632 | m 618 12028 633 | m 619 14320 634 | m 620 11123 635 | m 621 4497 636 | m 622 22666 637 | m 623 2756 638 | m 624 30506 639 | m 625 29153 640 | m 626 30813 641 | m 627 13050 642 | m 628 19520 643 | m 629 2667 644 | m 630 6593 645 | m 631 28121 646 | m 632 27556 647 | m 633 5440 648 | m 634 14676 649 | m 635 22058 650 | m 636 26708 651 | m 637 28783 652 | m 638 15957 653 | m 639 30346 654 | m 640 99 655 | m 641 3675 656 | m 642 12549 657 | m 643 25952 658 | m 644 7497 659 | m 645 20553 660 | m 646 32456 661 | m 647 10912 662 | m 648 30561 663 | m 649 6286 664 | m 650 21317 665 | m 651 30968 666 | m 652 8622 667 | m 653 13061 668 | m 654 10794 669 | m 655 12287 670 | m 656 15831 671 | m 657 29730 672 | m 658 1476 673 | m 659 16790 674 | m 660 30975 675 | m 661 25886 676 | m 662 6318 677 | m 663 1474 678 | m 664 3096 679 | m 665 3692 680 | m 666 594 681 | m 667 2942 682 | m 668 2353 683 | m 669 1302 684 | m 670 32523 685 | m 671 13714 686 | m 672 9196 687 | m 673 27039 688 | m 674 19164 689 | m 675 26508 690 | m 676 19523 691 | m 677 26765 692 | m 678 4170 693 | m 679 8884 694 | m 680 128 695 | m 681 29744 696 | m 682 653 697 | m 683 8266 698 | m 684 30135 699 | m 685 23096 700 | m 686 13774 701 | m 687 29811 702 | m 688 11486 703 | m 689 23137 704 | m 690 10932 705 | m 691 8783 706 | m 692 29172 707 | m 693 31108 708 | m 694 31814 709 | m 695 4999 710 | m 696 12999 711 | m 697 22834 712 | m 698 8462 713 | m 699 14677 714 | m 700 12799 715 | m 701 24660 716 | m 702 15161 717 | m 703 15923 718 | m 704 5439 719 | m 705 25319 720 | m 706 21138 721 | m 707 7625 722 | m 708 7019 723 | m 709 19395 724 | m 710 28808 725 | m 711 12121 726 | m 712 3123 727 | m 713 4045 728 | m 714 31669 729 | m 715 24169 730 | m 716 17628 731 | m 717 31069 732 | m 718 23851 733 | m 719 22625 734 | m 720 29385 735 | m 721 8221 736 | m 722 26449 737 | m 723 7474 738 | m 724 25725 739 | m 725 32093 740 | m 726 3917 741 | m 727 9509 742 | m 728 9503 743 | m 729 17533 744 | m 730 10253 745 | m 731 31137 746 | m 732 29270 747 | m 733 3156 748 | m 734 30474 749 | m 735 29353 750 | m 736 25015 751 | m 737 22068 752 | m 738 7577 753 | m 739 26721 754 | m 740 20204 755 | m 741 32702 756 | m 742 12225 757 | m 743 16492 758 | m 744 10727 759 | m 745 1511 760 | m 746 7559 761 | m 747 7789 762 | m 748 9902 763 | m 749 10381 764 | m 750 16863 765 | m 751 20103 766 | m 752 14887 767 | m 753 25745 768 | m 754 5488 769 | m 755 28907 770 | m 756 27198 771 | m 757 4732 772 | m 758 4811 773 | m 759 27599 774 | m 760 26112 775 | m 761 16579 776 | m 762 21786 777 | m 763 22575 778 | m 764 30923 779 | m 765 24226 780 | m 766 31241 781 | m 767 28063 782 | m 768 2849 783 | m 769 21953 784 | m 770 2993 785 | m 771 18732 786 | m 772 1450 787 | m 773 30976 788 | m 774 187 789 | m 775 5357 790 | m 776 2008 791 | m 777 7996 792 | m 778 12266 793 | m 779 27757 794 | m 780 30201 795 | m 781 21515 796 | m 782 17185 797 | m 783 24146 798 | m 784 1205 799 | m 785 16788 800 | m 786 7074 801 | m 787 19649 802 | m 788 17446 803 | m 789 10202 804 | m 790 23616 805 | m 791 10993 806 | m 792 16612 807 | m 793 18908 808 | m 794 10685 809 | m 795 19547 810 | m 796 32191 811 | m 797 10881 812 | m 798 4631 813 | m 799 24216 814 | m 800 456 815 | m 801 9196 816 | m 802 4730 817 | m 803 11585 818 | m 804 5637 819 | m 805 21018 820 | m 806 23874 821 | m 807 12376 822 | m 808 32303 823 | m 809 16429 824 | m 810 381 825 | m 811 15391 826 | m 812 12599 827 | m 813 10367 828 | m 814 20528 829 | m 815 14545 830 | m 816 11224 831 | m 817 5666 832 | m 818 17489 833 | m 819 9966 834 | m 820 28683 835 | m 821 1669 836 | m 822 3762 837 | m 823 32636 838 | m 824 18512 839 | m 825 8164 840 | m 826 20103 841 | m 827 1587 842 | m 828 7733 843 | m 829 15580 844 | m 830 9382 845 | m 831 17075 846 | m 832 30179 847 | m 833 13534 848 | m 834 30082 849 | m 835 15902 850 | m 836 10891 851 | m 837 8098 852 | m 838 24768 853 | m 839 2649 854 | m 840 27186 855 | m 841 14188 856 | m 842 19805 857 | m 843 9172 858 | m 844 14484 859 | m 845 5102 860 | m 846 4365 861 | m 847 7262 862 | m 848 29899 863 | m 849 22184 864 | m 850 23818 865 | m 851 27733 866 | m 852 23515 867 | m 853 2461 868 | m 854 19978 869 | m 855 6390 870 | m 856 29896 871 | m 857 9378 872 | m 858 4802 873 | m 859 7358 874 | m 860 87 875 | m 861 306 876 | m 862 12212 877 | m 863 29369 878 | m 864 28296 879 | m 865 17102 880 | m 866 28574 881 | m 867 2305 882 | m 868 17013 883 | m 869 5167 884 | m 870 18446 885 | m 871 7507 886 | m 872 27596 887 | m 873 18509 888 | m 874 27110 889 | m 875 9013 890 | m 876 32281 891 | m 877 23762 892 | m 878 6036 893 | m 879 6223 894 | m 880 31873 895 | m 881 8085 896 | m 882 10298 897 | m 883 6367 898 | m 884 1519 899 | m 885 15711 900 | m 886 19781 901 | m 887 2461 902 | m 888 24873 903 | m 889 23765 904 | m 890 12961 905 | m 891 2707 906 | m 892 17761 907 | m 893 9161 908 | m 894 29367 909 | m 895 26913 910 | m 896 13890 911 | m 897 14578 912 | m 898 12589 913 | m 899 3368 914 | m 900 22171 915 | m 901 29938 916 | m 902 29096 917 | m 903 511 918 | m 904 3934 919 | m 905 5134 920 | m 906 23373 921 | m 907 10348 922 | m 908 31609 923 | m 909 624 924 | m 910 6336 925 | m 911 1183 926 | m 912 4112 927 | m 913 4999 928 | m 914 7032 929 | m 915 30935 930 | m 916 2556 931 | m 917 3867 932 | m 918 14082 933 | m 919 25928 934 | m 920 25608 935 | m 921 32205 936 | m 922 20248 937 | m 923 13228 938 | m 924 30646 939 | m 925 30577 940 | m 926 15780 941 | m 927 4372 942 | m 928 28848 943 | m 929 25431 944 | m 930 3942 945 | m 931 32583 946 | m 932 8772 947 | m 933 12633 948 | m 934 1862 949 | m 935 14218 950 | m 936 27210 951 | m 937 11917 952 | m 938 14398 953 | m 939 4756 954 | m 940 28709 955 | m 941 6152 956 | m 942 29361 957 | m 943 31964 958 | m 944 28316 959 | m 945 23068 960 | m 946 8890 961 | m 947 2730 962 | m 948 13878 963 | m 949 8783 964 | m 950 866 965 | m 951 5922 966 | m 952 15764 967 | m 953 27206 968 | m 954 13617 969 | m 955 23293 970 | m 956 21181 971 | m 957 32065 972 | m 958 14118 973 | m 959 21960 974 | m 960 28338 975 | m 961 8295 976 | m 962 20943 977 | m 963 6197 978 | m 964 21748 979 | m 965 29401 980 | m 966 17331 981 | m 967 16696 982 | m 968 25488 983 | m 969 5160 984 | m 970 22326 985 | m 971 7260 986 | m 972 26350 987 | m 973 20016 988 | m 974 14981 989 | m 975 13145 990 | m 976 17993 991 | m 977 8675 992 | m 978 20368 993 | m 979 5324 994 | m 980 24521 995 | m 981 13933 996 | m 982 13676 997 | m 983 22023 998 | m 984 0 999 | m 985 8283 1000 | m 986 21972 1001 | m 987 1700 1002 | m 988 13082 1003 | m 989 12509 1004 | m 990 12508 1005 | m 991 17730 1006 | m 992 10825 1007 | m 993 8975 1008 | m 994 19023 1009 | m 995 3837 1010 | m 996 4876 1011 | m 997 5920 1012 | m 998 22255 1013 | m 999 26568 1014 | m 1000 10362 1015 | m 1001 4099 1016 | m 1002 21345 1017 | m 1003 10666 1018 | m 1004 139 1019 | m 1005 26115 1020 | m 1006 24858 1021 | m 1007 30984 1022 | m 1008 3236 1023 | m 1009 6244 1024 | m 1010 26198 1025 | m 1011 15268 1026 | m 1012 19086 1027 | m 1013 25533 1028 | m 1014 14948 1029 | m 1015 11889 1030 | m 1016 32659 1031 | m 1017 7592 1032 | m 1018 3401 1033 | m 1019 14577 1034 | m 1020 31637 1035 | m 1021 7397 1036 | m 1022 1923 1037 | m 1023 16631 1038 | m 1024 14387 1039 | m 1025 11665 1040 | m 1026 12263 1041 | m 1027 30505 1042 | m 1028 12893 1043 | m 1029 1637 1044 | m 1030 24707 1045 | m 1031 26260 1046 | m 1032 1319 1047 | m 1033 17430 1048 | m 1034 2896 1049 | m 1035 25602 1050 | m 1036 24117 1051 | m 1037 3742 1052 | m 1038 16087 1053 | m 1039 8481 1054 | m 1040 5982 1055 | m 1041 16759 1056 | m 1042 9766 1057 | m 1043 13817 1058 | m 1044 7463 1059 | m 1045 9662 1060 | m 1046 2932 1061 | m 1047 7550 1062 | m 1048 25034 1063 | m 1049 17701 1064 | m 1050 14644 1065 | m 1051 15321 1066 | m 1052 22036 1067 | m 1053 25731 1068 | m 1054 3117 1069 | m 1055 27497 1070 | m 1056 25931 1071 | m 1057 24318 1072 | m 1058 9941 1073 | m 1059 27551 1074 | m 1060 19665 1075 | m 1061 21381 1076 | m 1062 23352 1077 | m 1063 29840 1078 | m 1064 19885 1079 | m 1065 16344 1080 | m 1066 9883 1081 | m 1067 17260 1082 | m 1068 3480 1083 | m 1069 12529 1084 | m 1070 8270 1085 | m 1071 1697 1086 | m 1072 26461 1087 | m 1073 16039 1088 | m 1074 28917 1089 | m 1075 6375 1090 | m 1076 6394 1091 | m 1077 25969 1092 | m 1078 24267 1093 | m 1079 31742 1094 | m 1080 6697 1095 | m 1081 6844 1096 | m 1082 26006 1097 | m 1083 31060 1098 | m 1084 8063 1099 | m 1085 30094 1100 | m 1086 23953 1101 | m 1087 31444 1102 | m 1088 32271 1103 | m 1089 5087 1104 | m 1090 14758 1105 | m 1091 23100 1106 | m 1092 20849 1107 | m 1093 23916 1108 | m 1094 29748 1109 | m 1095 4998 1110 | m 1096 27938 1111 | m 1097 1910 1112 | m 1098 26890 1113 | m 1099 20712 1114 | m 1100 28818 1115 | m 1101 16088 1116 | m 1102 28636 1117 | m 1103 4323 1118 | m 1104 26232 1119 | m 1105 32370 1120 | m 1106 6460 1121 | m 1107 29068 1122 | m 1108 22033 1123 | m 1109 3414 1124 | m 1110 5663 1125 | m 1111 2712 1126 | m 1112 3899 1127 | m 1113 30731 1128 | m 1114 17269 1129 | m 1115 26161 1130 | m 1116 16238 1131 | m 1117 26949 1132 | m 1118 15817 1133 | m 1119 26703 1134 | m 1120 17314 1135 | m 1121 20819 1136 | m 1122 10354 1137 | m 1123 4191 1138 | m 1124 3073 1139 | m 1125 16649 1140 | m 1126 23104 1141 | m 1127 17048 1142 | m 1128 9681 1143 | m 1129 24727 1144 | m 1130 5380 1145 | m 1131 25513 1146 | m 1132 7450 1147 | m 1133 22378 1148 | m 1134 653 1149 | m 1135 6097 1150 | m 1136 12223 1151 | m 1137 26051 1152 | m 1138 5162 1153 | m 1139 25050 1154 | m 1140 12902 1155 | m 1141 26303 1156 | m 1142 16248 1157 | m 1143 25527 1158 | m 1144 8446 1159 | m 1145 9463 1160 | m 1146 24485 1161 | m 1147 27776 1162 | m 1148 32303 1163 | m 1149 16985 1164 | m 1150 1770 1165 | m 1151 28391 1166 | m 1152 9153 1167 | m 1153 26967 1168 | m 1154 3638 1169 | m 1155 12765 1170 | m 1156 14496 1171 | m 1157 6823 1172 | m 1158 433 1173 | m 1159 11572 1174 | m 1160 14766 1175 | m 1161 24669 1176 | m 1162 1068 1177 | m 1163 27765 1178 | m 1164 13935 1179 | m 1165 20639 1180 | m 1166 9681 1181 | m 1167 29824 1182 | m 1168 2724 1183 | m 1169 5491 1184 | m 1170 17131 1185 | m 1171 27311 1186 | m 1172 5796 1187 | m 1173 1857 1188 | m 1174 25319 1189 | m 1175 25336 1190 | m 1176 12280 1191 | m 1177 23519 1192 | m 1178 7729 1193 | m 1179 24447 1194 | m 1180 16804 1195 | m 1181 5526 1196 | m 1182 15073 1197 | m 1183 12102 1198 | m 1184 23776 1199 | m 1185 2735 1200 | m 1186 9003 1201 | m 1187 26202 1202 | m 1188 19705 1203 | m 1189 337 1204 | m 1190 29928 1205 | m 1191 27900 1206 | m 1192 7855 1207 | m 1193 30011 1208 | m 1194 3932 1209 | m 1195 31046 1210 | m 1196 2382 1211 | m 1197 8149 1212 | m 1198 27855 1213 | m 1199 7167 1214 | m 1200 8107 1215 | m 1201 8734 1216 | m 1202 3139 1217 | m 1203 13877 1218 | m 1204 22434 1219 | m 1205 26381 1220 | m 1206 3053 1221 | m 1207 10627 1222 | m 1208 24972 1223 | m 1209 17726 1224 | m 1210 28313 1225 | m 1211 1107 1226 | m 1212 6113 1227 | m 1213 20261 1228 | m 1214 9005 1229 | m 1215 334 1230 | m 1216 19770 1231 | m 1217 17377 1232 | m 1218 32717 1233 | m 1219 7280 1234 | m 1220 13393 1235 | m 1221 22381 1236 | m 1222 18241 1237 | m 1223 5142 1238 | m 1224 16399 1239 | m 1225 19105 1240 | m 1226 4445 1241 | m 1227 9061 1242 | m 1228 25962 1243 | m 1229 19836 1244 | m 1230 2042 1245 | m 1231 15332 1246 | m 1232 13916 1247 | m 1233 25267 1248 | m 1234 3827 1249 | m 1235 7204 1250 | m 1236 12835 1251 | m 1237 8851 1252 | m 1238 30152 1253 | m 1239 14290 1254 | m 1240 15598 1255 | m 1241 18471 1256 | m 1242 4983 1257 | m 1243 31415 1258 | m 1244 11865 1259 | m 1245 4447 1260 | m 1246 8744 1261 | m 1247 30354 1262 | m 1248 4089 1263 | m 1249 11690 1264 | m 1250 5580 1265 | m 1251 13937 1266 | m 1252 18403 1267 | m 1253 8642 1268 | m 1254 32459 1269 | m 1255 24814 1270 | m 1256 23117 1271 | m 1257 8874 1272 | m 1258 20845 1273 | m 1259 1901 1274 | m 1260 10868 1275 | m 1261 25101 1276 | m 1262 27723 1277 | m 1263 14814 1278 | m 1264 20811 1279 | m 1265 4894 1280 | m 1266 16846 1281 | m 1267 29817 1282 | m 1268 16917 1283 | m 1269 31200 1284 | m 1270 5007 1285 | m 1271 16203 1286 | m 1272 1350 1287 | m 1273 20528 1288 | m 1274 7730 1289 | m 1275 28094 1290 | m 1276 23498 1291 | m 1277 11964 1292 | m 1278 17943 1293 | m 1279 8320 1294 | m 1280 29075 1295 | m 1281 31583 1296 | m 1282 12232 1297 | m 1283 1177 1298 | m 1284 2128 1299 | m 1285 21064 1300 | m 1286 31959 1301 | m 1287 16932 1302 | m 1288 25755 1303 | m 1289 1094 1304 | m 1290 13020 1305 | m 1291 11449 1306 | m 1292 17220 1307 | m 1293 21378 1308 | m 1294 6979 1309 | m 1295 1124 1310 | m 1296 25619 1311 | m 1297 11025 1312 | m 1298 1373 1313 | m 1299 7351 1314 | m 1300 18284 1315 | m 1301 11858 1316 | m 1302 16810 1317 | m 1303 103 1318 | m 1304 9501 1319 | m 1305 15811 1320 | m 1306 26075 1321 | m 1307 19348 1322 | m 1308 1213 1323 | m 1309 7555 1324 | m 1310 3573 1325 | m 1311 28356 1326 | m 1312 8114 1327 | m 1313 3272 1328 | m 1314 12572 1329 | m 1315 20351 1330 | m 1316 10115 1331 | m 1317 15355 1332 | m 1318 25229 1333 | m 1319 14680 1334 | m 1320 31076 1335 | m 1321 5421 1336 | m 1322 29544 1337 | m 1323 21851 1338 | m 1324 22599 1339 | m 1325 20581 1340 | m 1326 14829 1341 | m 1327 4745 1342 | m 1328 1643 1343 | m 1329 26233 1344 | m 1330 16914 1345 | m 1331 17171 1346 | m 1332 8807 1347 | m 1333 12809 1348 | m 1334 779 1349 | m 1335 26010 1350 | m 1336 25642 1351 | m 1337 6646 1352 | m 1338 5322 1353 | m 1339 1188 1354 | m 1340 23679 1355 | m 1341 5843 1356 | m 1342 10064 1357 | m 1343 7813 1358 | m 1344 22581 1359 | m 1345 13442 1360 | m 1346 29601 1361 | m 1347 31928 1362 | m 1348 7143 1363 | m 1349 6953 1364 | m 1350 15772 1365 | m 1351 19997 1366 | m 1352 26200 1367 | m 1353 15748 1368 | m 1354 13251 1369 | m 1355 31601 1370 | m 1356 25447 1371 | m 1357 12223 1372 | m 1358 9945 1373 | m 1359 6220 1374 | m 1360 15840 1375 | m 1361 25870 1376 | m 1362 13825 1377 | m 1363 6621 1378 | m 1364 7733 1379 | m 1365 16939 1380 | m 1366 14307 1381 | m 1367 7513 1382 | m 1368 25123 1383 | m 1369 2601 1384 | m 1370 13163 1385 | m 1371 26927 1386 | m 1372 10334 1387 | m 1373 16976 1388 | m 1374 20585 1389 | m 1375 21032 1390 | m 1376 24132 1391 | m 1377 18000 1392 | m 1378 27413 1393 | m 1379 20531 1394 | m 1380 27952 1395 | m 1381 8108 1396 | m 1382 30592 1397 | m 1383 10635 1398 | m 1384 5777 1399 | m 1385 11556 1400 | m 1386 20390 1401 | m 1387 13846 1402 | m 1388 1017 1403 | m 1389 24892 1404 | m 1390 10886 1405 | m 1391 19954 1406 | m 1392 22376 1407 | m 1393 2712 1408 | m 1394 14965 1409 | m 1395 30308 1410 | m 1396 21374 1411 | m 1397 335 1412 | m 1398 30625 1413 | m 1399 4268 1414 | m 1400 16545 1415 | m 1401 16591 1416 | m 1402 27774 1417 | m 1403 18628 1418 | m 1404 26678 1419 | m 1405 15197 1420 | m 1406 2603 1421 | m 1407 10788 1422 | m 1408 20581 1423 | m 1409 20097 1424 | m 1410 2048 1425 | m 1411 30771 1426 | m 1412 30570 1427 | m 1413 2883 1428 | m 1414 5395 1429 | m 1415 20061 1430 | m 1416 31164 1431 | m 1417 14786 1432 | m 1418 10503 1433 | m 1419 9788 1434 | m 1420 17515 1435 | m 1421 708 1436 | m 1422 5963 1437 | m 1423 28772 1438 | m 1424 24576 1439 | m 1425 12669 1440 | m 1426 12022 1441 | m 1427 14091 1442 | m 1428 13652 1443 | m 1429 15819 1444 | m 1430 31871 1445 | m 1431 12689 1446 | m 1432 10100 1447 | m 1433 19510 1448 | m 1434 8332 1449 | m 1435 27865 1450 | m 1436 20643 1451 | m 1437 14653 1452 | m 1438 3945 1453 | m 1439 22176 1454 | m 1440 22378 1455 | m 1441 11483 1456 | m 1442 5190 1457 | m 1443 11187 1458 | m 1444 1597 1459 | m 1445 14769 1460 | m 1446 20639 1461 | m 1447 4421 1462 | m 1448 30755 1463 | m 1449 28258 1464 | m 1450 26041 1465 | m 1451 30605 1466 | m 1452 24956 1467 | m 1453 8020 1468 | m 1454 28261 1469 | m 1455 23727 1470 | m 1456 9411 1471 | m 1457 11916 1472 | m 1458 31737 1473 | m 1459 10016 1474 | m 1460 20890 1475 | m 1461 31497 1476 | m 1462 15990 1477 | m 1463 16875 1478 | m 1464 15461 1479 | m 1465 15964 1480 | m 1466 2698 1481 | m 1467 7206 1482 | m 1468 13255 1483 | m 1469 3323 1484 | m 1470 27110 1485 | m 1471 6038 1486 | m 1472 500 1487 | m 1473 31058 1488 | m 1474 12584 1489 | m 1475 18258 1490 | m 1476 27105 1491 | m 1477 15799 1492 | m 1478 26368 1493 | m 1479 22174 1494 | m 1480 22088 1495 | m 1481 15462 1496 | m 1482 27995 1497 | m 1483 1512 1498 | m 1484 22544 1499 | m 1485 16935 1500 | m 1486 11259 1501 | m 1487 2575 1502 | m 1488 7713 1503 | m 1489 8998 1504 | m 1490 15054 1505 | m 1491 18565 1506 | m 1492 5690 1507 | m 1493 23817 1508 | m 1494 12793 1509 | m 1495 23615 1510 | m 1496 25423 1511 | m 1497 949 1512 | m 1498 25365 1513 | m 1499 231 1514 | m 1500 19922 1515 | m 1501 17194 1516 | m 1502 14871 1517 | m 1503 19616 1518 | m 1504 10775 1519 | m 1505 24022 1520 | m 1506 11407 1521 | m 1507 26086 1522 | m 1508 243 1523 | m 1509 4189 1524 | m 1510 30169 1525 | m 1511 1506 1526 | m 1512 16781 1527 | m 1513 17521 1528 | m 1514 24533 1529 | m 1515 17179 1530 | m 1516 18107 1531 | m 1517 12729 1532 | m 1518 4276 1533 | m 1519 22785 1534 | m 1520 4146 1535 | m 1521 27106 1536 | m 1522 10334 1537 | m 1523 23338 1538 | m 1524 22483 1539 | m 1525 30903 1540 | m 1526 15409 1541 | m 1527 29694 1542 | m 1528 18255 1543 | m 1529 21704 1544 | m 1530 14748 1545 | m 1531 18133 1546 | m 1532 28189 1547 | m 1533 28200 1548 | m 1534 11084 1549 | m 1535 3605 1550 | m 1536 8277 1551 | m 1537 21146 1552 | m 1538 9952 1553 | m 1539 31536 1554 | m 1540 9867 1555 | m 1541 32 1556 | m 1542 27468 1557 | m 1543 21540 1558 | m 1544 7450 1559 | m 1545 21906 1560 | m 1546 32453 1561 | m 1547 28582 1562 | m 1548 14968 1563 | m 1549 16492 1564 | m 1550 8933 1565 | m 1551 6631 1566 | m 1552 9262 1567 | m 1553 29404 1568 | m 1554 21657 1569 | m 1555 4430 1570 | m 1556 17420 1571 | m 1557 10241 1572 | m 1558 4409 1573 | m 1559 15672 1574 | m 1560 11057 1575 | m 1561 19775 1576 | m 1562 29142 1577 | m 1563 12505 1578 | m 1564 9490 1579 | m 1565 21260 1580 | m 1566 14721 1581 | m 1567 22037 1582 | m 1568 14392 1583 | m 1569 8557 1584 | m 1570 15213 1585 | m 1571 4513 1586 | m 1572 7855 1587 | m 1573 10290 1588 | m 1574 27587 1589 | m 1575 28082 1590 | m 1576 32141 1591 | m 1577 23473 1592 | m 1578 31482 1593 | m 1579 17022 1594 | m 1580 4330 1595 | m 1581 3690 1596 | m 1582 23839 1597 | m 1583 10639 1598 | m 1584 31252 1599 | m 1585 16552 1600 | m 1586 28841 1601 | m 1587 2558 1602 | m 1588 6554 1603 | m 1589 30263 1604 | m 1590 16183 1605 | m 1591 17635 1606 | m 1592 21355 1607 | m 1593 12527 1608 | m 1594 15172 1609 | m 1595 621 1610 | m 1596 22909 1611 | m 1597 18957 1612 | m 1598 14620 1613 | m 1599 24644 1614 | m 1600 7474 1615 | m 1601 26814 1616 | m 1602 7398 1617 | m 1603 29770 1618 | m 1604 26258 1619 | m 1605 11605 1620 | m 1606 26144 1621 | m 1607 31793 1622 | m 1608 1707 1623 | m 1609 27106 1624 | m 1610 30571 1625 | m 1611 16804 1626 | m 1612 9793 1627 | m 1613 12463 1628 | m 1614 13025 1629 | m 1615 4012 1630 | m 1616 28281 1631 | m 1617 31934 1632 | m 1618 21925 1633 | m 1619 19303 1634 | m 1620 5956 1635 | m 1621 4516 1636 | m 1622 23249 1637 | m 1623 27772 1638 | m 1624 334 1639 | m 1625 14237 1640 | m 1626 19743 1641 | m 1627 26661 1642 | m 1628 27708 1643 | m 1629 31312 1644 | m 1630 20924 1645 | m 1631 18647 1646 | m 1632 21320 1647 | m 1633 22299 1648 | m 1634 19130 1649 | m 1635 2567 1650 | m 1636 28452 1651 | m 1637 23428 1652 | m 1638 23332 1653 | m 1639 20563 1654 | m 1640 6103 1655 | m 1641 12344 1656 | m 1642 22372 1657 | m 1643 30282 1658 | m 1644 3230 1659 | m 1645 4318 1660 | m 1646 4877 1661 | m 1647 24546 1662 | m 1648 8805 1663 | m 1649 13938 1664 | m 1650 2468 1665 | m 1651 313 1666 | m 1652 21532 1667 | m 1653 5767 1668 | m 1654 31085 1669 | m 1655 3110 1670 | m 1656 16503 1671 | m 1657 22985 1672 | m 1658 10154 1673 | m 1659 6673 1674 | m 1660 25293 1675 | m 1661 12600 1676 | m 1662 23184 1677 | m 1663 11763 1678 | m 1664 18856 1679 | m 1665 27575 1680 | m 1666 24523 1681 | m 1667 7799 1682 | m 1668 13300 1683 | m 1669 26818 1684 | m 1670 18616 1685 | m 1671 10715 1686 | m 1672 29353 1687 | m 1673 30066 1688 | m 1674 18785 1689 | m 1675 12756 1690 | m 1676 27758 1691 | m 1677 17460 1692 | m 1678 27429 1693 | m 1679 356 1694 | m 1680 3330 1695 | m 1681 14046 1696 | m 1682 22678 1697 | m 1683 2330 1698 | m 1684 5963 1699 | m 1685 27087 1700 | m 1686 9295 1701 | m 1687 17972 1702 | m 1688 3874 1703 | m 1689 2743 1704 | m 1690 13659 1705 | m 1691 10012 1706 | m 1692 15523 1707 | m 1693 1679 1708 | m 1694 16597 1709 | m 1695 7201 1710 | m 1696 21295 1711 | m 1697 24449 1712 | m 1698 13831 1713 | m 1699 3189 1714 | m 1700 30498 1715 | m 1701 28935 1716 | m 1702 2964 1717 | m 1703 17786 1718 | m 1704 28548 1719 | m 1705 20433 1720 | m 1706 18955 1721 | m 1707 22814 1722 | m 1708 26254 1723 | m 1709 4133 1724 | m 1710 31544 1725 | m 1711 15371 1726 | m 1712 7841 1727 | m 1713 32316 1728 | m 1714 17596 1729 | m 1715 20194 1730 | m 1716 22838 1731 | m 1717 28935 1732 | m 1718 11483 1733 | m 1719 27312 1734 | m 1720 26647 1735 | m 1721 19825 1736 | m 1722 16640 1737 | m 1723 28296 1738 | m 1724 15801 1739 | m 1725 31963 1740 | m 1726 4960 1741 | m 1727 5342 1742 | m 1728 911 1743 | m 1729 14413 1744 | m 1730 23360 1745 | m 1731 32704 1746 | m 1732 17435 1747 | m 1733 30617 1748 | m 1734 30131 1749 | m 1735 17831 1750 | m 1736 23949 1751 | m 1737 29609 1752 | m 1738 4568 1753 | m 1739 12868 1754 | m 1740 17019 1755 | m 1741 9321 1756 | m 1742 9075 1757 | m 1743 5119 1758 | m 1744 27052 1759 | m 1745 21824 1760 | m 1746 31573 1761 | m 1747 14615 1762 | m 1748 21598 1763 | m 1749 28398 1764 | m 1750 26890 1765 | m 1751 5666 1766 | m 1752 5335 1767 | m 1753 28177 1768 | m 1754 16211 1769 | m 1755 2616 1770 | m 1756 26483 1771 | m 1757 24219 1772 | m 1758 5493 1773 | m 1759 17337 1774 | m 1760 14290 1775 | m 1761 29058 1776 | m 1762 14943 1777 | m 1763 27951 1778 | m 1764 21939 1779 | m 1765 6007 1780 | m 1766 14011 1781 | m 1767 14764 1782 | m 1768 26865 1783 | m 1769 22149 1784 | m 1770 21237 1785 | m 1771 21638 1786 | m 1772 16811 1787 | m 1773 19948 1788 | m 1774 26723 1789 | m 1775 32045 1790 | m 1776 19714 1791 | m 1777 21366 1792 | m 1778 10414 1793 | m 1779 19333 1794 | m 1780 11131 1795 | m 1781 16401 1796 | m 1782 23547 1797 | m 1783 28643 1798 | m 1784 11205 1799 | m 1785 18039 1800 | m 1786 17471 1801 | m 1787 12562 1802 | m 1788 16403 1803 | m 1789 21578 1804 | m 1790 21027 1805 | m 1791 8255 1806 | m 1792 7235 1807 | m 1793 4883 1808 | m 1794 27818 1809 | m 1795 7526 1810 | m 1796 18315 1811 | m 1797 12614 1812 | m 1798 10678 1813 | m 1799 4449 1814 | m 1800 13743 1815 | m 1801 31793 1816 | m 1802 3216 1817 | m 1803 30379 1818 | m 1804 21964 1819 | m 1805 21917 1820 | m 1806 20777 1821 | m 1807 31298 1822 | m 1808 8358 1823 | m 1809 7906 1824 | m 1810 17119 1825 | m 1811 21045 1826 | m 1812 18967 1827 | m 1813 11614 1828 | m 1814 13527 1829 | m 1815 19487 1830 | m 1816 10854 1831 | m 1817 4364 1832 | m 1818 23734 1833 | m 1819 24193 1834 | m 1820 119 1835 | m 1821 5905 1836 | m 1822 24594 1837 | m 1823 20086 1838 | m 1824 25104 1839 | m 1825 6155 1840 | m 1826 11233 1841 | m 1827 21508 1842 | m 1828 26122 1843 | m 1829 12826 1844 | m 1830 803 1845 | m 1831 7262 1846 | m 1832 31134 1847 | m 1833 5341 1848 | m 1834 23662 1849 | m 1835 23114 1850 | m 1836 17191 1851 | m 1837 19089 1852 | m 1838 5785 1853 | m 1839 19906 1854 | m 1840 13233 1855 | m 1841 25139 1856 | m 1842 3033 1857 | m 1843 24045 1858 | m 1844 30532 1859 | m 1845 16667 1860 | m 1846 27653 1861 | m 1847 30553 1862 | m 1848 3898 1863 | m 1849 19542 1864 | m 1850 13166 1865 | m 1851 32197 1866 | m 1852 4313 1867 | m 1853 21465 1868 | m 1854 2439 1869 | m 1855 6923 1870 | m 1856 32175 1871 | m 1857 8318 1872 | m 1858 23929 1873 | m 1859 17982 1874 | m 1860 14354 1875 | m 1861 21596 1876 | m 1862 9481 1877 | m 1863 30660 1878 | m 1864 31009 1879 | m 1865 27389 1880 | m 1866 9327 1881 | m 1867 31796 1882 | m 1868 27319 1883 | m 1869 11546 1884 | m 1870 14409 1885 | m 1871 17896 1886 | m 1872 16329 1887 | m 1873 22525 1888 | m 1874 23856 1889 | m 1875 8005 1890 | m 1876 8372 1891 | m 1877 10970 1892 | m 1878 27820 1893 | m 1879 18706 1894 | m 1880 26053 1895 | m 1881 6626 1896 | m 1882 26969 1897 | m 1883 28146 1898 | m 1884 26158 1899 | m 1885 28344 1900 | m 1886 3542 1901 | m 1887 29958 1902 | m 1888 6153 1903 | m 1889 8827 1904 | m 1890 15057 1905 | m 1891 32558 1906 | m 1892 25360 1907 | m 1893 26257 1908 | m 1894 21478 1909 | m 1895 16343 1910 | m 1896 26014 1911 | m 1897 4727 1912 | m 1898 31672 1913 | m 1899 29940 1914 | m 1900 16732 1915 | m 1901 9619 1916 | m 1902 27365 1917 | m 1903 26864 1918 | m 1904 6798 1919 | m 1905 30396 1920 | m 1906 28880 1921 | m 1907 5727 1922 | m 1908 22764 1923 | m 1909 4509 1924 | m 1910 30614 1925 | m 1911 14370 1926 | m 1912 21250 1927 | m 1913 17555 1928 | m 1914 17667 1929 | m 1915 19500 1930 | m 1916 24441 1931 | m 1917 8737 1932 | m 1918 23399 1933 | m 1919 593 1934 | m 1920 7193 1935 | m 1921 23837 1936 | m 1922 16578 1937 | m 1923 12815 1938 | m 1924 11978 1939 | m 1925 3733 1940 | m 1926 22907 1941 | m 1927 7296 1942 | m 1928 14586 1943 | m 1929 13737 1944 | m 1930 9938 1945 | m 1931 20440 1946 | m 1932 2604 1947 | m 1933 24841 1948 | m 1934 7903 1949 | m 1935 227 1950 | m 1936 26099 1951 | m 1937 30141 1952 | m 1938 26265 1953 | m 1939 29417 1954 | m 1940 18246 1955 | m 1941 21587 1956 | m 1942 14689 1957 | m 1943 14666 1958 | m 1944 24269 1959 | m 1945 1469 1960 | m 1946 29928 1961 | m 1947 14807 1962 | m 1948 3410 1963 | m 1949 16664 1964 | m 1950 18747 1965 | m 1951 21208 1966 | m 1952 32351 1967 | m 1953 18808 1968 | m 1954 4175 1969 | m 1955 15005 1970 | m 1956 7876 1971 | m 1957 3342 1972 | m 1958 12144 1973 | m 1959 26594 1974 | m 1960 24373 1975 | m 1961 17535 1976 | m 1962 12079 1977 | m 1963 15633 1978 | m 1964 24968 1979 | m 1965 25839 1980 | m 1966 16416 1981 | m 1967 31369 1982 | m 1968 24668 1983 | m 1969 25288 1984 | m 1970 18393 1985 | m 1971 11281 1986 | m 1972 11872 1987 | m 1973 20666 1988 | m 1974 25608 1989 | m 1975 1278 1990 | m 1976 30398 1991 | m 1977 29304 1992 | m 1978 19154 1993 | m 1979 21926 1994 | m 1980 12766 1995 | m 1981 28401 1996 | m 1982 14752 1997 | m 1983 14582 1998 | m 1984 9194 1999 | m 1985 5104 2000 | m 1986 5172 2001 | m 1987 29025 2002 | m 1988 8192 2003 | m 1989 7700 2004 | m 1990 17959 2005 | m 1991 17862 2006 | m 1992 23091 2007 | m 1993 22483 2008 | m 1994 24135 2009 | m 1995 10472 2010 | m 1996 7777 2011 | m 1997 7824 2012 | m 1998 15326 2013 | m 1999 11013 2014 | m 2000 3047 2015 | m 2001 9806 2016 | m 2002 29745 2017 | m 2003 23836 2018 | m 2004 28629 2019 | m 2005 12254 2020 | m 2006 9857 2021 | m 2007 32122 2022 | m 2008 5351 2023 | m 2009 1399 2024 | m 2010 1307 2025 | m 2011 22636 2026 | m 2012 22994 2027 | m 2013 10734 2028 | m 2014 20681 2029 | m 2015 24422 2030 | m 2016 12047 2031 | m 2017 5509 2032 | m 2018 171 2033 | m 2019 4886 2034 | m 2020 11169 2035 | m 2021 497 2036 | m 2022 2959 2037 | m 2023 30878 2038 | m 2024 22243 2039 | m 2025 29083 2040 | m 2026 14434 2041 | m 2027 19447 2042 | m 2028 439 2043 | m 2029 18496 2044 | m 2030 29632 2045 | m 2031 31884 2046 | m 2032 29362 2047 | m 2033 12040 2048 | m 2034 17683 2049 | m 2035 30466 2050 | m 2036 12688 2051 | m 2037 4328 2052 | m 2038 11059 2053 | m 2039 11682 2054 | m 2040 30447 2055 | m 2041 23046 2056 | m 2042 25254 2057 | m 2043 12495 2058 | m 2044 27077 2059 | m 2045 3844 2060 | m 2046 2845 2061 | m 2047 14553 2062 | stop 2063 | stat 2064 | -------------------------------------------------------------------------------- /tests/demo.dmas: -------------------------------------------------------------------------------- 1 | # 2 | # Demo 3 | # 4 | 5 | dataseg 0x2000000 6 | heap implicit 7 | 8 | mode correctness 9 | 10 | log ds 1 11 | log mm 1 12 | 13 | start 14 | m 1 16 15 | m 2 50 16 | m 3 47 17 | m 4 48 18 | m 5 32 19 | m 6 1000 20 | m 7 10000 21 | v 22 | f 2 23 | f 5 24 | v 25 | m 5 40 26 | v 27 | m 2 40 28 | v 29 | f 6 30 | f 1 31 | f 2 32 | f 3 33 | f 5 34 | f 7 35 | v 36 | stop 37 | stat 38 | 39 | -------------------------------------------------------------------------------- /tests/ls.dmas: -------------------------------------------------------------------------------- 1 | # 2 | # memory allocations of executing ls -R 3 | # in the handout directory 4 | # 5 | 6 | dataseg 0x4000000 7 | heap implicit 8 | 9 | mode correctness 10 | 11 | log ds 1 12 | log mm 1 13 | 14 | start 15 | 16 | m 0 5 17 | f 0 18 | m 1 120 19 | m 2 11 20 | m 3 776 21 | m 4 112 22 | m 5 1336 23 | m 6 216 24 | m 7 432 25 | m 8 104 26 | m 9 88 27 | m 10 120 28 | m 11 168 29 | m 12 104 30 | m 13 80 31 | m 14 192 32 | m 15 11 33 | m 16 11 34 | m 17 11 35 | m 18 11 36 | m 19 11 37 | m 20 11 38 | m 21 11 39 | m 22 11 40 | m 23 11 41 | m 24 11 42 | m 25 11 43 | m 26 11 44 | m 27 11 45 | f -1 46 | f -1 47 | m 28 34 48 | m 29 10 49 | m 30 56 50 | m 31 56 51 | m 32 1656 52 | m 33 40 53 | m 34 40 54 | m 35 40 55 | m 36 40 56 | m 37 40 57 | m 38 40 58 | m 39 40 59 | m 40 40 60 | m 41 40 61 | m 42 40 62 | m 43 40 63 | m 44 40 64 | m 45 40 65 | m 46 40 66 | m 47 40 67 | m 48 40 68 | m 49 40 69 | m 50 40 70 | m 51 40 71 | m 52 40 72 | m 53 40 73 | m 54 40 74 | m 55 40 75 | m 56 40 76 | m 57 40 77 | m 58 40 78 | m 59 40 79 | m 60 40 80 | m 61 40 81 | m 62 40 82 | m 63 40 83 | m 64 40 84 | m 65 40 85 | m 66 40 86 | m 67 40 87 | m 68 40 88 | m 69 40 89 | m 70 40 90 | m 71 40 91 | m 72 40 92 | m 73 40 93 | m 74 40 94 | m 75 40 95 | m 76 40 96 | m 77 40 97 | m 78 40 98 | m 79 40 99 | m 80 40 100 | m 81 40 101 | m 82 40 102 | m 83 40 103 | m 84 40 104 | m 85 40 105 | m 86 40 106 | m 87 40 107 | m 88 40 108 | m 89 40 109 | m 90 40 110 | m 91 40 111 | m 92 40 112 | m 93 40 113 | m 94 40 114 | m 95 40 115 | m 96 40 116 | m 97 40 117 | m 98 40 118 | m 99 40 119 | m 100 40 120 | m 101 40 121 | m 102 40 122 | m 103 40 123 | m 104 40 124 | m 105 40 125 | m 106 40 126 | m 107 40 127 | m 108 40 128 | m 109 40 129 | m 110 40 130 | m 111 40 131 | m 112 40 132 | m 113 40 133 | m 114 40 134 | m 115 40 135 | m 116 40 136 | m 117 40 137 | m 118 40 138 | m 119 40 139 | m 120 40 140 | m 121 40 141 | m 122 40 142 | m 123 40 143 | m 124 40 144 | m 125 40 145 | m 126 40 146 | m 127 40 147 | m 128 40 148 | m 129 40 149 | m 130 40 150 | m 131 40 151 | m 132 40 152 | m 133 40 153 | m 134 40 154 | m 135 40 155 | m 136 40 156 | m 137 40 157 | m 138 40 158 | m 139 40 159 | m 140 40 160 | m 141 40 161 | m 142 40 162 | m 143 40 163 | m 144 40 164 | m 145 40 165 | m 146 40 166 | m 147 40 167 | m 148 40 168 | m 149 40 169 | m 150 40 170 | m 151 40 171 | m 152 40 172 | m 153 40 173 | m 154 40 174 | m 155 40 175 | m 156 128 176 | m 157 20000 177 | m 158 15 178 | f -1 179 | m 159 24 180 | m 160 32 181 | m 161 15 182 | f 158 183 | f -1 184 | f -1 185 | m 162 32816 186 | m 163 7 187 | m 164 9 188 | m 165 4 189 | m 166 10 190 | m 167 4 191 | m 168 6 192 | m 169 10 193 | f 162 194 | f 159 195 | m 170 168 196 | r 171 336 197 | m 172 840 198 | m 173 1024 199 | f 161 200 | f -1 201 | f 160 202 | f 173 203 | 204 | stop 205 | stat 206 | --------------------------------------------------------------------------------