Good morning, everybody. Good morning. All right. Second week of class. End of the second week of class. And so today, we're going to wrap up our discussion of bread and structure. We'll talk a little bit about, we're going to finish up from last time a couple of things about context switching that we didn't get to. We're going to talk about what a thread is, right? You guys pretty much know this now, but I think it's worth sort of comparing a little bit, we'll talk about maybe why you want to use threads in the program, right? And how threading differs as a programming model for handling concurrency from working out multiple times. Now we're going to talk about threading implications, because this is kind of an interesting design discussion here. So you can, from a threading user's base, we'll talk about how, which is an example. You can also put them in the frontal, which is more common now. Both of those have their blossoms of minds, so we'll talk a little bit about what those are and why. Because, and actually I think this is a good discussion on how, because it helps drive home some of the key things that we've been talking about, context switch overhead, state, and overhead associated with state. So some of the pros and cons here, if you understand the pros and cons of user's base versus terminal threading, you really manage to internalize what we're talking about, which is the point, right? And then finally, we're going to finish up today of talking about thread states. So we have to start an abstraction. And one of the things that we can do with abstractions is we can start to talk about them as these sort of independent things that can be doing something that can be in different states relative to the system. And we'll talk about what those states mean and what. So assignment zero is completely out. Everything's up there. I would know how it was released. And I was poking around a little bit. And there were not very many people who had uploaded the script, so it makes me a little bit nervous. So the assignment zero is out. And assignment zero is not supposed to be hard, either. Actually, if you're struggling with assignment zero, I would encourage you to come to office hours, send an email to the staff, get help now, because stuff ramps up really fast. And assignment one, which we're going to release on Monday, is much more difficult than assignment two. We haven't actually written any real code for assignment zero. So the offer asking you to do for assignment zero, you've got to put in some debacle statements or something. That is easy piece of stuff. For assignment one, you're going to actually have to build a little bit of stuff in the kernel. It's going to have to work. And that's when the bar starts to come up. And then assignment two and assignment three just kind of keep going. So this class builds on itself. And the assignments get more difficult and more challenging as we go through this semester. So again, right now, we're in this kind of weird, and weird period where you guys have to turn anything in. So I can't tell what's going on. But if you need help, if you're struggling, if there's things that you really don't understand, please email us. We're not always going to answer your question. And maybe that will frustrate you. But part of what you need to learn to do in this class, and in general in your programming life in the future, is find ways to access resources online. So maybe other positives that, oh, no, you can't use Google or whatever. Use Google, right? I mean, there's a lot of great resources out there about Git. There's a lot of great resources about GV. There's a lot of tutorials about how to use various command line tools. So go find those things, right? I mean, you shouldn't think that the material, as far as the programming assignments are concerned, there is not enough up there to teach you how to do whatever else you need to do. Some of the stuff, you will have to go and find for yourself. And that's part of the journey, part of the fun, right? OK, so a couple other things. So we're trying to adjust the recitation, the recitation. So there are two issues with the recitation. One was four, I think, is probably one more than is ideal for this class. And a personality here has to essentially regurgitate the same material four times, right? So if you feel some pity on her, and you imagine, if I had to get the same lecture four times a week, I think by the end it would be really weird, because I would be trying to use myself by making things different, right? So I think that maybe we'll try to cut it down to three. The ADM recitation is popular. That recitation, I think, is one of the state public. The others are all sort of candidates to move around. The other problem with the recitation was one of the rooms didn't have a projector in it, which is fantastic. We were thinking to set all the bombs off and she went there to teach. So we're going to look for the projector. We've already moved two of the recitations. And again, if the Tuesday noon recitation, that one, according to Sonali, was not that well attended. So that one might go away. Both the Thursday, ADM and Tuesday 12th year recitations are now in the Davis 113. It's a much nicer room. It's in our building. And so we've done that. I'm actually trying to get all of the recitations in the Davis 113 by hand. But for now, those two are definitely moving. All this stuff's updated on the website now, so if you have questions, go over there. And yeah, so we'll probably put a poll up on the website. Please, if you can make a recitation and we ask if you can make a recitation, say you can make a recitation. We're going to try to find three recitations and three times that cover the entire problem. So please, you can help us out. And check out recitations that you can attend, not the one that you'd like to attend the most. OK. The office hours schedule has also changed a little bit. The website now has video on it. So all the videos of the yesterday's lecture are up there, and we're going to kind of keep adding things, like some other videos of all day in terms of maybe a screencast, like people have to be assignment a little bit or some other things. But anyway, so keep up to date on the website and we'll try to do stuff as well. The slides are coming. There's still a little bit of a noise process for me to go through to get the slides up online. And yesterday, I was consumed by the time. So the slides for Wednesday and slides for today I will come up with a sandwich. All right. So Wednesday, questions about Wednesday. Wednesday, we talked a little bit about the limitations of the CPU that the operating system tries to address. We talked about concurrency, the illusion of concurrency. And we talked about context, which is the mechanism that makes the illusion of concurrency possible. So questions on any of this? Yeah. Just real quick, I was on the line with the reading of context. It seems that some places use the terms synonymously with multiplexing and with some other places of it. So are they the same? No. Well, OK. Here's what I was saying. This is my class, so I get to make good notes. Context switching is a mechanism by which we implement CPU all the time. If we weren't able to switch between the right context, we couldn't actually multiplex the CPU. Or we could, but we'd have to go back to this whole BAP schedule idea where we'd have to run something and build a finish, let it stop, and reload a whole loop. So the ability to switch context. And again, if you look in MIPS, there are some hardware features that allow that. So things like the kernel-only registry, those are hardware features that's designed to enable them. So when the kernel starts running, it's got a little bit of space that it can use before it saves all the other registers that the kernel needs. Also, the exception PC is another feature that's built with that. So when I start executing in the kernel, I don't go away, I'm afraid that this exception may not happen to one. But again, I think a product's machine is a mechanism that allows us to multiplex. Does that make sense? All right, any other questions? So it's a good question. All right, so, yeah, I've got a good question. Is there a difference between a friction happening with a foundation, a difference in time, and then I need to win the idea of having to make a difference with a fight? I don't think that's a difference. All right, so, right, okay, good question. Yes. So remember what we talked about before. There are at least hardware interrupts, which are generated by devices, okay? And if I'm a user application, I can be running along and hardware can happen and I can switch into kernel mode and I need to cost it, right? Maybe I kind of cost it. Maybe I was the one who initiated the disk reading but I didn't cost it by executing an instruction, right? Whereas, I can see, I can see when you're talking about, you know, types in particular, is this what I'm gonna name, what, what, what, what do I, what do I do to my, right? And what, I want to read and write. What are, now I know what that is. Now I know, I know what they're reading, right? So what, what are we gonna write? So in order to form a read and write, I have to use this as a small instruction machine that I have to be asking the CPU to do this thing. I'm sorry, asking the kernel to do this, right? So I think the difference between scheduling, right? Scheduling is called a type of timer, right? Which are not under the operations control. Whereas, asking the kernel to do this thing and forming the wider region of the body of the CPU doesn't call its. So that's what I, I think that's a good example of the difference between, you know, non-collitional kind of activities, right? Where I got stopped and the restarted later and to the front, there were 20 of them that looked like any of them. Oh, all right. And collitional kind of expression where I get a lot of control because I'm asking the kernel to do something about that. All right. All right, any other questions? They're a good question. Yeah, okay. Yeah, the notion of contingency you were talking about last time. So it basically came down to like a timer interrupting every very often. Right. So that means every time you want to switch in between each small piece of each program, you have to go through all the processes of saving the stage and all that. We're cool, we'll get there. I think I know where you're going with this because that seems expensive. Yes. And we're going to talk about that as soon as I get to the review. Yeah, it's a great, it's a great point. And it's an interesting, it's an interesting point that points out one of the trade-offs we're talking about. Yeah. Can we talk about the loss? Yes, I can. And I will do that next week. All right. So next week we're going to talk about second position. And that's fun stuff, actually. I don't know, I don't like all this stuff. But I think the synchronization next week I think it's going to be fun. And you guys are going to experience it more, right? You will probably get on the system multiple times when it works, it's not going to work, right? Yeah, how does the DNA fit into this? Are we going to be talking about that in this class? Yeah, what are we talking about now? We can talk about DNA. And yeah, actually, we will talk about it. We will talk about it. We will talk about it. All right, any other questions? Great questions. Good. That's good. All right, so let's do our review. A transition between two is about just a small A. Everybody. So I'm going to change my mind. I'll text you, see how long it's going to take me. All right, what are some problems with the CPU that the operating system tries to address? Now I'm going to have to take another question for a second. Let's start back here. What's one of the problems with the CPU? I don't know. I just left it here. Oh gosh, it's here. What's that? I guess I can't pick on you. Oh, here it is. What's one limitation of the CPU that the operating system tries to address? What about speed? Speed is a part of one of the answers. What's specific? Can you help them out? No, OK, so the CPUs are expensive. But what does that mean? Let's keep going. Any ideas? No ideas at all. All right, here. So speeding costs are part of two of the answers, but they're not the answers. Do you want to venture again? I think it's one of the things you see. I think things are beat-related. It's coming back to you. Like multiple problems of running something like that. I don't know. I can't think. Over here. What? There are fewer CPUs. I don't have enough CPUs. That's the most fundamental limitation. I don't have enough. I only have one or two or maybe four or four or eight cores. Maybe 16 cores. But I've got a lot of threads that need to run. A lot of things that I find difficult. And I'm just going to look at them. What's the other limitation? Do you think we're getting the most of the CPU? Do you think we're getting the most of the CPU? OK, so that's a good answer. It's something I'm looking for. There are usually a limited number of hours. Sometimes I need 10 hours to be shared. But I don't have time. That's the first part. I mean, some are at speed. Yeah, so we've got that answer. That answer's taken. Speed. Something about speed. Does it have anything to do with that? It comes so fast. It has to wait for the... Yes! Thank you. The operating system is way faster than other parts of the system. Discs. And even better ones. And disks in our own devices in particular are things that the operating system will actually help find latencies from in the CPU. Memory has a lot of memory. Memory is what you have as part of a lot. But other devices. If the CPU had to wait around for these devices to finish what they're doing, it would waste a lot of cycle. OK. Batch schedule. What is batch schedule? OK. To complete one test versus completing the first test. Yes. I run one process to completion. And I run another process. I run another process. What's the problem with batch schedule? We just talked a little bit about something that would be a problem. If it's hung up waiting for one of the processes, it can't do anything else with the resources. Well, it wouldn't be waiting for a process. It would be waiting for a device. So if a batch has got a process, does I owe, the CPU just sits there doing nothing. Potentially. And fill the I owe. But this is one of the issues of batch. OK. Slow device is going to own a CPU. The illusion of concurrency. This is one of those matrix X things that the operating system does. So how do I implement that illusion right here? She doesn't know. You want to help her? What's that? Scheduling the process. Scheduling, but more fun than that. To you, it looks like two processes are running at the same time. But what's really happening? Time multipixing. Time multipixing. Right. So I'm switching back and forth very rapidly. Past limits of human perception to all multiple devices and multiple processes to get these whole work done at quote unquote at the same time. It seems synchronous to you, but on a uniprocessor system, keep in mind, there is never more than one thing happening. And on an A-core system, there's never more than A-things happening at the same time. To you, you might think you have 30 different things over. But that's not what's actually happening. What's actually happening is that things are getting shared very apologically. And we'll come back to this in a week when we talk about scheduling. Scheduling is a policy that tries to make sure that this looks concur and not slow. OK. How does the operating system ensure that it retains control over what threads are running? What do I do? Yeah. Right. But how does it get into the spectrum? What sends it into the spectrum? What? Kernel trap. Kernel trap caused by an interrupt caused by a... I hear it, I hear it. Timer, right? So to ensure that I get a chance to stop a process from running, you know, I might have a process that just isn't a wild one. If there's no I-of going on in that process, it's never going to give up the CPU all the way to make sure that I get it back. What's that? Sure, sure, sure. Sure, sure, sure. OK, so let's be clear here, right? In this class, we are talking about the idealized operating system. The idealized operating system. In over 50, 60 years, I would say that we have managed to build a lot, right? But this is what the average system is trying to do, not always what it actually manages to accomplish, right? And in particular, you guys will have fun with this when you start building your own system. All right. Let's see. So when I actually perform a context search, what do I need to say? What is the state I need to say to perform a context? Program counter, pretty much all of us. Program counter is one. Program counter is actually an example of a... Register, right? What else? Stack. Anything else? No. Oh, I'm getting it wrong. Somebody who's going to... registers that the thread was using in the NRR and a stack to actually perform a context search. All right, any other questions about this? Any other questions about currency? We're going to do a little bit more of what's going to look like for you today. Hopefully it won't be a mistake. All right. So let me finish off with some of the material that we did cover about context switching on Wednesday. So a couple of details about context switching. When a thread begins running in a curl, it does not continue to use the stack that the user thread was using. Why? Or why not? Any ideas? Why wouldn't I keep using the user stack? What would happen if I kept using the user stack? Well, it could be an overflow, but let's say I don't blow the stack. I'm good. I don't call like this massively recursive function. I just move the work and it's still there. What? What else? There's two problems here. Yeah? Also, you'd like to redo the stack when you switch to the previous thread again. Right. So the first problem is that I could make a mess. I changed the state of the stack. And remember, when I restart the thread, that stack has to be exactly the way it was when the interrupt happened. There's another problem here. This is the case with any context switch, right? Yes. So any context switch, we have to replace the stack. Correct? Right. Every time I trap it in the kernel, I start using, so if you look at OS 161, every thread is a kernel stack. And that's the stack that is like one page or something. And that's a stack that uses when it's running an interrupt. But what's the other problem with using the user stack? We've hinted at this before. What does the kernel not do to process it? Yeah, security. I don't trust the process. I don't trust anything about it. I don't trust the arguments that pass me. I don't trust memory. So if I was starting to try to use its stack, I would basically be trusting its memory. And who knows what it's set up on the stack to try to put me up? So first, I don't want to make a mess. Second, it's not safe, right? Yeah. What is the stack container? What is the stack container? This is good. So I don't... Here's the thing. And I think that this is not just you guys, but sometimes I think that this kind of stuff is getting missed in early programming classes. And I can't completely address this in this class. But if you're curious about how the stack is used, particularly across functions, I encourage you to find that.  So in a nutshell, what does the stack contain? So first of all, the stack contains any local variables that you allocate. So in C, if you allocate a variable in a function local to the function, that variable gets stored on the stack. Meaning that when you enter that function, and you can look it up in the assembly code, the compiler inserts instructions to create space on the stack to hold that variable. So if I create a local variable in a C function, is that variable available outside of that function context? No. And the reason is because it's stored on the stack, and when I return from the function call, I go back up the stack, and whatever space I allocated to that variable is reused for. So when I make a function call, what happens is I push space onto my stack for the arguments to the function. That's also how you pass arguments in C. And then I jump to another location, the code has started. And what happens over... So how many people have ever written a recursive function in C? Raise your hand. How many of you guys have written a recursive function that had a bug in it so that it never had a base case and never continued recursing? What happens when you do that? You will have a stack overflow. Because what's happening is every time you make a function call, you're allocating more and more and more and more and more and more and more and more and more and more and more and stays on the stack. And pretty soon, the operating system... We'll talk when we get to memory. The operating system will hand out new stack pages to processes if it thinks that they're well-to-hate because processes do use their stack events. But at some point, the operating system is going to be like, this thread is allocated four megabytes of stack and that seems a little weird. So I think it's time for this thread to be done. And that's what happens. There are usually limits that you can set on the amount of stack stays that a process can allocate before. But if you write a recursive function without a base case, you will hit any limit. You might overwrite the entire heap and overwrite all of the code and try to... At some point, you're going to also run out of memory eventually, because it's unlikely that you have 32... Or it's like four gigabytes. Well, maybe now you might have four gigabytes. It's unlikely that you have enough memory to push the stack of the pointer all the way down to the bottom of the graph. So this is what happens. But there are going to be times in this class, especially in the programming science room, where we know about the mechanics behind how this is done in C. So there's a programming design for example where we tell you store this variable on the thread stack. And there are people in the past when we told them to do that, they said, I don't want them to do that. And then we thought, well, something's going to be missed. So if you're confused about how this works, I encourage you to find out. All right, so... And then again, so the equivalent... We saw on Wednesday the code for registers to form a context switch. And you could find the corresponding code that uncloses those registers once the context switch is over. And so... And I told you there's this MIPS instruction that generates a software interrupt. What is that instruction? Anybody remember? What's that? Cisco. Cisco generates a software interrupt. There's an equivalent instruction on MIPS that is called RFB or returned from exception that performs kind of the opposite thing. It takes the processor back into user mode, jumps back to a certain portion and starts executing instructions. So this is what happens. So when I enter the kernel application called Cisco, I push all the registers. I do some work. When I'm finished, I'm leaving. I pop the registers back off the stack. I load all the registers that the process was using.  So back to the point that you made before that timer. What do you mean by that? An element?  Yeah. Is there only one kind of software interrupt or... like different needs may be... requiring different ISRs. So just one... Okay, so that's a good question. Is there... It depends on what you mean, right? So is there just one system call? Let me ask that question. Is there just one system call? No. No, we talked about four system calls last week, right? And there's like 30 more. So, but there is only one syscall assembly instruction. So how does... how do you think the user process tells the kernel which system call it wants to perform? Passes an R. Passes an R. And actually somebody stopped by my office last week and we actually looked at this code together and if you look at that hand... There's a handout about the MIPS architecture.  And then based on which system call I'm trying to do there are other arguments that will be put in other places. And you guys will find out in great detail how this works for assignment two because you will actually have to pull those arguments into the kernel and process them. Okay, so back to Connix with Jordan. Yes, Connix switches are now free. Connix switches are actually pretty expensive. And on more mature systems they've gotten even more expensive because there's a lot of states associated with the process. So I'm going to save and make sure that things happen. Connix which it establishes a cost to enter the kernel which means again, cross this user kernel boundary start to execute kernel code and process a hardware. And as Calvin pointed out what does this mean about timer interrupts? So you might think the solution of concurrency is great. And I can make it even better. I can generate timer interrupts. So maybe I have a timer on the system that generates interrupts every ten mils. I can make the system seem even more concurrent by generating timer interrupts every one mils. Or a hundred microseconds, ten microseconds. What's the problem? You have to save a message to Jordan. It would escape space. It's not that I have to save more per context. But the overhead is constant for each context. So as I increase the number of timer interrupts the overhead of Connix switching will start to dominate the amount of time that I actually am able to spend and run. The system doesn't want to just spend time pushing in, you know, pop-in registers. It wants to allow applications to do these over, right? Yeah. Doesn't it have a threshold and would you respect the CPUs so busy? So it's not really an issue of the busyness of the CPU. It's more an issue of the granular, right? So when most systems do they pick a timer interval that is short enough so that I can implement concurrency so I can provide that illusion. If the timer was like one second, right? What would your computer feel like? You know, it would play an MP3 for one second and then it would load the web page for one second and then it would play the MP3 again. That would be really helpful, right? So it's got to be fast enough that it could actually fool you into thinking that a bunch of things are happening at the same time, right? But in fact, it can't be so fast that the context which overhead starts to dominate. So there is a balance in systems, essentially. One is you try to make sure that the context which overhead is as small as possible, right? You don't want to do, you know, I worked one summer at Microsoft in one of the courses of Core Windows of Performance Groups. And I was working at desktop performance which is kind of a different issue. I'll talk a little bit about that because we're curious, but there was a server performance group, right? And the server performance group, I mean, these guys, essentially a lot of what they do, I would say a lot of what they do is they hunt for ways to optimize these critical path, right? So if these guys can find one instruction that they can remove a piece of code that's getting executed billions of times, you know, they go out and have beers and stay home for a week, right? Because they may have spent the system up by a huge amount. We're going to talk a little bit about performance in this class and actually there's a good performance story on this slide as well. But, you know, if you can optimize just a little bit, a piece of code that runs all the time, you can have a huge speed up, right? So taking one cycle of a hot critical path millions of times a cycle is more effective than removing a thousand cycles from a piece of code that never existed, right? And this is one of the common mistakes people make when they try to improve performance. There's just a stack of walls. Alright, so, there is a balance here between... So what is the practical result like with the MIPSU-DU? How many, I don't know, can give us a rough idea about how many cycles does the less allocate per thread and then how many cycles per actually on the island. Well, okay, here, I'm not going to answer that question because I don't know what the problem is. But you can find this out. And actually, this is configurable on your system. So I insist 161.com which you guys will have to edit a little bit. Or maybe, I can't remember if it's there or somewhere else. But you can set the time or rate, right? The rate at which time are on our expire. And you play around with it, right? Try setting it to something really low and then try setting something really fine so you have it. So, and one of the things we do for Assignment 1 to test your code is we set that rate on fire because it creates more synchronization problems because there are more opportunities for things that you don't want to have happening in the same time. So this is configurable, and you can figure it out. You can actually profile your system too and figure out how long it takes for a competition. You count the number of distortions if you look at this. But I'll top my head. Sorry. So basically, the structure would also depend on the application and I think about the memory, say, co-processed memory being much memory or much memory. There would be a lot of stack activity. Right, right, right. So remember, I don't have to save the stack. That's the good thing, right? I just leave the stack where it is. The stack is already in memory. So I don't actually have to copy anything more than that. It's different than fork. Fork essentially has to do a lot of copy, right? To do a context switch, I don't actually have to copy. But the overhead is getting registered. We'll come back to this issue when we talk about the stack. All right. So again, let's back up a second. So we've had a conversation about context switching and stuff. But let's come back. What is the threat? Threat is an abstraction. We're going to talk about threads. It's some real thing. But what is the threat? What does the threat consist of? CPU stack and? CPU on CPU? So that's the idea, but what? The most granularity solution. The most granularity solution. So that's what the threat is. Light weight process. Okay, so that's what Linux calls them. Right. But that's good. It's good to know. So register state, and then what's the other thing that makes up the stack? Let's just take the stack. That's what the threat is. Let's go through this little review with a picture. Okay, so, and I'm just going to ask you guys, for each one of these pieces of state, is it private to a threat? Is it private to a process? Or is it shared between potentially multiple processes? So what about registers? Private to a threat. So they live up here in these little threads. What about the stack? Private to a threat. Actually, private to a threat. And I will admit, and I did book this up and I should have, but it's part of the address phase, right? Meaning that I'm not sure if it's I'm not sure if it's actually in force that threads can't bind to each other's stack. So I think that might vary based on the limitations there. I admit that I just have time to look it up and I should have. But the idea is that a stack should be private to a threat. There might be cases where you want to share information but that might not be advised. So a thread needs some state other than the registers that can constitute its view of it, right? All right, memory. Rest of the address phase. Private to the process, meaning what? It's shared between threads, right? So every thread, I should have had more of one thread here. Every thread shares the heap. Every thread shares the code that's loaded into the address phase. And it's the sharing that makes all that good for a company. What about the file distributor table? Shared. Shared between threads, private to the process, right? And the file handles, so I put them on here to potentially be shared. Okay, questions about this? I think this is important to develop a mental model of what stuff Yeah. You mentioned that in exec, this file distributor table is not modified. So then that means that two processors are sharing file distributor table as well. Right, so, when I share the file table, they share the file handles, right? So they share the objects that the file table points to. But they have separate, okay, they have separate copies of same things? So I copy the file table initially when I fork, right? And that means that I have these objects, and I wish I had the whole slide, that have potentially two pointers to them by separate processes. But when I modify, when a process opens files you know, dupes file handles, closes file handles, all those operations are local to its own file table, right? So I can remove the pointer to that shared file handle and point it somewhere else, right? But I can't change the other guy's files. All right, any other questions? Maybe... Yeah, I'm sorry. I have a question about the heap. Do you mean data structure like a tree or just some random structure with a dynamic allocated memory space? So the heap is used, so we haven't talked about VN yet, right? But does anybody know how do I create memory objects in the heap using C? Now, right? Now it creates, now it allocates memory in the heap and returns a pointer to the process that called, to the thread that called. But all the... So the heap is shared memory. Any thread can read and write... I think it's going to be a little bit confused about the data structure which is a tree structure basically I have an owner. Don't worry about it. So for the purposes of this class, the heap is an area of the address space. That's all it is. There's no data structure implied. There's a lot of different ways to implement memory allocation in the heap. But to the outbreak system, the heap is just a part of the address space that I'm allowing the process to use, okay? And again, we'll come back to this when we talk about memory. So the heap is a small that is designed to allow the process to ask for more heap. What the process does with that heap is the kernel doesn't care. And it doesn't help. So implementations of mallet and tree can use a lot of different data structures. But those are all done in user space. There's nothing to do... It's a little bit confused about the names. Like heaps, stacks, all like... So heap is used over and over again. But in this class, and again, we'll come back to this when we're talking about how it's been. So the heap is not completely unstructured. I wouldn't be able to find exactly like if I require, you know, 512 kilobytes. If you wouldn't do the unstructured, you wouldn't be able to find 512 kilobytes. So you're right. The heap is not unstructured, but the structure is up to the process itself. The outbreak system... All the outbreak system does with the heap is the process will say, and the outbreak system will say, sure, and it will give the process permission to use those addresses. What you do with them, it's totally up to you. So again, the implementation of math is in the standard spot. And it called... So behind the scenes, it asks the operating system to remember when it needs it. And then it figures out how to structure it. So you can't allocate objects of various sizes. You can free things. We will come back. This is one of those nested loop situations where I just need you guys to suspend disbelief for a couple of weeks. We were talking about allocations. It's kind of close. All right. Let me even have to say this. So why, as a programmer, just from the perspective of writing, and we talked about this a little bit already, why use threads? So we already talked before that there's a way to create new processes. So one of the ways of providing the notion of concurrency is that it doesn't do anything. Why is a user space programmer would you want to use threads? Why would you want to have a process with multiple threads? So one of the problems with a single process is if I try to do I.O. I might block the thread that's doing I.O. However, there are asynchronous operations and interfaces for doing I.O. So I could get around that. It could be a little clever. They're not necessarily easy to use. You don't have to spend time to do that. So processes are potentially high overhead. And remember, what's the goal of the operating system with regard to processes? Two processes, we talked about ways for processes to communicate but in general the operating system doesn't try to what? Isolate and protect them from each other. And that makes communication harder for them. Whereas if you fork a thread, A, that thread can do anything you want. If it doesn't make stupid, the thread communication can be a little bit easier. But again, just think about it from a more conceptual view. Why would you use a thread? Why would you want the notion? Sharing the address space. So it shares memory. But I'm trying to go up another level in terms of what kind of problems would you use threads to solve in that? So there are applications where it's natural to think about things happening at the same time. And again, this is an illusion that you're asking the operating system to create and then you're exploiting. But it can be a good mental model to think, you know, yeah, so I'm going to talk about some things, right? So firstly you could really think about application of two multiple things, quote-unquote simultaneous. And just be a good mental model. There's actually kind of a big debate in terms of design between using threads and events. I don't want to talk about events at all, that doesn't use as many threads. If there's some, the people who advocate the threading model will claim that threads are a good mental model we're thinking about. We talked about some of this other stuff. So the other thing is state that is private to a thread can be a good way of encapsulating some information about what's happening in your process. So threads don't share everything. Threads do have some private state. And if that private state is a good map for what your what your application is doing then this can be a good example. And then finally something I can point it out threads can help you hide delays caused by slow devices. So one thread in a process blocks waiting for I.O. Every thread in the process doesn't have to block. Whereas a single-threader process one thread blocks and everybody waits. Or there is nobody else the only thread. So I found this example on Wikipedia and in general I try to kind of shoo these metaphors because I think that the problem with these metaphors is that you take them too far they end up confusing you rather than helping you. But I actually think this is a pretty good metaphor for the process. So cooking. How many people have ever been to a nice fancy restaurant where there's like a large number of people in the kitchen so this is a photo from one of my wife and my favorite restaurants in Cambridge, Massachusetts which we were sad to believe and in a really good restaurant the ratio of cooks to diners actually starts to approach one-to-one and sometimes even exceeds one-to-one. So at the famous the famous restaurant in Spain I think there was actually something like two cooks to each person that would be seated for me. Right? So, large number of folks they're all, and what are they trying to do? Well, they're trying to prepare one meal one plate, even potentially one you know, element on that plate. They're all doing one thing at a time they've got a private state what is their private state? Okay, that's what I'm talking about. I think it's time for the public a private state. What's your private state? Whatever you're thinking about in your head right now I don't know this guy's insane but whatever, that's private so your own thought process this is the private state this is the equivalent of the register for a quote but they communicate easily how do they communicate? they talk, they say things, they shout you've seen these terrible cooking shows where things are always on fire some guys on this red face and making someone else cry they can talk and they have to coordinate to get things done efficiently and to bring things together and that coordination is going to be the topic next week sorry, but this is not I thought about this a little bit I couldn't find some of them where the wheels came off in terms of there being a metaphor so maybe if you find them out I'm sure it brings out so let's talk about a naturally multi-threaded application we've been here a little long time what about a web browser so if I have multiple threads and a web browser, what might those threads be doing? so web pages modern web pages especially if you use a terribly designed site like Hub for example have like thousands of different things that it's trying to do a web page might have images a web page might have eight images that all have to be downloaded what modern web browsers do is they fork off a bunch of threads to request all those separately with separate sockets and then as the data comes in they assemble a page that's one of the things that speeds page load if you have one thread that was just going through connection by connection making each request your browser would seem much slower than it does right now and the reason is why there's IO delays but I can fetch those four images at the same time and they probably take roughly the same amount of time to fetch them currently as they were fetched together so web browsers you could have several threads you'd fork off a bunch of threads to grab each part of the page and then sort of sit to the back together and a lot of scientific applications have these what are called embarrassingly parallelizable workbooks or embarrassingly parallelizable that you can take this huge two terabyte data set that needs to be processed and essentially process it in one megabyte chunks by separate threads, maybe on separate processors and there's almost no communication that's required to perform this task so the less communication that's required the easier it is because essentially those threads, you could take the two terabyte task and send half of it to one of Amazon's daters half of it into the other the end is like add two numbers combining the results is very good alright so we talked a little bit about processes and why not do this so I think in the interest of time let me do this I don't want to go through this stuff this is too much so let me get the thread states so the user thread and kernel thread stuff is in the slides so this is not terribly important stuff I wish we had time to talk about I think we had a great class today there's a lot of questions that we're really happy about so let me finish up by talking about thread states because this is stuff that you will need to talk about so now we have this thread abstraction and now that we have the thread abstraction we can start talking about it in abstract terms so we talk about threads on the system as being typically one of three states so a thread could be running that thread may be blocked sometimes we call this waiting sometimes we call this sleeping so what do you guys think it means for a thread to be running what does it mean for a CPU? it's using the CPU it's running on the CPU what about a thread that's ready? no it is a runnable thread it is a thread that could be running but it stopped waiting to be stuck what about a leak come back to you you got the answer to the third question waiting what was your answer? waiting for something to happen this is a thread that cannot be run right now it cannot be run until something happens until disc read finishes until another thread releases a lock or something so even if I wanted to schedule a thread I can't if it's not available I can't run these threads there's something else that has to happen on the system so thread state transitions how do threads go from the running state to the ready state I was running on the CPU and then I'm ready to run on the CPU what do we call that? these are mechanisms but we think of this as the thread being how about de-scheduled the operating system because again the thread didn't ask for anything to happen it didn't perform something it didn't perform a system call it required that it wait around for something to happen it was running it was really happy running on the CPU and then suddenly it's ready and that means that the operating system time runner on the operating system decided that disc read was no longer going to use the CPU in order for another thread to run it was running to waiting system call yes system call usually requires the thread wait around for the kernel to finish what it asked the kernel to do there are already synchronous system calls I don't want to talk about them but generally you think of the system calls being synchronous I ask the kernel to read some data from disk and when that read completes the kernel will restart me and the data will be where I ask the kernel to put it so when that happens the kernel, the thread goes into the waiting queue waiting for whatever it asks to happen all right waiting to write what does this mean system call right whatever the thread was waiting for half of it disk read completed and the data has been loaded into the processes average states the signal that I was waiting for half of it or whatever all right waiting to run what is this this is scheduling right this is a thread being scheduled the kernel has chosen this thread to run both being out of the ready queue on to the running and the running to terminate it's done right and maybe it wanted to be done or maybe it didn't want to be so I might have called accident or I might have put some sort of bail exception the kernel to decide that I couldn't continue do all kinds of system calls put in the thread to the waiting state no so in certain cases there would be two cases there are what are called asynchronous system calls meaning I'm going to ask the kernel to do the read and I'm not going to wait for the read to complete and then there needs to be some way for the kernel to tell me what the read to complete the other thing that could happen is I might do a system call there are system calls like get my process ID right that don't require a lot of work on the kernel's part it's like look it up some of these are actually now implemented in libraries in user space why would you implement something like that in a library? it's back to why I don't have to switch it to the kernel remember this is context which overheads but if I could do that in user space it could be yeah this is about the slipping is slipping voluntarily or not voluntarily we get the kernel put so remember when I make a system call that is blocking system call until that system call completes the thread cannot be broken because a blocking system call the thread has asked me to create the illusion that it did a read and that read to complete the meaning like a couple of times I think I'll have to look that up and see if there really is a mistake no I mean the terminology is kind of interchangeable you can say that the thread has finished waiting or the thread wakes up I wake up a sleeping thread it depends on how lazy you think the thread is just the threads stand around waiting for the weight to complete or does it like take a nap and ask the kernel a week ago so next week we're going to talk about synchronization so we've created this running abstraction we've implemented it using context switches we talked a little bit about some of the overheads that are required in the states the thread can be in but now we've got to deal with the details man we've got to like work out how are threads going to coordinate what kind of primitives is the kernel going to provide especially the kernel threads what is the most important multi-credit application running under system the operating system so we're going to talk a little bit about how to handle concurrency inside the operating system which is pretty critical if the kernel gets concurrency wrong who cares if the kernel gets concurrency wrong then it's so assignment one is going to be on Monday assignment so I've set this up so there's a nice stuff here the stuff we're going to talk about next week is the stuff you're going to be building for assignment one so that will be two weeks but by the end of next week you'll have all the conceptual tools that you'll need to do it and I think your understanding of synchronization by the faster you're going to be using and building some of them there's going to be a split of 9s in the overseas what's that? oh yeah no no no, it's the overseas don't really join us as well with the GF alright I'll see you guys on Monday have a great week guys