‫Hello and welcome and this lecture, we're going to implement tasks, so firstly, what is a task?
‫Well, first, let me tell you what you do know.
‫What is a process?
‫A process is simply an application that you can run.
‫And it's called the process whilst it's running, tasks are the thing that actually gets run.
‫So processes can have many tasks.
‫You can think of tasks as threads.
‫If you've ever done multithreaded programming, you will know what a threat is.
‫So in this lecture, we're going to implement the task functionality and the task will be dealing with
‫the registers and so on, the CPU registers and so on, essentially.
‫Right.
‫And it will also describe some basic information about the tasks it's running.
‫It's a very core piece of ass implementing processes.
‫So it needs to be done and we're going to do that in this lecture.
‫OK, so the first thing we're going to do is we're going to go to task the task directory, and we're
‫going to create a new file called Test on how much we know if and task, hashtag, define task, hashtag
‫and death.
‫And in here, we're just going to go include config dot org.
‫And we also need to include the paging stuff.
‫So we're going to go include paging, paging dot org.
‫And now here we're going to go struct registers.
‫We're going to create a we're going to create a register structure which is in charge of holding CPU
‫registers, OK, because if we decide to implement multitasking at some point, we'll need to be able
‫to flick between them.
‫So now we're going to go unit three to T Eddi, Unit three, Tuti Essi, Unit 32 T SBP, Unit 32 T SBX,
‫unit thirty two T IDEX Unit 32 T X, Unit 32 T X.
‫And now we're going to go unit thirty two T IP.
‫Now the IP is the program counter guys.
‫It's the current address that this task is Porres that so when there's some sort of interrupt will be
‫in charge of getting all the CPU registers and storing them in the tasks registers structure.
‫We're going to have a task structure soon that has a registered structure in it.
‫OK, so the IP here will be the address that it was last executing.
‫OK, and we need that so that if we flip between tasks, we can jump back and forth between them.
‫OK, so now we're going to go Unit 32 T six, unit 32 T Flagg's Unit 32 T ESP Unit 32 T SS.
‫OK, and so that's our structure for the registers.
‫OK, so the next step guys is to create a task structure.
‫So we're going to go struct task.
‫And now in here, we're going to have a page in directory.
‫OK, and this will be the page directory for the task, so essentially, you know how when we set up
‫paging, we had a kernel page directory.
‫So let me just go into the page in here, show you Colonel Chung equals page new for gigabyte.
‫And you know how we set all these bets from all paging is present, paging is rideable and so on.
‫While in the task, we can also set up these pages and we can remove the paging axis from all bets by
‫here, which will mean that, one, the CPU is in a is in New Zealand and I'm privileged state it will
‫not even be had access any of the task memory.
‫Now, that's absolutely fine because we can find the pages that we want the task to be to access and
‫we can reapply this bit to them, paging access from all.
‫And by doing this we can literally manipulate the entire task memory.
‫It will not be able to access or even see the memory that the colonel can see.
‫OK, and when we switch task, we essentially switch which page directory we are accessing.
‫So Task One will have an entire different page directory than Task two, and they may even share some
‫of the same virtual memory addresses as are the processes.
‫And this is absolutely perfectly fine because they have different page directories and the virtual addresses
‫point to different physical addresses.
‫Why?
‫Because they're different page directories.
‫So if we go back to test Hajj and we're going to continue here now.
‫OK, so it just can be a little common here.
‫The page directory of the task.
‫OK, now here we're going to go struct registers, registers, and we'll just say the registers of the
‫process, no, no, no, the registers of the task when the task is not running, because when the task
‫is running, guys, we can't possibly know what the registers are.
‫However, as soon as we switch task, we're able to store what those registers were at the point where
‫there was an interrupt on the processor and we can store them in the task at that point in time.
‫OK, and yes, if we want to manipulate the execution or the task itself, we can change these registers,
‫by the way.
‫OK, so now we're going to have struck task next, because this is this will be a linked list.
‫OK, so the next task in the linked list and we're going to have a previous in the linked list, previous
‫task in the long list.
‫So is the double link list.
‫OK.
‫Now, as you can see, this structure is rather limited as we go through the course.
‫This will get more advanced.
‫We don't really show much here right now because we just want to we just want to get to use the land
‫at the moment.
‫OK, it doesn't need to be any more advanced than this right now.
‫OK, so that's it for our test header.
‫And this structure here will represent a task.
‫This structure here will represent CPU registers.
‫So we're now going to create a new file called Test C in the task directory.
‫OK, so the first thing we're going to do, we're going to include test Hajj.
‫Next, we're going to go struct task, current task.
‫And this will be the current task that's running
‫now.
‫We're going to have struck Task Task Taihu.
‫This will be for our linked list.
‫Struck the task task head, if you don't know what linked lists, I suggest you research about that,
‫guys, because you're going to need to understand that essentially a task has pointed to another task
‫which has appointed to another task, and then we can iterate through them all.
‫You know, I mean, and then when we find a zero for the next task, the list is complete.
‫So that's what what link lists are essentially.
‫OK, so now we're going to want to go struct task task cards and this will return the current task.
‫So now we're going to make a task and it function.
‫And this will be responsible for initializing the given task.
‫And we will also have a process parameter here, but we don't want that yet because we haven't actually
‫created the process structure yet.
‫So we'll just have task and a task like this.
‫OK, well, we'll add that later on.
‫So what we're going to do is we're going to memsahib the task.
‫And we're going to map the entire fogie goodbye address space to itself by creating a page directory
‫for that task.
‫So that's going to be a present directory.
‫It's going to have access from all and that should be it.
‫Let's just check that.
‫Access from all, OK, perfect, perfect, so that gives us a read only address space.
‫OK, that's fine.
‫Now we're just going to say if the page directory is null.
‫Then return minus.
‫And, of course, we need to include Col's on the Hajj.
‫We need to include status that Hajj and we need to include paging Don Hajj as well, guys.
‫So now we're going to go TASC registers dot IP equals Peatross program, virtual address.
‫So we're setting up some default registers here now, ready for when we start the task.
‫So I told you earlier that the IP is where the task was last executing before there was interrupt.
‫Well, when we first create a task, it's never executed anything.
‫So we are in charge of setting these values.
‫So here we're going to set the start address to the program, virtual address, which you haven't created
‫yet.
‫So just copy this definition here and we're going to go to status stage.
‫No, no, no.
‫We're going to go to config stage.
‫And just down here, we're going to go the fine and we're going to pay Sedin.
‫And the virtual address will be 400000 a hexadecimal.
‫So for one, two, three, four, five.
‫OK, so that's our program virtual address.
‫So that's perfect.
‫We've now said that we're now going to go TASC registers, SS equals use the data segment which we haven't
‫created yet.
‫Task Registers E.S.P equals Peatross program Virtual STAC address starts.
‫So this will be where our starts address will be for our stack essentially, and we'll define these
‫definitions later.
‫So here we're just going to return zero.
‫So this is a very basic implementation of task initialization here.
‫OK, you can see we only change the registers that matter.
‫The simple stack registers and the IP and everything else is ignored.
‫OK, we will now implement these definitions.
‫OK then.
‫So back to config.
‫Today we're going to define these things.
‫So down here we're going to go hash tag, define purchase,
‫use program, stack size.
‫So that's the first one.
‫So we'll have a 16 kilobytes stack for userspace.
‫So now we're going to go to find Peatross program.
‫Virtual Stack address starts.
‫So we'll start the at virtual address three f f zero zero zero.
‫OK, so remember, this is a virtual address, not a physical address.
‫So all all tasks will share the same program, virtual address on this same stack address.
‫And that's completely acceptable because they have different page directories and the different page
‫directories point to different physical addresses.
‫OK, so now we're going to find the end of the stack.
‫So we're going to give a hash tag to find Peatross program, virtual stack address.
‫And and that will be equal to the PTW program.
‫Virtual address start minus the Peach OS user program stack size.
‫And the reason we minus ID is because the stack end address is lower than the stack start address because
‫the stack grows downwards by default intel architectures.
‫OK, we go back to test to see if we can see.
‫We just need to define the user data segment now.
‫So back to configured Hajj and we're just going to go define user data segment.
‫That'll be zero x twenty three.
‫And now we're going to go define user code segment and that'll be zero X won't be.
‫So I'm just I'm just basing these offsets off of the offsets in the G.T. table, guys.
‫OK, another GGC structured the GDP table here.
‫OK, the real one.
‫Once this structure does pass through our algorithm we made.
‫So these numbers aren't just numbers I'm making up.
‫They represent offsets in that table.
‫In this table.
‫OK.
‫So they use a code segment is zero x one be multiplied by one in offset, OK, and offset in that table?
‫OK, so yeah, we've now implemented that.
‫OK, and there's one slight mistake here, guys.
‫Go to test out the Hajj.
‫Our registers should not be a pointer.
‫OK, we just want that as a value.
‫Not not a pointer guys.
‫Just a structure variable police here and yes, now you'll see that error is gone.
‫OK, so that's our task and function completed.
‫OK, so now we're going to create the task, new function.
‫So we're going to go struct task task new.
‫And this would take a process structure in here.
‫But we haven't created the process functionality yet, guys, so we're not going to have that right
‫now.
‫We have to start somewhere and unfortunately they need each other.
‫So we take it slowly and we'll come back to that.
‫But yes, so here we're going to go in and rest equals zero struct task task equals Casula size of struct
‫task.
‫And obviously now we need to include the heap as well.
‫So we're going to go heap keyboard.
‫OK, so just include that father.
‫So here then we're going to say if the task was failed to be, if we had to create the task, then there's
‫no memory or something else went wrong and we're just going to go out and have our out label by here
‫guys as well.
‫And we'll come back to that.
‫So now we're going to go sequence task in it and we're just going to pass in the task that we just created
‫with Casula.
‫And we're going to say if rest does not equal features, all OK, then there was a problem.
‫And if there was a problem, then we're just going to go to our OK.
‫Now down here, we're going to say, is the task ahead?
‫No, OK, if the task head is no, then we need to set the task head to the task which is created.
‫So we're going to go to task.
‫Difficult task, task, tail equals task and we're going to go to out now.
‫We're just going to say task tail next Eco's task task, previous Eco's task tail.
‫And then finally, we're going to go test tail equals task.
‫OK, so I hope that makes sense.
‫So we're setting the next variable to the current task tail to the task which is created.
‫And we're setting the previous on our tasks, the task tail, because that's the previous to us.
‫And then finally we replace the task tail with the new task.
‫So it's pretty, pretty straightforward, right.
‫OK, so now we're going to say F is error rest, then we're going to go test free task and we and we
‫need to create that as well.
‫And we're going to say return error rests.
‫OK, and now down here, we're just going to say return task, OK, X and so that is our task, new
‫function.
‫So people call this when they want to create a new task.
‫OK, so we're now going to scroll down here.
‫We're going to implement test free.
‫So we're going to go into in a tax free struck task task and we're just going to go paging free for
‫gigabyte and we haven't created that yet task.
‫Page directory.
‫We're also going to go TASC list, remove TASC so that are removed from the list, we need to create
‫that finally free the task data.
‫OK, free task and then we're just going to return zero here to signify everything went fine.
‫So page in free for Gigaba.
‫We need to create that.
‫We need to create tessellation move.
‫So we'll start with task lists remove.
‫So we're just going to go static void task list, remove struct task task.
‫We want that to be a static function because we don't want people calling this.
‫People should not have access to this link list.
‫They should not be manipulating it.
‫They should just be calling task new and task free.
‫So here we're going to say if task previous, then task previous, next equals task next.
‫So the very first thing.
‫Now we're going to say if the task is equal to the task ahead, then task head equals task.
‫Next here, we're going to say if the task is equal to the task tale, then task tail equals task previous.
‫And then here we're going to say if the task is equal to the current task, then we will change the
‫current task to task at next.
‫OK, so we will have to implement task at next now as well.
‫So essentially what happens is Tharsis remove.
‫We check if the task has a previous pointer.
‫If it does, then we should be setting the previous point is next variable to our next, which basically
‫takes us out of the equation.
‫It basically lifts us out of the last, you understand.
‫Otherwise, if the task is equal to the task ahead, then obviously we need to replace the task, head
‫with ourselves here because we're removing the task head.
‫Likewise, the same for the tail.
‫If the task is equal to the task tail, then the new task tail should be the task previous.
‫OK, and then obviously if the task is the current task, then we call task at next, which will get
‫us the next task in the in the list.
‫But we're going to create that now.
‫OK, so we're just going to go struct task task, get next.
‫And here we're going to say if the current task next variable is no, then we're just going to return
‫the task head so it loops back around on itself to understand that's the idea.
‫It'll go round like that in the circle.
‫Right.
‫Otherwise, we're going to go return task next.
‫So that's what task get next will do.
‫OK.
‫Oh, current task context.
‫Current task next.
‫So that's what current that's what tax techs get next.
‫Will do.
‫So um yeah.
‫Essentially we call task at next.
‫It'll look in the current tax context to see if there's a next variable.
‫If it's no, then it will just return the task ahead.
‫Now task at next can can technically return no because of the heads know it's going to return.
‫OK, and that's perfectly acceptable.
‫That just means that all the tasks are now finished.
‫Executing the current tasks will become now.
‫OK, so that's our task lists.
‫Remove function now.
‫We need to now implement page in freefall gigabyte because we haven't done that yet.
‫OK, so let's go to paging DOT see in the memory paging section here.
‫And we just going to go here and we're going to say void's paging three four gigabyte and we're going
‫to expect a four gigabyte chunk here.
‫And I was just going to go for Ingi zero, I blow one or two for I plus plus and we're going to go you
‫in a three to entry equals chunk directory entry, I and I, we're going to go unit three to table.
‫And this is a point.
‫Guys, don't forget unity two three pointer and we're going to go entry ampersand zero x f f f f f.
‫Zero zero zero.
‫So, as you know, on the on the lowest few bits of these directory entries are flags and which is why
‫we and we end this to get the actual page table address.
‫OK, that's why we do that.
‫So don't forget that.
‫And it also is the reason why pages are page aligned, Bashur line to four thousand eighty six bytes
‫is because of this reason, as I've explained in previous lectures.
‫So we're just going to go Kifri table, OK?
‫And now outside of this loop, we're going to go Kifri Schunk Directory entry.
‫And now the final thing to do is to go free, John, so you can see that basically loops through all
‫the page tables.
‫It frees them all and then it deletes the directory entry data and then finally deletes the four gigabyte
‫chunk we made here.
‫So copy and paste that into the header file.
‫And now we are done with that now we're going to need to add the task that she to the makefile and then
‫I think we are done for the time being with the task functionality.
‫OK, so let's just go to the makefile here.
‫We're going to look for TASC because I know we've done something.
‫Yes, we have.
‫Here it is.
‫And we're just going to copy and paste one of these C++ compilations by here, and we're just going
‫to paste that there.
‫And we're going to go build task task, auto task test to see we can change the argument here to point
‫to test tube.
‫And this will be our source file task task that C task test.
‫Oh, OK.
‫And now we're going to put our test O at the very top with our object files.
‫OK, so just pass that by here and there we go.
‫So that should be by then.
‫OK, and if we now make clean that builds at that stage we can now see it's fair to compile this.
‫So let's go to Task C, scroll up and we're going to change this to memory.
‫Paging paging Dr. Hajjaj.
‫We now try that again.
‫Makes you control s on.
‫This guy's got a test as well.
‫And we've also got it up here.
‫So, yeah, it should be a memory.
‫Paging paging Dr. Hatcheck in both Tastykake.
‫And we also don't need this actually intestacy because we included in tests so you can get rid of it
‫in test to see.
‫OK, everything looks fine now because we've now changed that to memory paging paging Dr. Hatch, so
‫just recompile that.
‫OK, good.
‫So now we see some more areas that we can fix.
‫So test starts, see twenty eight and we see that there's a complete declaration of task in it.
‫OK, that's no problem.
‫We need to declare this.
‫At the very top here, so just paste the prototype here, OK, at the very top and we also want to put
‫test new in the test had.
‫OK, let's just do that.
‫And we're going to put a lot of these functions in there actually test current as well.
‫OK, we won't put a task in it because really that should be initialized in test of sea.
‫So we could probably even make that static.
‫But we won't we won't make it static right now.
‫So, yeah, we've got test new tests current in the head of.
‫Now.
‫Good.
‫We want Tasket next in the header file as well.
‫And what else do we have here.
‫We don't need to remove we need TASC free in the Hadifa.
‫OK, and yes, that's it.
‫So there we are.
‫We have all of those now.
‫So make sure all of those functions in the test chheda file.
‫So let's take a look at the complication errors here.
‫Our last error is meme's said, so we need to include the memory header.
‫So we're going to go include memory, memory, the intestacy and have we now build.
‫We can see that that works absolutely fine.
‫And it built that successfully.
‫So we now have basic prototypes.
‫Well, prototype work for the the task functionality.
‫So essentially when we when we create some processes, the process needs one task to begin.
‫OK, so when we create processes, it will basically call task new the process functionality which we
‫have, which we haven't created yet.
‫It'll basically test new, which will create new task, and then they will associate that task with
‫itself where elektro.
‫So away from that right now.
‫So brief overview then.
‫We have a task in here that basically creates a new page directory that is present and it's available
‫from everybody.
‫And when we say everybody, we mean all privileges.
‫So use the land.
‫And Conolan can access this entire four gigabyte address space.
‫It should also be noted that this address space is not right.
‫Writable Sony read only.
‫Now, we could probably do with getting rid of this paging axis from orbit to and then only map in what
‫the tache should be accessing.
‫But just to keep things simple for now, we're just going to keep this bit here just to ensure we don't
‫run into complications.
‫Yes, it means that this task may be able to find other tasks, physical memory, but it's not a big
‫deal right now.
‫This is just a learning environment for you.
‫What's important is every task has its own four gigabyte address space, which is amazing.
‫And that's thanks to the very clever paging model from Intel.
‫OK, so, uh, yeah, you've DNAPrint tasks.
‫Congratulations.
‫We're not actually seeing any Corunna right now.
‫That's because we need to create all the foundations before we jump into the, you know, the concrete
‫down below.
‫So we need to build it from the ground up.
‫Basically, we can't just jump and take shortcuts, which is why it'll be a few lectures before you
‫see use of programs running.