 Last size seems to dwindle week by week. Maybe we'll need to do something about this. As it dwindles, maybe you guys can in the back and like come up front. There's lots of room that way. I won't burn so many calories walking back and forth. Can you please? This is my line in the sand today, right here. Five rows from the back. You guys? You? Yeah? Yeah, yeah, I know. I know you're right on the border, but that is the border. No, you've got to move forward. There's got to be a cut off. Morning. All right, so today, this week, we're going to talk about scheduling. We basically, we started this unit about the CPU kind of right at the bot. We talked a little bit about some of the things, issues with the CPU that the operating system is going to try to correct. We discussed some of the abstractions that we create in the operating system to do that. And today, we've kind of reached the top level, right? So we started at hardware. We built up some useful abstractions. And now, we're all the way up to the policy level, where we're going to start talking about how we manage these abstractions we've created and also some of the ways that we try to get good performance out of the system. So this is kind of, this is it. This is the last hurrah for the CPU. Once we talk about scheduling, we're going to be finished. So this week, my goal is today to introduce you to scheduling, kind of talk about some of the goals of scheduling. Now, some of the presentations of scheduling, I've seen don't really do this. They just kind of like jump right into simple scheduling algorithms. But I think it's worth slowing down a little bit and talking about what are the goals of scheduling and also how do those goals connect with the way that you guys use your computers, right? So this is a place where you guys can actually use some of the intuition that you've built up as actual computer users to think about how this stuff works, right? And I lost a slide, so yeah, I know. It's just, there's always one thing in the morning that I managed to forget. All right, cool. So and then on Wednesday, we're going to talk, we're going to go through kind of a rapid fire introduction to a bunch of simple scheduling algorithms. And we'll talk a little bit about some slightly more complex scheduling algorithms and some scheduling abstractions, right? So some abstractions that we use in the scheduling process, things we might assign to threads, different ways we might think about how threads compete or vie for the CPU or different pieces of information that we might want to store along with the thread in order to do better scheduling. And then on Friday, what we'll do is we'll spend one class and we'll look at a real scheduling implementation in a little bit of detail. And that'll be the Linux 01 scheduler. And then after that, we'll also talk on Friday a little bit about issues with multi-core scheduling, which is kind of interesting. This is new. I'm trying to keep this class new and up to date, right? So most machines now, including even low-end phones and tablets, are going to have multiple cores in them. So multiple core scheduling is kind of where it is. And there's some interesting issues that arise in multi-cores. So any questions about the plan? OK, a couple of announcements. So Assignment 01 is out. How many people have started the assignment? OK, awesome. That's good, because you have a week and a half and I get going. And again, so the last thing I need to do today or tomorrow is to just finish describing how we're going to do the testing. And I've kind of reversed myself on that, but I'll update the website once I finish what that means. Week from Wednesday. Yes, yes, at 5 PM. And look, I'm working on getting the slides up online. I get a lot of emails about this. Some of the tone of those emails is a little irritating. I understand that you guys want to have the slides. And I am aware of the fact that I would like to put the slides up online. One of the reasons I stopped doing it is if you go to that page, it takes 10 or 15 seconds to load at this point. So the way I'm putting up the slides online is not scaling, so I need to fix that. They're coming, but sending the emails like, put the slides up online is not a good way to build a beautiful, long, and wonderful relationship with me. I know that the slides need to go up online. I don't appreciate getting little orders over you, but they're coming. And hopefully that will satiate people for another five or six hours so I can buy myself some time to work. All right, so let's talk about last week. Last week we talked about synchronization. Synchronization week, right? You guys have an assignment that is out right now that is on synchronization. So any questions arising either from the material that we went through or from the assignment or from the depths of your fevered imagination? Anything, any questions about synchronization? Anything, anything. So the assignment is just easy, straightforward, no problems. OK, so let's do some review. Starting in the back here. Concurrency is the illusion that multiple things are running at the same time. Yes, everything even. Everything would be great. Atomicity is the illusion that you're not sure. OK, let's keep going. Atomicity, what is atomicity? Concurrency is the notion that multiple things are happening at the same time. Atomicity is everything is isolated in what sense? It has something to do with safety. Malik, I'm not going to call on people with hands up. I'm working the back of the room. Eh, not quite there. Do you want to help her out? Yeah, we're trying to run out the clock back here. Robert, you want to help these guys? That you by yourself. So that's part of doing this. But what is atomicity? Right, atomicity is the illusion that something that actually takes multiple instructions, multiple changes to stay down the CPU happens all at once. So there's no way to observe it at any point in between. I either see it, I have a bunch of changes I need to make to some shared state. And either a thread sees it before I make those changes or after I make all the changes. So this is atomicity. Questions about this? It's important to understand this distinction, particularly these definitions. OK, so let's talk about the assumptions that you cannot make. So people where they're settling here in the back, I've encouraged everybody today to move forward, especially you Vishwa. I like having you up in the front. Here, come up. While you're moving up a few rows, can you tell me one of the things that we can't assume anymore about threads? Unless explicitly synchronized threads may, why do we need synchronization? So that the access to shared resources is constrained. Right, right. But when I'm looking at code, when I'm looking at what a thread's going to do, what can I not assume about that? Yeah. So I can't assume, so I have to assume that the threads can be run in any order. So interleaved execution is your new reality, especially for assignment one. Yeah. Also they can be started and stopped at any time. This is preemptive context switching. What else? I heard it. Yes, they can be stopped for an arbitrary length of time. OK, I think that's it. All right, let's talk about some of the synchronization primitives we talked about last week, OK? Locks, what is the interface to a lock? Two functions, right here. OK, get, which, OK, acquire, and then what's the other thing I do with the lock? Release, acquire and release. And acquire will sleep, and that's still wrong. Dang it. I shouldn't have cut and pasted it. I'm not going to jump up and down again, but you guys know what lock release does. Cut and paste fail. OK, so yes, lock release will drop the lock. Lock release will not sleep, right? Look at me. Don't look at the slide. Look at me. OK, what are locks for? What do I do with the lock? Right over here. Mature exclusion, or what else do we call that? Critical sections, protecting critical sections. I acquire the lock at the top of the critical section, and I drop the lock when I leave the critical section. And dropping and acquiring the lock defines what the critical section is, right? There's no notion of a critical section if you don't protect it using a lock or some sort of other device for ensuring mutual exclusion, right? If you don't do that, then you don't have a critical section. You just have a bunch of stuff that may or may not happen in any order, OK? What's the interface to a condition variable? Three functions. Let's see if we can get one at a time right over here on the right. One, one out of three. No. Next, next, right here. What's the interface to a condition variable? Signal is one of them. OK, what else? Weight and? Right here. Signal, weight, and? Post? Post sounds like a fun call, but I don't know what it does. Broadcast, OK. Signal, weight, weight, signal, broadcast. Weight, weight, sound the condition variable until the condition changes. Signal, signal is one thread that the condition has changed. Broadcast signals all threads that the condition has changed, OK? What do I use a condition variable for? Anybody. So the condition variable provides a more flexible signaling mechanism than locks do, right? With a lock, really I can only signal implicitly that a critical section is available or not available, right? Condition variables allow me to signal that a condition has changed, right? And that condition is usually encapsulated in a what? In change to some shared state, right? It's a condition variable, right? The condition is that the variable has taken on some value, right? Or stopped taking on a value, right? Why are condition variables always associated with a lock? Anybody? Yeah? Because of the shared state, right? The lock protects the shared state, OK? And also the lock allows me to tie together any changes I make to the shared state and the signals that I'm going to send to other threads, right? And if I don't do that, the shared state actually might change in some other way, right? So let's say I'm the last, let's say the buffer is full, using our example from last week, and I'm taking an item out of it. If I take out the item, I've changed the shared state. Maybe I use a lock for that. But maybe I dropped the lock before I signal threads that are waiting to produce into the buffer, right? The problem is that in between the time I drop the lock and I send that signal, another producer may have run and already put something in there. So the condition that the buffer is available may no longer be true, right? And that's why we use a lock. That's why the condition variable interface requires that in order to signal and broadcast, you hold the lock, right? Because it ensures that the state that you are signaling hasn't changed. OK, questions about CVs, condition variables. You guys are going to have to use these on assignment one. Build them first, right? That's the fun. OK, deadlock. Deadlock occurs when what? What's the definition of a deadlock? Let's see here. What about right there? Definition of deadlock. Yep. Don't remember the exact definition. What's that? Right, so and waiting in cycles, will that wait ever stop? No. So waiting is when a set of threads are waiting for each other to finish. And because of the cyclical nature of that, as you pointed out, no one will ever wake up, right? So a deadlock is usually a very serious condition, right? Because there's no way to wake up the threads, and there's usually no way to break the cycle, right? Other than to do something drastically kill a thread, right? Which could have all sorts of other weird consequences. Four conditions for deadlock, right? This is from last Friday. I know that was a long time ago. Long weekend full of brain cell destroying activities, OK? But let's see if we can fire up the brain cells that stored this information, all right? So deadlock and atticker, four conditions. Anyone want to give me one? There's already one that's floating around the room, yeah. Right, so if I can take a shared resource away from a thread, then I can break out of a deadlock. Any deadlock, right? So that's one condition. What's another condition? Protected access to shared resources, right? So I actually have to, you know, if I don't need a lock to access a shared resource, because I've done some tricky thing with the resource itself to make sure I don't need a lock, then I don't need a lock. And then I can't ever deadlock, all right? Three, cyclic dependency, right? I need a cycle in my dependency graph, OK? And fourth, one more. We're really close. What's that? Priorities? No, that's not the one I'm looking for. Fourth, yeah. Multiple, and what does that mean? So what it means is that I can hold one resource while requesting another, right? If every time I needed a resource, I had to surrender all of their exclusive access to resources I held, then I can never deadlock, right? If I only hold one resource at a time, there's no way for me to deadlock, right? And last win, run small catch to this, right? A single thread can deadlock. How? It cries to be required a lock that already holds. OK, good. I attempted to require a lock. OK, good. So back to the top. Your questions about synchronization, right? Have people started to look at the synchronization problems, the little toy synchronization problems that we gave you on the assignment? Who's looked at those, OK? Who's chosen a synchronization primitive to use to solve them? OK, now we're getting into the drugs. OK, get started on the assignment, right? Because you guys actually have to implement those before you can even use them, right? So the first part of this assignment is building your synchronization primitives and getting them to work, OK? The second part is actually using them to solve the problems, right? So you guys aren't even going to get to those synchronization problems until you have primitives that you can use for life. Do you have a question? Yeah. Signal and broadcast, right? So if I have n threads that have slept on the condition variable, right? So they are waiting for the condition to change. And I call signal. The system will wake up one of those threads, only one. If I call broadcast, the system will wake up all of them, OK? And this came up, I think somebody asked about this toward the end of last class, right? So in general, I guess what I would say from a programming perspective, broadcast is safer. Because let's say I have a condition like the one that we discussed in the example that we did on Friday, which was that I had a buffer, and the buffer could be in three states. And I could have potentially, depending on the ordering in which threads run, I could have threads waiting on the condition to change. Some of them are producers, some of them are consumers, right? So some are waiting for one condition, some are waiting for the other. If I use CV signal, all I know is that I'm just going to wake up one thread. But I have no idea what thread is going to wake up. And unless you can really convince yourself that the thread that wakes up is always the right thread to wake up, then it can be safer to use broadcast. What's the problem with broadcast, though? Anybody? Venu? You look like you were raising your hands, so I'm going to call. What's the problem with broadcast? Signal wakes up one thread. Broadcast wakes up all threads. What's that? Well, yeah. I'm cabling an answer here from parts of multiple answers. What's that? Well, right. So the first thing, remember, CV weight drops the lock, but when it gets up, it holds the lock. So the first thing CV weight has to do when it gets up is hold the lock again. So now I've got n threads that are banging to get into the critical section. And in many cases, what are many of those threads going to do again immediately? They're just going to call CV weight again. Because they're going to wake up, they're going to check the condition. The condition has changed, but it hasn't changed in the way that they wanted. Or maybe it changed, and by the time they woke up and checked, it changed back to the way that they had originally caused them to wait. So yes, broadcast will wake up all the threads. And each thread will have to reacquire the lock, check the condition. And in many cases, many of those threads will immediately go back to sleep. So you're paying the overhead of all that extra context switching and all those extra mechanisms to in order to perform the broadcast. On the other hand, again, unless you can convince yourself that signal will always wake up the right thread, or a thread that can actually do something helpful based on the condition, then it can be safer to use broadcast. Pay the penalty and get it right. Any other questions? This is a good question. Any other questions about synchronization? I'm not going to tell you how to implement it. So my advice is to read the assignment and then to go look at how semaphore is implemented and to use many of the things that are already there. But you may have to build some new features to do this. One of the things I'm doing about the testing, the original testing scheme was to have you send us a couple files. I think we're actually going to invert that. So I'm going to tell you, you apply a patch to this particular version of the kernel. And we're going to replace a couple files. But I want you guys to feel free to, for example, modify stuff in thread.c. If you want to change the primitives that we've given you, some of the ray stuff, whatever. Again, it's your kernel. So there's a small set of changes we will have to make for testing. But other than that, it's up to you to do that. So I'm not going to promise that all the functionality that you need to wake up and have threads go to sleep in the way that you will need to implement CVs is there. It might be, but I can't remember. So today we're going to talk about the schedule. Yeah, that's all right. I just had a question about the project. How are we going to test? That's a good point, actually. So OK, good point. So we will probably have to require you to use a particular set of names. So I'll change the assignment to make sure that you guys use the set of names. And I'll give you what the interface is. Because we have a testing code for that, that we're not going to release. And as I stated in the assignment, this is an exception to our usual stated policy of giving you guys the testing suites that you need. But in this case, it's because we want you to build a test yourself. But you're right. Yeah, we do need to figure out what that interface is and standardize on the name. That's a great point. Stuff I don't think through. OK, any other questions? All right, so again, so today we're going to talk about scheduling. We're going to focus on scheduling this week. So we've talked a little bit on and off about scheduling. And I think you guys know this. And that's a good chance for us to review some of the stuff that we've done in our sort of CPU thread unit. So what is scheduling? Anybody want to venture a guess? What is for? OK, so now you're telling me what scheduling is trying to do. But what is it? Just like, what is scheduling doing? OK, so scheduling is going to use the mechanism of context switching. OK? It's switching between threads. Forget the time run up for now. Scheduling is just when the operating system has a choice about which thread should have access to the core or cores, how do I choose which thread will run? So it's the process of choosing the next thread or threads to run on the CPU or CPUs. Again, for most of the next day and a half, I'm going to talk about this as if it's a single core system. Some of the algorithms that we'll talk about will generalize easily to multiple core systems and others don't. And there are some other interesting issues that arise in multiple core scheduling. And again, we'll talk about that in a Friday. And I just said that. Yeah, good, OK, I get ahead of myself. All right, so next question. Why do I need, why schedule threads? Why is this necessary? Fundamentally. Right, I've got this illusion of concurrency. And the illusion of concurrency is based on the reality is required because of the reality that there are more threads than there are processors. And so I have to make a choice. If I had a core for every thread on the system, I wouldn't have a scheduling problem. I would just hand out, I would say to each thread, I'd say here's your core, go have fun. And you never need to stop running. So I never need to make this choice. So again, this scheduling is the policy of how we implement this abstraction of concurrency. And this goes back to our earlier discussion about multiplexing and why the kernel needs special privileges. So this is another case where I'm multiplexing the resource, I'm dividing up the core cores that I have between the threads that are active on the system. And in order to do this, I need these special powers. So the kernel needs to be able to tell a particular thread, you're done, you're not going to run anymore for now. I need to use the CPU for another core. And this is one of those things that applications submit to as part of running on the system, is allowing the CPU, sorry, allowing the operating system to gate their access and control their access to resources, including the CPU. Any questions about this? This is review going back a couple of weeks. I thought it was kind of good to talk about. OK, when does the scheduler run? OK, when the timer interrupt goes off, when else? There's actually, I've got four things up on this slide. That's one of them, right? When else does the operating system get to schedule a thread? OK, so context switching is the mechanism, right? All of these involve a context switch. One at a time. Yield. Good, OK, we're going to talk about yield on the next slide. We haven't really talked about yield yet, but I'm going to talk about yield. So yield is when a thread will actually say to the operating system, hey, I could keep running, but I don't want to. I'm going to let you make another scheduling decision. I don't need your help with anything right now, and I'm not necessarily waiting for anything to happen, but I just kind of want to be rescheduled. And a thread might decide to do that if it's like a nice thread. OK, yield, hardware interrupt, sorry, timer interrupt, what else? And how do I block for input? When a thread asks the kernel for help with something, right? When the thread makes a system call. Because I trap it to the kernel, I context switch into the kernel, and now if the kernel wants to, it can stop that thread. Now, whenever I make a system call, whether it's a non-blocking system call that can return immediately, or a blocking system call where the thread has to wait until something happens, I have a chance to make a scheduling decision, right? Because the operating system has started to run, OK? In the case where it's a blocking system call, I have to schedule another thread, right? Because that thread cannot be run for some period of time until something else happens, right? A disk IO completes or whatever, yeah. When a thread exits, all right, you guys are good, right? Got all four. Voluntary yield, which again, we're going to talk about on the next slide. Blocking system calls, thread exit, and when the kernel decides that the thread has run for long enough, and the way that this is implemented is as Ben pointed out, through a timer interrupt, right? So number four, now I can have, you know, depending on the system, I'm trying to think of if I would have some mixture of one through three, but I would probably have, definitely have one through three, right? When a thread exits, clearly I need to run another thread. When a thread asks me for help, especially if it's a blocking system call, I definitely can't run that thread, so I have to choose something else to run, right? And if a thread calls yield, then again, what it's asking me to do is to stop it, right? So I should probably do that, or at least it's giving me an opportunity to stop it, right? The existence of number four is what differentiates preemptive and cooperative scheduling policies. So on a preemptively scheduled system, the kernel can stop a thread at any point, right? Whether or not the thread has asked to be stopped, exited, or made a blocking system call, and we talked about the mechanism for that, and can someone remind me what it is, Ben, just said it. How do I implement preemptive scheduling? How do I give the kernel a chance to run? Through a timer, right? So the timer and up causes the system to trap into the kernel, and at that point, I'm allowed to stop the thread that's running and choose something else to run, OK? So if number four exists, I have a preemptive scheduling policy. I can stop a thread that hasn't asked to be stopped. Number four doesn't exist, and I have a cooperative scheduling policy. And the points that the kernel is allowed to make scheduling decisions are on some level determined by the applications themselves. So an application that sits in a while one loop for a long time may not ever give the kernel a chance to make another scheduling decision. So that could be bad. That's why we have preemptive scheduling, OK? So let me talk about yield just for a sec, because this hasn't come up earlier. So kernel threads, and I don't know if there's actually an interface in the standard Unix system call interface, if there's a call to do this. But I wouldn't be surprised if there is. But particularly in the kernel, kernel threads can call a function called thread yield. And yield is essentially a way of, we talked about before, how threads transition between different queues, right? So if I make a system call, I go from the running queue to the waiting queue. Yield is how I move from the running queue to the ready queue directly. And I do that voluntarily. I say, again, for right now, I don't need your help with anything, but I would just like to be stopped. And this could be a good thing. I mean, if a thread woke up, it checked whether it had any work to do. It didn't have any work to do, and it doesn't have anything else to do. So it essentially says, hey, I'm finished, and I would like to yield. So this is a voluntary mechanism, allowing well-behaved threads to tell the CPU, hey, I don't have anything else to do right now. So if you have another thread to run, then that would be a good thing to do. And yield is essentially a cooperative mechanism. It allows a thread to explicitly tell the kernel that it's not doing anything important anymore. You may not, the thread may not have anything else to do at all, right? Okay. So let's talk about policy versus mechanism, because we've come to the point in our discussion of the CPU where this split is nice and clear, okay? So we talked a little bit about early in the class how one of the goals of the system is to separate policy and mechanism, right? And separating policy and mechanism allows me to separate their implementations, right? Allows me to, for example, write a variety of different scheduling policies, right, that decide how to choose the next thread while relying on the same fundamental underlying mechanism. So yeah, the kernel makes that decision, right? You're essentially telling the kernel, I'm done for now. I'd like to be like, I'm still alive, right? I'm not blocked waiting for something, but you decide when to run me next, right? So that's one of the things about yield. You don't have that, necessarily have that control, okay? So let's talk about, and we've already talked about this stuff, right? We spent most of this unit talking about mechanism, right? We talked about context switching, we talked about thread abstractions, which are a way of organizing information that's necessary to do some of this stuff, right? We switched between threads by moving it between these cues, right? Those cues are abstractions, but moving this, putting things back and forth, this is all mechanism, right? The context switch is mechanism, right? And now we're gonna talk about the policy. So this is gonna be what we're gonna do this week. But let me just go through this because I wanna make sure that this split is really clear, right? Because the fact that this split exists is a really useful design principle, right? Okay, so, deciding what thread to run, policy or mechanism? Policy or mechanism, anybody? Policy. Policy, who said mechanism? Why? Right, right? But that determination itself is a policy decision, right? Okay, so maybe we can contrast this. Contact switch, mechanism, right? Maintaining the ready, running and waiting cues, mechanism, right? What about if I have something that gives preference to interactive jobs? Policy. Using time run-ups to stop running threads, mechanism. Choosing a thread to run at random, policy. Okay, good. I know you can tell by the indentation, but you weren't supposed to. I know, I'm only, I only have so many skills, okay? I did think of that though. And I actually, originally the slides had policy and mechanism, but then it was too obvious, right? So you're right, it's still a little. Okay. The last thing I wanna impress on you is you guys look into this. And this is gonna be hard to really drive home because unfortunately on OS 161, we've never had great workloads that will bring out different features of scheduling. So for assignment two, we're actually gonna ask you to write an experiment with a couple of simple thread schedulers, right? The problem is that we don't have a realistic workload that allows you to say, oh, this thread scheduler is way better than this other one, right? So I'm just gonna have to try to argue this from first principles, right? The fact is that how the CPU is scheduled and how I make this decision is really incredibly important to how the system runs. Why is that, right? And why in particular is the CPU so important to schedule, right? There's all these other parts of the system. Why is the CPU so critical? How do I do the CPU right here? Yeah, you don't know. What about working down the road toward the code rack? He doesn't know. Why is the CPU so important? It manages all the other devices. That's close enough. I don't know, but so if I wanna use the disk, what do I have to do? I have to use the CPU, right? Well, I don't know if it's the main computer, but the computer I think is the whole collection, right? It's required to use every other device, right? If I wanna use memory, I need to use the CPU. If I wanna use the disk, I need to use the CPU. If I wanna use the network card, I need to use the CPU. So this, how I schedule threads determines their access to essentially every other resource on the system, right? We'll talk later about how I divide up other resources like memory, for example, right? But a thread that's not scheduled can't use it to memory. So there might be memories sitting around, waiting for it, where it's stored stuff that it wants to come back to, but if it doesn't have the CPU, it can't use it. It can't request more, et cetera, et cetera, right? So this is why CPU is scheduling, it's having such a huge impact, okay? So, and intelligent, the difference between intelligent scheduling and stupid scheduling is essentially the difference between a computer that you like and a computer that you don't, right? Intelligent scheduling will make your system seem really fast and responsive, even if it's like an old, I don't know, I mean, old 386 is probably just don't seem responsive anymore, period, right? But, you know, maybe if it's an old, like, you know, at least sort of late model, penny and four or something, right? Depending on what you're doing, I mean, if you have a smart system, right, and allocates resources well, it'll make your system seem really good. And stupid scheduling will make your system seem terrible, right? Really slow and sluggish, yeah. How much of it depends on the scheduling process and the code and... Again, I mean, one way of thinking about it is that the hardware inside your computer is not changing, right? So once you buy a computer, you have a fixed set of resources. And at that point, it's all about how those resources get used, right? You're right that to some degree, I would argue that the computer systems community has gotten out of having to write really sophisticated schedulers. And the reason is that hardware just has kept getting so much faster, right? So hardware has kept biggling us out, right? You know, you get this new version of Microsoft Word and it's slow and terrible, and then you get a new machine and it runs okay for a couple weeks, right? So that's kind of like, that's been the story of technology. Now, some of those curves are starting to flatten out, right? So I think it, and especially on mobile devices, right? I mean, some of those curves are really much more battery dependent than they used to be. The point is that, yes, to some degree, hardware has continued to move the bar, right? So yes, if you have a system that has a dumb scheduling policy, the best way to make it better is to add some more, you know, or a good way to make it better, or a guaranteed way to make it better is to add some more RAM or add a faster processor or something. Okay. So this is how I decided to break down kind of the interaction between what you expect from your computer and what the scheduling discipline provides, right? So I wanna start with kind of how people use their computer, how you guys use your computer, and use that to evaluate the different scheduling disciplines, okay? So when you're using your machine, I think that there are three, this is my taxonomy, but I think there are three things that we expect from our computers, right? The first is that when I do something, it responds, right? It's responsive. When I click on something, it indicates that something has happened, right? It may not finish what I ask it to do immediately, right? But it gives me some feedback that says, oh, I've started that or maybe if when I'm asking it to do seems pretty easy, it finishes rapidly, right? The second which I think is interesting and more a function of media on computers is this idea of the computer continuing to perform some regular tasks in a smooth and well-defined way, right? So what's an example of something like that that you guys do all the time? Watching video, for example. MP3s, audio, things like this, right? So these are examples of something and I kind of think of this as active waiting, right? I started something and I'm paying attention, right? I'm not interacting with the computer but I will notice that the computer doesn't do a good job of scheduling, right? If the audio starts to skip, you know, if the video sits there and starts buffering or starts getting old choppy or whatever, you will notice that, right? Despite the fact that it's not really interactive. In the usual sense of it, right? And then the final thing I expect my computer to do is to finish things that take a while, right? So, I think sometimes there's two kinds of things we ask our computers to do. There's the ones that we're willing to wait for and then there are ones that we're not willing to wait for, right? And that we just expect to happen overnight. So last night I backed up my wife's laptop again and it had to start over and it took, you know, 13 hours or something, right? And I didn't spend 13 hours staring at the progress bar, right? I probably, you know, 10 years ago I might have. But now I've kind of come to this attitude where it's like, you know what, computer? Like, that's fine. You know, I'll forget about this as fast as possible and then maybe when I wake up in the morning you'll be done and it just finished like 15 minutes after I woke up, right? So it was like, okay, it really did take a while, right? So let's talk about how these expectations nap down into scheduling policies, okay? So again, responsiveness. When I give the computer input, it responds in a timely way, right? It may not finish the thing I asked it to do but at least it gives you some, you know, feedback that it started, that it kind of understood what you wanted it to do, right? And this constitutes most of what humans do with our computers, right? Most of what we do with our computers is interactive activities, right? There's actually much, much fewer examples of the other two here, although they might be equally important. And think about it, I mean, that's kind of what makes computer, entirely what makes computers different than television, right? Television is totally passive, right? Computers are interactive, we expect computers to do that. Television, okay, if you change the channel you expect it to do something. So give me, I mean, this is obvious stuff but give me some examples of responsive tasks, right? What's something that you would do that you expect the computer to respond to? Robert? Exactly, right? So, you know, web browsing, when I click on a link, starts to retrieve the webpage, right? If I'm editing, I'm typing things at the keyboard, every one of those keystrokes creates more data that's being read by that program and displayed on the screen, right? And then chatting, right? If I hit send, I actually want the chat program to do that, right? And when these programs violate our expectation it gets very frustrating, right? So I've been using a Google voice chat program for the past three, four months and I like it on some level, but it has this irritating feature where maybe 10% of the time when you type a little text message and hit send, it takes like 10 minutes, right? So I'm sitting there spinning, right? And you're like, are you ever gonna finish? You know? And so, I've realized that it actually does finish, so I just put it back in my pocket and wait for it to get done, right? But for a while I would wait for 10 seconds and I would kill it because I would think it was broken or something. Probably it is broken, there's clearly something broken about it, right? But yeah, so when these programs violate our responsive expectations using the computer becomes very frustrating, right? All right, so again, continuity, right? Continuing to perform some task that has deadlines, right? Over time. And as I pointed out, as we started to use our computer's media devices, this is more and more important, okay? And examples of this we already kind of went through, right? But I like the top one, right? Blinking the cursor, okay? That seems kind of like a stupid thing. But if you were sitting there at your computer and you had a terminal window open and you hadn't disabled the blinking cursor, which I very kindly did for all of you on the virtual machine that you're using for this class, right? Because for some reason, a bunch who now has a blinking cursor by default, which reminds me insane, right? But if you were sitting there and the cursor was like blink, blink, blink, blink, blink, blink, you know? Like you'd be like, what is going on, you know? You'd start to poke around and there's some big background process that's running a killing of anything. So anyway, so this is an example of something as dumb as it sounds, right? That really does, you know, your expectations are that cursor is going to blink really, really regularly, right? Playing music or movies is another thing, right? I mean, there are buffers on these cards, but they're small, right? And so on a regular basis, I've got to feed more audio data into the buffer on that audio card so that it doesn't stop, right? Or skip or do something else, right? And then little things in JavaScript on your web browser, right? I mean those, again, that have some sort of regularity, okay? And then finally, these background tasks, right, are completion oriented. I couldn't find a good term for this, so I used three interchangeable. And completion implies this passive waiting, you know? Like you've asked the computer to do something and you kind of want it to finish at some point because if it doesn't finish, it's really going to get annoying. But in the meantime, you maybe want to use your computer for other things, right? You want to watch a movie, you want to continue to interact with it, right? You don't want it to just shut down completely, you know, until the background task finishes, right? Until I finish my backup, this thing just stops, right? So other than backup, can anybody think of other examples of these kind of tasks? What's that? Installation is a good one, anything else? Virus scans, yeah, exactly. And a lot of these are not user initiated, right? A lot of these are initiated by your expectations about how the system runs, right? So for example, a system backup, I've set up my system to backup at certain intervals and I just want that to happen, right? Indexing files on your computer, I think is a good example because why do you do, why does your computer do this background indexing? Why? Because when I search, it's fast, right? Like it's essentially front loading a task. So when I start, you know, typing into the spotlight bar on my Mac, things come up really quickly. The reason they come up really quickly is not because it's doing a live search, it's because it's already built the index, right? While the computer is sitting there, you know, serving a slideshow or something like that, okay? So, and again, I mean most applications combine some mixture of these activities, right? So a music player, you know, changing tracks, that's a quick responsive expectation, right? You know, playing the track is the watch and then the finish oriented task is updating album artwork, right? That's just supposed to kind of happen, right? Without my really noticing. Web browser, follow the link, play web video, index my searches, right? So any questions about this taxonomy? I'm hoping that this maps down well to the expectations you guys have about how you use your computers, right? So, now going back to scheduling, right? So the idea of scheduling is what we're trying to do is we're trying to balance, right? Two things, one is meeting deadlines, okay? And I'm gonna talk about how deadlines are involved in two of these user expectations in a second, right? And the other is optimizing resource allocation, right? So here's a little brain exercise to help you think about how these two things compare, right? You know, you guys graduated from SUNY Buffalo, you get an A in this class, you know, you get a job at Facebook because, you know, they know how awesome you are because you took this class and you got an A. And, you know, every week it's kind of like, you know that there are these ongoing tasks, you're building a new feature for the site or whatever. And, you know, on Monday morning, you go into work and you kind of say, okay, how am I gonna plan out my week, right? How am I gonna plan out my week and kind of optimize my own resources so that I get a lot of work done on these tasks that I'm trying to finish, right? Okay, and you sit down, you do that, and you've got everything all in place and you're kind of working away on whatever feature it is that you're working and you're interacting with other people and there's a lot of different resources you have to use. And then, you know, Mark Zuckerberg walks in and it's like, hey, you know, there's a bug in the thing that you built, you know, two weeks ago, you know, that is crashing the site, okay? You need to fix that right now, okay? And then this really nice plan that you had for the week, the really nice plan that you had for the rest of your afternoon, the concert tickets that you had for that night, the, you know, reservation that they're really hard to get into restaurant in San Francisco that you made, it's all over, right? Like, you are ASAP, get this thing done as fast as possible, doesn't matter, right? So, and systems are kind of constantly torn between these two things, right? On one hand, in order to get some of these background tasks done and to do a lot of other useful work, they're trying to carefully allocate resources, but then when you click on the link, it's like, well, okay, you know, perception delay, I've got five seconds to redraw the screen and then I've got to go get this webpage, right? So that's, you know, think about your computer, you know, you're sitting here in class and it's kind of sitting there being like, okay, man, I'm planning my next five minutes, I'm gonna do this, I'm gonna do that search indexing, et cetera, et cetera. And then things get boring in class and you start looking on YouTube and it's like, well, you know, now I have deadlines, right? And I think of, you know, responsiveness and continuity are about deadlines, right? Responsiveness is about meeting unpredictable deadlines. Suddenly you sit down and act with a computer and there's a new set of deadlines and those deadlines are driven by you, right? Your keystrokes, your input, your clicks, okay? Continuity-based tasks are a little bit different, right? Continuity-based tasks establish a set of deadlines in the future that the system now has to meet at regular, right? So that's the difference. When you start playing a video, you've essentially set up two hours with the small little deadlines for your machine that it has to meet, right? And if it doesn't meet one of those, you'll get irritated, right? Because again, the movie will stop or skip or whatever, okay? Throughput on the other hand and being able to finish these completion-oriented tasks requires this careful resource allocation, right? So this is, in my opinion, this is the big, you know, this is the big tension in scheduling, right? How do I have a computer that's interactive and useful for doing continuous things like watching a video and playing music? Well, at the same time, it does a good job of optimizing its resources. Here's the thing though. Humans notice deadlines and responsiveness, okay? You notice if your screen stops refreshing, right? You notice if the movie skips. What you don't notice is resource allocation and how effective it is, right? So for example, you hear people say this all the time, my computer feels slow, you know? Like, my computer's feeling a little sluggish, you know? I think I need to take it to the Mac bar so they can like, you know, scrape some mud off the tires or something. I don't know. Has anybody heard anyone ever say this? Okay, you've got dork friends. That's good. So, wait, tell me the story though, quickly. Okay, okay, so I think my intuition is that this is a much less common thing for somebody to say, right? Most of us have really very little idea on a day-to-day basis how many resources our computers are consuming. We just don't know, right? I hope that things using all of its RAM. I don't know. I have no clue. All I know is that it's not as fast as it used to be, you know? It doesn't feel fast, it feels sluggish, right? So, and again, and this is fundamentally going back to that thing that we talked about before, right? Your time, computer time. Responsiveness wastes your time, okay? That's irritating, right? And your time is actually really important, I would argue. And the poor throughput is just the computer time, right? So, you know, my computer last night had to work overtime to finish that back up, right? I don't care, you know? I, you know, it's, it's, it doesn't make very much an hour, right? I don't know what electricity costs to power that thing, but it's not that much. So, this is, so as we talk about schedulers starting tomorrow, right? This is how I want you guys to think about how do you, how we evaluate schedulers, right? Can the scheduler meet deadlines, right? Can it meet unpredictable or continuous predictable deadlines? And how well does it completely and fully allocate system resources? And as I talked about before, how I allocate the CPU has a big impact on how the rest of the system resources get allocated in use, right? And again, on human-facing systems, interactivity is almost always wins. There's usually big, big sort of biases in the direction of interactivity on these types of systems, right? Because, you know, humans don't want their time wasted and your time is much more precious and in some ways meant much less compressible than computer time, right? Okay, just one quick note here before we leave. So, I'm not gonna talk about real-time scheduling because there's a whole class here that looks at real-time operating systems. But, again, so we've established that deadlines are important, right? And deadlines are important because when computers don't meet deadlines, human users get annoyed, okay? On real-time system, deadlines are the only thing that that system is allowed to care about, right? And it's because, you know, like, if the robot task forgets to turn off the motor because it was, you know, I don't know, if it's like running the backup or whatever and it goes to feet too far, then, you know, like, there's the end of your, you know, $2 billion in Mars Pathfinder mission or whatever, right? So on real-time systems, you know, like deadline, meeting deadlines is completely critical, right? On human-oriented systems, meeting deadlines is just the thing that we focus on a lot, okay? All right, next time we're gonna go through simple policies, we're gonna go through some scheduling abstractions and we will talk more about the stuff. See you on Wednesday.