 So I hope you guys enjoyed your video lectures last week. And I'm back. So I could just show the videos for the rest of the semester, I guess, but that wouldn't be very much fun. All right, so today we're going to pick up where the last video you guys saw on Friday left off. So we'll finish talking about interrupts and exceptions. And then we'll move forward to talk, start talking about how we abstract the CPU. All right, this is on, no, there we go. OK, so congrats, you guys are done with assignment one. You guys are pretty far ahead of where last year's class was at this point, so I think that's good. That'll give you guys time to spread out and work on the rest of the assignments. Speaking of which, as a reminder, the code reading questions and design document for assignment two are due Friday, as in this Friday. So please get working on those. The goal here is to get you guys embedded in assignment two so that you guys will start thinking about it. And once you start thinking about assignment two, it's really hard not to just get really excited and then start working on assignment two. So that's the goal. So please finish the code reading questions. There aren't as many as there were for assignment zero and assignment one, but they're still designed to be helpful. And the design document is due as well. So office hours this week are a great place to come for some feedback on your designs. But we try to give you pretty specific instructions on the website. If you follow the instructions on the website, it is difficult to not get full credit for the design document. Any questions about course logistics? That's good. So question, what if your design is wrong? That's the point. So part of writing a design document is writing down how you're going to do something so that you can show it to the TA and the TA will say, that's a terrible idea. Don't do that. So for example, you might decide, as my partner did when I took this class, that it would be fun to support an infinite number of file handles that could be opened by a process. So why have a limit on a number of file handles a process can have open? We'll just let that number be billions. The engineering effort required to support that design choice is really pretty intense. And it's kind of a stupid idea. In fact, it's not kind of a stupid idea. It's a really stupid idea. So if you write that in your design, you come in, you bring it to the TAs. Now when we grade the designs, we can't really give detailed feedback. We're just going through the rubric looking for specific things. But when you come, start asking questions for assignment two, please print off a copy of your design and keep it with you or have it available on the computer. So when you sit down with the TA, they'll be more able to help you. It also, remember, the TAs and the Ninjas are looking at a gazillion different assignment twos. And there's lots of different ways to do assignment two. So having a design document there helps then help you when you come in for office hours. By the way, I don't know how many of the TAs or Ninjas are here, but I'm assuming that those guys were pretty helpful last week. How many people feel like the TAs and Ninjas were pretty helpful with assignment 0 and assignment 1? All right, so let's give them a round of applause. It's the first time I've been away for a deadline in this class. It's a little weird. So any other logistics questions? That was a great question. So any questions about Friday's material? Well, we didn't talk about. You guys heard about operating system privilege, exceptions, any questions about this stuff. I really like that lecture. I was really sad and good to get it. I like kernel proofs. I think it's cool. I like thinking about being the kernel and being in charge of the machine. All right, so let's just do a little bit of review. So we talked, or you heard on Friday about how the operating system gets these special privileges. Why are they required? Why does the OS need special privileges? Whoa, that doesn't work. OK, I guess I'll do hands, yeah. So to multiplex resources and to enforce those divisions. So the operating system has been put in charge of making efficient use of the resources on the system. And in order to enforce those divisions, because I have multiple processes that are trying to use the machine at the same time, and ideally, every process would say, hey, I want all the resources for me. But the operating system is in charge of making sure that everybody makes progress and that the resources on the system don't go to waste. So the goal of operating system privilege or the reason the operating systems have these special powers is that they can perform their essential functions. OK, so true or false, implementing common operating system abstractions requires kernel privilege. How many people think true? How many people want to disagree? All right, someone from the false camp. Yeah, why not? Yeah, so exec requires some help from the kernel, but how many people have ever used a threading library to write some multi-threader code? A lot of those threading libraries were originally implemented in user space, particularly on operating systems that didn't, for a period of time, support a kernel idea of multi-threading. We'll come back to that on Wednesday. We'll talk about different ways that we can implement the thread abstraction, which we're going to introduce either today or Wednesday. So false. And there is an operating system design called an exo-kernel that we'll come back to much later in the semester that actually was able to tease these two things apart. So that design separated the multiplexing that's required by the operating system from all the abstractions. So it's possible to completely divide the operating system into the part that performs multiplexing. It tries to make the machine go fast and protect processes from each other and other, including the abstractions and the support for different types of programming paradigms that make applications easier to write, operating mode. So what's the hardware basis for operating system privilege? Remember, most of these ideas we talk about in operating systems software have their origins in hardware. Hardware provides some level of support. So what does it actually mean for the operating system to be privileged or to be special? What is it allowed to do that applications are not? Yeah. So on many machines, there's a subset of the full hardware instruction set that the kernel is allowed to execute and other applications are not. What else? It's part of it. Yeah. So there's this thing called privileged mode. And privileged mode does a couple of things. And this depends a lot on the hardware architecture you're using. But usually, privileged mode will do a couple of things. One thing it'll do is it'll allow the kernel to use some special instructions that applications are not allowed to use. And we'll talk today a little bit later about what happens if an application tries to use those special instructions. Privileged mode can also provide the kernel with access or a different view of memory, which can be useful. Sometimes the kernel needs that in order to multiplex memory. And there's some other types of things that go along with this. But you can think of privileged mode as the mode of execution the operating system has access to that applications do not. And that comes from some special features that are designed to allow the operating system to do what it needs to do. So what is an interrupt? That's the first question. Someone tell me what an interrupt is first. It's lowest level. What causes an interrupt? How do I interrupt the CPU? So how is that, again, get lower, closer to the hardware. What is that flag? So that's what the flag is connected to. But literally, a flag is usually indicated by a logic line going high on the processor. So there are pins on the processor that are connected to peripherals. And when one of those pins shows a logic level of true or maybe false, depending on how the pin is configured, that will generate a interrupt. That's a hardware interrupt. These are designed to allow hardware, which is not necessarily directly connected to the CPU, to signal the CPU that it needs some kind of attention. When that happens, what happens? There are three things that you can think of as roughly happening at all together at the same time. Three things. This is important. This has been on every midterm exam I've ever given. Three things that happen when an interrupt is triggered. What happens a little bit later? OK, so I'm going to enter privileged mode. What else am I going to do? What else? You go to privileged mode. I'm going to stop what I'm doing. And what am I going to start doing? Yeah. Yeah, so I'm going to jump to a specific place. So I'm going to enter privileged mode. Once I start executing this, the processor, I'm going to record some state that was necessary. And I jump to a fixed memory location and begin executing instructions. Technically, number two actually sort of happens after number three. I enter privileged mode. I jump to a hardwired or preconfigured location that the CPU and the operator doesn't have agreed on. And I start executing code. And frequently, the first thing that code does is it stays state necessary for me to handle the interrupt. OK, do you guys understand this? This is pretty important, right? So what is, I mean, what's located, someone called it the interrupt service routine, right? So that code that's located there is itself part of the operating system, right? This is how the operating system gets control when an interrupt is triggered, right? Because think about it. If the operating system can't handle interrupts from hardware, then it's very unlikely it's going to be able to multiplex the system resources properly. I certainly can't, in most cases, allow applications to handle hardware interrupts. If I do, I'm giving them full control over that piece of hardware, and that makes it difficult or impossible to multiplex it and ensure that it's shared properly with other processes, right? So give me some examples of hardware interrupts. What would trigger a hardware interrupt? We know now it's a logic line that goes high, but why would some device send this signal? What are some types of higher level events that would trigger a hardware interrupt? Yeah. Yeah, the mouse. Mouse has moved a certain amount. That's one example. You can imagine that generating quite a few interrupts, right? Yeah. So we're going to get back to that, right? There are certainly timer interrupts that are delivered to the processor, and those are really important for scheduling, right? What else? Yeah. Oh, yeah. Yeah, that's super complicated. Yeah, but certainly there's probably an interrupt involved if you can even do that, right? If your device, if your machine supports hot swapping, or, well, I guess, for example, when I unplug or plug in a USB device, right? The hub probably sends an interrupt to the processor to alert it that it has a new device that's attached and needs to communicate with. Yeah, so a disk read gets done, right? Or a series of disk reads get finished. Network card receives a packet, right? Hey, Operating System has some data that just came in over the network. And again, we'll get back to timer interrupts, right? That's a pretty good idea of what causes these, right? So the video told you a little bit about the Operating System potentially wanting to ignore certain interrupts. And most processors have a way to do this through interrupt masking. So I can tell the CPU, do not trigger the interrupt service routine when this set of interrupts is triggered. Why would I need to do that? I'll give you this one, right? So first of all, I can establish priorities between hardware devices, right? It's possible, for example, that there's a piece of hardware where I need to service the interrupts more frequently, or I need to make sure those interrupts get quicker attention, and there's other hardware where the interrupts can be delayed for a longer period of time, right? So by using interrupt masking, I can make sure that when I process an interrupts for lower priority device, I still get interrupted by the higher priority device, but that the inverse of that is not true, right? OK, so again, so the interrupt service routines, interrupt handlers, are pretty important. What would happen if the application were allowed to overwrite the interrupt service routines? It's a pretty simple answer to this question. Let's say I'm a malicious application, and somehow the kernel has allowed me to overwrite the interrupt service routines. What can I essentially become? Yeah, yeah, I can do that, but I pretty much can just become the kernel, right? Remember, this is normally how the kernel gets to run. This is the entry point, the most common entry point into the kernel. In fact, it's probably one of the only entry points into the kernel. This is how the kernel code gets triggered. This is what causes the kernel to run. So if I put my own code there, I can just vector everybody into my own code, right? So I can essentially become the operating system kernel, not something that I want to allow to happen, right? And normally, I shouldn't say normally. The kernel interrupt service routines are always put in a spot in memory where applications get up, right? OK, just a little bit of a longer review since I was away. I don't know what happened. Any questions about that? All right, cool. OK, so to continue, on Friday, I heard about hardware interrupts. So today, I want to talk about a different type of interrupt that's equally important if not more important, right? So there's something called a software interrupt. And software interrupts exist to answer the question, how do I give applications? How do applications get the kernel's attention, right? We talked about hardware. Hardware needs attention, right? Hardware, something happened that the hardware needs to tell the operating system about. I'm the mouse, and I moved like a millimeter or something, or even smaller than that, right? Or I'm the disk, and I got done reading a byte of data or a block of data that the operating system asked me to do. But at the same time, software also needs attention, right? So what's an example of a time where a piece of application code would need attention from the operating system? Yeah? Ooh, that's a good one, actually. So most malloc calls actually don't go to the operating system. But malloc relies on an operating system, on some support from the operating system. But you're close. You guys just got done talking about a bunch of these, yeah. Yeah, so you guys just got done on Wednesday hearing about some of these, right? What's reading from disk is one, but what about the stuff you guys already know about? What's one thing that you guys know happens that requires a process to get the kernel's attention? What's that? No, the locks can be normally implemented. And fork, I want to create my own, I want to create my clone, right? Remember, that's something that the operating system does for me. That's something I do. I can't create new processes. If I could create new processes by myself, that would potentially be problematic, right? So I asked the operating system, hey, I want to make a copy of myself right now, right? Fork, exec, wait, exit. The whole system call interface are all examples of times that the application wants to get the kernel's attention, normally because it wants the kernel to do something for it, and always it wants the kernel to do something for it that it can't do itself because doing it itself would somehow mean that the kernel was not able to adequately protect the resources on the machine, right? In general, the kernel does not want to get in applications way, it wants to stay out of the way. That way applications can run fast, and they don't need much help. But there are times when because of the responsibilities the kernel has, it needs to actually, there are certain features that applications have to ask the kernel to do on their behalf, right? So reading from the disk is one example. Getting big chunks of memory. Now again, the malloc call itself actually doesn't go into the kernel. The malloc requires a system call called sbreak that does request more memory from the kernel, right? And you guys, if you implement sbreak for assignment three, it's not that hard, actually. So system calls in general, right? And the way this works is kind of clever, right? Cp, what we do is that we override the existing interrupt mechanism, right? So there's this mechanism for getting the kernel's attention that's used by hardware, right? When hardware wants attention, it flips a line on the, you know, it flips a pin on the chip, right? On the processor. An application can't do that, right? It can't reach out and like twiddle the pins that are going on out there. But instead, what happens is the operate, there's an instruction provided that accomplishes the same thing, right? So the syscall instruction on the MIPS, it is, I think it's int on the x86 architecture, generates a, essentially what you can think of is a synthetic interrupt. It looks exactly like a normal interrupt, except that it's not triggered by any of the pins attached to the processor, right? So just a little lightning review. When I call system call, what happens? What three things happen? This is short term memory test. What's one? Yes, we enter privileged mode. What else? I save some state required to process the interrupt and most importantly or very importantly, I jump into the interrupt service routine, right? So again, this is important to remember, right? Under privileged mode, record that the state I need to process the interrupt jump into a pretty determined memory location, okay? So essentially the way this works is pretty simple, right? Now here's the problem, right? I mean, like the syscall command and you guys can find this being generated in your own OS 161 code, right? The system call requires a convention between the application and the kernel so that the application and kernel can decide what needs to happen, right? So syscall, the argument at least in MIPS, takes no arguments. It's a single instruction. And so what it means is that there has to be a convention about how we pass arguments inside in and out of the kernel. You guys are gonna start encountering this in assignment two when you guys start implementing the system call interface in OS 161, right? And on every machine it's a little bit different but in general what happens is I load some instructions into registers before I call system call. And usually I also load the number that identifies the system call, right? So for example, if I wanna read data from the disk there's a number that indicates that I wanna do that and then that read also requires some extra information like what blocks I want or what file I'm trying to read from or something like that, right? So I need to figure out how to tell the operating system what system call I wanna perform and pass the arguments corresponding to that system call into the kernel so that the kernel can do what I want. In many ways this is really, really similar to a function call, right? And if you guys know how function calls are made, it's close enough, right? If you sort of squint at it, it looks pretty simple, right? And then once I have everything set up I execute the system call instruction, right? The kernel, once I execute system call what's gonna happen? Those three things, we don't have to go through them, right? But when the process executes the system call instruction that will trap into the kernel immediately, right? So when the program does that what's happening is it's giving up control, right? It needs something to happen and it's asking the kernel to do that on its behalf, right? So again, if you guys look around in your code base you can find this code maybe Jain Ha will go through it in recitation this week but all this is there actually, right? I mean remember when you guys are working in OS 161 you're not only building a kernel but you're building the whole system, right? When you guys do a make in your root directory you're building all the binaries, you're building the C library, you're building the shims that connect the binaries to the C library everything, right? So there's nothing external, I mean everything is all self-contained in that little blob of code. There's nothing outside, so you can see all of this code, right? You wanna see what generates the stubs that load the correct number into the right register and then call system call, it's all there, right? Okay, so again, so now there's another, there's one sort of final way, important way to know that the OS gets control of the system, right? And that's when something called a software exception takes place. Now exceptions are different than interrupts, right? An exception indicates that some kind of unusual condition has arisen that the CPU wants the kernel to help it handle, okay? So can you think of an example of an exception? So one way of thinking about an exception is the program cannot execute another instruction until somebody figures out what to do, right? The program did something and again, it just cannot make any more forward progress. And so what the CPU does is it can't execute the next instruction, so it traps into the kernel and says, hey, kernel, please help me, please tell me what to do. So can anyone think of an example of a software exception? Yeah. Divide by zero, it's my favorite, right? What's the result of a divide by zero? No one knows, right? So what happens after, what would normally happen after a program would try to divide by zero? What can I do? Can I allow it to continue? Because there's no value to put in the register, right? There's just like, you know, the machine doesn't have like a special value for unknown, you know? So what normally happens when I divide by zero? And you're done, right? I mean, the program cannot be allowed to continue and normally that exception is handled by the operating system terminating the program. And you can verify this yourself, right? And write a little piece of C code to divide by zero and see what happens. Other languages, interpreted languages do different things, right? They don't allow that instruction to hit the processor, so you do this in Python, for example, it's not gonna crash, it'll just catch that and say, hey, by the way, I don't know what this is, right? Or maybe it'll give you some fun Pythonic value like undefined or whatever, right? So that's, you know, that's the canonical one. Anything else? So other than weird math things, what else could the program do that the kernel would want to know about, yeah? Yeah, so, but what would I have to do in order to read for a file that was not there? I'd have to perform a read system call, right? So that's different, right? I can certainly have errors caused by system calls, that's a great point. I can certainly have cases where the arguments to the system call are malformed or something. A lot of times what happens in those cases is the program doesn't die, the call just fails, right? And the kernel will say, hey, by the way, that file isn't there. What's another thing that a process could do that the OSP really curious about? Okay, we're getting closer, yeah. Yeah, so those are essentially the same thing, right? And when we get to the VM stuff, you will finally learn what segmentation fault is. I know you guys have been waiting your entire lives to figure out, you've seen this stupid error and you're like, what is a segmentation fault? It makes no sense, right? And I will explain this to you, don't worry, right? That'd be like the one thing you'll remember about this class 10 years from now. You'd be like, I know what a segmentation fault is. Yeah, so if I try to read memory that I'm not allowed to read, right? Or maybe I try to use some sort of privileged instruction I'm not allowed to use, okay? A lot of various types of protection violations end up as exceptions, right? Same path, the CPU sees, hmm, this is interesting. This program is not running in privileged mode but it just executed an instruction that requires privilege. What am I gonna do? I'm gonna go to the operating system and say, help me out. Do something about this, right? Okay, now this is a nice mechanism, right? Because the CPU could also crash, right? The CPU could just say, hey, see ya. You know, I'm gonna power down, you power me back up and you figure out what's wrong, right? Before you do that. Why is it better to trap into the operating system? Remember one of our goals, right? If the CPU just shut off every time there was a divide by zero, how would that suck? Yeah, yeah, like any dumb program could crash your entire computer, right? You guys could take down Timberlake by just writing like two lines of seco, right? And then kaboom, right? So that's not good, right? We don't wanna isolate processes from each other and particularly we don't want one process to indirectly affect another, certainly not by just torching the whole machine, right? Not okay. So now I want you guys, I wanna make a point here and this is something we'll come back to when we talk more about virtual memory in maybe a month. Exceptions are not always bad, right? So exceptions are an exceptional condition. A lot of them end up being bad, but this is probably the most common exception encountered by a running program. And it's an attempt to access memory that has not been mapped yet. And we'll get back to this when we come to virtual memory. And this, the nice thing here is that this is normally handled completely transparently to the process by the operating system, right? This generates a software exception in the same way, but that exception is handled and the program is allowed to keep running, right? Because in this case, this is not a problem, right? It's just something that the program doesn't know about, right? We're playing games with the memory behind its back. It's not aware of that. And so a lot of these get triggered. And again, my suspect maybe 99.99% of software exceptions are memory related faults that are handled completely transparently to the program. Some of them generate segmentation faults but that's a pretty, pretty small number, right? Most of them just get handled and the program goes on its way, okay? So who can identify the difference between a software exception and a software interrupt? Okay? Now keep in mind, exceptions are not always bad, right? So you can't say, well, exception is gonna kill the process. That's not true, but there's a difference from the perspective of the application, right? Can anyone spot it? It's a little subtle, yeah. Yeah, great. So an interrupt is intentional. A software interrupt is generated by the process itself. It generated that system call, right? Didn't appear out of nowhere, right? That was in its code, right? It wandered through its code, taking all sorts of branches, responding to your input and at some point it hit the system call and it asked the kernel for help, right? Exceptions are involuntary, right? So, you know, again, interrupts you can think of as voluntary. It's like, been true, need some help, right? Exceptions are non-voluntary. The program isn't aware that it generates an exception, right? I mean, maybe you know that you wrote the program to divide by zero, right? But the program doesn't really know that, right? It's just like, well, I have R1 and R2 and you told me to divide the two, so here I go, right? And then, you know, that's the last thing it ever knows. But exceptions, again, are something that I'm not asking the kernel for help, but the kernel may get involved anyway. And again, with the VM-related exceptions, this happens all the time. Completely transparently to the process. Okay, so let's pause here before I try to convince you why this is all a good idea. Any questions about interrupts, exceptions, privileged mode? Yeah. No, so software interrupts trigger the same behavior, right? So, essentially, the result is identical, right? Now, it's not intentionally, it's unnecessarily completely identical. Sometimes there's a flag on the CPU that allows the kernel to determine whether or not the interrupt is generated by hardware or by software, because I might wanna know that, right? If you look in your own OS-161 cone at the interrupt handling path, that's one of the first branches that I take, right? The first, one of the first things the operating system does when it starts to handle an interrupt is it figures out is this a hardware interrupt or is it a software interrupt? The hardware interrupts get handed off to some big blob of code that you guys really don't need to worry about at all, ever. If you ever find yourself reading a lame bus code, just stop, right? You've blundered, you've gone down the wrong path. And then the software interrupts get vectored in a different direction and that's actually, they end up in stubs that you guys need to write for assignment two, right? Other questions, yeah? No. So typically I have a small number of handlers and this depends on the hardware architecture, right? But usually I do not have a handler per interrupt. What I do is that the interrupt sets some state on the processor that allows there to be a common interrupt handler that branches based on what happened, right? So rather than having like a different interrupt service routine for every interrupt because that would be actually quite a bit of wasted code, right? Because a lot of them are very similar. I have one thing that eventually hits a case state, right, or a switch statement and I use a value that the either that the system call loaded for me or in a hardware interrupt, the processor has to tell me something, right? It has to be like which line triggered the interrupt, right? So I need some more information but that's something that the CPU tells me, right? On MIPS there are actually two interrupt handling paths. One is for anything that's not memory related and there's a separate interrupt handler for memory related interrupts, right? And that's because sometimes I want a little bit of a faster path for memory related interrupts because they are very, very common, right? They happen all the time. That's a great question though. Any other questions about this before? Going to our history lesson, yeah. Yeah, that's such a great question. I wouldn't, I'm not sure I would describe them as being cued, right? They are not necessarily, so here's my understanding. When the interrupt mask is dropped, any interrupts that are still pending will be handled, now there's certain cases where a hardware device may trigger an interrupt but then drop it after a period of time, right? If it doesn't receive a response from the operator, right? For example, timer interrupts. I don't need to handle every timer interrupt. I don't want to handle every timer interrupt, right? I just want the timer to keep firing at a regular rate but if I decide to block timer interrupts for a bit of time, I don't want to handle all the stupid ones that came through. I don't care, right? I just want to know that there's a clock that's ticking, right? That's going to wake me up every period, right? Good question, though. And I think, yeah, I think depending on how much the sort of the semantics for handling those are probably pretty dependent on that what the CPU actually supports, right? Another good question. All right, anybody else? Let's see how much time I have left. Oh, goodie, okay. So let me, let me, this is, let me try to get through the history lesson in ten minutes. Okay, so, you know, and this is really just designed to motivate some things that you guys probably think are sort of obvious, right? But let's take a trip down memory lane back to when computers were big and slow, all right? So multiplexing in the CPU is really designed to work around limitations of the CPU. One of the limitations of the CPU, and this is something that we already hinted at a little bit when we talked about synchronization early this year, is that the, there aren't that many of them, right? The CPU is probably the most expensive part of the machine and the most complex. And of course, those are, that's two ways of saying the same thing, right? I mean, computer stuff is expensive because it's complicated, right? It's not like it's big, you know, like I had to pay for all the metal to make this massive, you know, four foot wide CPU. It's expensive because it's really, really, you know, intricate, right, and complex. So, you know, originally you had one and that was because, you know, until you have one, you don't have a computer, right? And then when you have one, you've blown all the money you wanted to spend on that and then you sort of move on, right? So there was a long period of time where, you know, computers had single, had had a single core, single process. Does anyone, I mean, has anyone grown, I just want to sort of figure out, because I'm old, right? You guys are young, how many people, maybe this is the right way to ask the question. How many people have never owned a single core computer? Oh, okay, wow, wow. Yeah, this is the brave new world. I think five years from now a lot of hands will go up, right? And I mean like a real computer, not a phone, it won't do something deaky, right? But I think in 10 years, even phones will have caught up, right? So really, you know, we're growing up in the multi-core world. How many people have ever owned a P4? Good old Pentium 4, oh, here we go. So you guys are gonna, you guys may or may not have witnessed one of the reasons why you now have multi-core machines. Anyone remember something distinctive about the Pentium 4? Yeah, yeah, so there was a period of time where games and computing were essentially achieved by making transistors smaller, okay? Now, smaller transistors generate more heat per unit area. Does anyone remember what the P4 heat things used to look like? They were like that tall, right? I mean, there was just like massive, you know, you needed like a, there's no way you could get that into a compact form factor case, right? Because the heat sink would have had to stick out the side, right? How many people have installed a processor recently? How many people like the heat sinks are now, now we're back to like an inch high heat sink, okay? So what happened, right? What happened is that after years and years and years and decades of cramming more and more stuff onto the same physical dye, we just hit the limit at that, right? And they're both thermal, but there's also leakage power sort of issues that go along with trying to go down into smaller and smaller and smaller transistors processes, right? And so at some point we said, give up, right? This is not gonna work. I can't keep doing this. I'm on an unsustainable path. And what's happened is we started to spread out, right? So if you've installed a modern multi-core processor, they're big, you know? They're bigger than those old P4s. Those old P4s were smaller, right? Now it was too bad they were so small because it's hard to fry an egg on something that small, right? But you could have fried an egg on those things because of how hot they were, right? The new guys are larger. And what's happening is we're starting to expand out. We're starting to trade off core transistor size for area, right? So we're getting more transistors on the dye by adding more cores, right? Now of course this is an interesting train up because it requires that the computer be able and required to execute parallel tasks, right? So if I asked you, would you rather have one processor that's like a 64 gigahertz core or would you rather have 32 2 gigahertz cores? What would you say? I would take, I mean, I think you would take the 64 gigahertz core, right? That thing doesn't exist sadly, okay? So now what we're saying is, look, I can't give you that. So I'm gonna give you the 32 2 gigahertz cores. And I hope that you have 32 things to do, right? If you don't, it's not gonna be that helpful, right? If you have 32, you know, Epi3 is playing at the same time, or if your word processor needs 32 threads to do a spell check or whatever, right? Then you're golden, right? If you don't have 32 things going on at the same time, if like LaTeX needs like, yeah, I really, I'm a little embarrassed about the computer I own right now because it's really over matched to the things I tend to do, right? Like writing these slides, one core, right? The other 63 are sitting there hanging out, right? Having a beer. So, you know, we've, and so this is what's funny. I mean, if you have four, if you have two, right? Maybe this is true, right? But if you start adding cores, if you start adding enough cores to certain classes of machines, you really get to the point where it's not really clear when that's gonna be useful, right? You're doing like really, really, really intensive numeric computing, great, right? 64 cores are for you. If you're running LaTeX compilations, you don't need them. All right, so, uh-oh, I think I broke all the images on these slides, okay? So anyway, sadly, that's not gonna be good. Well, let's go through the text, right? Okay, so the other limitation with the CPU, and it's not really a limitation, it's really a limitation of every other part of the computer, right? So we talked about this a little while ago. How does the CPU compare to every other part of the computer, right? Computer components are sitting around, hanging out. They're like impairing attributes, right? And there's the one, I heard someone say it over there, I'm gonna come back to it. There's the one thing that the CPU just always brags about, right? The other components get tired of hearing it, yeah. It's fast, right? You know, like it's only doing a few things. Memory's like, look, I've got like millions and millions of banks, dude. The CPU's like, no, no, I don't care, right? I can add and subtract extremely rapidly, right? And that's true, right? So in general, the amount of time it takes the CPU to do stuff. It's just way, way, way, way faster than the rest of the system, okay? And this is kind of where some of the, I mean, I shouldn't say kind of, this is exactly where the early motivation for multi-programming and multi-processing came from, right? Is that if I have run a single program on the computer at one time, the CPU is gonna spend a lot of time, most of time, it's time potentially, waiting for other things to happen. And that's done, remember? I spent a lot of money on this expensive CPU. It's not very useful if it spends all of its time waiting for the disk, right? Which is never gonna be as fast as the CPU. I mean, until recently, disks were physical objects, right? There was something spinning in there. It's so weird, right? I mean, I'm so glad for Flash now because it just, there's like that last bit of cognitive dissonance about your computer, right? There was actually a mechanical component in there, no more, right? That's kind of nice. All right, so the CPU is way faster. And where that speed difference is addressed varies, right? So the CPU is actually quite a bit faster than memory, it turns out. Now, this is something that the operating system has really historically not been involved in handling. Normally, this speed difference has been addressed by CPUs themselves, right? So if you're familiar with sort of modern out of order cores, they play a lot of games internally. What you see is a stream of instructions going into the processor and a stream of instructions coming out that have been completed, but that is not what's happening, right? Inside, once those instructions get in there, they're being moved around and reordered and deferred and there's dependencies that are being computed between the instructions and all of that's happening so I can hide the latencies caused by memory, right? You guys know how many people knew that was happening? Oh, it's super cool, right? I should look into this, it'll blow your mind, right? It'll totally change the way you think about CPUs, right? You thought they were simple, no. So yeah, there's a lot going on internally that the CPU is doing and the reason it's doing it is because there's some stupid instruction that's gonna come along and it's gonna require that it grabs some data from memory and memory is so slow, right? And so the CPU is like, what else can I do while I'm waiting for that memory read or write to complete, okay? The disk, so this is something where it starts to be addressed by the operating system, right? Again, the memory speed difference is small enough that the CPU tries to handle that internally. Once I start waiting on things like the disk, this is, or the network, or you, right? This is where the operating system starts to play a role, okay? And yeah, so the slowest part of the system is you, right, by far, okay? It's not even close. So, you know, the computer, I mean, certainly has some time waiting for the disk, waiting for memory, but it has a lot of time waiting for you to sit there and figure out like, which button am I supposed to push? Like, you know, which sub-sub menu has Microsoft Word hidden the one feature I knew how to use in Microsoft Word, right? So yeah, that's, a lot of the latencies on these devices are really caused by human beings, particularly user-facing devices, right? This isn't so true in a data center, but it's certainly true on your smartphone or on a tablet. And yeah, there's not much I can do about it, okay? So, and one of the things, and this will come, this is something that will sort of drive our discussion of scheduling, and maybe this is where we'll stop for today, right? Is, I just wanna make this really, really explicit. How slow you are, right? Okay? So for example, the 15 millisecond rule of thumb, which is something that is sort of taught to UI designers that's supposed to be an indication of responsiveness, right? So when they do studies, this is sort of what they've discovered, that if certain things start to take longer than 15 milliseconds, you, you incredibly slow human being, start to realize that something's wrong, right? You start to be like, oh, this is a little laggy, right? Has anyone described their computer as laggy? A smartphone app is laggy? Oh yeah, right? So you know what I mean, right? It's just like a little, it's a little off, right? It's taking a little too long to respond. That's 15 million clock cycles on a one gigahertz processor, right? That's the processor you have in your smartphone, okay? So the CPU was able to do like 15 million different things in between redrawing the screen before you even figured out that it was slow, right? This is when you're just starting to notice, okay? Smooth video, right? So 25 frames per second is a pretty typical video encoding rate. That's 40 million clock cycles, right? So again, I throw some data onto the screen. I've got 40 million clock cycles to hang out and do other stuff before your eyeballs are ready for the next frame, right? 100 milliseconds, so this is, I found this really interesting. Old telephone systems were really, now new telephone systems, hopefully are not still using this as a constraint, right? But old telephone systems used this rule of thumb because this is apparently the point where human conversational patterns start to break down. How many people have ever talked on like a really slow telephone length that felt like it was being bounced off the moon and back, right? And it's hard to carry on a conversation, right? Cause like you're waiting for the other person to talk and then they start to talk but you started to say, are you there? So again, 100 million clock cycles, right? So you guys are slow, right? And this slowness, right? Particularly when it comes to illusion of, go back to the illusion of concurrency, right? This is what drives the illusion of concurrency, right? I'll have a lot of opportunities to do stuff before you start to notice what I'm doing, okay? So we'll stop here for today and we'll pick this up on Wednesday. Welcome. I am happy to be back. You guys have been here. Get started on this.