Let's try that again, shall we? Hello there, my beautiful, lovely internet friends. I come to you today with a new tool and a lot of feelings about it. And I wanna be honest right off of that and say that I don't love that I am feeling the kinds of ways that I am feeling about this lovely, beautiful, fantastic new aid that I have. But I do think that being honest about what we might actually feel is a good place to start. I hope to look back on this video a year from now and think, wow, Joe, you have grown a lot. Your thoughts and feelings about how you see mobility devices have evolved and changed. Good job, girl, but we're not there yet. I got a wheelchair, which I'm really grateful for. And I also feel super gross about. And I feel gross about the fact that I feel gross about it. So let's chat. So earlier this week, one of my dearest darlings friends, Anika, the amputee. You can check her out, the link's down below. Flew out to Colorado to bring me her old wheelchair. And by old, I mean it is still absolutely in fantastic condition, it works great. And I'm incredibly grateful for it because if I'm being honest, this is something that I need to have. Realistically, I probably should have learned how to use a wheelchair on my own, like, you know, a decade ago, but I haven't. So Mr. McNabbins here is having a lot of problems. I'm having a lot of nerve pain. I just had some issues. I kind of tweaked my knee the other day. It is becoming really difficult to use my prosthetic leg all day every day because of the amount of pain that it causes. Still really good days. I can go hiking, I can walk. You know, I can get myself about, but it is really taking a physical and emotional toll and using a wheelchair that's actually built for me that I can, you know, propel myself about that isn't pushed by someone else is a fantastic tool. I can take my leg off, it relieves stress, it relieves pressure, but I have resisted that with every bone in my body because since the age of like 13, when I initially broke my ankle, started having surgeries, I've had a certain perception about using a chair that I don't feel comfortable saying out loud, but I'm going to anyways. I've been so against them, even at points in my life when it would have really been beneficial to use one because I wanted to use my own two feet, even when two feet were gone. I wanted to get myself about on my own. I wanted to stand up and be eye level with people. And though perhaps not a conscious thought, an underlying one is the idea that if I'm using a mobility device like this, that is more obviously different than the average person about in society that I will be seen as less or that maybe I would see myself as less. And I've let that belief stop me from getting and using tools that I genuinely need. I feel like as a member of the disabled community and especially someone who has a presence and a voice on the internet, that I should probably have worked through this a long time ago by now. We're kind of all raised with this idea that being different is not great period. Being disabled is definitely not great period. And then the more visibly disabled you are, the more not good it becomes. I think that's an idea that most of us get from age zero onward. So as I've gone through my whole surgery and limb loss journey, I've always been very vehement about like, friends were like, hey, we're gonna go walk around target.  Cause I can see that you're limping and your leg is hurting. I'm like, no, I'm fine. I'm good. I'm great. When I'm obviously not, and that would be very helpful to me. The only times I've allowed it are like being wheeled out of the hospital to my car before I start using my crutches again after surgery or like in some very, very rare situations. It's long overdue that I face and work past those feelings. But I think it's important to acknowledge them before I can actually move past them. But I've come to the point in my life where I've realized things like this are necessary and are going to be necessary. And I think one of the painful things about sitting here in this fantastic item that by the way is purple and super pretty. I don't know if you can see that, but I really like it. It's purple, purple's the best color. I don't care what anyone else has to say. Like sitting in this is a reminder that the mobility that I have most days isn't gonna be forever. And not that I ever thought it was because I know that my body will degrade over time and that over decades of using a prosthetic, like I'm probably not gonna be using one at like 70 if I happen to make it that long just because like I lost my leg at 28 and things happen and things happen in your body. Like I knew intellectually that I will need more help as time goes on. But coming to the realization that time is now is not something that I love. And honestly, more than any like societal perception, I think the biggest reason I haven't wanted to get and use a chair is because I'm afraid it will change how I see myself. Because realistically what other people think doesn't matter and I don't care that much on any given day, some days more than others to be fair. But I think that I've put a lot of myself worth or how I see myself, like my self identity and image in what I can do. Going hiking, going snowboarding, being able to just walk around and coming to terms with the fact that yeah, I can still do those things but I'm gonna need to take breaks and I'm still gonna need to do things and this is a great tool for that is a hard pill to swallow. And I don't like that it's a hard pill to swallow because it means that I too have been infected by the ableistic, is that a word? I think it is. By the ableism that exists in our society telling us that using mobility devices is not as good or worthy as walking on your own two feet. But I don't have two feet and when I do have two feet, it causes me pain. And thus I began the journey of deconstructing. The idea that this is somehow bad and here's the thing, like for instance, my friend Annika has used a chair around me very often and I never once thought that she was weak or less. I don't see people in public or my friends online and think that like, oh, you use a chair that's never ever conscious thought towards other people but when it comes to myself, there's a block there. When it comes to myself allowing myself to use these things that would be helpful to me, I have resisted it for way longer than would be healthy for me, than would be beneficial for my body. And so I'm taking the first steps is the wrong word. I'm taking the first ride today towards changing those beliefs and confronting in myself feelings that I don't feel great about, that I don't feel comfortable with and trying to begin to understand that using a wheelchair does not make me weak or less. As I use this probably pretty quickly, I will get to the place where I feel good about it. You know, there was a brief period of time where I felt very self-conscious and weird about using a press that I like mostly just like with all the stairs but I worked past that pretty quickly and I think that this is also a mental hurdle that I can get past but damn, is it challenging? Okay, so let's talk like logistics, right? So I moved into this house about four months ago. I made the decision to live here pretty quickly.  It's probably a little dizziness inducing, isn't it? So there were like one level houses that I looked at where I was like, oh, that would be better for my body but I chose this house because I liked the feeling that it has when I walked in. It felt very peaceful. There's a giant backyard for my dogs but I really should have put more thought into where I was living because this is not an accessible house. My bedroom is upstairs, trying to get the dogs outside. There's a couple stairs. The doorways are barely big enough for me to get this through like I'm scratching them every time I'm going and so I'm trying to figure out what to do and I think I'll give it some time, right? Like I'll use this inside for a while, see how I feel, see what modifications can be made here to make it easier for me but I'm not sure if I will be able to stay here. I'll probably finish out my lease, breaking my lease would be expensive to try to find a new place but I will let my body dictate that. You know, if it's causing me too much pain to try to like be mobile and go up and downstairs and let the dogs out on stairs then I'll definitely consider seeing if I can make that happen. It's funny, but like when I signed the rental agreement on this place, I was like, I know this isn't good for my body but I don't care right now because I need a place that I feel like I can recover and breathe and be and it's gonna be fine. Breaking news alert, it was not fine and I'm really hoping I don't have to move because that would just be, that's just a headache. We all know moving is a nightmare. Here's the thing though guys, when I sit down in this and I start moving about the house there is this like physical sigh of relief because I'm like, oh, I don't have to take another step which doesn't feel great. I already kind of feel some of the physical benefits of this and I'm kicking myself with the one good foot that I have that I did not do this sooner because it feels good. It is helpful to my body and I'm really glad that I have this. Working through some of the mental hurdles isn't comfortable but it never is and as not great as I feel about some of the thoughts that I have about my chair, I'm really proud of myself for using it. For saying, no, this is something that would be good for me and thus I'm gonna use it and trying not to assign any like good or bad or strength or weak value to that because realistically, that stuff doesn't matter.  However, I do feel like, don't run over puppy paws. The dogs are not quite used to the chair. They're like, mom, what are you doing? And they don't get out of the way. I feel like she needs a name because I've named every piece of mobility equipment that I've had my prosthetic legs. I almost just fell over again. I gotta learn how to actually use this without cracking my head open. But I feel like maybe we should have a live stream or a Patreon poll or something like that to name her. Because she is benefiting me, she is benefiting my life and she deserves a name, gosh darn it. So with that being said, I think the dog's gonna bark again, yep. So with that being said, thank you for listening. Thank you for hearing me out on some feelings that I don't like that I have, but I do think it's kind of honest to say them out loud because I have a suspicion I might not be the only person who has ever felt this way. And also it's really hard to work past something and deconstruct ideas that you're not willing to admit that you have. And so saying this is where I'm starting from, it's really important to me. I also feel like there are like cool wheelchair tricks that I could learn how to do, but maybe I should learn how to like get around effectively without falling over first. With that all being said, I'm gonna go make some breakfast because it is 10 a.m. on a Sunday and I've only had coffee. Thank you. Thank you so much for hearing me out. Thank you for listening to you watching this video right now. I truly appreciate you spending your time here with me today. You could be anywhere else in the world doing anything else and you chose to spend eight, 10, 12 minutes, however long this video ends up being. You're listening to me talk and I really appreciate that. To my patrons over on Patreon, thank you so much for your continued support. You guys mean the world to me and enable these videos to be made. Thank you. I love you guys. I'm thinking about you and I will see you in the next video. Bye guys.


So it might be weeks where we cancel some office hours because I need TAs to do grading or other things. We get awesome. And all the stuff to get you bootstrapped and started and digging through the source is there. And today, what we should be able to get up there is at least the rest of the assignment in terms of what else you have to do. And then, hopefully, we'll have the forums up so you can start submitting answers. There are also, for each assignment this year, I've learned my lesson last year, there are going to be, and there are already, for Assignment Zero, very clear collaboration guidelines. So please look at those and make sure that the way that you're going about doing the assignment is in accordance with our expectations for how you will complete it. And I know people would like to have access to the slides. That's something that we'll get to. My priority right now is the assignment, but the slides will be posted online. And the videos are doing them to put them up. Yeah, one look. They're pretty much the same. There may be, it depends on if I decide to change some things. I haven't made too many changes to the beginning stuff, but there were things down the road that I was kind of unhappy with. So hopefully, I'll get ahead of myself at some point and start to. But yeah, the slides for last year are up. People have asked how to print them. Another feature that we haven't implemented yet, but we'll try to get to that as well. Any other questions about sort of logistical things? OK, so last time we talked about fork, we talked about file handles. So questions about the stuff that we covered on Wednesday. This, I would expect you guys to remember, it was only two days ago. This is a game I started playing with myself. I put my water bottle down somewhere, and then I see, five minutes later, I can find it again. Because I usually want it, and I don't know where it is. So today, we're going to finish talking about fork, and then we'll start on exec if we have time. So file handles. Who remembers file handles? Who remembers what a file handle is? Who wants to help us out with some review? So file handles established three levels of indirection between a process and disk blocks. So a process wants to store some state in a stable way, and disks are designed to do that. Disks have blocks of data that they can hold. What is the process of getting from the process to blocks on disk? Let me start over here. AJ, what's our first step? Want to help him out? File descriptor. So what is a file descriptor in a UNIX process? Anybody remember what it is? What is it actually? You call open, and what do you get handed back? An int. So a file descriptor is an index into my file table, and that points to a file handle. So there's our first level of indirection. So clearly, the next level starts with the file handle. What is that file handle point to? To our file object. And then what is that file object in the kernel actually refer to, eventually? It represents a file. Are you going to take a block? Yeah, like the actual blocks on disk. So this is our three levels of indirection. I map a file descriptor to a file handle. I map that file handle to a file object, and then I map that file object finally down to the actual disk blocks, assuming this file is on disk somewhere that store the data for this file. OK? So I wish I remember what was on the slide. So the file descriptor is an int. It's part of the process. It's what processes receive from open, and they pass this to other file system calls. So this is just an index into my process file table. And the file handle is this object. Now this is now a kernel object. So the file handle is an object maintained inside the kernel that contains some state about the file. It contains an offset, permissions, and then potentially some other information. And the file object is another kernel object that contains everything else. Or you can think of it as containing all the other information about the file. So why did we do this? Why not just have some file descriptor or some representation of a file that maps directly down to a box on disk? Why did I establish all of these levels of indirection, or the extra level of indirection? Yeah, because I want to share it differently. So what this allows me to do is to say, file descriptors are private. The file table is private to each process. This is going to make a little bit more sense today when we talk about fork, and when we start talking about exact, because fork in particular manipulates the open and closed or fundamentally what manipulate the file table. But fork has some semantics related to the file table that are important. And the reason we did this is to set up some interesting semantics with fork that allow processes to communicate in a nice way. But what we've done here is we split pieces of information between different objects so that they can be shared differently. Process creation. Where do processes come from? Unfortunately, it's on the slide, but that's OK. It's good to have some easy questions, Brian. It's on the slide. What's the system called I use to create a new process? I use fork. Yes, there we go. Fork, right? Fork, what I forgot to hide on the other side. Alissa, after fork, we refer to the caller as the what? Parent and the terrible slide, lots of bugs. So fork creates a new process that is related in what way to the process that called fork. It's a clone. It's a copy. And in this class, we're going to think of the forked process as being a complete copy. Although we pointed out that there are versions of fork that allow you to do copy of a variety of different types of things. So it creates a copy of the calling process. And we refer to the caller as the parent and the newly created process as the child. And the parent and child on Enix systems have a special relationship that allows the parent to do certain things and gives the child a way to communicate with the parent. So again, so this is what we covered last time. Questions about this before we keep going. I see some confused faces in the audience. Maybe that's just a 9, 10 AM sort of look and not confusion. OK, any questions? All right, so let's review what happens in fork, right? So I have this process here that has a couple of threads and address space. And here's my file table, right? I've got my file descriptors, which point to file handles, which refer to file objects, right? After, so fork copies one thread. Remember, we talked a little bit about the difficulties between fork and threads, right? So fork is potentially going to copy the thread that called fork. It makes a complete copy of the address space. So we're going to come back to this in a few minutes, right? So all the memory that the parent is using, right? The parent's address space, all the memory the parent has access to, has to be copied for the child, right? And this is, some people may be able to identify a problem with this immediately, OK? It copies the file table, right? So after fork, the child has the same files open as the parent. But what's interesting about this, and one of the reasons that we created this level of indirection here, is the file table, the file descriptors in the child point to these same file handles as the parents. So what you can see here is that there is now this shared state. It's difficult to see, because these are really very unappealingly horizontal lines. But what this is designed to show is that the parent and child are now sharing the same file handle objects. So what does this mean, right? What state is in the file handle object? This is another one of those relatively easy questions that's on the slide. I'll pick somebody from the back of the room over here. Kevin? Well, so what's, yeah, it's very small from back here, actually. So this question is more difficult for the people in the back of the room. And what state was in the file handle? Jim? Sure. Jeremy? The current position. So the offset into the file, right? So this is interesting, and maybe it's something that people aren't familiar with. But when you use, when you do reads and writes, the kernel and unix maintains the position into the file. So if I start, if I open a file, the file position is usually initialized to zero. Then I read 512 bytes, then the file position is now at 512. So I've read another 512 bytes, I get 512 to 1024, right? But what's happening now is that that state is going to be shared between the parent and the child. So if the child does a read and modifies the offset, the parent is going to see that modification, right? So if the parent reads 512 bytes, it gets from zero to 512. The child then reads 512 bytes, it gets from 512 to 1024, right? So there's this piece of shared state, right? And there's a reason for this, right? Which we'll cover in a minute. All right. So fork and exec, which we make it to today, have these really kind of nice, have a nice duality, right? From the perspective of a process. Because fork is a funny system call, right? Most function calls that you make as a programmer go off and do some work and then they return, right? But fork is weird because fork returns twice, right? It's just the semantics of fork because after fork returns, there are two copies of the process that was called in and has to return to, right? So when the child starts, so the child's entry point, the child's birth into life, essentially, is at the exact moment that the parent called it. So the child starts executing. Again, it's like you've cloned, right? And in some systems, it's called clone. You clone the parent process and it wakes up with the exactly same memory, the exactly same state that the parent had, right? Except there's one important difference, which I think is up on the slide. So fork returns twice, but it doesn't return the same thing twice, right? And that's kind of important because if you really had an identical copy, then it would be very difficult because frequently what I use fork for is to run another program. So we're going to talk about how that looks in a minute, right? So if I was trying to use fork to run another program and then I'm going to wait for that to complete and then I'm going to do something else, right? This is what your shell does over and over again, right? It calls fork, runs a program that you passed in with the arguments you gave it, waits for it to complete, and then draws the prompt again, right? That's how a shell works, basically. I mean, clearly there's a little bit more to it, right? But that's the simplest possible shell you can write, right? So fork returns two different things. So the child, it returns zero, right? To the parent, it returns the process ID of the new process that was created, right? So this is kind of important, and it means that you can, you see frequently blocks of code like this, right? So I've called fork, right?  Now there are two processes executing this piece of code. One process is going to see return code zero and say I'm the child. The other one is going to see something else and realize that it's a parent, right? Frequently what you see is if return code is not equal to zero, do something, right? And if return code is equal to zero, wait on the process ID that I just created, right? So again, all the contents of memory are identical. Same file is open with the same positions, right? Because remember, I didn't copy the file handle objects, they're actually being shared, right? So the child has pointers to the same file handle objects that the parent had opened, right? And again, changes that the child makes will be reflected. Yeah. What if there is, so fork creates one child at a time, right? There are no twins here, right? This is a, you only get to create one process. What's your name? Amit. Yeah. Guru. Yeah, well what process, what do you think gives out PIDs? The kernel, yeah. I mean the kernel is the process or the entity that distributes process ID, right? And one of the things you guys will have to do for assignment two is to figure out how to allocate PIDs, right? Because there are some interesting semantics on most systems associated with PIDs, yeah. So, right, there are, and welcome to multi-threaded programming, there's no guarantees about the ordering in which these threads are running, right? We'll come back to this when we talk about scheduling. But they are on a multi-core, I mean, on a single core system they are fundamentally running sequentially, right? Because there really is no real parallelism, right? But unless they coordinate their activities, there's no guarantees about the order in which they will run. On a multi-core system they could be running at the same time, right? Yeah, well, yeah, no, no. So, once the child is cloned first, right? So fork enters the kernel, it does all sorts of work, right? It creates a new process for the child and then it returns twice, right? So, when it returns to the parent, because the idea is when it returns to the parent, I should be able to access that PID, right? If I hadn't set up the process yet, if I hadn't even allocated the PID, I wouldn't be able to return the PID to the parent, right? These are good questions, yeah. Why? What's that? So, yeah, I mean, this is a good question. So, why return zero to the child?  Yeah, what's your name? Dan. Yeah, I mean, zero is not a valid PID, right? If I returned, so I could return the parent's process ID, right? What would be wrong with that? You don't know either PID, so there's no, like, you'd have two integers coming back and no one would know whether it was the parent or child. The parent wouldn't be able to tell, is this my parent's PID or my child's PID and the child wouldn't be, like, that would be very weird, right? So, zero is just the special value that's used as a signal to indicate that I am the child process, right? Any other thing would cause confusion, right? I guess you could return, like, a negative value that was, these are the semantics of fork, right? That have been passed down on stone tablets through the generations. But anyway, there's kind of a reasonable reason for that, yeah, true. Yeah, so zero, okay, so that's a good question. No, no, no, if fork fails, so actually if fork fails, then actually, I think if fork fails, then it returns a negative value, right? Yeah, or something to indicate to the, the other thing to keep in mind, and I just wanna point this out when you guys are trying to map, because if you guys have done C programming, you probably use things like, what's the Erano or whatever, right? Erano is not a kernel construct, right? So, most of what you're used to using in C, if you programmed in C, are the C standard library functions that wrap system calls, right? So, the semantics, and you guys have to keep this in mind when you're doing assignment two, because the semantics of your system calls have to match the kernel system calls, right? Not the C library, right? So for example, Erano, people think, well, how do I set Erano? The kernel doesn't set Erano, right? Erano is set by the C library, right? The C library takes the return from the system call, stores that in this global variable called Erano, and then returns something else, right? From the wrapper function that it wrapped around, right? So there's a difference between fork, frequently, which is the C standard library fork, and sys fork, which is the actual system call, right? And if you, once you guys build your kernel, there's some code in there that actually generates those wrappers for the C library, right? So you guys, I mean, when you guys start writing, running the test for assignment two, you guys will be compiling against a version of the C library that's in your tree that's built specifically for your kernel. So if you, and if you add system calls, which you can, if you want to, I don't know why you would, but if you add system calls to your kernel, you need to make sure the C library knows about them and knows how to call them, right? We'll get back to talking about how the processes and the kernel communicate in a couple lectures. All right, great questions. Let's go on, right? So one of the reasons that we have this funny semantics with file handles, right, is to support pipes. And pipes are this programming, are really this programming methodology that's been designed, you know, like old school UNIX hackers and even some new school UNIX hackers take pride in their ability to build up these really gnarly programs by stringing together like little UNIX utilities, right, with pipes in between, right? So you can see these things where it's like, I can compute 600 digits of pi using like grep, cat, LS, I don't know, whatever, like I'm making this up, but you see people doing these things where you can find these huge long shell pipelines that actually do something pretty helpful, right? So pipes create this, the pipe system call creates an anonymous object that essentially allows the parent and child to pass data through the kernel as if it was a file, right? But there's no actual file that's used, right? Instead, data that gets written into a pipe gets buffered in the kernel up to a certain degree. And then when the, when another process reads from the pipe, they get that data, right? So it's kind of a producer-consumer buffer, right? And again, I mean, the reason this is useful is because we can use this to compose these streams of programs. I wish I should have an example of that, actually, that's too bad. Maybe I'll put one up on Piazza, all right? So this is one way that we can accomplish sort of some nice IPC between parent and child processes, right? So the way this is done is using both pipe and fork, okay? So, and I have a graphic for this, so if this doesn't make any sense, we'll walk through it in more detail. So let's say I wanna communicate with my child through a pipe. So before I call fork, I create this pipe object. Then I call fork, and then when I create the pipe object, I have file handles pointing to both the read and write ends of the pipe. That's not very useful, right? It just allows me to read and write data from me to myself, which is not very helpful, okay? But after fork, what happens is that the child closes one end of the pipe and I close another end and now we have this buffer, right? So again, let's see here, let me go through here and then we'll go back to the example, right? So parent is about to call fork, it creates this pipe object, right? So here's my producer consumer buffer inside the kernel. I have a file descriptor pointing to the, this is the read end and this is the write end, right? And again, if I don't do anything special with this, this is not very interesting because I can read and write data to myself, okay? Now I call fork, right? So now my child has those same file handles, right? So it has a file handle that points to the read end and a file handle that points, sorry, a file descriptor that points to the write end, right, because we're sharing this file handle, right? Now what happens is that I close the read end and the child closes the write end. So I can now write into this pipe, right? I have the write end of the pipe and the child has the read end of the pipe and now we can communicate through this anonymous share buffer, right? Let me go back to the example and then we'll walk through this again, right? Yeah, so here's an example of how to do this, yeah. You could do two pipes, yeah, in general, like the whole idea of pipe lining is usually thought to be like a left to right linear thing, right? But yeah, if you wanted bi-directional buffer communication between processes, you could certainly use multiple pipes and you could do all sorts of whack things with pipes, just weird stuff, right? So here's the C-like pseudocode that gets this to work, right? So I had this pipe ends array that's gonna hold my two file descriptors. I initialize it by calling pipe, that might call fork. So my, this is, who is here? Who executes this code? The child, right? Because this is return, this is return zero, okay? So the child closes the right end of the pipe and by right I mean W-R-I-T, like not, I don't know what the right end, the right end might be, the right end might be the left end and the read end might be the right end. Not that it doesn't make any sense, clearly. I know why this has been confusing me actually, at the right end, like right, the writer end, maybe that's what we should call it, that still sounds wrong, okay? Anyway, so the child closes the end that is used to write data into the pipe and then can now read data from the pipe and the parent closes the data that's used, the end that's used to read data from the pipe and can now write to the pipe, right? And so the parent can now read it's beautiful new child process, right? Questions about fork, yeah? One end is closed, can't I open it like just the same way that I'm doing it right now? Can't I use the same pipe to again, now interchange the open and the close end? Instead of creating a new pipe for the reverse? Yeah, that's a good question. I don't know how that works. I think pipes are a directional abstraction, I wish I knew the answer to this, I think they're a directional abstraction in the kernel. So a pipe has, so I can't push data through pipes in two directions, right? I put data in one end and it goes to the other end, right? If I put data in, there's no way to, there's no way to write into the read end of the pipe, right? That would cause an act, that would cause a problem. God, all right, so again, we'll go through this again, right, because this is kind of clever. So I create my pipe, I have file handles pointed to both ends, I clone my child, it has file handles pointed to both ends, and we both close the end that we don't need, and now we have this nice communication, right? Yeah? Can you go back to this? Oh, right here? One more. Yeah, that's what I'm saying. Yeah, I think the pipe is a directional abstraction. Oh, yeah, no. So you're saying if I... In the other two, if the other two arrows vanished. Okay, so let's see. Oh no, okay. If the other two arrows vanished, yeah, okay, fair enough, fair enough. Okay, right. The pipe is a one-way abstraction, but it can be initialized to point either direction, right? I just don't know what would happen if I tried to open two file handles to both ends, I don't think that works, right? So you're right, if I close the other ends, right, and I can't show this on the slide very easily, but the ends that would be left would be this end, right? And this end, so I could pass data back from the child, right? But I don't know what the semantics are if I try to pass data both directions to the pipe, right? So once you initialize, you cannot initialize. That's what I hope is true, right? But that's... I'll look that up, that's a very interesting question. I hadn't thought about that before, yeah, good question, all right. Okay, so let's go back to fork, right? We talked about one of the things that has to be copied for each child process is all of the state in the parent, including the parent's address space, right? So after fork, the parent and child are identical, but they should not share memory, right? Remember, one of the main things the operating system is trying to do is to isolate processes from each other, and that starts when I call fork, right? I do have something that's shared, I have those file handles, right?  It can just close all of its file handles and reopen them and it has its own file handles with its own offsets, even to the same files, right? So if I wanted to, after fork, let's say I didn't wanna communicate with my parent, I could be just like, sorry, man, I'm closing that pipe and you can write into it so your heart's content and at some point it's just gonna fill up and the rights are gonna fail and I'm on my own, I'm independent, my own person, my own process, so yeah, so there's semantics associated, but again, the child is in control of that relationship. The child can completely sever all ties with the parent and initialize its own file handles to its own files and everything, right? And sometimes in certain cases that's the first thing that certain types of fork do, right? So there's certain types of fork that don't copy the file table, right? Because the child doesn't wanna share file handles with the parent, right? But one of the things I do need to copy is the memory, right? Because that should not be shared, right? Threads are a different thing, right? And we can talk, we'll talk a little bit, I think in a few lectures about multithreading and running the multiple threads in the same address space. But fork is creating a new process, right? A new process is a completely separate container for threads and memory and other things and so it has its own copies of these things, right? And the other problem, this has been up on the side for a few minutes, so I won't try to surprise anybody with it with fork, and the semantics of fork is frequently, so, I mean, this type of code you'll see sometimes, right? And there are certain processes that fork, there are certain applications that fork new processes to act as clones of themselves, right? So who can give me an example of a process like that? We've talked about one in the past. It's an example of a process that would call fork to create more copies of itself, yeah. So tabs would probably be done with threads, right? So we'll come back to that. That's a good idea, it's a good example of a multithreaded process, right? But what about, what about a, because remember, it's not necessarily easy to communicate between processes. So I need an application where individual instances of that application can essentially act pretty much independently from each other, right? But what's a case where I might need multiple instances of an application to run?  A web server, right? Because a web server process, and newer web servers frequently do this with threads instead of processes, right? But for a period of time, Linux support for multithreading was done in user space and we'll get to that later, right? But frequently old web servers would spawn off like 10 copies of themselves because the work of a web server is pretty much independent, right? They didn't really need to talk to each other, right? They would wait, they would get a request on some port, right? There was maybe something that had to distribute the request initially, but then all the request processing is completely independent, right? I go to disk, I find the file, I render the file if I'm doing some sort of dynamic web crap and then I blast it out over the port and I'm done, right? So requests come in and I can just hand the request to each separate process and after that there's very little communication that's required between those processes, right? With tabs in a web server, right? There's frequently, there's more state that's shared, right? You might be able to do tabs with processes, that's a great question, I don't think about it more, but I think that that's probably done with threads, yeah? Yeah, so they're frequently like kernel type services, like a lot of different type of servers, right? That expect to handle multiple requests, achieved concurrency by calling in fork and just creating new copies of themselves, right? And usually they had to have some limited coordination between each other, right? But it's a question of how much coordination is necessary, right? And if it's not much, then you can get away with doing fork, right? Yeah, yep, yeah. I mean, as far as the file table is concerned, yeah. I mean, if the parent wants to, it can just close all of its files after it calls fork and reopen and then we'll have its own file handle objects. The only time those pointers are copied is by fork, right? So this is kind of an important, I wonder if I can back up here and, yeah, let's get this right before we go on. Where is my diagram with fork in it? Nope, I went back way too far. All right, oh wow, I forgot that these things, okay. Okay, so this is kind of important, right? And I wish I had a better description of this, but this is what things look like after fork, right? If the child wants file handles pointing to these files that are independent of the parent, it can close the file handles it has and open slides.html and file.svg again. And then what it will look like, it'll have its own file handles, right? Those file handles will still point to these same file objects, but now the offsets won't be shared, right? So if you had a case where you said, I want my child to have the same files open as the parent, but I don't want it to share file offsets and file handles, what I would do is I would go through my file table and I would just basically figure out which file that handle was pointing to, close it and reopen it, right? And then I would have the same files open, but I wouldn't share offset with the parent, right? Reading and writing for multiple files at the same time for multiple processes is a little wiki, right? It requires some coordination, right? Because again, I'm writing in the file, you're writing in the file, and who knows? So that's not necessarily always something that processes want, right? Coordinating access to files is hard because if I write at a particular portion and then somebody else writes there, then we're gonna overwrite each other's changes, right? Yeah, I don't think so. No, no, no, they can't be, right? Because the child, because let's say, let's say I have these files open and I have that index saved in a local variable that's on my stack, it has to point to the same file, right? Otherwise I'm not the same process, right? So the file table has to be copied exactly, right? You can't change the indexes. Because if you change the indexes, again, like the parent has file handle one open and it points to slides at each TML. If I made that two in the child, then the child's gonna do a read on file handle one and the kernel's gonna say there's no such, like that file descriptor's invalid, right? So yeah, the handle objects have to be identical. That's part of the state I'm copying, yeah. No, it doesn't have to. I always forget what the semantics are. In general, concurrent IO to multiple files is not a good idea, period. But I think that, can you ask that on the forum? Because there is an answer to this question and I forget it every year. And I will remember it because it's important because you guys, this is one of the things you guys have to get right for assignment two, right? You need to figure out what the semantics are. I think you might be right. It might be possible that changes to the offset are done atomically, right? So we're gonna talk about synchronization more in the next few weeks, right? But yeah, so if, here's what has to be true, right? So if the parent and child both write 512 bytes to the file at the same time, right? One of those writes goes from zero to 512. The other goes from 512 to 1024, right? So when I'm finished, the offset should be 1024, right? Which ordering they go in? I don't know if that's well-defined, right? But they shouldn't, like, if they both write 512 at the same time, the offset shouldn't end up as 512, right? It should, so the offset should be changed atomically, right, and the right should not overlap. That's a good point. And again, but please post that in the forum because I wanna make sure that I, I get the right answer to this. Okay, let me talk a little bit about fork overhead and then we'll be done for today. So, so there's, and again, so sometimes I'm making a copy of myself, right? And in that case, fork is great, right? But frequently what I'm doing is I'm making, frequently what I'm doing is I'm trying to create a new process, right? So fork is what creates new processes, right? But all the processes on your system aren't forks of in it, they're not clones of in it, right? That would be a very boring system, right? That system wouldn't be usable, right? So on Monday, we're gonna talk about exec and how processes change. But frequently the first thing a process does after calling fork is calls exec. And exec wipes away the whole address space. Exec basically is like that, you know, the pre-Madonna dressing room person, right? Like they just come in there and they totally, whatever was in there before, it's gonna be totally exactly according to the instructions that are in the binary that I call exec, right? So now this is irritating for the operating system, right? Cause I did all this work, right? On fork, right? To copy all this memory potentially. And then the first thing that happened is the process came in and blew away all my changes, right? So what do I do about this? So there are two solutions to this problem, right? One solution is I can use something called copy unwrite. And I wanna point out that these solutions fall into sort of interesting categories, right? So fork and exec and the Unix system call interface has been stable for a long, long time, right? There's been changes to inhibitions, but in general, it's a pretty narrow interface and it's been standardized. But I think it's kind of a neat idea, right? You implement fork and exec and then you figure out how to get them to perform well. So they didn't create a new system called it's like fork and exec, they just figured out how to do this. So one of the things they did is they optimized the existing semantics. So there's a nice memory optimization that we'll talk about later when we talk about memory management that avoids the copy that I would have to do after calling fork in many cases, right? So it removes a lot of the work while allowing the process and child to share memory safely, right? So I won't give away all the secrets of how this works, but the idea is that I don't have to copy memory, but changes that the parent or child make to memory are not reflected in the other process, right? So they are not sharing memory, but I don't have to copy all the memory, right? So this is a copy on right, kind of gives you a clue to what exactly is happening, right? And then there is one addition to the system call interface which is this thing called v fork. And v fork is a different system call and what it does is it says if you call v fork and the first thing you do after calling v fork is not call exec, I'll fail. Like I'm just gonna terminate your process, right? So v fork is only to be used in this design pattern where I call fork and I immediately call exec to do something else, right? If I was running a web server and I used v fork to create new copies of myself, it would die, right? Because v fork doesn't do all this work, right? It doesn't copy the address. All right, so let's see here. And then, yeah, so there's a new system call also called clone, which I think I mentioned before, which essentially gives a lot more control to the calling process over what gets copied, right? Pieces of memory can be shared, signal handlers can be shared, things like this, and we won't get into this in detail, right? But this is another very interesting thing, right? Which says that clone allows the child to start at a different place, right? So the child doesn't even have to start executing at the same place that the parent, right? All right, so when you start forking processes, right? Fork establishes essentially this parent-child relationship between the process and then when the child calls fork, then child has children, right? And what you end up seeing is this kind of tree of life type of thing. And if you run this Unix utility called psTree, which may be installed in your virtual box or maybe just be able to install it yourself, you can see that, you know, here's the process tree on a web server I was using to run last year's website. So here's init, right? Remember, init is the parent of everybody, right? And it is the boss, or God, or whatever you want to say it. And then, you know, so here's an Apache process, right? Which gave birth to another Apache process. And I think these are actually a condensed version of saying that there are many, many other Apache processes which respond by these, right? Oh, these might indicate that there are, actually, you know what? Sorry, that's not true. So this notation here indicates that these processes have multiple threads, right? So this is Apache running in a configuration where it both creates several processes, but those processes also create their own threads, right? So there's a way to configure Apache so that it uses a mixture of multi-processing and multi-threading, yeah, Jim. Good question, you could try it. Try it in your virtual box and see what happens, right? I don't know if, in it, handle signals.  So it probably doesn't handle just kill, right?  No, no, it doesn't, right? So that's a great question, right? So all of these processes here may have been, it's not necessarily true because we'll talk about what happens when a child's parent exits, right? But these potentially could have been created by in it, right? But they are not in it, right? So you can see that these are various system services, SSH, and so here was my interactive session, right? This is me, SSHD, SSHD, SSHD bash PS tree, right? So here's PS tree, which I just ran, and it's in its own tree, right? So this shows you, this is a nice way of visualizing everything that's running on the system and how it's related to itself. So what is, so has anyone ever tried running and compiling this program? It's kind of a fun program. What does this code do? Yeah, yeah, yeah. Yeah, this will just exponentially spawn new processes, right? It's worse than threads, right? If it was threads, actually you might, your machine might survive it, but processes usually not, right? So this is like, yeah, this is my favorite. Like what is the, like more, more. Okay, so I think we're at a good point, right? So we're done with the fork. Monday we will talk about exec and then finish the system called Stuff Next Week. So keep your eye on the website for new parts of assignment zero, which should be done today, and have a great weekend. I'll see you on Monday.


So, I guess we can start. So, the last talk of the day, I guess everyone is tired and yet one more distribution on RISC-5. So, we're going to talk about Fedor and RISC-5, David Abdukmanov, Independent Software Engineer. So, that means that I'm not employed by Red Hat, I'm not employed by Sci-Fi. So, I'm leading with Fedor RISC-5. So, for the last years, basically it was a full-time endeavor. So, before we go into the talk, let's do a few questions. So, do you have people who are running Fedora or used to run Fedora? Can you raise your hands? Nice, very nice. Okay, do you have people who used to run or still run Red Hat Enterprise or CentOS? Very nice. Do you have people who do not know what RISC-5? Okay, that sounds good. So, we're going to look into basically three parts. So, the first part, again, how we bootstrap a new distribution, a new brand-new architecture. I guess you can kind of go very fast on that, because if you watch the Debian talk, or if you haven't, please go and watch the Debian talk. There's very nice and detailed descriptions of what the Debian did, what is the RISC-5, and the whole history. Basically, 94 plus percent of Fedog directly applies to Fedora and probably other distributions also. So that, let's start talking about how you build. So, Fedora and basically every distribution, it's natively built, so if you don't do a cross compilation, which probably is what you do when you're using an open embedded or build route. So, most software is going to be written for the native design, so though it intended to be cross-compiled, so if you want to do a cross compilation, for new architecture, you need to probably port it, you probably need to have custom environments, scripting to do a cross compilation, that takes all the time, and then there are some pieces of software which try to cross-compile and even attempt to run itself or some utilities, and you're probably gonna need to hack that software to get it cross-compiled for the new architecture.  So, at this point, for at least for the RISC-5, the QM is actually a strong target, you can even run on full-length cores, that's very nice, so it's very good to build the whole Fedora stack and probably the distributions. So, it's a bit chicken-egg problem, so again, Fedora is built on top of the previous version of Fedora, so if you don't have that for the RISC-5, so we need to get to that, and the way to do that is basically build a very minimal route file system, it's not gonna look like Fedora, it's gonna be very hacked, but basically, it needs to have a tool chain, the minimal bits, some form of a kernel with some features, and it needs to have Fedora packaging tools. And then you can start putting in the sources and trying building their PMs. So, basically, the picture looks like that, you do it in stages. So, again, you build a cross-tool chain, then you take the tar balls and you build some form of a very minimal route file, which you can build, which you can boot natively or under emulation, and again, it has the RPM tool, so you can start building in RPMs, so you're gonna rebuild it. In reality, when you think stage one, stage two, you think it might be independent, it's not exactly the case, sometimes you need to go back to the previous stage, enable more features, so it's kinda going back and forward sometimes to get all the features done so you can build a large set of RPMs, and then for most RPMs, you actually assemble the new route FS and you keep building on the new one and you keep redoing that. So, we have done all of that basically two and a half years ago. We did some of that, again, then we finally got the final agility version, so the ABI is locked, nothing is gonna be changed, so it's finally we can build the last distribution. The last step, which was done basically almost a year ago, was moving to a fedorant's construction bit, so that is the Kaji infrastructure. So that means I'm talking to the Kaji hub and web, I'm submitting the packages, we have a lot of the QEMU builders and we have the boards, we are running KajiD, so it takes one of the package, it creates a pristine, stage route environment exactly for that build, it builds the package, sends it back to the Kaji, Kaji does internal repositories, distro repositories, simple disk images and stuff like that. So the first bootstrap, I believe, was done, so Richard started the whole project and he's sitting right there. That was in 2016 August, I believe, based on the blog post when he said that he has something which runs our PM build and I think he announced that on Fedora mailing list and very quickly me and Stefan who is sitting right there joined this effort, so we have been working on this for a very long time. In 2016, I think you already had 5,000 packages, so that's like one quarter of Fedora at that point. But yeah, let's move forward. So Fedora is, of course, its upstream first policy, so that means if you wanna build a RISC-5, all the changes we do, we have to go upstream and then we have to rebuild the whole thing. So we have to do not only release engineering, but for structure stuff dealing a lot of all supporting. So a lot of things happened, the GDC happened, building the team that happens, they had to wait for a kernel, G-Lypsy was the last part. When that happened, we started going like mad to get it done. So we also had second and the third bootstrap and the third one was the final one. Once we have done that, we actually move to the Codian for structure. So that's, again, being a Codian, that means we're building the package in the same way that the Fedora official is doing. But this alternative architecture, so it's not using the official infrastructure, we're using a separate infrastructure. So that's a very quick overview of how we got to this point where we can actually boot something. So let's maybe look at how does it look in real life? One thing is to build something, get the console maybe, maybe it looks like a Fedora, like a distro, but what can you do to how does it look in real life? I think so the first time Fedora booted was in sci-fi offices in California. I think that was at the end of the March and last year. So that's first time Fedora 28. It's not exactly Fedora 28 because what we did was we built, I think, 24 on top when 25, 26, 28. So it's kind of a hybrid something, which kind is 28 at that point. So that's a board, sci-fi and leash boards is FPGA. And again, that's a screenshot from the display. Later, I think a month after, we started getting a board. So the sci-fi actually were donating the boards for various projects. So Richard got one, he got also another one from crowdfunding, so we got two boards. DJ from Red Hat got another one for Gillip C, which he also used for Fedora and also using for kernel stuff. So this is probably the most expensive way you can attach a CD to the system. That's probably five or $6,000 just to attach a CD. The other boards that Richard was running, we're running NBD, and we do not use the SD cards because those are crappy on the board. And then Atish from Western Digital came in and said, and wanted to try something, and he had the micro-semi board, so that means you can actually get the USBs, you can have the SSDs, you can get the graphical cards. And I started working on the GNOME desktop, I think, when I visited sci-fi offices. So it was like six months past since that time. And I think it's a total tragedy, it's not gonna work, it's definitely not gonna work. And surprisingly, it did work. The only thing that the struggle was to figure out what you needed to enable on the kernel to get the mouse and the keyboard. And that took like a week to figure out. Other than that, it did work. So this is the first picture of Atish actually booting in sci-fi with a micro-semi. And that's GNOME desktop, the same stuff that's running on this laptop, basically. And also Atish did more demos in various conference. So we have Fedora 29 running an AS demo, here's a media server demo. So it's basically not exactly the toy, so you don't need to go to the console. If you have a hardware, you can actually run real stuff on it. So basically, you're not limited to something. So if you have a goal, if you wanna do something on the board, just figure it out and then just try to get it running. It might work out the box, like it happened with the GNOME stuff, might not, but then come to a channel, tweet me, whatever, and you can figure out what's actually wrong. Another thing, so Bellard, the same guy who actually invented QMU, he wrote an email, and he has another project called JS Linux. And if you go to a website, you actually can boot Fedora 29 in the command line. You can also boot in X11. And by the way, the GNOME desktop, that's running Veylon. But you also can do X11 in a browser. You don't need to install anything. The performance might be not exactly what you expect, but it actually works. And also we have a tiny move emulation. That's also the thing you can actually boot Fedora in the graphical user interface. Not exactly at the current versions, things are a bit changed. We need to get the adjustment, for example, the BBL, and the kernel itself is now separate. And also you cannot specify the integer D for the tiny move, but that's at some point supposed to be happening. So let's go in the current state. What I did and what's probably is very wrong, especially if you're Fedora user, you probably not wanna hear what I'm gonna tell in the next slides. So I would build farm. So again, we have three boards, three physical targets, a couple X8664 nodes for running Kaji, Kaji Hub, Kajiras, the databases, various system D stuff to schedule. We also have some backup solutions for running Seth and Restick to ensure that if by accident the server dies, we can recover and we had to use that just after a Christmas. So originally all our builders, the QMU stuff was running on the Richard server, private servers. We had only like eight, I believe. Yeah. And then we moved to a GCT compiling farm. So Facebook donated loads of servers and we have eight of 16 core servers and based on my assessment, we have about 64 and we can add another 30 something QMU targets. And the whole infrastructure at this point, all the QMUs, that's fully managed by LibDirt. So not running long QMU commands or anything like that. And also everything you build, at least the disk images at this point and the repositories are now fully mirrored to official Fedora infrastructure. So if this dies, you can take disk images, you can set up a new Kaji, you can import the whole stuff and just kickstart when you want. Yeah, and that's the URLs. And we have two streams. So I'm still building 29 and Fedora Rohite. It's basically like a rolling release and we're also discussing potentially doing centralized aid, which is a bit more complicated, a lot more complicated at this point. Statistics. So I don't exactly like the numbers because numbers constantly changing. But according to the Kaji, we had 24,000 successful builds and about 3,500 failed ones. The best week in terms of builds, I did four and a half thousand successful builds per week. But again, I could do more. But what you don't do, I'm gonna be more slides about that, you don't run tests. And I do an other stuff. Basically, when we are running only on those eight machines, I had some hacks to ensure that you have loads of successful builds and you don't attempt something which is not successful and optimized for the speed. And if you do a comparison for Fedora 30, which is a raw hide. So the first line is directly from our Kaji. The last two lines are from the official Kaji infrastructure. So we have more total packages at this point. So Fedora removed some, we still didn't catch up to that point. Total build, if you look at the ARCs and this one is actually smaller, but when they look at a dozen of a package, apparently 29 and F30, we have packages added, which we never built but there are plenty of them for some reason. And then again, RPMs, I just asked for directly for the architecture and how much we have on RPMs. And then also including all the debug info and debug sources in general. So the package is, if you have to think of package as a source RPM and that source RPM produces artifacts which can be multiple of RPMs. For example, TextLive, that's delivering you like 6,000 of RPMs. A certain root package delivers a bit more than a hundred RPMs. And again, some of these packages might be in general exclusive architecture or something or we might produce some sub-packages or not based on architecture. So we count in exactly like, I have like a hundred percent, 95% for each architecture is different number. So that's why I don't like exactly when statistics and numbers. We have lots of problems. Loads of them. We basically try, we are running on more than 10 year old machine which was donated.  We don't, there's no big company kind of like pushing our money and you know, to get it done. And we try, we are running basically everything on one single machine. At some point, we also even run the QMU instances on the same, our main server which does everything. Also our domain ended up in HTTP secure or something, something. Yeah, a preload list. And once it ends in that, basically it says if you go to HTTP site, you automatically go to HTTPS and you cannot, normal users cannot go to HTTPS because of that self-signed certificate which we use to log into our Cajun infrastructure. So the people complain that they cannot log in and get the disk images from our Cajun. So we are going to change the domain. So that's going to be Fedora.Ris5.ROX. So this is going to be very simple. And we still have the boards and QMU failing. If I basically every day have like two to three QMUs failing, that's basically CPU stalls. I don't know why exactly. The boards fail maybe, I don't know, once. So in two months and three months, very rarely, but we still happen. And the whole infrastructure requires a lot of time and maintenance. So the more you do that, the less you can actually do on the porting which is truly interesting part. So what's missing? Okay, so at this point, we did not sign any RPMs. That might be scary for some people. We could do that, but that's probably has a big impact on IOs. And again, the server is not exactly handling the current situation. So I'm not doing that, but we could do that. You don't have a body. Basically, body moves RPMs for different tags in the Cajun. So for example, you build a package which lands in one tag, but someone needs to sign it. So you need to move it for different tags before it lands in the final repository. We don't need it. At this stage, you don't need it. You don't need it. You're using a PNG. PNG is something which assembles the repositories and the disk images and everything else. We just use the basic Kaji stuff and does exactly the same stuff. And we don't do defaults to do our disk images, but we probably could do that. I don't see actually why not. We don't do modularity support. I don't think a lot of people are using it at this point, but if we want to do send to us, that's probably a requirement. Modularity basically means that you have a base OS, for example, and then if you want to have a different PHP version, you can just select a different stream and that stream is independent from the distribution life cycle. We are gonna do a similar thing with this RME7. We don't support a bootloader specification and it's basically because we're gonna end up using UBOOT at some point, which doesn't do that. You need to use grep2 for that and we're at patches for grep2, but there's no, still missing parts in the kernel for doing EFI. And also if you need to update the kernel, you can do DNF upgrade and everything is gonna install but it's not actually gonna run it if you reboot it because at this point, we're using a BBL and the BBL comes as embedded kernel, so you need to power down, copy a new BBL and reboot the machine. And again, globally, we don't run any tests. Again, we have a lot more QMUs, so it means I can now start to sacrifice them and I can then start running the tests and I can do other stuff which I didn't do before because I needed to optimize it for actually for throughput. Custom bits. We don't use KajiShadow. Basically at this stage, if you're supposed to use a KajiShadow, what it does, it just follows the official Kaji. If someone puts a build, it automatically goes to our infrastructure. It ran for half an hour and I killed it because it tagged something from Fedora 12 and I wasn't happy because it's so fat. So I have my own custom stuff but it probably needs to be rewritten to do a correct, more correct thing. Again, we don't do git to source package. I do it on the x86 machine because it takes just two minutes to do that. It takes one hour, two hours. If we do on the QMU, that's like expensive thing. Also, my script attempts to figure out if you have all the dependencies so we can build it. We want to have more successful builds, not just some builds which fail in two days and because it didn't have something. Yeah, and we have, so all the source code for Fedora sits in what you call the diskit, which basically are lots of git repositories and they have an overlay. So there are some patches which I'm not yet happy. I'm not in the Fedora. So I'm supposed to go to Fedora plus we're just in general some ports. So I need to work on getting some of that in the Fedora. Probably some of that sending to upstream and some of that never gonna land anywhere because the official stuff is gonna be different. We do four separate disk images. If you don't know what you want, you probably want to go to this developer. That's one big image. It still fits in the Z card. Yeah, it has everything. It's a Kaja builder. It has all the tools for 8 p.m.s. It has X11 minimal stuff. You just wanna do a Flexbox, I3, Awesome, all the Emacs, Vim, NeoVim, the Bugas, all the tools I can figure out to debug L stuff, hex editors, compilers, working with disk images. It has a lot of stuff. If you get an image, the smaller image, and you do it enough, make hash. If your silicon is very weak, you might need to wait some time, 10, 15, 20 minutes. If you need to do that a lot of times, you don't want to do that.  You need it, you want to test it, download the image, you have your packages in it, and that's it. And I also had to change the scheduling because, again, we have problems with IOs and doing images are a very costly thing. So this is basically where you can get the images. The old one, stage four, that we did before going to Kaji, is still very, you can boot them and I know that some people are still using it. You can directly grab something for Kaji. Most are untested, so there might be some issues because it's automatic. And for the root file system, you need to use VDA1 because there is one partition. I cannot actually not, I have to make one partition required the way it's built. But if you use the new ones, I kind of select and test, so I'm going to boot them a few times, I'm going to do some, I'm going to enable ac Linux, I'm going to do QMU, Libvert basically. I know that they work to some extent. The targets we actually support, so again, it's a QMU, Libvert QMU, a tiny move, but again, that needs a bit of modifications and you can also run it on the boards, and again, you saw the pictures from ATUS, presentations and some people are running it, but it doesn't run upstream kernel. A year passed, it still doesn't support the hardware. I don't know how many drivers I'm missing. Yeah, a few. Yeah, so I guess a few more months also needed to get that in, hopefully. But I guess that's 2019 material, it's going to happen. So, and you don't have, for the latest images, we don't have kernel builds for that. So if you're running on the board, come to our ac channel and then ask for as explicitly, probably ATUS has a tree or something that you can pull and run. A few, maybe annoying things about risk five in general. So the same thing that happened is a 64 bit arm, make sure that your config scripts are up to date. The last time we had modified what, just several months ago, basically six months ago. Risk five only does a what size of Tomics. That means there's a hack basically in a GCC. If you use a minus P thread, then there's a lip spec that's going to say, as needed, link with the Tomics, and then you don't have any issues, but majority of the case is going to be minus LP thread, which works on most common architectures, but not on all architectures. Because that's minus P thread, I don't know, some architectures like minus, it's actually P threads, I believe. So yeah, I think there's a bug report, and I think there's an idea to inline those atomic calls, but no one has time to implement that. And I guess there are only two people who might do that. It would be Jim and Palmer. Another thing that we recently found when they debugged a D language, so D front and final end in the GCC, but we had some problems was dynamic sections has to be read only, but that's not the case. As far as I know, as far as the Jim comment, that's a direct copy path from a MIPS, and does not apply to risk five, even if a comment says it applies. Yeah, so hopefully you're going to send the patch to Geolipsy. Yeah, and another thing is you might think it's slash, slash, slash, lip 64, it's not. Even if we are not multi-lib, Fedora risk five is not a multi-lib, but the way the natural risk five works, it's going to work as a multi-lib. So in reality, what the linker's going to expect is lip 64 slash and ABI. We have sim links, so the old way is still working, so it's somewhat compatible, but in general, on risk five, it's like a different situation. And there's a load of plans, so we have a new main server, so it's slightly better hardware. So Polymer finally sent pull request to Kernel, so 5.0 RCT got my audit support, so that's in the kernel, it's working. The user space is posted, but not yet merged. I have a second patch, I know that it works, but it's not yet in the kernel, probably maybe in the next version you could manage to get it done. The D-lang works in the one in the GCC, but I still work in upstream patches, so again, I need to send a lot of changes from our dis-git overlay to either upstream or to Fedora dis-git. If you still don't have add as support in the GCC, so that's probably going to be a next thing to add, and then look into a Haskell compiler and a Free Pascal, enable the tests, enable building from GIT source packages, improving the shadow codger functionality, dump in BBL and go and use OpenSBI in the U-boot, maybe XT Linux, and also Alistair recently joined the Fedora's five channel, and he asked to do more testing for QMU, so also looking into building QMU daily nightly builds for CentOS and the Fedora on the Intel architectures on also in the RIS 5, because there is a TTG backend for RIS 5, so basically you can emulate Intel on RIS 5, I think, and we could maybe do a demo in three minutes. I have no DC, so this is my, so from the way to use, I suggest use LidWirt, because I think it's much more easier than actually running a QMU. This is command from the Vicky, so we're gonna copy it, and so I'm not, I don't have anything running, I don't have any VMs, but I do have images downloaded, so I'm gonna create a VM, so that should be running already. Yes, I probably cannot. Okay, so we connected to the console. For some reason, the latest BBL takes some time before it boots, but it's booting. So let's hope it boots fast. I have no idea which point it is. Nope. Oh, that's nice. So another interesting thing why it's still booting, what I would suggest to use, Sierra log file, so again, our QMUs are dying, usually the CPU stalls, but other bugs, I highly suggest enable that, because if something happens and you cannot log into a system versus Sierra log, and you're probably gonna find the kernel crash or something, so you can send. So I highly suggest you to run that, and it's still booting. No, I'm probably not interested in that. Okay, so it is five, nice. Actually, I think there's one bug in the kernel, so MMUSV48, the kernel doesn't support that. I did on the mailing list, but no one replied. Yeah, it goes from DTB. DTB says it just prints the one. So what we're gonna do, we're gonna have time. So this is a D-language. I'm not a D-language user very much, but it's still the bugger thing. And maybe one thing that we can change is go back to Intel. There's, if get the vp move to something better than a console, is now we should have at least colors. Yes, that looks nicer. So, you see, so we can compile it. So that's in the GCC9, again, we have a D front-end, which almost works by default. It's not yet enabled in upstream, but you have all the patches when you understand what's happening, so we're gonna figure out before the GCC9 is released. So we're gonna compile a word count, which basically is WC command in the D-language. It's gonna take a bit, a few seconds, I guess, like 20 seconds or something. Yeah, so that's a new language. Nice, so what we can do, so again, that seems correct, I guess. And that's also correct, 20 lines, 48 words. Yeah, it works, so that's a de-application running on Fedora 30 raw height on RISC5, the GCC9, which I think no one yet has. Also, there was a talk from Debin, Debin said that the GDP doesn't work in the Linux, so let's do the same with the GDP. So backtrace, this always make a mistake, how many? Yeah, so you can disassemble, you can do registers. Yes, so what happens with Fedora raw height, which again is the rolling, you get the latest kernel, the kernels are built basically a few times a week. You're in between the RISCs, you get the GDP bumps every week, every two weeks, same as the GCC and a few other bits. So it's, I mean, if you want to have a bleeding edge, it's in the Fedora raw height. If you don't want to wait for release a few months, it's in here, Gilep C is also bumped every, at least a week, the B weekly, and it's a kitchen sink. So the developer image is a kitchen sink. And if something is missing and you need it for demos or development because you want to depend on that, again, go to Fedora's five channel or something, tell us what's wrong, and you're probably going to put it in. It's basically, again, it's a one big integration for the upstream. And that, I think, yeah. So these are the companies that basically are the most important. So StoneQlity does our main infrastructure. Facebook gave us a servers, Open Source Lab in Oregon, I believe is hosting a hardware. GCC Compile Farm is managing run hardware. Sci-Fi did the boards and delivered to the developers. And our latest and greatest major new server is also going to be hosted by Academic Computing Club in Umea University. So hopefully that new server is going to handle the load better. And again, if you have any questions or you're missing something or something is not working on the test something, whatever questions you have, it's five or not, you can go to Fedora's five, you're going to find people from Sci-Fi, there's a Polymer, there's Jim, there's a DJ from Gilep C, there's Alistair now, we have Debian guys, we have Parabolic new Linux, we have Open Madriva guys sitting, so they have a lot of guys from all the places, they got almost 40 guys. And if you have a question with a risk five, you're most likely going to get an answer in that channel. So that's it.