OS Context Switching - Computerphile

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
right so in the previous video we looked at how we can build an operating system that can switch between multiple processes to create the illusion that they're running at the same time and we saw with the demo we got here we had this model that enabled us to conceive how we had different processes running at the same time so we always have one that's running and we can have other processes other programs that are either blocked waiting for something to happen from the operating system say waiting for user input or network io or disk io or something and we can have others that are ready to run but are just waiting if you watch the other video we can see that we can then switch the ones that are running to be runnable and so on so that we can then get another one running if we do that fast enough we do it say every 200th of a second we can give the illusion that these processes are all running at the same time and occasionally they become unblocked and they can then be ready to be runnable until one of them finishes i noticed somebody put a comment on a previous video saying would it be possible to go directly from create to runnable um yes and in fact that's probably what you would do if you look at the source code for unix say then yeah when the press is created it does end up being runnable but it's put into position so the next time you context switch which is what we're going to look at today it will um become running and so on we said when we looked at this video that there's three things we need we need this model so we know how we're going to switch them and which ones we can switch and so on we need a way of knowing which process we're going to move from runnable to running at which point in time and the final thing we need is some physical way that we can make the cpu stop running one program and then start running the other that's what we're going to look at today it's called what's called context switching because we're switching from the context which one program's running to switching to the context that another program is running so to understand how context switching works we need to think about how our cpu executes program so let's actually have a look at a very simple program i'm going to write it using our machine code because the context switching does happen at the machine code level doesn't happen higher up as we use a compil higher level language so let's think about a very simple program that is going to load in a string i'm going to use our machine code for this example so we're going to load in the address of a string into r0 so let's call this h string and then we're going to print it out and i use a development environment for developing our machine code which is written at the university of manchester which allows me to call the equivalent of the operating system using sy3 to print something out so that's going to print something out and we'll define h string up here to have a hello world in it and then let's do something else let's print out all the numbers from 1 to 10. so we'll move into r1 the value of 0 and then we'll start a loop we're going to add r1 comma r1 comma one we shall move that into the register r0 and then we'll call another pseudo operating system function to print out an integer so we're adding one to the value we put in there so it goes from zero to one because we've added one onto it we're moving to another register and then we call the operating system printed out we'll then compare our value in r1 with 10 and we'll branch if it's less than 10. so a branch if it's less than 10 to loop and then we'll print out something else here so again we set r0 to point to our string and we'll call this i string if you want to have a better name and we'll call out so i3 dot and that'll be the rest of the program so we've got a a simple arm machine code program here we'll just use arm for the example it could do exactly the same while the x86 amd 64 chip we could do exactly the same on the 6 8 000 chip a 6 502 it doesn't matter we're just using our example so we've talked about this before on computer file but the way this program works is every time we execute instruction somewhere inside the cpu this one's probably even worse to see we have a set of registers r0 r1 r2 and so on and these can just store a temporary value so as we run through the program this one says put the address of h string in our zero so we work out what it is and we write a value in there then we call this and this calls off into our pseudo-operating system and we'll print out whatever it is that it's doing so it'll use that value and probably manipulate the registers we then come to the next line which moves the value of zero into there and then we come to the next line which gets the value out of the register r1 which is zero adds one onto it which is uh one yep and then stores the result back in r1 we now have the next line which gets the value r1 which is one and stores it in r0 and moves it into r0 we then call sy4 which prints it out and we come here we compare r1 which is one with 10 it's less than so we go around the loop and then we do the same we get the value of r1 which is one we add one to it which is two and we update the value so we've now got two in r1 so that's the model that our cpu runs the program and to understand how context switching is we need to remember that this instruction only ever looks at the value of r1 we're interested in this yellow instruction here for it to work the only thing it needs is the value that's currently in r1 it doesn't care how that value got there it could have got there because we've moved zero into it here which is what happens the first time or it could have got there because we've added one into it previously it doesn't make any difference to the operation of that instruction as long as the value of r1 has the same value in then it will do exactly the same thing so if it has a value of one in it it will always add one and become two it has a value of zero and it'll always become one and that's store one in it so so it doesn't matter how it got there and that is the key to understanding how context switching works what happens when we context switch is we have one program running and he's executing lots and lots of different code to make things happen and at some point that probe gets interrupted either because it's called the operating system or because there's an interrupt in the computer which has hit the operating system and the operating system says okay you've had enough time on this i'm going to switch to something else the things that we talked about briefly in the previous video let's say we are here we've got to this point in our program we've got an interrupt happening here and we're going to context switch now the operating system when it contacts which is needs to make sure that when it comes back here this problem continues as if nothing had happened so just so that we can be absolutely clear on this so when you say context switching this is switching jilly babies in our preview yeah so this is switching from one program running to the other program running so we're going from this one to this one and then back to this one as if nothing had happened when this one had run so we need to switch from this one so this is the first one and we're going to start running this one so at this point we need to store the state or the context of this program so that we can then after we've run this one switch it back to running this program instead and this can continue as if nothing had happened and as we've seen the reason we can do that is because as long as the values in our registers have exactly the same values and as long as the value in memory have exactly the same values then the program will continue to execute in the same thing each of these instructions only depends on the values on the registers not how they got there so all we need to do is make sure whenever we switch from one program to another that we keep track of the state of the program its context so that when we come to load a different one we can switch in its state and it will carry so how do we go about storing the state of the program we need to store certain things we need to store the value of the registers and any other state that is responsible for keeping the program running now things in memory we can hide quite easily modern operating systems support virtual memory and so we can just map one process memory out and map another process memory in so that preserves the state of the memory very easily the more involved part it comes in storing the state of the registers and storing the state of the cpu but actually that ends up being relatively straightforward what we do is we have a process control block for each process in our operating system and as part of that we store the values of the registers and a few other things in there so if we start off by having a look at our process control box we have a register pointing to that and we can use r13 for this then we'll point into it at a certain point now the thing about the arm chip is that to make interrupts fast it actually has registers that can overlay other registers so i'm using r13 here but this is the register that exists in supervisor mode inside the cpu it's not the same register that we use when we're writing our code that runs in user mode we talked about that in another video so the first thing i'm going to do is store multiple registers into memory at the dress pointed to by r13 and i'm actually going to take all the registers r0 through r14 so i'm dumping the registers into memory so these get written in here r0 r1 and that's just copying the values in and that's just ram as it is just normal ram that's been allocated as part of the operating system we're calling this bit we've set things up so pointing at that but we need to be careful because the state of our cpu isn't just stored in the registers that we can access it's another register the status register which contains the flags that decide whether we can branch because if things have been compared and they're equal or not equal or less than they're greater than so we also need to store that the way we do that is we move that status register into r0 like so so we're copying that register into there and then we can store that into memory below here so we're storing again relative to r13 the value of r0 which is now the value of the status register so that goes in below where we were before and also the value in r14 which because of the way the arm places the work will be the return address of our program or way we want to continue running from so we store that in there what do we want to do next well next we want to get the process control block of the next process we want to do and the way the arm suggests you do that is that you load r13 with the value in memory pointed to by the register r12 again that would have been set up by something else and then you add four on to the end so that you're then porting the next process probably want to check here that you're not pointing at a null pointer because if you are things would crash and so if we're not then what we do is we load multiple registers and then down db if not equal to zero from our 13 which we've now pointed out but remember we're still pointing at the same thing actually we're pointing down here now so we load them back into r0 and r14 we then move back into the status register that we had before we'll just simplify things a bit for the point of this video the value on so we're setting the status register back up and then we move the registers that were at our r13 back into r0 sorry to r14 but of course these are the registers from the other process because we changed here which process we're pointing at and the last thing we need to do is we just need to wait a bit so we run an instruction which doesn't do anything and we then set up the program counter so we move into the program counter the value which we put in r14 but because of the way the pipeline works on the arm cpu we have to subtract four and so if we execute that block of code we can preserve the contents of the current process copying its registers in your status register that's the important bit and then loading the value of the previous programs status register and values so then we can just go back to our program and continue running our instructions as if nothing had happened because all the registers have the same values or the memory addresses have the same value and the status register of course which we didn't have before also has the same value now for instruction like this preserving the status schedule wouldn't have made any difference but if our switch had happened here after the compare instruction then if that got corrupted then the branch wouldn't do as we'd expect so context switching is relatively easy to implement you just have to preserve all the registers of one process and then load back in the preserved registers for the new process same thing can be done to start a new process we just set up a dummy process control block which contains empty values for those registers zero say and then we can just load it in and move it from runnable back to running to get things started so that's the sort of mechanics about how we save one process and then moving another one the only other thing we need to do is decide when we do this that's where things get slightly trickier so we said that there's two places we could do it we could either do it when an operating system call is made i when the user asks the operating system to do something we could then make a switch and that's relatively straightforward the operating system gets to the end of whatever it was it was doing for the process and it can then make a context switch so it moves to the different process so we can just execute the code like that and do that and that's fine the other time we can do it is by using an interrupt so what we do is we set up the hardware of our system and this can either be a dedicated heart piece of hardware it's generates this interrupt or the some cpus enable you to do that on the actual cpu itself to generate an interrupt at a regular piece of time because the circuitry's all got integrated into the system we set up that interrupt to happen regularly let's say every 200th of a second and when that fires we can stop whatever process is running because we're now in the operating system code so it can execute the contact switch to stop it running and then move in to another process and it will continue as is the only time you have to be careful is if you're actually running operating system code at that point when the interrupts happen you probably don't want to switch out in the middle of an operating system call so probably what you do in that situation is defer it until the operating system call it finished and then switch at that point otherwise you get some weird things happening which you might be halfway through setting up the network to listen for something and then you switch out and things could get slightly corrected so you have to be slightly careful when you do it what happens when a program relies on say time or the clock how does that work i mean is that something you just have to factor into your code or ah so so for example if you wanted a program that say was drawing a real-time clock on screen how do you make sure that well this again comes down to things about scheduling which we'll look at in another video is that you probably want certain
Info
Channel: Computerphile
Views: 102,826
Rating: undefined out of 5
Keywords: computers, computerphile, computer, science, Computer Science, University of Nottingham, Dr Steve Bagley, Context, GUI, UI, OS, Multitasking
Id: DKmBRl8j3Ak
Channel Id: undefined
Length: 14min 49sec (889 seconds)
Published: Wed Sep 18 2019
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.