Computer Systems: A Programmer's Perspective / Edition 2

Hardcover (Print)
Rent
Rent from BN.com
$26.81
(Save 82%)
Est. Return Date: 09/23/2014
Buy Used
Buy Used from BN.com
$90.76
(Save 39%)
Item is in good condition but packaging may have signs of shelf wear/aging or torn packaging.
Condition: Used – Good details
Used and New from Other Sellers
Used and New from Other Sellers
from $92.98
Usually ships in 1-2 business days
(Save 37%)
Other sellers (Hardcover)
  • All (95) from $92.98   
  • New (22) from $133.06   
  • Used (73) from $92.98   

Overview


For Computer Systems, Computer Organization and Architecture courses in CS, EE, and ECE departments.

Few students studying computer science or computer engineering will ever have the opportunity to build a computer system. On the other hand, most students will be required to use and program computers on a near daily basis. Computer Systems: A Programmer’s Perspective introduces the important and enduring concepts that underlie computer systems by showing how these ideas affect the correctness, performance, and utility of application programs. The text's hands-on approach (including a comprehensive set of labs) helps students understand the “under-the-hood” operation of a modern computer system and prepares them for future courses in systems topics such as compilers, computer architecture, operating systems, and networking.

Visit the CSS:AP web page http://csapp.cs.cmu.edu for more information and resources.

Read More Show Less

Product Details

  • ISBN-13: 9780136108047
  • Publisher: Addison-Wesley
  • Publication date: 2/19/2010
  • Series: Pearson Custom Computer Science Series
  • Edition number: 2
  • Pages: 1080
  • Sales rank: 184,515
  • Product dimensions: 7.50 (w) x 9.20 (h) x 1.60 (d)

Meet the Author

Randal E. Bryant received the Bachelor's degree from the University of Michigan in 1973 and then attended graduate school at the Massachusetts Institute of Technology, receiving the Ph.D. degree in computer science in 1981. He spent three years as an Assistant Professor at the California Institute of Technology and has been on the faculty at Carnegie Mellon since 1984. He is currently the President's Professor of Computer Science and head of the Department of Computer Science. He also holds a courtesy appointment with the Department of Electrical and Computer Engineering.

He has taught courses in computer systems at both the undergraduate and graduate level for over 20 years. Over many years of teaching computer architecture courses, he began shifting the focus from how computers are designed to one of how programmers can write more efficient and reliable programs if they understand the system better. Together with Prof. O'Hallaron, he developed the course "Introduction to Computer Systems" at Carnegie Mellon that is the basis for this book. He has also taught courses in algorithms and programming.

Prof. Bryant's research concerns the design of software tools to help hardware designers verify the correctness of their systems. These include several types of simulators, as well as formal verification tools that prove the correctness of a design using mathematical methods. He has published over 100 technical papers. His research results are used by major computer manufacturers including Intel, Motorola, IBM, and Fujitsu. He has won several major awards for his research. These include two inventor recognition awards and a technical achievement award from the Semiconductor Research Corporation, the Kanellakis Theory and Practice Award from the Association for Computer Machinery (ACM), and the W. R. G. Baker Award and a Golden Jubilee Medal from the Institute of Electrical and Electronics Engineers (IEEE). He is a Fellow of both the ACM and the IEEE.

David R. O'Hallaron received the Ph.D. degree in computer science from the University of Virginia in 1986. After a stint at General Electric, he joined the Carnegie Mellon faculty in 1989 as a Systems Scientist. He is currently an Associate Professor in the Departments of Computer Science and Electrical and Computer Engineering.

He has taught computer systems courses at the undergraduate and graduate levels, on such topics as computer architecture, introductory computer systems, parallel processor design, and Internet services. Together with Prof. Bryant, he developed the course "Introduction to Computer Systems" that is the basis for this book.

Prof. O'Hallaron and his students perform research in the area of computer -systems. In particular, they develop software systems to help scientists and engineers simulate nature on computers. The best known example of their work is the Quake project, a group of computer scientists, civil engineers, and seismologists who have developed the ability to predict the motion of the ground during strong earthquakes, including major quakes in Southern California, Kobe, Japan, Mexico, and New Zealand. Along with the other members of the Quake Project, he received the Allen Newell Medal for Research Excellence from the CMU School of Computer Science. A benchmark he developed for the Quake project, 183.equake, was selected by SPEC for inclusion in the influential SPEC CPU and OMP (Open MP) benchmark suites.

Read More Show Less

Table of Contents

Contents
Preface xv
1 A Tour of Computer Systems 1
1.1 Information is Bits + Context . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.2 Programs Are Translated by Other Programs into Different Forms . . . . . . . . . . . . . . 3
1.3 It Pays to Understand How Compilation Systems Work . . . . . . . . . . . . . . . . . . . . 5
1.4 Processors Read and Interpret Instructions Stored in Memory . . . . . . . . . . . . . . . . . 6
1.4.1 Hardware Organization of a System . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.4.2 Running the hello Program . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
1.5 Caches Matter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
1.6 Storage Devices Form a Hierarchy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
1.7 The Operating System Manages the Hardware . . . . . . . . . . . . . . . . . . . . . . . . . 12
1.7.1 Processes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
1.7.2 Threads . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
1.7.3 Virtual Memory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
1.7.4 Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
1.8 Systems Communicate With Other Systems Using Networks . . . . . . . . . . . . . . . . . 17
1.9 Important Themes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
1.9.1 Concurrency and Parallelism . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
1.9.2 The Importance of Abstractions in Computer Systems . . . . . . . . . . . . . . . . 22
1.10 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
I Program Structure and Execution 25
2 Representing and Manipulating Information 29
2.1 Information Storage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
2.1.1 Hexadecimal Notation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
2.1.2 Words . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
2.1.3 Data Sizes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
2.1.4 Addressing and Byte Ordering . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
2.1.5 Representing Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
2.1.6 Representing Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
2.1.7 Introduction to Boolean Algebra . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
2.1.8 Bit-Level Operations in C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
2.1.9 Logical Operations in C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
2.1.10 Shift Operations in C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
2.2 Integer Representations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
2.2.1 Integral Data Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
2.2.2 Unsigned Encodings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
2.2.3 Two’s Complement Encodings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
2.2.4 Conversions Between Signed and Unsigned . . . . . . . . . . . . . . . . . . . . . . 61
2.2.5 Signed vs. Unsigned in C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
2.2.6 Expanding the Bit Representation of a Number . . . . . . . . . . . . . . . . . . . . 67
2.2.7 Truncating Numbers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
2.2.8 Advice on Signed vs. Unsigned . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
2.3 Integer Arithmetic . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
2.3.1 Unsigned Addition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
2.3.2 Two’s-Complement Addition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
2.3.3 Two’s-Complement Negation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
2.3.4 Unsigned Multiplication . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
2.3.5 Two’s-Complement Multiplication . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
2.3.6 Multiplying by Constants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
2.3.7 Dividing by Powers of Two . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
2.3.8 Final Thoughts on Integer Arithmetic . . . . . . . . . . . . . . . . . . . . . . . . . 93
2.4 Floating Point . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
2.4.1 Fractional Binary Numbers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
2.4.2 IEEE Floating-Point Representation . . . . . . . . . . . . . . . . . . . . . . . . . . 97
2.4.3 Example Numbers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
2.4.4 Rounding . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104
2.4.5 Floating-Point Operations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
2.4.6 Floating Point in C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108
2.5 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110
3 Machine-Level Representation of Programs 145
3.1 A Historical Perspective . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147
3.2 Program Encodings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150
3.2.1 Machine-Level Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151
3.2.2 Code Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152
3.2.3 Notes on Formatting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155
3.3 Data Formats . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157
3.4 Accessing Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158
3.4.1 Operand Specifiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159
3.4.2 Data Movement Instructions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160
3.4.3 Data Movement Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164
3.5 Arithmetic and Logical Operations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 166
3.5.1 Load Effective Address . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167
3.5.2 Unary and Binary Operations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168
3.5.3 Shift Operations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169
3.5.4 Discussion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169
3.5.5 Special Arithmetic Operations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171
3.6 Control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173
3.6.1 Condition Codes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174
3.6.2 Accessing the Condition Codes . . . . . . . . . . . . . . . . . . . . . . . . . . . . 175
3.6.3 Jump Instructions and their Encodings . . . . . . . . . . . . . . . . . . . . . . . . . 177
3.6.4 Translating Conditional Branches . . . . . . . . . . . . . . . . . . . . . . . . . . . 181
3.6.5 Loops . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 184
3.6.6 Conditional Move Instructions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 194
3.6.7 Switch Statements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 203
3.7 Procedures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 206
3.7.1 Stack Frame Structure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 206
3.7.2 Transferring Control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 208
3.7.3 Register Usage Conventions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 210
3.7.4 Procedure Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 211
3.7.5 Recursive Procedures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 216
3.8 Array Allocation and Access . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 218
3.8.1 Basic Principles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 219
3.8.2 Pointer Arithmetic . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 220
3.8.3 Nested Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221
3.8.4 Fixed-Size Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 223
3.8.5 Variable-Size Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 225
3.9 Heterogeneous Data Structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 227
3.9.1 Structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 227
3.9.2 Unions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 230
3.9.3 Data Alignment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 234
3.10 Putting it Together: Understanding Pointers . . . . . . . . . . . . . . . . . . . . . . . . . . 237
3.11 Life in the Real World: Using the GDB Debugger . . . . . . . . . . . . . . . . . . . . . . . 239
3.12 Out-of-Bounds Memory References and Buffer Overflow . . . . . . . . . . . . . . . . . . . 241
3.12.1 Thwarting Buffer Overflow Attacks . . . . . . . . . . . . . . . . . . . . . . . . . . 246
3.13 x86-64: Extending IA32 to 64 Bits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 251
3.13.1 History and Motivation for x86-64 . . . . . . . . . . . . . . . . . . . . . . . . . . . 252
3.13.2 An Overview of x86-64 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 253
3.13.3 Accessing Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 256
3.13.4 Control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 262
3.13.5 Data Structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 273
3.13.6 Concluding Observations about x86-64 . . . . . . . . . . . . . . . . . . . . . . . . 274
3.14 Machine-Level Representations of Floating-Point Programs . . . . . . . . . . . . . . . . . . 274
3.15 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 275
4 Processor Architecture 317
4.1 The Y86 Instruction Set Architecture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 319
4.1.1 Programmer-Visible State . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 320
4.1.2 Y86 Instructions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 320
4.1.3 Instruction Encoding . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 322
4.1.4 Y86 Exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 326
4.1.5 Y86 Programs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 327
4.1.6 Some Y86 Instruction Details . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 332
4.2 Logic Design and the Hardware Control Language HCL . . . . . . . . . . . . . . . . . . . 334
4.2.1 Logic Gates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 335
4.2.2 Combinational Circuits and HCL Boolean Expressions . . . . . . . . . . . . . . . . 335
4.2.3 Word-Level Combinational Circuits and HCL Integer Expressions . . . . . . . . . . 337
4.2.4 Set Membership . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 341
4.2.5 Memory and Clocking . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 342
4.3 Sequential Y86 Implementations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 345
4.3.1 Organizing Processing into Stages . . . . . . . . . . . . . . . . . . . . . . . . . . . 345
4.3.2 SEQ Hardware Structure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 355
4.3.3 SEQ Timing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 359
4.3.4 SEQ Stage Implementations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 362
4.4 General Principles of Pipelining . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 370
4.4.1 Computational Pipelines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 370
4.4.2 A Detailed Look at Pipeline Operation . . . . . . . . . . . . . . . . . . . . . . . . . 372
4.4.3 Limitations of Pipelining . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 374
4.4.4 Pipelining a System with Feedback . . . . . . . . . . . . . . . . . . . . . . . . . . 376
4.5 Pipelined Y86 Implementations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 377
4.5.1 SEQ+: Rearranging the Computation Stages . . . . . . . . . . . . . . . . . . . . . 377
4.5.2 Inserting Pipeline Registers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 379
4.5.3 Rearranging and Relabeling Signals . . . . . . . . . . . . . . . . . . . . . . . . . . 383
4.5.4 Next PC Prediction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 384
4.5.5 Pipeline Hazards . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 386
4.5.6 Avoiding Data Hazards by Stalling . . . . . . . . . . . . . . . . . . . . . . . . . . . 391
4.5.7 Avoiding Data Hazards by Forwarding . . . . . . . . . . . . . . . . . . . . . . . . . 393
4.5.8 Load/Use Data Hazards . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 397
4.5.9 Exception Handling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 401
4.5.10 PIPE Stage Implementations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 403
4.5.11 Pipeline Control Logic . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 410
4.5.12 Performance Analysis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 422
4.5.13 Unfinished Business . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 424
4.6 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 426
4.6.1 Y86 Simulators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 428
5 Optimizing Program Performance 449
5.1 Capabilities and Limitations of Optimizing Compilers . . . . . . . . . . . . . . . . . . . . . 451
5.2 Expressing Program Performance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 454
5.3 Program Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 457
5.4 Eliminating Loop Inefficiencies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 460
5.5 Reducing Procedure Calls . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 466
5.6 Eliminating Unneeded Memory References . . . . . . . . . . . . . . . . . . . . . . . . . . 466
5.7 Understanding Modern Processors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 470
5.7.1 Overall Operation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 471
5.7.2 Functional Unit Performance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 474
5.7.3 An Abstract Model of Processor Operation . . . . . . . . . . . . . . . . . . . . . . 476
5.8 Loop Unrolling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 481
5.9 Enhancing Parallelism . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 486
5.9.1 Multiple Accumulators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 486
5.9.2 Reassociation Transformation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 491
5.10 Summary of Results for Optimizing Combining Code . . . . . . . . . . . . . . . . . . . . . 497
5.11 Some Limiting Factors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 498
5.11.1 Register Spilling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 498
5.11.2 Branch Prediction and Misprediction Penalties . . . . . . . . . . . . . . . . . . . . 499
5.12 Understanding Memory Performance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 503
5.12.1 Load Performance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 504
5.12.2 Store Performance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 505
5.13 Life in the Real World: Performance Improvement Techniques . . . . . . . . . . . . . . . . 511
5.14 Identifying and Eliminating Performance Bottlenecks . . . . . . . . . . . . . . . . . . . . . 512
5.14.1 Program Profiling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 512
5.14.2 Using a Profiler to Guide Optimization . . . . . . . . . . . . . . . . . . . . . . . . 514
5.14.3 Amdahl’s Law . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 518
5.15 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 519
6 The Memory Hierarchy 531
6.1 Storage Technologies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 532
6.1.1 Random-Access Memory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 532
6.1.2 Disk Storage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 539
6.1.3 Solid State Disks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 551
6.1.4 Storage Technology Trends . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 553
6.2 Locality . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 556
6.2.1 Locality of References to Program Data . . . . . . . . . . . . . . . . . . . . . . . . 557
6.2.2 Locality of Instruction Fetches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 559
6.2.3 Summary of Locality . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 559
6.3 The Memory Hierarchy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 560
6.3.1 Caching in the Memory Hierarchy . . . . . . . . . . . . . . . . . . . . . . . . . . . 562
6.3.2 Summary of Memory Hierarchy Concepts . . . . . . . . . . . . . . . . . . . . . . . 564
6.4 Cache Memories . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 565
6.4.1 Generic Cache Memory Organization . . . . . . . . . . . . . . . . . . . . . . . . . 566
6.4.2 Direct-Mapped Caches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 568
6.4.3 Set Associative Caches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 574
6.4.4 Fully Associative Caches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 576
6.4.5 Issues with Writes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 579
6.4.6 Anatomy of a Real Cache Hierarchy . . . . . . . . . . . . . . . . . . . . . . . . . . 580
6.4.7 Performance Impact of Cache Parameters . . . . . . . . . . . . . . . . . . . . . . . 581
6.5 Writing Cache-friendly Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 583
6.6 Putting it Together: The Impact of Caches on Program Performance . . . . . . . . . . . . . 588
6.6.1 The Memory Mountain . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 588
6.6.2 Rearranging Loops to Increase Spatial Locality . . . . . . . . . . . . . . . . . . . . 592
6.6.3 Exploiting Locality in Your Programs . . . . . . . . . . . . . . . . . . . . . . . . . 596
6.7 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 597
II Running Programs on a System 619
7 Linking 623
7.1 Compiler Drivers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 624
7.2 Static Linking . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 625
7.3 Object Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 626
7.4 Relocatable Object Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 627
7.5 Symbols and Symbol Tables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 628
7.6 Symbol Resolution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 631
7.6.1 How Linkers Resolve Multiply Defined Global Symbols . . . . . . . . . . . . . . . 632
7.6.2 Linking with Static Libraries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 635
7.6.3 How Linkers Use Static Libraries to Resolve References . . . . . . . . . . . . . . . 638
7.7 Relocation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 640
7.7.1 Relocation Entries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 640
7.7.2 Relocating Symbol References . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 641
7.8 Executable Object Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 645
7.9 Loading Executable Object Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 646
7.10 Dynamic Linking with Shared Libraries . . . . . . . . . . . . . . . . . . . . . . . . . . . . 648
7.11 Loading and Linking Shared Libraries from Applications . . . . . . . . . . . . . . . . . . . 650
7.12 *Position-Independent Code (PIC) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 653
7.13 Tools for Manipulating Object Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 656
7.14 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 656
8 Exceptional Control Flow 667
8.1 Exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 668
8.1.1 Exception Handling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 670
8.1.2 Classes of Exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 671
8.1.3 Exceptions in Linux/IA32 Systems . . . . . . . . . . . . . . . . . . . . . . . . . . 673
8.2 Processes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 677
8.2.1 Logical Control Flow . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 677
8.2.2 Concurrent Flows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 678
8.2.3 Private Address Space . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 679
8.2.4 User and Kernel Modes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 679
8.2.5 Context Switches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 681
8.3 System Call Error Handling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 682
8.4 Process Control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 683
8.4.1 Obtaining Process ID’s . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 683
8.4.2 Creating and Terminating Processes . . . . . . . . . . . . . . . . . . . . . . . . . . 684
8.4.3 Reaping Child Processes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 688
8.4.4 Putting Processes to Sleep . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 694
8.4.5 Loading and Running Programs . . . . . . . . . . . . . . . . . . . . . . . . . . . . 695
8.4.6 Using fork and execve to Run Programs . . . . . . . . . . . . . . . . . . . . . . 697
8.5 Signals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 701
8.5.1 Signal Terminology . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 701
8.5.2 Sending Signals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 703
8.5.3 Receiving Signals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 706
8.5.4 Signal Handling Issues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 710
8.5.5 Portable Signal Handling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 716
8.5.6 Explicitly Blocking and Unblocking Signals . . . . . . . . . . . . . . . . . . . . . . 717
8.5.7 Synchronizing Flows to Avoid Nasty Concurrency Bugs . . . . . . . . . . . . . . . 719
8.6 Nonlocal Jumps . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 721
8.7 Tools for Manipulating Processes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 727
8.8 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 727
9 Virtual Memory 741
9.1 Physical and Virtual Addressing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 742
9.2 Address Spaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 743
9.3 VM as a Tool for Caching . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 744
9.3.1 DRAM Cache Organization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 745
9.3.2 Page Tables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 745
9.3.3 Page Hits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 746
9.3.4 Page Faults . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 747
9.3.5 Allocating Pages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 748
9.3.6 Locality to the Rescue Again . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 749
9.4 VM as a Tool for Memory Management . . . . . . . . . . . . . . . . . . . . . . . . . . . . 749
9.5 VM as a Tool for Memory Protection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 751
9.6 Address Translation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 752
9.6.1 Integrating Caches and VM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 755
9.6.2 Speeding up Address Translation with a TLB . . . . . . . . . . . . . . . . . . . . . 756
9.6.3 Multi Level Page Tables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 756
9.6.4 Putting it Together: End-to-end Address Translation . . . . . . . . . . . . . . . . . 759
9.7 Case Study: The Intel Core i7/Linux Memory System . . . . . . . . . . . . . . . . . . . . . 763
9.7.1 Core i7 Address Translation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 763
9.7.2 Linux Virtual Memory System . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 767
9.8 Memory Mapping . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 770
9.8.1 Shared Objects Revisited . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 771
9.8.2 The fork Function Revisited . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 773
9.8.3 The execve Function Revisited . . . . . . . . . . . . . . . . . . . . . . . . . . . . 773
9.8.4 User-level Memory Mapping with the mmap Function . . . . . . . . . . . . . . . . 774
9.9 Dynamic Memory Allocation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 776
9.9.1 The malloc and free Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . 777
9.9.2 Why Dynamic Memory Allocation? . . . . . . . . . . . . . . . . . . . . . . . . . . 780
9.9.3 Allocator Requirements and Goals . . . . . . . . . . . . . . . . . . . . . . . . . . . 781
9.9.4 Fragmentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 782
9.9.5 Implementation Issues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 783
9.9.6 Implicit Free Lists . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 784
9.9.7 Placing Allocated Blocks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 785
9.9.8 Splitting Free Blocks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 786
9.9.9 Getting Additional Heap Memory . . . . . . . . . . . . . . . . . . . . . . . . . . . 786
9.9.10 Coalescing Free Blocks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 786
9.9.11 Coalescing with Boundary Tags . . . . . . . . . . . . . . . . . . . . . . . . . . . . 787
9.9.12 Putting it Together: Implementing a Simple Allocator . . . . . . . . . . . . . . . . . 789
9.9.13 Explicit Free Lists . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 797
9.9.14 Segregated Free Lists . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 798
9.10 Garbage Collection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 800
9.10.1 Garbage Collector Basics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 801
9.10.2 Mark&Sweep Garbage Collectors . . . . . . . . . . . . . . . . . . . . . . . . . . . 802
9.10.3 Conservative Mark&Sweep for C Programs . . . . . . . . . . . . . . . . . . . . . . 804
9.11 Common Memory-Related Bugs in C Programs . . . . . . . . . . . . . . . . . . . . . . . . 805
9.11.1 Dereferencing Bad Pointers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 805
9.11.2 Reading Uninitialized Memory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 805
9.11.3 Allowing Stack Buffer Overflows . . . . . . . . . . . . . . . . . . . . . . . . . . . 806
9.11.4 Assuming that Pointers and the Objects they Point to Are the Same Size . . . . . . . 806
9.11.5 Making Off-by-One Errors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 807
9.11.6 Referencing a Pointer Instead of the Object it Points to . . . . . . . . . . . . . . . . 807
9.11.7 Misunderstanding Pointer Arithmetic . . . . . . . . . . . . . . . . . . . . . . . . . 808
9.11.8 Referencing Nonexistent Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . 808
9.11.9 Referencing Data in Free Heap Blocks . . . . . . . . . . . . . . . . . . . . . . . . . 808
9.11.10 Introducing Memory Leaks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 809
9.12 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 809
III Interaction and Communication Between Programs 819
10 System-Level I/O 823

10.1 Unix I/O . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 824
10.2 Opening and Closing Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 824
10.3 Reading and Writing Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 826
10.4 Robust Reading and Writing with the RIO Package . . . . . . . . . . . . . . . . . . . . . . 828
10.4.1 RIO Unbuffered Input and Output Functions . . . . . . . . . . . . . . . . . . . . . 828
10.4.2 RIO Buffered Input Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 829
10.5 Reading File Metadata . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 832
10.6 Sharing Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 837
10.7 I/O Redirection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 840
10.8 Standard I/O . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 841
10.9 Putting It Together: Which I/O Functions Should I Use? . . . . . . . . . . . . . . . . . . . 842
10.10Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 843
11 Network Programming 847
11.1 The Client-Server Programming Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . 847
11.2 Networks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 848
11.3 The Global IP Internet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 853
11.3.1 IP Addresses . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 854
11.3.2 Internet Domain Names . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 856
11.3.3 Internet Connections . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 860
11.4 The Sockets Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 861
11.4.1 Socket Address Structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 861
11.4.2 The socket Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 862
11.4.3 The connect Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 863
11.4.4 The open clientfd Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . 864
11.4.5 The bind Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 865
11.4.6 The listen Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 865
11.4.7 The open listenfd Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . 865
11.4.8 The accept Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 867
11.4.9 Example Echo Client and Server . . . . . . . . . . . . . . . . . . . . . . . . . . . . 868
11.5 Web Servers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 871
11.5.1 Web Basics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 871
11.5.2 Web Content . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 872
11.5.3 HTTP Transactions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 873
11.5.4 Serving Dynamic Content . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 876
11.6 Putting it Together: The TINY Web Server . . . . . . . . . . . . . . . . . . . . . . . . . . . 877
11.7 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 887
12 Concurrent Programming 893
12.1 Concurrent Programming With Processes . . . . . . . . . . . . . . . . . . . . . . . . . . . 894
12.1.1 A Concurrent Server Based on Processes . . . . . . . . . . . . . . . . . . . . . . . 895
12.1.2 Pros and Cons of Processes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 896
12.2 Concurrent Programming With I/O Multiplexing . . . . . . . . . . . . . . . . . . . . . . . 898
12.2.1 A Concurrent Event-Driven Server Based on I/O Multiplexing . . . . . . . . . . . . 901
12.2.2 Pros and Cons of I/O Multiplexing . . . . . . . . . . . . . . . . . . . . . . . . . . . 903
12.3 Concurrent Programming With Threads . . . . . . . . . . . . . . . . . . . . . . . . . . . . 906
12.3.1 Thread Execution Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 907
12.3.2 Posix Threads . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 907
12.3.3 Creating Threads . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 908
12.3.4 Terminating Threads . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 909
12.3.5 Reaping Terminated Threads . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 910
12.3.6 Detaching Threads . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 910
12.3.7 Initializing Threads . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 911
12.3.8 A Concurrent Server Based on Threads . . . . . . . . . . . . . . . . . . . . . . . . 911
12.4 Shared Variables in Threaded Programs . . . . . . . . . . . . . . . . . . . . . . . . . . . . 913
12.4.1 Threads Memory Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 913
12.4.2 Mapping Variables to Memory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 915
12.4.3 Shared Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 915
12.5 Synchronizing Threads with Semaphores . . . . . . . . . . . . . . . . . . . . . . . . . . . 916
12.5.1 Progress Graphs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 919
12.5.2 Semaphores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 921
12.5.3 Using Semaphores for Mutual Exclusion . . . . . . . . . . . . . . . . . . . . . . . 922
12.5.4 Using Semaphores to Schedule Shared Resources . . . . . . . . . . . . . . . . . . . 924
12.5.5 Putting It Together: A Concurrent Server Based on Prethreading . . . . . . . . . . . 928
12.6 Using Threads for Parallelism . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 929
12.7 Other Concurrency Issues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 936
12.7.1 Thread Safety . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 936
12.7.2 Reentrancy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 939
12.7.3 Using Existing Library Functions in Threaded Programs . . . . . . . . . . . . . . . 940
12.7.4 Races . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 941
12.7.5 Deadlocks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 943
12.8 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 945

A Error Handling 957
A.1 Error Handling in Unix Systems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 957
A.2 Error-Handling Wrappers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 959

Read More Show Less

Preface

This book, Computer Systems: A Programmer's Perspective (CS:APP), is for programmers who want to improve their skills by learning what is going on "under the hood" of a computer system.

Our aim is to explain the enduring concepts underlying all computer systems, and to show you the concrete ways that these ideas affect the correctness, performance, and utility of your application programs. Unlike other systems books, which are written primarily for system builders, this book is written for programmers, from a programmer's perspective.

If you study and learn the concepts in this book, you will be on your way to becoming the rare "power programmer" who knows how things work and how to fix them when they break. You will also be prepared to study specific systems topics such as compilers, computer architecture, operating systems, embedded systems, and networking. Assumptions About the Reader's Background

The examples in the book are based on Intel-compatible processors (called "IA32" by Intel and "x86" colloquially) running C programs on Unix or Unix-like (such as Linux) operating systems. (To simplify our presentation, we will use the term "Unix" as an umbrella term for systems like Solaris and Linux.) The text contains numerous programming examples that have been compiled and run on Linux systems. We assume that you have access to such a machine, and are able to log in and do simple things such as changing directories.

If your computer runs Microsoft Windows, you have two choices. First, you can get a copy of Linux and install it as a "dual boot" option, so that your machine can run either operating system. Alternatively, by installing acopy of the Cygwin tools, you can have up a Unix-like shell under Windows and have an environment very close to that provided by Linux. Not all features of Linux are available under Cygwin, however.

We also assume that you have some familiarity with C or C++. If your only prior experience is with Java, the transition will require more effort on your part, but we will help you. Java and C share similar syntax and control statements. However, there are aspects of C, particularly pointers, explicit dynamic memory allocation, and formatted I/O, that do not exist in Java. Fortunately, C is a small language, and it is clearly and beautifully described in the classic "K&R" text by Brian Kernighan and Dennis Ritchie 40. Regardless of your programming background, consider K&R an essential part of your personal systems library.

Several of the early chapters in the book explore the interactions between C programs and their machine-language counterparts. The machine language examples were all generated by the GNU Gcc compiler running on an Intel IA32 processor. We do not assume any prior experience with hardware, machine language, or assembly-language programming. How to Read the Book

Learning how computer systems work from a programmer's perspective is great fun, mainly because it can be done so actively. Whenever you learn some new thing, you can try it out right away and see the result first hand. In fact, we believe that the only way to learn systems is to do systems, either working concrete problems, or writing and running programs on real systems.

This theme pervades the entire book. When a new concept is introduced, it is followed in the text by one or more practice problems that you should work immediately to test your understanding. Solutions to the practice problems are at the end of each chapter (look for the blue edge). As you read, try to solve each problem on your own, and then check the solution to make sure you are on the right track. Each chapter is followed by a set of homework problems of varying difficulty. Your instructor has the solutions to the homework problems in an instructor's manual. For each homework problem, we show a rating of the amount of effort we feel it will require:

* Should require just a few minutes. Little or no programming required.
** Might require up to 20 minutes. Often involves writing and testing some code. Many of these are derived from problems we have given on exams.
*** Requires a significant effort, perhaps 1-2 hours. Generally involves writing and testing a significant amount of code.
**** A lab assignment, requiring up to 10 hours of effort.

Each code example in the text was formatted directly, without any manual intervention, from a C program compiled with Gcc version 2.95.3, and tested on a Linux system with a 2.2.16 kernel. All of the source code is available from the CS:APP Web page (csapp.cs.cmu.edu). In the text, the file names of the source programs are documented in horizontal bars that surround the formatted code. For example, the program in Figure P.1 can be found in the file hello. c in directory code/intro/. We encourage you to try running the example programs on your system as you encounter them.

Finally, some sections (denoted by a "*") contain material that you might find interesting, but that can be skipped without any loss of continuity. Origins of the Book

The book stems from an introductory course that we developed at Carnegie Melton University in the Fall of 1998, called 15-213: Introduction to Computer Systems (ICS) 7. The ICS course has been taught every semester since then, each time to about 150 students, mostly sophomores in computer science and computer engineering. It has since become a prerequisite for most upper-level systems courses in the CS and ECE departments at Carnegie Melton.

The idea with ICS was to introduce students to computers in a different way. Few of our students would have the opportunity to build a computer system. On the other hand, most students, even the computer engineers, would be required to use and program computers on a daily basis. So we decided to teach about systems from the point of view of the programmer, using the following filter: We would cover a topic only if it affected the performance, correctness, or utility of user-level C programs.

For example, topics such as hardware adder and bus designs were out. Topics such as machine language were in, but instead of focusing on how to write assembly language, we would look at how C constructs such as pointers, loops, procedure calls and returns, and switch statements were translated by the compiler. Further, we would take a broader and more realistic view of the system as both hardware and systems software, covering such topics as linking, loading, processes, signals, performance optimization, measurement, I/O, and network and concurrent programming.

This approach allowed us to teach the ICS course in a way that was practical, concrete, hands-on, and exciting for the students. The response from our students and faculty colleagues was immediate and overwhelmingly positive, and we realized that others outside of CMU might benefit from using our approach. Hence this book, which we developed over a period of two years from the ICS lecture notes. Overview of the Book

The CS:APP book consists of 13 chapters designed to capture the core ideas in computer systems:

  • Chapter 1: A Tour of Computer Systems. This chapter introduces the major ideas and themes in computer systems by tracing the life cycle of a simple "hello, world" program.

  • Chapter 2: Representing and Manipulating Information. We cover computer arithmetic, emphasizing the properties of unsigned and two's complement number representations that affect programmers. We consider how numbers are represented and therefore what range of values can be encoded for a given word size. We consider the effect of casting between signed and unsigned numbers. We cover the mathematical properties of arithmetic operations. Students are surprised to learn that the (two's complement) sum or product of two positive numbers can be negative. On the other hand, two's complement arithmetic satisfies ring properties, and hence a compiler can transform multiplication by a constant into a sequence of shifts and adds. We use the bit-level operations of C to demonstrate the principles and applications of Boolean algebra. We cover the IEEE floating point format in terms of how it represents values and the mathematical properties of floating point operations.

  • Having a solid understanding of computer arithmetic is critical to writing reliable programs. For example, one cannot replace the expression (x
  • Chapter 3: Machine-Level Representation of Programs. We teach students how to read the IA32 assembly language generated by a C compiler. We cover the basic instruction patterns generated for different control constructs, such as conditionals, loops, and switch statements. We cover the implementation of procedures, including stack allocation, register usage conventions and parameter passing. We cover the way different data structures such as structures, unions, and arrays are allocated and accessed. Learning the concepts in this chapter helps students become better programmers, because they understand how their programs are represented on the machine. Another nice benefit is that students develop a concrete understanding of pointers.

  • Chapter 4: Processor Architecture. This chapter covers basic combinational and sequential logic elements and then shows how these elements can be combined in a datapath that executes a simplified subset of the IA32 instruction set called "Y86." We begin with the design of a single-cycle nonpipelined datapath, which we extend into a five-stage pipelined design. The control logic for the processor designs in this chapter are described using a simple hardware description language called HCL. Hardware designs written in HCL can be compiled and linked into graphical processor simulators provided with the textbook.

  • Chapter 5: Optimizing Program Performance. In this chapter we introduce a number of techniques for improving code performance. We start with machine-independent program transformations that should be standard practice when writing any program on any machine. We then progress to transformations whose efficacy depends on the characteristics of the target machine and compiler. To motivate these transformation, we introduce a simple operational model of how modern out-of-order processors work, and then show students how to use this model to improve the performance of their C programs.

  • Chapter 6: The Memory Hierarchy. The memory system is one of the most visible parts of a computer system to application programmers. To this point, the students have relied on a conceptual model of the memory system as a linear array with uniform access times. In practice, a memory system is a hierarchy of storage devices with different capacities, costs, and access times. We cover the different types of RAM and ROM memories and the geometry and organization of modern disk drives. We describe how these storage devices are arranged in a hierarchy. We show how this hierarchy is made possible by locality of reference. We make these ideas concrete by introducing a unique view of a memory system as a "memory mountain" with ridges of temporal locality and slopes of spatial locality. Finally, we show students how to improve the performance of application programs by improving their temporal and spatial locality.

  • Chapter 7: Linking. This chapter covers both static and dynamic linking, including the ideas of relocatable and executable object files, symbol resolution, relocation, static libraries, shared object libraries, and position-independent code. Linking is not covered in most systems texts, but we cover it for several reasons. First, some of the most confusing errors that students can encounter are related to glitches during linking, especially for large software packages. Second, the object files produced by linkers are tied to concepts such as loading, virtual memory, and memory mapping.

  • Chapter 8: Exceptional Control Flow. In this part of the course we break the single-program model by introducing the general concept of exceptional control flow (i.e., changes in control flow that are outside the normal branches and procedure calls). We cover examples of exceptional control flow that exist at all levels of the system, from low-level hardware exceptions and interrupts, to context switches between concurrent processes, to abrupt changes in control flow caused by the delivery of Unix signals, to the nonlocal jumps in C that break the stack discipline.
    This is the part of the book where we introduce students to the fundamental idea of a process. Students learn how processes work and how they can be crested and manipulated from application programs. We show them how application programmers can make use of multiple processes via Unix system calls. When students finish this chapter, they are able to write a Unix shell with job control.

  • Chapter 9: Measuring Program Execution Time. This chapter teaches students how computers keep track of time (interval timers, cycle timers, and system clocks), the sources of error when we try to use these times to measure running time, and how to exploit this knowledge to get accurate measurements. To the best of our knowledge, this is unique material that has never been discussed before in any consistent way. We include the topic at this point because it requires an understanding of assembly language, processes, and caches.

  • Chapterl0: Virtual Memory. Our presentation of the virtual memory system seeks to give students some understanding of how it works and its characteristics. We want students to know how it is that the different simultaneous processes can each use an identical range of addresses, sharing some pages but having individual copies of others. We also cover issues involved in managing and manipulating virtual memory. In particular, we cover the operation of storage allocators such as the Unix malloc and free operations. Covering this material serves several purposes. It reinforces the concept that the virtual memory space is just an array of bytes that the program can subdivide into different storage units. It helps students understand the effects of programs containing memory referencing errors such as storage leaks and invalid pointer references. Finally, many application programmers write their own storage allocators optimized toward the needs and characteristics of the application.

  • Chapter 11: System-Level I/O. We cover the basic concepts of Unix I/O such as files and descriptors. We describe how files are shared, how I/O redirection works, and How to access file metadata. We also develop a robust buffered I/O package that deals correctly with short counts. We cover the C standard I/O library and its relationship to Unix I/O, focusing on limitations of standard I/O that make it unsuitable for network programming. In general, the topics covered in this chapter are building blocks for the next two chapters on network and concurrent programming.

  • Chapter 12: Network Programming. Networks are interesting I/O devices to program, tying together many of the ideas that we have studied earlier in the text, such as processes, signals, byte ordering, memory mapping, and dynamic storage allocation. Network programs also provide a compelling context for concurrency, which is the topic of the next chapter. This chapter is a thin slice through network programming that gets the students to the point where they can write a Web server. We cover the client-server model that underlies all network applications. We present a programmer's view of the Internet, and show students how to write Internet clients and servers using the sockets interface. Finally, we introduce HTTP and develop a simple iterative Web server.

  • Chapter 13: Concurrent Programming. This chapter introduces students to concurrent programming using Internet server design as the running motivational example. We compare and contrast the three basic mechanisms for writing concurrent programs—processes, I/O multiplexing, and threads—and show how to use them to build concurrent Internet servers. We cover basic principles of synchronization using P and V semaphore operations, thread safety and reentrancy, race conditions, and deadlocks.
Read More Show Less

Introduction

This book, Computer Systems: A Programmer's Perspective (CS:APP), is for programmers who want to improve their skills by learning what is going on "under the hood" of a computer system.

Our aim is to explain the enduring concepts underlying all computer systems, and to show you the concrete ways that these ideas affect the correctness, performance, and utility of your application programs. Unlike other systems books, which are written primarily for system builders, this book is written for programmers, from a programmer's perspective.

If you study and learn the concepts in this book, you will be on your way to becoming the rare "power programmer" who knows how things work and how to fix them when they break. You will also be prepared to study specific systems topics such as compilers, computer architecture, operating systems, embedded systems, and networking.

Assumptions About the Reader's Background

The examples in the book are based on Intel-compatible processors (called "IA32" by Intel and "x86" colloquially) running C programs on Unix or Unix-like (such as Linux) operating systems. (To simplify our presentation, we will use the term "Unix" as an umbrella term for systems like Solaris and Linux.) The text contains numerous programming examples that have been compiled and run on Linux systems. We assume that you have access to such a machine, and are able to log in and do simple things such as changing directories.

If your computer runs Microsoft Windows, you have two choices. First, you can get a copy of Linux (see www.linux.org or www.redhat.com) and install it as a "dual boot" option, so that your machine can run either operating system.Alternatively, by installing a copy of the Cygwin tools (www.cygwin.com), you can have up a Unix-like shell under Windows and have an environment very close to that provided by Linux. Not all features of Linux are available under Cygwin, however.

We also assume that you have some familiarity with C or C++. If your only prior experience is with Java, the transition will require more effort on your part, but we will help you. Java and C share similar syntax and control statements. However, there are aspects of C, particularly pointers, explicit dynamic memory allocation, and formatted I/O, that do not exist in Java. Fortunately, C is a small language, and it is clearly and beautifully described in the classic "K&R" text by Brian Kernighan and Dennis Ritchie 40. Regardless of your programming background, consider K&R an essential part of your personal systems library.

Several of the early chapters in the book explore the interactions between C programs and their machine-language counterparts. The machine language examples were all generated by the GNU Gcc compiler running on an Intel IA32 processor. We do not assume any prior experience with hardware, machine language, or assembly-language programming.

How to Read the Book

Learning how computer systems work from a programmer's perspective is great fun, mainly because it can be done so actively. Whenever you learn some new thing, you can try it out right away and see the result first hand. In fact, we believe that the only way to learn systems is to do systems, either working concrete problems, or writing and running programs on real systems.

This theme pervades the entire book. When a new concept is introduced, it is followed in the text by one or more practice problems that you should work immediately to test your understanding. Solutions to the practice problems are at the end of each chapter (look for the blue edge). As you read, try to solve each problem on your own, and then check the solution to make sure you are on the right track. Each chapter is followed by a set of homework problems of varying difficulty. Your instructor has the solutions to the homework problems in an instructor's manual. For each homework problem, we show a rating of the amount of effort we feel it will require:

* Should require just a few minutes. Little or no programming required.
** Might require up to 20 minutes. Often involves writing and testing some code. Many of these are derived from problems we have given on exams.
*** Requires a significant effort, perhaps 1-2 hours. Generally involves writing and testing a significant amount of code.
**** A lab assignment, requiring up to 10 hours of effort.

Each code example in the text was formatted directly, without any manual intervention, from a C program compiled with Gcc version 2.95.3, and tested on a Linux system with a 2.2.16 kernel. All of the source code is available from the CS:APP Web page (csapp.cs.cmu.edu). In the text, the file names of the source programs are documented in horizontal bars that surround the formatted code. For example, the program in Figure P.1 can be found in the file hello. c in directory code/intro/. We encourage you to try running the example programs on your system as you encounter them.

Finally, some sections (denoted by a "*") contain material that you might find interesting, but that can be skipped without any loss of continuity.

Origins of the Book

The book stems from an introductory course that we developed at Carnegie Melton University in the Fall of 1998, called 15-213: Introduction to Computer Systems (ICS) 7. The ICS course has been taught every semester since then, each time to about 150 students, mostly sophomores in computer science and computer engineering. It has since become a prerequisite for most upper-level systems courses in the CS and ECE departments at Carnegie Melton.

The idea with ICS was to introduce students to computers in a different way. Few of our students would have the opportunity to build a computer system. On the other hand, most students, even the computer engineers, would be required to use and program computers on a daily basis. So we decided to teach about systems from the point of view of the programmer, using the following filter: We would cover a topic only if it affected the performance, correctness, or utility of user-level C programs.

For example, topics such as hardware adder and bus designs were out. Topics such as machine language were in, but instead of focusing on how to write assembly language, we would look at how C constructs such as pointers, loops, procedure calls and returns, and switch statements were translated by the compiler. Further, we would take a broader and more realistic view of the system as both hardware and systems software, covering such topics as linking, loading, processes, signals, performance optimization, measurement, I/O, and network and concurrent programming.

This approach allowed us to teach the ICS course in a way that was practical, concrete, hands-on, and exciting for the students. The response from our students and faculty colleagues was immediate and overwhelmingly positive, and we realized that others outside of CMU might benefit from using our approach. Hence this book, which we developed over a period of two years from the ICS lecture notes.

Overview of the Book

The CS:APP book consists of 13 chapters designed to capture the core ideas in computer systems:

  • Chapter 1: A Tour of Computer Systems. This chapter introduces the major ideas and themes in computer systems by tracing the life cycle of a simple "hello, world" program.


  • Chapter 2: Representing and Manipulating Information. We cover computer arithmetic, emphasizing the properties of unsigned and two's complement number representations that affect programmers. We consider how numbers are represented and therefore what range of values can be encoded for a given word size. We consider the effect of casting between signed and unsigned numbers. We cover the mathematical properties of arithmetic operations. Students are surprised to learn that the (two's complement) sum or product of two positive numbers can be negative. On the other hand, two's complement arithmetic satisfies ring properties, and hence a compiler can transform multiplication by a constant into a sequence of shifts and adds. We use the bit-level operations of C to demonstrate the principles and applications of Boolean algebra. We cover the IEEE floating point format in terms of how it represents values and the mathematical properties of floating point operations.


  • Having a solid understanding of computer arithmetic is critical to writing reliable programs. For example, one cannot replace the expression (x

  • Chapter 3: Machine-Level Representation of Programs. We teach students how to read the IA32 assembly language generated by a C compiler. We cover the basic instruction patterns generated for different control constructs, such as conditionals, loops, and switch statements. We cover the implementation of procedures, including stack allocation, register usage conventions and parameter passing. We cover the way different data structures such as structures, unions, and arrays are allocated and accessed. Learning the concepts in this chapter helps students become better programmers, because they understand how their programs are represented on the machine. Another nice benefit is that students develop a concrete understanding of pointers.


  • Chapter 4: Processor Architecture. This chapter covers basic combinational and sequential logic elements and then shows how these elements can be combined in a datapath that executes a simplified subset of the IA32 instruction set called "Y86." We begin with the design of a single-cycle nonpipelined datapath, which we extend into a five-stage pipelined design. The control logic for the processor designs in this chapter are described using a simple hardware description language called HCL. Hardware designs written in HCL can be compiled and linked into graphical processor simulators provided with the textbook.


  • Chapter 5: Optimizing Program Performance. In this chapter we introduce a number of techniques for improving code performance. We start with machine-independent program transformations that should be standard practice when writing any program on any machine. We then progress to transformations whose efficacy depends on the characteristics of the target machine and compiler. To motivate these transformation, we introduce a simple operational model of how modern out-of-order processors work, and then show students how to use this model to improve the performance of their C programs.


  • Chapter 6: The Memory Hierarchy. The memory system is one of the most visible parts of a computer system to application programmers. To this point, the students have relied on a conceptual model of the memory system as a linear array with uniform access times. In practice, a memory system is a hierarchy of storage devices with different capacities, costs, and access times. We cover the different types of RAM and ROM memories and the geometry and organization of modern disk drives. We describe how these storage devices are arranged in a hierarchy. We show how this hierarchy is made possible by locality of reference. We make these ideas concrete by introducing a unique view of a memory system as a "memory mountain" with ridges of temporal locality and slopes of spatial locality. Finally, we show students how to improve the performance of application programs by improving their temporal and spatial locality.


  • Chapter 7: Linking. This chapter covers both static and dynamic linking, including the ideas of relocatable and executable object files, symbol resolution, relocation, static libraries, shared object libraries, and position-independent code. Linking is not covered in most systems texts, but we cover it for several reasons. First, some of the most confusing errors that students can encounter are related to glitches during linking, especially for large software packages. Second, the object files produced by linkers are tied to concepts such as loading, virtual memory, and memory mapping.


  • Chapter 8: Exceptional Control Flow. In this part of the course we break the single-program model by introducing the general concept of exceptional control flow (i.e., changes in control flow that are outside the normal branches and procedure calls). We cover examples of exceptional control flow that exist at all levels of the system, from low-level hardware exceptions and interrupts, to context switches between concurrent processes, to abrupt changes in control flow caused by the delivery of Unix signals, to the nonlocal jumps in C that break the stack discipline.

    This is the part of the book where we introduce students to the fundamental idea of a process. Students learn how processes work and how they can be crested and manipulated from application programs. We show them how application programmers can make use of multiple processes via Unix system calls. When students finish this chapter, they are able to write a Unix shell with job control.


  • Chapter 9: Measuring Program Execution Time. This chapter teaches students how computers keep track of time (interval timers, cycle timers, and system clocks), the sources of error when we try to use these times to measure running time, and how to exploit this knowledge to get accurate measurements. To the best of our knowledge, this is unique material that has never been discussed before in any consistent way. We include the topic at this point because it requires an understanding of assembly language, processes, and caches.


  • Chapterl0: Virtual Memory. Our presentation of the virtual memory system seeks to give students some understanding of how it works and its characteristics. We want students to know how it is that the different simultaneous processes can each use an identical range of addresses, sharing some pages but having individual copies of others. We also cover issues involved in managing and manipulating virtual memory. In particular, we cover the operation of storage allocators such as the Unix malloc and free operations. Covering this material serves several purposes. It reinforces the concept that the virtual memory space is just an array of bytes that the program can subdivide into different storage units. It helps students understand the effects of programs containing memory referencing errors such as storage leaks and invalid pointer references. Finally, many application programmers write their own storage allocators optimized toward the needs and characteristics of the application.


  • Chapter 11: System-Level I/O. We cover the basic concepts of Unix I/O such as files and descriptors. We describe how files are shared, how I/O redirection works, and How to access file metadata. We also develop a robust buffered I/O package that deals correctly with short counts. We cover the C standard I/O library and its relationship to Unix I/O, focusing on limitations of standard I/O that make it unsuitable for network programming. In general, the topics covered in this chapter are building blocks for the next two chapters on network and concurrent programming.


  • Chapter 12: Network Programming. Networks are interesting I/O devices to program, tying together many of the ideas that we have studied earlier in the text, such as processes, signals, byte ordering, memory mapping, and dynamic storage allocation. Network programs also provide a compelling context for concurrency, which is the topic of the next chapter. This chapter is a thin slice through network programming that gets the students to the point where they can write a Web server. We cover the client-server model that underlies all network applications. We present a programmer's view of the Internet, and show students how to write Internet clients and servers using the sockets interface. Finally, we introduce HTTP and develop a simple iterative Web server.


  • Chapter 13: Concurrent Programming. This chapter introduces students to concurrent programming using Internet server design as the running motivational example. We compare and contrast the three basic mechanisms for writing concurrent programs—processes, I/O multiplexing, and threads—and show how to use them to build concurrent Internet servers. We cover basic principles of synchronization using P and V semaphore operations, thread safety and reentrancy, race conditions, and deadlocks.
Read More Show Less

Customer Reviews

Average Rating 4
( 4 )
Rating Distribution

5 Star

(3)

4 Star

(0)

3 Star

(0)

2 Star

(0)

1 Star

(1)

Your Rating:

Your Name: Create a Pen Name or

Barnes & Noble.com Review Rules

Our reader reviews allow you to share your comments on titles you liked, or didn't, with others. By submitting an online review, you are representing to Barnes & Noble.com that all information contained in your review is original and accurate in all respects, and that the submission of such content by you and the posting of such content by Barnes & Noble.com does not and will not violate the rights of any third party. Please follow the rules below to help ensure that your review can be posted.

Reviews by Our Customers Under the Age of 13

We highly value and respect everyone's opinion concerning the titles we offer. However, we cannot allow persons under the age of 13 to have accounts at BN.com or to post customer reviews. Please see our Terms of Use for more details.

What to exclude from your review:

Please do not write about reviews, commentary, or information posted on the product page. If you see any errors in the information on the product page, please send us an email.

Reviews should not contain any of the following:

  • - HTML tags, profanity, obscenities, vulgarities, or comments that defame anyone
  • - Time-sensitive information such as tour dates, signings, lectures, etc.
  • - Single-word reviews. Other people will read your review to discover why you liked or didn't like the title. Be descriptive.
  • - Comments focusing on the author or that may ruin the ending for others
  • - Phone numbers, addresses, URLs
  • - Pricing and availability information or alternative ordering information
  • - Advertisements or commercial solicitation

Reminder:

  • - By submitting a review, you grant to Barnes & Noble.com and its sublicensees the royalty-free, perpetual, irrevocable right and license to use the review in accordance with the Barnes & Noble.com Terms of Use.
  • - Barnes & Noble.com reserves the right not to post any review -- particularly those that do not follow the terms and conditions of these Rules. Barnes & Noble.com also reserves the right to remove any review at any time without notice.
  • - See Terms of Use for other conditions and disclaimers.
Search for Products You'd Like to Recommend

Recommend other products that relate to your review. Just search for them below and share!

Create a Pen Name

Your Pen Name is your unique identity on BN.com. It will appear on the reviews you write and other website activities. Your Pen Name cannot be edited, changed or deleted once submitted.

 
Your Pen Name can be any combination of alphanumeric characters (plus - and _), and must be at least two characters long.

Continue Anonymously
Sort by: Showing 1 Customer Reviews
  • Posted June 5, 2013

    I¿m loving McDonalds for fast food... MyDeals247 for the best de

    I’m loving McDonalds for fast food... MyDeals247 for the best deals;))

    0 out of 1 people found this review helpful.

    Was this review helpful? Yes  No   Report this review
Sort by: Showing 1 Customer Reviews

If you find inappropriate content, please report it to Barnes & Noble
Why is this product inappropriate?
Comments (optional)