Wait, do you have two cards? Whoa! Where'd that one come from? What? This is the big time Cookie Monster! Where are you to pull that card out of? I am joined by two monsters who need zero introduction. Cookie Monster and Gonga, the stars of the foodie truck. Guys, how are you doing? Ah, thanks, bro. That was a lovely introduction. What's special about your foodie truck? We got that terrific chef. Yeah, that's me. He's that little guy? That's me. He's killing it in the kitchen. Yeah, soak it up, Willy, baby. What would you do to make a lasagna? Well, I'd get the pasta sheets and the bachamel sauce. You like bachamel sauce? Love it. Yeah, and I got some veggies in there, some courgette, some aubergine, some cookies in there. Whoa, whoa, whoa, whoa. Cookies? Yeah. See, the thing is, I have to put cookies in most of the recipe. In a lasagna? Right. Which layer do they go in? Which layer? I want the main cookie. Well, the top layer, of course. Sometimes the top layer and the middle layer and the bottom layer. When you have an urge to eat a cookie, Yeah. do you ever use any techniques to try and fight that urge? Me glad you asked. Me struggle with, um, me have issues with self-control.  It's not easy for a monster. I've been trying to tell him he need to breathe in like this. I breathe out like this. That looked painful. You tried it. Breathe in.  Well, me have other strategies. Oh, yeah, yeah. Fine. What like what? Like to distract myself. You know, me can look away from cookie or me can like sing song.  Like what sort of song? Um, me like all kinds of songs. Me have me favorite song to see is from cookie, which probably isn't a good idea to sing song about cookie. You got any songs you can tell me about? Have you heard Billie Eilish's new album? Who? Billie Eilish. No, me not know that. You should listen to it. It's great. Okay. I like Ariana Grande. Oh, yes. Do you? Yeah.  Oh, yes. Speaking of that, thank you. Next question. Do you ever get tired of cookies? No. Next question. What's the go with that question? Cookie Monster. Your Twitter is all about a positive line. Of course. So how do you stay so positive? Well, you know, me just happy monster. You know, me surround myself with good friends. All me friends that says me street terrific. Yeah. Like Gonger. Yeah. Gonger, Elmo, Big Bird, the whole gang. How about you Gonger? How do you say positive? I'm the same on Sesame Street. We've got so many friends. We do keep each other happy. How do you keep positive and happy? I give people cookie. Cookie. Do you want to? Cookie. Cookie. I'm going to hide back here, though. I don't want to get crumbs on me. Take cover. I'm numb, numb, numb, numb, numb, numb, numb. It's raining cookies. Yeah. Where are you going to get a broom?  Fine. Thank you, Will, for cookie. Bye-bye. I'm going to get a broom. Sweep up, Will.


Network, TFNN, headline news update. Welcome folks. We had the Dow industrials finish up 220, NASDAQ up 63, S&P's up 25, S&P folks all-time high, NASDAQ composite all-time high, Dow industrials couldn't—well, it went to an all-time high. The differential is that the Dow didn't hold price. We got to a price point today inside the Dow industrials of $27,224, and $28,174 was the last high and bottom line couldn't hold price, so that's a heads-up to the Dow industrials. There's no doubt. Inside the composite, the NASDAQ composite, composite up here, that took away a tie closed above its high, which is $87.05. We closed at $87.17, and if we go take a look at the cash S&P, you're going to see the cash S&P also got way over its high. The cash S&P, that high was at $3154, your 14 points of wait, that's a big number folks, so $3169. Notes and bond. So let's go take a look at the note and bond market. What do you have out here? They took the note and bond market apart out here today. You had high volume, wide price spread, you're down 29 ticks inside the 10-year, 2.4 million contracts. That being said, the swing low that's going to go after is $127.30. Now you have much to volume on November 7th also. So if we go after this tomorrow, bottom line, I expect what you're going to see as you're going to see a failure on price, and we'll bounce right off that level once again. In fact, if I bring you over to the TLT, you can basically look at this right on your own quote system, and you're going to see the TLT. We did come down hard. The TLT is the 20-year plus ETF. We did 14 million shares, but guess what? You're coming into 19.2 million shares as well as 18.92. This is a big heads up that, yes, the bond market got hit today. What we also had today though, which was really intriguing, this was the refunding day for the federal government, and the 30-year bond auction, folks, you know, went off like, of course, beyond belief for the amount that the traders were going after versus what they had. It was a very successful offering. Folks, have a great night, safe night. We look forward to speaking right back here. Tomorrow morning, 9 o'clock, come over to TFNN. I'm M.S. Larry Pezzavento. Have a great program.


Welcome to yet another talk by really, really cool people. One is a little bit less cool, but he's a really great guy, Thomas. He's way cooler than me. And a bit more cool than, and also a really nice guy. They're going to talk about Kirigami with a really fancy title that they will pronounce. Yes. Great. So, I am going to say a dirty word during this. See if you can spot it. Well, the topic of the talk is about folding your applications. And the reason it is that is because we are talking about convergent applications. No one's noticed. Okay. So, the first point is we'll, yeah, quickly introduce ourselves very quickly as I understand it. I'm Dan Maynard, Arthur Jensen. And I've been a member of KDE for many years. And I'm a member of the Kaleegra and Gluon teams currently and have been a member of many other teams before that as well. Sorry, no, the Kaleegra and Discover teams Gluon is history and a leftover from a previous talk. I'm also an employee of Blue Systems and normally don't look like a blue bird. Yeah. I'm Thomas. I'm, yeah, I've studied psychology, focusing on human-computer interaction, use experience. And through that, I've come to KDE in 2008 and have been doing mostly, yeah, usability, use experience things since then as part of the KDE VDG, the design group. And since last year, I'm also a member of the board. I'm not paid to work on KDE. My day job is at Flare Games. Where you get to help Chuck Norris, a bunch of people, I think. Right, so, oh, yes, this was yours. Oh, yeah. Yeah, so first of all, what is Kirigami? Well, probably already heard about it because quite a few talks have actually mentioned it. It is a framework which, yeah, is useful to create touch-optimized applications. But that doesn't mean that they're only for touch devices. So as I've already said, it's for convergence. So Kirigami is your tool of choice if you want to create an application which runs both on traditional desktop computers with mouse and keyboard, but also on touch devices, mobile, embedded, whatever, with essentially the same code base. That's the key part. Yeah. And it is also a means to implement very specific human interface guidelines. We often get asked, why can't I create an application following exactly the Android material design guidelines, for example? And then usually our answer is two things. One is, well, you can, if you create an application that perfectly fits material design, then you cannot really use the same code base to deploy the application on desktop Linux or on iOS or on any of the other systems because then they would feel alien there even more. And would not be, or you would have to create different UIs which would not be consistent. Whereas Kirigami, we have our own human interface guidelines with some specific interaction design concepts which do diverge from what, for example, material design and iOS do, but they also have a lot of baggage from time, for example, when phones were still smaller and you could still easily reach the whole screen with your thumb, whereas right now you have large phones where your eyes should be more bottom heavy because that's what you can reach with your thumb. Yeah, it is a supporting technology, so what Kirigami does is offer you some building blocks for your application to create an UI easily which is consistent with other Kirigami-based applications and consistent across platforms. So it was born out of Plasma, so it was originally created to have something, actually for Plasma Mobile, but it is not only Plasma, so the same application can also run on, for example, Android, on iOS, and of course if you run it on a desktop computer, it can also run on any other desktop environment, it can run on Windows, it can run on Mac OS. Yeah, it was originally started as separate from KDE frameworks for the simple reason that the Qt version that Kirigami needed was higher than the one that KDE frameworks depended on at the time. By now this gap has been closed and with KDE frameworks 5.37, Kirigami will be an official part of KDE frameworks. Yeah, next up. Great, yes, that was mine. Right, so when you create a Kirigami application you have two options. The most important point here is that you have to have a container to host your application. And for the longest time that was called application window, which was basically a minor change on top of the Qt Quick controls to application window. These days, which will become apparent slightly later when that's important, we also have a thing called an application item, which simulates the application window API. Unfortunately we couldn't derive from it because that would make it a window and that would be bad because you'd end up hosting a window inside a window and that's a bit ugly. But what the application item slash window does is it implements some of the core user interface elements, which we will show you slightly later. It adds properties for inserting the user interface elements that the HIG defines as properties on this but it is very straightforward to construct the application without necessarily having to specify what edge something has to sit on or whatever. It also provides a very convenient method for showing passive notifications, the little toast things that you see on Android and iOS and so on, also recently on various other desktop applications, passive notifications which don't really have any kind of interactivity with a small caveat, but the purpose of them basically is to not do anything other than give you information. You're not supposed to do anything with them. And so the organization of an application in Kirigami is conceived as a scrollable row of pages and pages are what we'll mention next. As already mentioned, a typical Kirigami application is divided into pages. Usually on mobile you only see one page at a time, whereas if you scale up the same application to a desktop computer, you may very well see multiple pages in the form of columns in your UI. If you use the page class, then you already get all the standard behavior that the human interface guidelines describe. And one thing that makes it easy is that you have actions properties, how they are going to be visualized, we will see later, but you have a main action which will be the most prominent in your UI. And so this is in a button which is on the bottom center and it can also have a left and right wing or sub button because of secondary actions, which you can also just define in the page and they will automatically show up and be usable. And it can also define contextual actions, and these will then be shown in a contextual drawer, which I will also get to. Then something that you are likely to also use often is so-called scrollable page. So often it's lists of items or maybe just layouts which are too long for one screen, so you want them to be scrollable. And Kirigami also makes that pretty easy. And so you don't need to handle all the flickables yourself. The scrolling page will do that for you. And it also has nice things such as if you have a list, which you can refresh from some network source, for example. You can do the pull down. So if you scroll to the first item of the list and then you pull down further, then it automatically refreshes to give you newer items. And also something that was, an idea that was introduced in iOS at the point when phones became too large to reach everything with your thumb is that you can pull down the top of your UI so that everything that was at the top moves towards the center and you can reach it with your thumb. Right. And then we have the drawers, which are basically items which sit on top of everything else. They are a convenient way of giving you access to actions and supporting content to help with the things that are inside the page. So their base class is overlay draw, which allows you to, if you need something that is not supported by the core elements that we've got mentioned shortly, you can create your own as well, which is quite useful. It will attach to any edge and it was originally created because Qt Quick Controls 1 didn't have a draw, but not a draw of the way that we needed it. But these days it is, if you are compatible with the one that exists in Qt Qt 2. We also have a specific implementation of it, which allows you to push it onto the screen. This is less important on a desktop where you are working commonly in a window that doesn't sit against the screen edge, but if you are working on a pure touch user interface, say a phone or a tablet on incidentally any kind of platform, not just Android and iOS. This is also a problem on Ubuntu and on Windows. You need to be able to swipe it onto the stage. So you can do that on some of these platforms, the ones where those edges are not taken up by the system, you can do that by simply swiping your finger along the edge on the screen, but we have specifically Ubuntu and Windows 8 and 10, where that's not possible because that means on Windows 10 in particular that you suddenly are in a different application, which then meant that we had to come up with a way of making that easy to get to, which means we've now got a hook sort of gesture where you push up from the bottom of the screen and then pull to either side to show the corresponding drawer. Yes, so I think the next one is yours, but let's see. So by default there are two drawers, the global drawer and the context drawer. The global drawer is sort of the main menu of the application. It is very similar to the menu drawer that you have in many Android applications. And it slides in from the left, so either by an edge swipe, or there's also a little handle that you can use to open it. And it has a big fancy title where you can put an image in the background and make it look even nicer. And it has a main menu, which can also have multiple levels. And then you can also put in additional controls. As you can see here, you can also put in checkboxes, sliders, whatever you want. The global drawer is used for everything that is the same at any point in the application, so that users know that whenever they open the global drawer, they know what's going to be in there, they know what they can do with it. In contrast, the context drawer, as the name suggests, is dependent on your current context. So for example, it can have controls that apply to the current element that you have selected in the main view, or it can just change depending on where you currently are. For example, if you have a document viewing application and you have controls that depend on what kind of document is currently open, then these will be shown in the context drawer. And as you can see, it's also the elements are aligned to the bottom so that you can easily reach them with your thumb when using it with just one hand. Yeah, but then there are also custom drawers, as already mentioned, so you are not restricted to these main drawers. So the global and context drawers are very easy to implement because they're pretty much already there. You just have to fill them with things. But you can also use additional drawers for any arbitrary use you have. For example, a bottom drawer can be used as sort of a dialogue which is in material design and called sheet. So when you have something where you want to give users quickly some kind of some way to react to something, you can use a drawer so you don't have to replace the whole main screen. And then there's the overlay sheet, which, yeah, is better suited for when you have larger content. So the big advantage of that is that you can scroll even within the sheet. So one sheet can be larger than the screen height. Which means, yeah, you can show additional content on top of your main content, but people can still scroll through it. But then once they have reached either the top or the bottom, then they can just flick it away to close it again easily. Yeah, then one thing that I've already talked about, the primary action button. So if you define a primary action in your application window, then it will create a primary action button for you, which sits at the bottom center. So again, very easy to reach with your thumb. And you can just tap it. But it also serves as an additional handle for the drawer. So if you just press on the button but don't release, but instead swipe left or right, then you can also open the drawers with this, which is just a nice additional gesture. Yeah, but this is certainly mobile optimized, but the same actions on a desktop UI can go into a toolbar. So that is again something where Keregami helps with the convergence that you don't have to necessarily manually define everything that is different between mobile and desktop. The framework can do that for you. Yeah, another neat thing is the so-called swipe list item. So this is something where you have a list with contextual actions to the specific list items. There's one way to do that, to implement that is using the context drawer, but if you often have something that you want to do quickly with a list item, then a better way to do this is that you have a little handle on the list item, which you can just swipe away to reveal controls beneath it. Yeah, which gives you a very, very easy way to quickly do things. For example, if you have, let's say, a list of items, then you have things like delete the item, or if you have a list of emails, then you can quickly reply without having to open the full email first. The application header, so this is the title of the page, but it also doubles as a breadcrumb, because as we've already said, the typical thing that you do in kigami is using pages, and as you navigate through the pages, the application header creates a breadcrumb, which is interactive, so you can easily go back to any previous page by just tapping on it in the header. So there are, this obviously is not everything, this obviously is not everything that exists, so I'm going to rush through this for a bit. There is more stuff in kigami. We have a class called an action, which is kind of similar to a queue action, but which can be used more pleasantly in Qt Quick. We have list items which are not the swipe list item, so if you need something which is just a list item, you've got access to that as well. The item view header, which I will show you momentarily, which makes things pretty, and we've got a heading and a label which are semantic markup for text, just pure text. We have an icon which basically emulates the queue icon loading system without using a queue icon loader, and we have the toolbar application header, which is the thing you saw just before, which basically means even if you are on a mobile, you can still use the toolbar if you particularly feel the need to do so. So it's the thing that you can choose to do. We suggest you don't, but you can. And then there are a few applications which uses kigami. One of the first examples that we had was subsurface mobile. Subsurface is a dive log application which was started by Linus Torvats and Dick Hondle, and they wanted to create a mobile application. They had just recently switched the desktop application from DTK to Qt, so of course now they didn't want to learn yet another technology. They wanted to use Qt there as well, and then we told them, hey, we are currently creating that framework. It could be useful for you because it will make things a lot easier for you, and since then there has been a quite good collaboration with the team. They have given us a lot of input. We have helped them. They have given us ideas for new features, and yeah, both have benefited a lot from this. It's always nice to have external customers when you're working on a product, right? Here's one of our own, and it shows you the ListView header which makes things pretty. I realize I just forgot to scroll one of those screenshots because what it actually does is when you start scrolling the page, it will not be that big, which is useful. You will have run into this on Android and iOS in various places, so you start scrolling the list and the header stays visible but becomes really, really small, so it's not in the way. This is obviously discovered. You've probably run into that one at some point. This is Peruse, a somewhat smaller project, which looks a little silly right now because it is in the process of being remade somewhat, but it is an application which aims to fully implement Kirigami as a HIG, describes it, and function on both mobile and desktop with as few changes as absolutely possible for reading your comics. Then we have the very early stages of Kali Redim and I2, which was the reason for the creation of the application item because as much as this just looks like a straightforward Kirigami application there, what it actually is, it's sat inside another main window which will switch between a Q-Widget-based UI and a quick-based UI. Which is the Gemini thing. If you've spoken with me for the last couple of years, you will have heard me talk about this at length so I'll not do that here. There are other applications out there that are not ours purely, or some which are really ours, which is ClimbGrade, which is Marco's own. You will notice an overweight of extreme sports here. We have Koko, which is an image viewer project which has a summer code project to port the UI to Kirigami. It was originally written back before Kirigami was a thing, and we have Rukala, which I learned here, is also getting a Kirigami UI. And of course, all of the projects that you guys are working on. So please come talk to us, which is probably not now, I understand. But yes. So let's have at most two questions and let Kevin prepare. I have sort of a really nerdy question, but it's hard. What's the ratio of QML code to C++ code in the implementation of Kirigami? There is very little C++ code. The icon thing, I guess. Yes, the desktop icon thing is pure Qt code. It's all Qt code, pure C++ code, because we needed that to do it in any way efficiently. There is a non-C++ implementation of it, but I think it was originally written because of subsurface needing it, but it's usable in any application. So if you don't want the C++, or if you don't want all the abilities that the desktop icon implementation gives you, there is another option as well. It's a very, very lightweight thing which just loads icons out of a QRC. So it leads to a second question. Based on the blog from the guys, the kid guys, I think two weeks ago, about the performance in C++ and QML, how are you willing to think about changes, maybe some parts of the components in C++ just to improve the performance? That is essentially what we've done. So the really, really performance-dependent bits are done in C++. It is surprisingly minimal, but the performance there is, yes, that's why certain bits are done in C++, but there isn't a great deal of it. So most, a lot, yes, actually, he will know a lot more. Okay, quickly. Yes, just very quickly, as more recap on this, so basically now it's called Kirigami 2 because we basically re-implemented it completely from base to directly queue quick items to base on top of Qt quick controls too. So the amount of QML that has been instanced is already way less. That blog post was very interesting and what I would hope it comes out of that is Qt quick controls too, getting at least a bit of public C++ API and then at that point we can even go further doing some of our controls as actual C++ subclasses of Qt quick controls to classes. Okay, that's all the time that we have. So let's give a warm thanks. Thank you very much.


Unfortunately, there's no music for class today. Two reasons for that. One is that there's this terrible bus station in here at 8 a.m. You guys should all be happy that you're not required to attend.  As they say in Clark's, I'm just sad that it's in this town. Anyway, we'll see if we get that fixed by Friday otherwise I'll be sad. Okay, so today we're gonna finish talking about locks. We just almost got it fixed over to spin locks last time. We'll talk about what to do if you don't spin. So we're gonna do these two styles of locks, spin locks, and sleep locks, or what happens just called locks. And then we're also going to talk about some synchronization primitives. So, condition variables, which are a signaling mechanism, and semaphores. And if you started assignment one, these probably sound familiar because these are the synchronization primitives that are used by your kernel and that a subset of which you will have to implement. So these are good to understand what they do and why they do it. So, this is very similar to the slide on Monday. I won't make too many comments. I put up a post on Piazza, so it turns out there were maybe a day or two behind where we were last year at this time. And I'm wondering if that's my fault. So, if you think lectures are too slow, go online and vote. If you think they're too fast, go online and vote. And if you think they're just right, go online and vote. It's like Goldilocks. So anyway, I just want to, you know, again, I don't care if we're going at a good speed and people are happy with it. I just want to make sure that we are, right? I think we'll still get to the, through the material I want to cover. There might be a few lectures from last year that get dropped, but that's fine. But I just want to make sure I'm not, I'm not holding us back, all right? Okay, so questions on Monday's material. We talked about concurrency. We talked about animicity. We talked about critical sections. We started introducing some hardware support for synchronization that we're going to finish today. Any questions about this before we do our little review session? Yeah, Brian? Sure. You could do that. So, anyone have a clue? So, let's say you're writing bank management software. You have some code that modifies account balances. And you have decided to lock around that piece of code, which we'll talk about today, to ensure that that's a critical section. That seems like it would work, right? I have a lock that, or, and again, we haven't really talked about locks, so Brian's getting ahead of us. But I have some way of preventing multiple threads from running in that section of code. And that works well, right? And then maybe you do some performance profiling and you find out that your bank management application is running quite slowly and threads are spending a long time getting in and out of that code block. So what would be a solution to this problem? No, you're writing this, right? Yeah, no, no, but I mean, what's, so what's the problem here, right? I have one big lock that I grab whenever I'm modifying any account. What is an alternative solution to this approach? Jeremy? Yeah, why don't I just create a single lock for each account that protects that account balance, and you guys will find this. So when you start programming your kernel later in the semester, there'll be cases where you'll say, well, should I use a single synchronization primitive and how much area should that cover? So to some degree, the one big lock solution will work, but it introduces more protection than you need, right? Because any thread trying to modify any balance has to wait for every thread trying to modify any balance to finish, right? And that's actually a stronger thing than we need, right? What can happen, though, if you try to make your concurrency to fine-grained, right? Well, there's two things that can happen. One is that you can get it wrong. The second thing is that you start to have a lot of overhead for all of these extra structures necessary, right? So I could say I could have a lock for every byte of memory, right? And then you wouldn't have any memory left because for every byte of memory you'd have like 16 bytes for your lock, right? And that would be bad. Jeremy, yeah. I know that there's a... I mean, locks in semaphores that we're gonna talk about, you guys are gonna implement are data structures that are implemented and live in memory, right? So when you start using them, you have to think about the fact that when you add a lock to something, you are introducing some amount of overhead, depending on how you implement your locks for this class. Your locks might consume, I don't know, 8, 16 bytes, probably more because you have a string associated with them which is really just for debugging, right, but anyway, yeah. So there is some practical limit as you get more and more fine-grained with your synchronization, you end up having a lot of memory overhead for the structures associated with it, all right? But that's a good question. And yeah, there are, so you have to think about what's the right level at which to synchronize? We'll talk, and we're gonna go through some synchronization problems, hopefully, on Friday. So at that point, we'll give you guys some practice in choosing the right synchronization primitive. And since you asked this question, I'll try to rework one of the examples so we also can look at, you know, at what granularity to synchronize them. Fair? Cool. Any other questions? Good question. All right, my computer has to wake up. And so why do we use concurrency? The illusion of concurrency is what? From Monday's class. It's both blank and blank. Bart, one. Powerful, yes, Bethany, two. Do we have two Bethanese? I don't think so. You got off the hook, yeah. Powerful and useful, right? It helps us think about how to structure applications and it helps us hide latencies, right? Concurrency creates these problems. We identify two problems with concurrency that we're going to look at solving for Rune. What's one of them? Synchronization is a solution to these problems, not the problem itself. Anarok. Correct this, right? How do I ensure that my code is still correct when multiple things are happening at the same time? And coordination. That's the one that came up first. Coordination and correct this, right? How do we allow threads that are modifying the same data structure to communicate with each other? And how do we make sure that the answer that I get is correct when multiple things can be happening at the same time? Concurrency and animicity, right? So remember, we talked a fair amount about the illusion of concurrency, right? And on a uniprocessor system, what is that illusion? Frank, right? On a single processor system, only one thing is happening at the same time, but concurrency gives us the illusion that multiple things are happening, right? Animicity is also frequently an illusion, but what is animicity the illusion of? Chaudhary. Yeah. You're the only one within like a few degrees of my finger, so. One thing is, OK, that's close, right? The one thing happened, Tam, you want to help? Animicity melds a set of instructions or a set of operations into a single atomic, right? Atomic indivisible operation, right? That operation is indivisible in the sense that it either happens or it does not happen. And it's frequently indivisible in the sense that we try to protect other threads from seeing any of the stuff inside while it's happening, right? OK? Assumptions you have to make about the threads now that you're working on a multi-threaded system. Simon, what's one of the things we have to assume? That can be stopped for an arbitrary amount of time. OK, that's good. What else? Sam, compete for the same resource, but why would they be competing for that resource? OK, let's say I'm on a uniprocessor system, so they can't execute at the same time. So my thread can be stopped for an arbitrary amount of time. There's a hint of another answer in there for what? It can be executed in any order, and they can be stopped and started at any time, right? So your thread at any point. And it's important to point this out, and hopefully we'll go through this in recitation a little bit. Even in C, a single, so C's a pretty low-level language, right? But even in C, certain instructions may not actually be atomic, right? So you may think, well, I just set this variable to a value. Certainly, my program can't be interrupted in the middle of doing that. And the case is frequently false, right? Sometimes what looks like a single instruction in C, even a very simple one, actually ends up being multiple instructions to the CPU. And your thread can be stopped in the middle of doing that. So don't use any C constructs to make assumptions about the atomicity of your program, because they'll be wrong, right? So in order to, we start talking about this idea of a critical section. It's an area of code that only one thread is running at any time. We have three requirements for that critical section. Sarah, one of them. Or, well, they're up on the slide, I guess. What do they mean? She's like, I have all three. Yeah, that's the most basic property, right? What about progress? What are we made by progress? How? Or someone who I'm calling how? Who's not actually called how? What is your name? Yeah? Shin. What is progress? Yeah, every thread gets a chance to run into the critical section, right? If I try to enter the critical section, at some point, I will leave, right? Performance, gent. Yeah, I want to get the critical section. So all of us want to implement critical sections. I don't want to have to do too much weighting, right? I don't want to slow the system down too much, right? And I want to keep the critical section small, right? Without sacrificing corrections, OK? So remember, a critical section we defined is a series of instructions, and only one thread can be executed in a given period of time. And the set of instructions will look atomic with respect other threads, right? So another thread will not. We'll see all of the instructions inside the critical section as if they happened at once, right, in their entirety without being able to observe state in the middle, right? All right, any other questions about this before we plunge forward? OK, so right at the end of class, we looked at these two atomic primitives that are provided by hardware, right? We remember we had this idea, particularly on multi-core systems, which is reality today. Hardware has to help us achieve atomicity, right? We talked about this design pattern of stomping other things from happening so that I can implement a critical section. We talked about the fact that that's completely broken on a multi-processor system, because multiple things can be happening at the same time, right? So we looked at several different flavors of atomic instructions that are supported by modern architectures that give us a starting point for building higher level primitives, right? Your OS 161 kernel does this. If you look at the spin lock implementation, it uses an instruction like this that David has implemented in the simulator, right, that gives you these properties. So there's various types of these. We looked at two, right? One is a test and set that atomically writes a memory location and returns the old value, right? So the idea is that the hardware ensures that this blob of pseudocode happens all at once, right? Multiple cores are running this simultaneously. One of these series of instructions will run first, the second, one second. They will not interleave. And then compare and swap, right? Which is a similar type of instruction that compares the contents of memory with some value that you pass in, and if they're the same, sets it to a new value. And if they're not, return something else, right? So I should say many processors, right? So most processors provide some, you know, they're really the only way we can implement concurrency on multi-core systems is with some type of hardware support. So the hardware provides us with this little bit of goodness, right, this nice instruction that allows us to build these primitives on top. And again, if you look at your OS 161 code base, you'll see this, right? The spin lock implementation is directly reliant on an atomic, I think it's, I can remember is it a test and set or is it a test, test and set or something?  All right, so let's fix, remember we had this bank account example, let's fix it by using a test and set, right? Let's say we had this atomic hardware instruction, I'm gonna pretend it's callable through C code somehow, which it could be. So what about this? Before, so remember I had this critical section I identified in these three lines of code where I'm modifying my local copy of the balance and then writing it back to the global copy. And let's just set the test and set and clear it in and out of the critical section, right? And this works great, simple. And I'm done, right? Am I done? Does this work? Why not? Well, no, I think I've defined one critical section here that starts with this line and ends with this line and I've, I'm setting and clearing my test and set at the top level, I don't know if that's the answer I'm looking for, yeah, Bethany. So the question is this line, right? So I'm saying this is a test and set operation and it atomically sets some global variable and again, this would be like a memory address on the machine to one. But so what? Broom, I think this looks good. Yeah, like does, what happens, so what? Like I set this to one and then I just keep going, right? Does this accomplish anything if multiple threads? So the first thread's gonna come in here, it's gonna set the value and then it's gonna execute this instruction and then it's gonna get context switched and the next thread's gonna come in here, it's set the value and just keep going, right? So when I use a test and set, I actually have to check the value of the test and set and do something, right? So, okay, so this is better, right? So now the idea here is that my test and set is one, if there's a thread inside the critical section and it's zero if there isn't, right? So I set it to one at the top, I clear it at the bottom and what I'm doing here is I'm saying if the test and set is equal to one, that means what? Okay, if the test and set returns one, what does that mean? Something wrong, well, could be, right? Frank, yeah, that the critical section is locked, there's a thread inside the critical section, right? So now what do I have to do? If there's values one, my thread can't go in. So what do, Swetha, what do I need to do? Reset the value, do I wanna reset the value up here? What would that mean? That would essentially mean that there is a thread inside, but I've said that there isn't, yeah, Satish. I have to wait, right? I can't go in. There's someone inside the critical section, my thread can't proceed, right? So here is a solution. This will actually work, Jeremy, yeah. You're always like three slides ahead of us, right? Yes, so, okay, so what are the problems with this approach? So what does this do, right? This essentially says, I'm running this atomic test and set instruction, if it returns one, I know someone is still inside the critical section, right? And what do I do if it returns one? What do I do while I'm waiting? No, no, what about this code? What does this code do? I check it, and then what do I do next? I check it again, I check it again, check it again, check it again, check it again. And maybe at some point, it will actually be cleared, and then I'll go, right? So essentially, what this design pattern or this type of approach is called busy wait, right? So whenever a thread is waiting for something to happen, in this case, I'm waiting for the other thread to execute the critical section, but I am not giving up control of the CPU, I'm not allowing other threads to run, I'm busy. I'm busy waiting, right?  You know, it's like if you've ever been on a whole, right?  But that's not what you have to do, you have to sit there listening to the music over and over, right? So that's what this thread is doing. Sitting there, it's busy waiting, it's constantly checking, and so this is interesting. So on a multi-core system, this can sometimes be bad, right? So why would this be bad on a multi-core system? Got two cores, I've got a core where a thread is just sitting there spinning. Yeah, Jeremy. Yeah, no one else gets to run, right? And potentially, if I'm doing this inside the kernel and maybe I've disabled interrupts and I'm not allowing other threads to even be scheduled, I might sit there spinning for a while, right? What's wrong with this on a single-core system? Does this even work on a single-core system? What would happen if I ran this on a single-core system? What's the problem with this design pattern on a single-core system? Manish. Well, yeah, so that's the worst-case scenario, right? If I'm preventing anything from being scheduled, I could run forever, right? But why? Why would I run so long? Why won't, eventually, that's gonna be zero, right? Masakazu, what's gonna happen? I'm on a single-core system. There's one processor. I'm on the processor. I'm spinning, waiting for the value to change. Wembley. Is it 30 of them? The thread that's inside the critical section can't run, right? I've got the CPU. So I'm waiting for something to change that will never change as long as I'm waiting. As long as I keep spinning and banging on the testing set, the other thread will never get a chance to clear it, right? So on a single-core system, if I was never descheduled, this could be a deadlock, right? I might sit there spinning forever. On a multi-core system, eventually, the other thread would run probably on another core and clear the testing set, right? But I'm still waiting, right? Right, if I'm preemptible, right? If I'm not in the kernel, why I've turned up interrupts and I'm not allowing the schedule to run right? But even if I'm preemptible, right? What's still gonna happen? Let's say that the kernel will eventually schedule another thread. What have I done with my entire quantum of time? I've wasted it, right? Because this will never change while I'm waiting, right? On a single-core system, as soon as I check the test and set and see that it's one, I should stop trying and let somebody else run, right? Because I can sit there waiting for another 10 milliseconds of what other scheduling quantum is, but I know it's never gonna change, right? The only way this makes sense is on a multi-core system because it's possible that the other thread in the critical section is running on another core and so that value can change, right? So again, this is kind of what happens on a busy waiting system with preemption, which is what you're talking about, right? The first thread runs, it comes in, it sets the test and set, and then my blue thread just sits there in this loop, right? Until it's descheduled, exhausts its quantum, and then finally the red thread will finish the critical section and the blue thread will be able to run, right? So essentially what we're implementing here with this very simple test and set operation is a very common synchronization primitive that's called a LOCK, right? And LOCKs can be used to establish critical sections, they can also be used to protect data structures and in other ways, and we'll talk about some of those other things on Friday, right? But for now, we're gonna talk about LOCKs as a synchronization primitive that we use to implement critical sections. So when I enter the critical, at the top of the critical section, I acquire a LOCK. At the bottom of the critical section, I release LOCK. Any other thread that's trying to acquire that LOCK will have to wait for me to exit before it can proceed, right? And essentially what we've implemented is today in this little blip of code is called a SPIN LOCK. Why is it called a SPIN LOCK, AJ? It's called a SPIN LOCK, Tim. Yeah, so it's a LOCK because it guards a critical section. Oops, there's another date reference that I should have scrubbed today's Wednesday. And SPIN describes how this LOCK is acquired, right? I acquired this LOCK by busy waiting. I acquired this LOCK by repeatedly performing some operation until it returns the value I was looking for, right? So, Brian, yeah. Yeah, you, so. You can guarantee progress, right? The only way that this would, the only way that this would break would be if you had a single core system and you had disabled interrupts so you couldn't be descheduled, right? In that type of system, you could deadlock on this, right? And in fact, if you guys look at the code for the SPIN LOCKs that is in your kernel, right? SPIN LOCKs are implemented for you. You guys are gonna use them to implement some other primitives for assignment one. That code checks to see if another threat on the same CPU already holds the SPIN LOCK. And if it does, it dies. Because it essentially says, I'm not gonna make any progress, right? Someone on my core has the SPIN LOCK. I'm trying to get the SPIN LOCK and I'm gonna prevent him from running, right? In reality, maybe that threat would be moved to another core but a lot of times on modern systems, there's a fair amount of affinity between threads and cores, right? So, my thread might not be, the operating system might not move my thread to another core, right, until something happens. So, it might sit there. So, two threads on the same core trying to acquire the same SPIN LOCK can produce what's called a deadlock. We'll look at that later, right? But in most cases with SPIN LOCKs, as we've implemented, you can make progress, right? You may not make it efficiently and we'll talk about the difference between SPIN LOCKs and more traditional sleeping-based LOCKs and a couple of slots, right? That's a good question, yeah? Uh-huh. Yeah, so what'll happen? I have one thread that has acquired the LOCK, right? And I have two threads that are spinning that are waiting for, right? So, what's the first thing that has to happen? Well, okay, so I have two threads spinning. I have one thread holding the LOCK. What's the first thing that has to happen? In order for that to happen? Yeah, Frank, it has, yes, in order to do that, it has to do what? In order to do that, it has to do what? Run, right? It has to be able to run, right? So that's the first thing. That thread has to be able to finish. And then at that point, another thread will grab it, right? One of the two spinning threads will grab it. It'll depend on the schedule, in order, who gets it first, right? It'll run and the other thread will also get it. So, okay, this is a good question. So, in general, if you had, let's say there's always contention for the LOCK, meaning there's always somebody holding it and there's always some number of threads that are then spinning, right? The question is, can you guarantee that all those threads will eventually get a chance to have the LOCK? The answer is in the limit, yes, right? I mean, if for some reason there's some unlucky thread that keeps never being scheduled, right, and never gets a chance to run, then it could happen. And actually, we'll look at an example where when we get into scheduling, where there can be bad interaction between scheduling and LOCK acquisition, right? So there are certain cases, for example, where if I prioritize threads, then a low-priority thread that's trying to get the LOCK might never get a chance to acquire, right? But in general, I don't know, it's difficult to, it's difficult to guarantee that type of product, right? But that's a good question, yeah, that's... Okay, cool, yeah? You mentioned in the previous slide that a single core system will not be able to process because the spinning thread will keep bombarding it. Yeah. Right. Yeah, the spinning is running, right? Spinning is a type of running on the CPU, right? A thread that is spinning for the LOCK is executing a series of instructions on the CPU repeatedly, right? Those instructions are frequently a very tight loop that involves testing the testing set over and over. Right? But it's just, it's a subclass of running, right? It just happens to be executing a very specific set of instructions, yeah. So it's, the number of threads that can spin is limited by the number of cores you have, right? Yeah, okay. Oh, yeah. Yeah, that's bad. Yeah, so it could exit in the critical section, it could die in the critical section. Again, I mean, these things are, and that could crash your whole system, right? So that's actually a variant of deadlock that we'll talk about later, right? In general, you know, again, when we talk about these kernel primitives, yeah, you gotta be careful because if you grab a LOCK and then die, I think modern kernels have ways of unwinding LOCKs when the thread exits to try to make sure other threads make progress. But in general, if I grab a LOCK and I'm in the middle of doing something and I exit for some reason, then who knows what the state of the world is, right? Like I was trying to perform some atomic series of instructions, I might have only got halfway through, right? So if I die while I'm holding a LOCK, then the system could take the LOCK away from me and allow other threads to run. It's not clear that that's safe, right? It might be, in certain cases, the only thing I can do, right? If the opportunity is, okay, this thread was running in the kernel and it died while I was holding a LOCK, like I could just let every other thread that's trying to get that deadlock or I could try to go on and hope that things are okay, right? It's not a good series of options, but some kernels may choose to just try to keep going and hope that things are okay. Some might just say, you know what? Tough, I'm just gonna die now, right? Good question. These are, I don't know, good question. All right, so let's modify our bank example now to use a LOCK, right? So what do we need to do? We need to identify the critical section. We did that already. We found these three lines of code that we need to protect with a LOCK, right? And then we need to LOCK around. And this is the way to think about how to protect data, protect critical sections in your own code for this class. Identify the critical section, LOCK around the critical section, right? In general, this gets you a long way, right? When you start acquiring multiple LOCKs and there's complicated data structures, you have to be a little more clever and we'll talk a little bit about that when we talk about deadlock. But in general, this is how we do this, right? So we've identified the critical section. I need to create some sort of LOCK structure and I would have to also initialize it, but let's say it's initialized and now I just acquire and release the LOCK around the critical section, right? So again, this is kind of basic stuff, right? But Jeremy, yeah. Well, okay, so I've declared this as a global variable and I would have to initialize it, right? Yeah, I just left that out, right? But on your system, don't try this at home, right? Well, you can, it will just panic, right? Because this will be garbage or null or something bad, right? So in general, yeah. But in general, this doesn't work. I would have to have LOCK in it somewhere and some boot structure code, right? So actually, if you look at your system, one of the things you guys will have to do in future assignments is make sure you write this initialization code so that at boot time, your kernel allocates any sort of global synchronization data structures that you need, right? So you'd have to like allocate a LOCK and initialize it properly, right? Normally that just happens once at boot and then I have the LOCK to protect that and then I just use it throughout the rest of the time the kernel's running. Good question. So if I call a LOCK acquire while another thread is in the critical section, the thread acquiring the LOCK has to wait, right? And essentially, we looked at one pattern for waiting which was spinning, right? So we had this busy waiting approach, okay? There is a more frequently used probably and in many cases, better pattern for waiting. It's different. We'll talk about why to use each one. Which is passive waiting or sleeping, right? And sleeping for something to happen essentially means that I need a way of telling the kernel this is what I'm waiting for. And then I tell the kernel I would like to be descheduled, right? I mean, before I ask the kernel to deschedule me, I tell the kernel what I'm waiting for and then the kernel puts me somewhere while I wait and then when that thing changes, the kernel will awaken me a lobby to run it, right? This is the design pattern for sleeping on your system, these are implemented using something called a wait chain, right? So, and again, now we have these two approaches, right? We can activate, we can set their spinning waiting for something to happen and we can also sleep, right? There are actually, and this is an interesting sort of design decision, there are cases when either one of these things can be the right approach, right? So there are cases in real operating systems where I use spin locks and there are cases where I use sleep locks, yeah. What do you mean? I mean, it could be like two threads which are with spinning. Yeah, I mean, either one of these locks allow arbitrary number of threads to enter and leave the critical section. The question is, while I'm waiting, what do I do, right? Yeah, I mean, it can be pre-empted and send back to the ready queue, right? Yeah, I mean, in the general case with spin locks, unless you've done something to disable this, right? Your thread can be descheduled and then run again later, right? And as soon as it starts up again, it'll start checking the testing set again, right? I mean, yeah, say we have disabled it, so will that be considered sleeping or still spinning? Are you using the CPU? No. Then you're sleeping. If while you are waiting, right, you are actively checking the testing set over and over again, right? The thread that goes to sleep will not run again until the condition changes, right? So I see what you mean. If I was running and I was checking the testing set and I was descheduled, I'm spinning, right? And I start up again, because I haven't told the kernel, like I haven't gone to sleep, right? The kernel has descheduled me, but I haven't told the kernel, this is what I'm waiting to happen and only wake me up when it happens, right? Yeah, that's a good question, right? So even if I'm not running, but when I start running again, I'm checking the testing set over and over again, that's spinning, right? I'm using my time actively to check the variable over and over again, right? I'm not using the feature of the kernel to tell me when something is happening, right? So these are good questions and I think it's prepared you guys to answer this question. So when do you guys think that I should spit, right? So sleeping sounds like a really nice idea, right? I can leverage this feature of the kernel to essentially make sure that I don't waste any CPU time while I'm waiting for whatever it is to change, right? But why would there be cases where I actually need to spin? Yeah, Sean, okay, you're getting towards an answer, right? Why, so what are you getting at? If I'm spinning, what am I kind of certain of? Right, so remember, getting from running, so what do I need to do in order to get from running onto the sleep queue? What has to happen? What has to take place? Yeah, and what do I have to do to deschedule a thread? I have to perform a what? A context switch, right? And there's overhead to performing a context switch, right? So we're getting towards the right answer or a answer. When is a case when I would not want to go to sleep? I have all the stuff I have to do to put the thread to sleep and I have to change the state of the kernel, I'm gonna pick another thread to run. I might spin if what, Jeremy? Okay, that's, yeah, that's another subcase, but I think it's something a little bit more, a little bit different here, right? Frank, right, so we'll come back to that one, right? If the critical section is short, right? Because if the critical section is short, if there's somebody inside of it, right? And also I would say if the critical section is short and there isn't a huge amount of contention for this critical section, right? Because if the critical section is short and there aren't that many threads also banging on it, the likelihood is I won't spin for very long, right? Because I'm only gonna do this, I'm like, we're a system, somebody else will be running, that thread that's inside the critical section is probably running on another CPU, so I'm just gonna sit there poking it a few times and quite quickly the critical section will become available and I'll enter, right? The reason I don't want to sleep is it might actually take me longer to context switch, be put on the sleeping queue and then be recontext switch. It might be more efficient from the perspective of the machine to just wait by checking the test and set over. So when I have very, very small critical sections then I can use them, I can use the spin lock to protect them, I could do that efficient, right? Is there a question back there or is it a? What is your name? John, okay. Okay, okay, great question. Who makes this decision about whether or not to use a spin lock or a sleeping lock? The programmer, right? The kernel doesn't do this automatically, right? There might be profiling tools that you could run to try to help you make the decision, but in general, this is a decision that kernel designers make, right? When they're writing various pieces of code, right? They look at a piece of code, they say okay, you know, I'm a, there's only a few instructions, right? So I can use the spin lock, right, yeah. Yeah, so well, okay, so you could implement some of these in user space, actually. Some of these permits, that's a good question. I don't think test and set is a privileged instruction, but it might be. Can you ask that on Piazza, because I'll look at it. I don't see any reason that a test and set would have to be a privileged instruction, right? It's not modified in any privileged state, right? It's just, it's a nice feature that allows multiple cores to coordinate, right? So it's, I don't, good question, yeah. I think that you could use a test and set in user space. Yeah, yeah, okay, so this is another good question, right? Let's say, you know, I mean, is there a case there that a thread could be stopped in the middle of a critical section, right? Does anyone want to venture a guess? I mean, there's two answers to this question, and one is pretty categorical, right? So if I was guessing, if I was a guessing man, what would I say? Done. Is there a case when a thread could be stopped in the middle of a critical section? Oh, hmm. Jeremy. I don't believe. I'm still looking for a strong answer here. I mean, in general, the answer is, of course, right? Because you guys are defining critical sections, right? So what could happen in a critical section that would cause the thread to stop running? Yeah, it might do disk IO, right? So actually, this is, and this is another case where you would never want to use a spin lock, right? So let's say I grab a spin lock, and the first thing I do is initiate some disk IO, right? Which takes, remember, how long does disk IO take on your system? In rough terms. Forever, right? Like that's a technical definition of how long disk IO takes from the perspective of the CPU. So I've got a spin lock now, and now I'm gonna write a bunch of stuff to disk, right? So someone else is gonna try to grab that spin lock, and what are they gonna do? Gonna sit there, exhausting every one of their quantum for forever, taking the test and set, right? So yes, if you do anything that would cause you to sleep, don't grab a spin lock, right? Never grab a spin lock, right? Because someone else will waste a huge amount of time, right? What else could happen inside a critical section that would cause you to stop running? Yeah, sure. So okay, what did we say about test and set? Who provides the atomicity of the test and set instruction? Right? The hardware, right? So remember, I wish I could go all the way back, but I don't want to. That code I showed you, let's see, that's, maybe I shouldn't have used C code to do that, but that's executed atomically by the hardware itself. So there's no way to be interrupted between the test and set. Those happen at like the same time, right? You could think of them as happening at the same time. Yeah, yeah, Sumit. Who implements the test and set instruction? It's implemented by what? Are you saying this is the hardware? Hardware, right? So, I just want to answer this question first. So it's a hardware instruction. So what is hardware implemented by? Like a bunch of like ICs, and it's an instruction offered by the CPU, right? There's no code in it, what's that? But it's not even hard-coded, it's hardware, right? Hard code, what does that mean, hard-coded? Yeah, it was coded by somebody at Intel, right? Maybe in their simulator, right? But it's baked into the chip, right?  So it's like an ad or a subtract or a jump. It's a hardware instruction, right? So I don't like the word hard-coded. Sounds like a programmer did something, right? And they didn't. Yeah, Spencer. Are you saying the CPU did something? It is one instruction, yeah. It wouldn't even, no, no, it wouldn't compile that. The compiler would generate a bunch of instructions. I'm saying there is a single hardware instruction that implements that SQL. So on MIPS, there's like, I don't know what it's called, but there's a single instruction that performs those series of operations, right? The compiler wouldn't generate it. The compiler's not smart enough, right? How would you generate this instruction if you were programming a kernel? Does anyone know? You can look in your OS 161 code to see how to do this. There's a way when you write C to include little bits of assembly code. And that's probably the only way to do this properly, right? Because you have to tell the compiler, I want to use the test and set, and you do that by including a little piece of the assembly code. So you tell it exactly which instruction to use. All right, these are great questions, all right. Were there more? I thought there were more hands up. This is a good, okay. So when we think about spinning or sleeping in general, what we're trying to do is we're trying to balance the length of the critical section against the context which overhand, right? So in this case, if the critical section is very short, right? Thread one comes in, tries to get the lock, fails, decides to sleep, right? So all this context which overhead occurs, and now it's running down here, and it could have entered right here, right? So this is a case where because of the length of the critical section, a spin lock was the right choice. I used a sleep lock, and I paid the price of doing a context switch when I didn't really need to, right? If the critical section is long and I use a spin lock, then this is the problem I have, right? So now what's happened is this thread is inside the critical section, and maybe it's, there's just a lot of instructions to execute, or it's done to my O, or whatever. It's just taking forever. And CPU two is now occupied by this thread spank, right? So these are, these are the, these is, this is the what not to do, right? Critical section short, I used a sleep lock, I paid the context switch overhead, didn't need to, critical section was long, used a spin lock, banged down the door for a long time, didn't want to, yeah, sure. I have two thread ones, yeah, so it should be thread one and thread two, right? Yeah, yeah, yeah, bugs in the slide.  Problems, yeah, a lot of problems. Frank, good question. So what is, what is this, what is this relative to? Right, right, say short and long, what am I balancing it off against? What, what specifically? So, so that would be longer or shorter, right? This was just up on the slide. Someone should know that, nothing. It's the context switch overhead, right? So, you know, what I'm saying is, if I wait, right, if I busy wait, right, what's the probability that I'm gonna get a lock pretty quickly, right? If I context switch, I know I'm gonna, it's gonna take X amount of time, right? Cause I'm gonna go all the way into the kernel and I'm gonna sleep and the kernel's gonna put me somewhere and I have to save all my state, right? So that's really, it's the context switch time, right? The context switch overhead that really creates the balance point for a spin or a sleep block, right? This also depends on lock contention, which I didn't get into because I don't wanna like blow people's minds a little bit, but it really depends on, you have to think about how long will I have to spin, right? If the spinning life gets really long, I should wait, right? And I should let the kernel tell me when to wake up, right? If the spinning is pretty short, then it might be worthwhile, right? It's just a few extra instructions and I can get the lock and keep going, right? Yeah. Yeah, yeah, there is.  Probably know almost exactly how many instructions it takes to perform a context switch, right? And they've probably been trying to reduce that number for a long time. So, in general, and again, your kernel provides a version of this. Sleeping requires, you know, remember we talked about how to sleep, we said I have to tell the kernel what I'm waiting for, right? And normally, kernels provide some type of primitive that allows me to say, I'm waiting for this particular thing, right? A key value or, you know, again, an OS 161, this is idea of a weight channel. It's like a line that you get in or Q that you get on that's associated with some event, right? It could be associated with a lock. It could be associated with a piece of hardware that is periodically delivering interrupts or whatever. But the idea is that there's a semantics associated with it. So, you know, when the thing associated with this channel or this key happens, the kernel will wake up some number or all of the threads that are weight, right? So the idea is I say to the kernel, I'm waiting for this thing. And the kernel knows what that thing is. And then sometime later, someone else will say, this thing happened. And the kernel will say, okay, I've got a bunch of threads over here waiting for that thing. I'm gonna let them all run again. And I'm gonna put them into the ready queue and mark them as running, right? And this goes back to the question that maybe who asked it about users doing this in user space. So a certain amount of this can be done in user space. And you guys know this, right? Because, you know, you use languages that provide synchronization permits, right? So we're focusing in this class because it's a class on operate systems, on multi-threading within the operating system. But, you know, almost any user space application is multi-threaded and they have the same problems and they use the same primitives, right? They may be implemented slightly differently, but in general, they're really are the same, right? So if you use Java, you have locks, you have monitors, you have various types of synchronization primitives, all modern languages provide these. Because they're necessary to do a sort of multi-threaded programming, safe. All right, we're right at the gate to CVs. So I'll stop today, we'll do CVs on Friday and I will see you on Friday.


Chair Muser, it's 430 if you'd like to call the meeting to order Well, good afternoon everybody. Welcome to the city of Santa Rosa cultural heritage board It's 430 p.m. And I'm calling this meeting of the cultural heritage board to order Recording secretary if we could please have a roll call Thank You chair Board member boron your board member carney Yeah, board member fennel is absent board member climb here board member marzlin here Vice chair Garrett is absent and chair mezer Here let the record reflect that all board members are present with the exception of board member fennel and board member vice chair Garrett Okay, thank you very much Moving on to item two approval of the minutes Does anyone have any changes to the January 17th draft minutes the minutes for the January 17th are approved as submitted then Recording secretary. Do we have any public comment on item two approval of the minutes? If you are in chambers and wish to make a comment, please make your way to the podium Chair Muser looks like we have no public comment Thank you Moving on to item three public comments We're now taking public comments on item three non agenda items This the time when any person may address the board on matters not listed on this agenda But which are within the subject matter jurisdiction of this committee Recording secretary, can you please provide instructions to the public? If you are in chambers and wish to make a comment on non agenda items, please make your way to the podium You will have three minutes for your comment and a countdown timer will alert you at the conclusion of that period Looks like we have no public comment chair Muser It'll close a public comment Item four point one our statement of purpose the principal duties of the board include Undertaking and updating historic inventories or surveys recommending designation of landmark and preservation districts reviewing proposed alterations to historic buildings and promoting public awareness of preservation issues Moving on to item four point two board member reports. Do any of our board members have anything they'd like to report? Okay, seeing none move on to item four point three vice chair election We don't have that today, but it's probably up and coming Miss Murray, I believe that's on the April 17th agenda so that's and Yeah, I'll talk about that in the in my comments Thank you. Okay, so department reports So yeah, we'll be coming up The vice chair election coming up on April 17th There's also an item Fremont Park that is right now. It looks like it's on that schedule So I if you haven't already responded to the quorum check, please do so All right, Scott Wilkinson from our parks department will be here to tell you what about the Historic report and give you an update on that project. So it's It's real important to have as many of you here as possible then and that is it gives me my my Segway to my nag If you guys can all make a point to review your emails on a weekly basis Twice a week would be ideal, but I would settle all compromise on one so that because I am Running out of time and giving reminders over the text is difficult for me So if y'all could just review your email put a reminder on this is not intended This is not pointed at one person. I will tell you that So I get it I have several hundred that are unread in my own email, but I'd rather read them than text you so thank you and then the The other thing that I want to kind of brag about even though I don't know all that much about it is that one of our Staff members has just completed a process to do it And it's a QR code that we have posted in the lobby and it is a customer service check Kind of how are we doing? Did we were we able to help you and do you have any comments? And I would encourage board members to go by and if you're on campus when the door is open Which is every weekday go in and scan that and just follow through. I'm hoping to have a presentation To you at some point on that. I know that it's widespread It's going to be all of our business cards are now going to be printed with that QR quote code But it is it was a big effort and they did he they did a great job I was super impressed when I went through it and I am not a savvy person with with the technology stuff And even I could figure it out. So I'm guessing all of us in the room can so I would encourage you yeah to stop by their QR codes are posted in the lobby and If can't find it ask and they'll point you to it. So thank you and that concludes my department reports Did you say that the next meet? I think we did a cancellation notice for the yeah on April 3rd That meeting is canceled. So the next time this board convenience will be on April 17th The cancellation notice will come out a week prior to that April 3rd date. I stand corrected I Can't stress enough how important the April 17th meeting is I know a lot of the board members probably weren't weren't here when the Fremont Park issue was first brought to us, but Basically this this board is kind of somewhat responsible for putting a big stall on a project so that we could get a historic report and so that we don't stall it any further it would be great if we could all all be here and and able to comment on on their report Okay, so moving on then to item 6 statement of abstentions. I don't believe we would Comment anybody has any reason to refute themselves or abstain Oh, okay, moving on Consent items we have none an item 7 and so that brings us then to our scheduled item So this is a concept review. So we're not going to be making any decisions tonight Just just to provide good comments back to our planner for a truck dock ramp At 808 Donahue Street, I think that's the old deterred winery building I'm correct and our presentation is okay. Now, please. I hope I don't destroy your name. So You can call me nor yeah nor Bistra nor Bistra. Okay. Nice to meet you. I thought it's the first time I think I've seen you as well. Okay All right, it's all yours Yes, thank you chair muser. Let me share my screen The project before you today is a truck truck dock ramp located at 808 Donahue Street The request is for a conceptual review of the addition of a concrete truck dock ramp with a 2.3% slope and metter metal guardrails to the existing roll-up door on site the zoning code chapter on landmark alterations states that new site features and accessory structures require a minor landmark alteration permit while Substantial alterations that do not match the original design require major landmark alteration permits and The section on major landmark alteration permits typically applies to readily visible portions of buildings Here is the location. It is a part of the deterred winery village and you can see that it's located across from the round barn This is a close-up image of where the ramp would go in front of the roll-up door that was provided by the applicant and Here's just a screen grab from Google Maps as you can see the red brick building That is where the ramp would go That is where the historic building ends Here's a site map that shows the location of the proposed work the highlighted area. You can see there and Here is a Elevations image. I'll let the applicant go over the plans more in detail after my presentation again another elevations sheet from the I believe the East side Staff and the applicant are seeking direction from the cultural heritage board for the proposed truck dock ramp and For any comments or questions here is my contact information And I will allow the applicant to go over the plans as well We're bringing up the plans so that we have something to talk about was there anybody um The applicant or any representatives the applicant wanting to speak tonight as well Are they here? Oh That's podium. Okay. Sorry. I forgot to look up Scott Bartley the Holland Bartley architects. I'm representing the property owner It's kind of interesting to be here talking about design review on what is basically a hole in the ground First I want to give a little history. I think a number of you probably are aware that this project Had been rezoned into a ACA condominium project Where by virtually all buildings were being gutted and replaced with new structure inside that approved plan was done by two previous owners The reason I'm mentioning that is there is no intention By the current owner of really altering the building they want to continue to use the building as is and enhance its character And they do want to keep the tenants that are there Occupied okay, so In order to keep the largest tenant in the building right now one of their requests is to add a loading dock to the store And that's primarily for safety right now They have to lift everything up into their vehicles and they would like the ability just to move them in Straight into the back of the truck. I want to note that the ramp Does not Touch the building. There's actually no alteration whatsoever to the existing building the total project consists of two retaining walls a ramp that slopes down so that it's four feet below the level of the existing roll up door and The required safety guardrails That's all that's involved in the project. I'm basically here if you have any questions regarding it I'm happy to answer them. Thank you, Mr. Partley Okay, so questions for Planning staff or mr. Bartley About one question. Are there mr. Bartley? Are there any other ramps like that on the other side of the building seem seem like I They're on the south side of the building There is a whole bank of roll-up doors But they're not convenient for this Tenant to use that the building is subdivided into different tenancies and so access internally is a little difficult You know, you're going through another person's prop another person's space to access those, but there's a whole bank of roll-up doors between the the square brick building and the The bulk of the to Turk winery and I do want to note also that this Went through this with Susie that this roll-up door is actually in the last ten feet of the actual historic structure Everything to the north is not deemed historic So we just missed it and then the the material that would be removed So that the ramp could be installed. Is there anything significant about that material? No, it's it's basically a Concrete I don't think go back to the photo. It's basically just a concrete Sidewalk or driveway any further questions for mr. Bartley or staff. I Have a question so this property is for a moving company. Is that what it that's the current tenant, but there's another tenant who's Least of the bill of the space is contingent upon getting this So there's there's a number of tenants and the criminal baking is in there There's Myer restaurant equipment has storage in there. So there's a number of different uses in the building right now So this piece of property is kind of useless without having that ramp Whoever rents it is what it sounds like that's that is what we're hearing from the the tenant again from a safety Standpoint from an employee safety standpoint. They don't like having to have them lift everything into the back of the truck That makes sense. Thank you other questions Seeing no further questions. Let's go ahead and open up public comment if we could if we could give instructions Thank you chair If you are in chambers and wish to make a comment, please make your way to the podium you will have three minutes For your comment and a countdown timer will alert you at the conclusion of that period Please state your name, please Kelly McMullen I live right on an adjoining street and this actually sounds like an improvement for the neighborhood Because instead of when we're driving in and out to drop my son off at school Having trucks unloading in the middle of the street then they'd be off the street It'd be safer for those of us driving as well as the people working Just as a neighbor comment. That's all Thank you very much for your comments. It looks like we have no more public comment chair They say no further comments will close the public comment period and So now it's time that we can provide any comment to the applicant as far as things that you might want to see or Or change or disagree with or me again, I don't see any problem with Putting this in I mean it's not going to historically affect this building And if you're saying that it's of necessity that you're not going to be able to rent it out again Without that and I'm hearing from her that it's a safety issue as well I see no problem with with putting this in and approving that Thank you. I had a quick question How far is there actually a sidewalk on that side of the street from the building? There is not there's not yeah Yeah, and then how far back does that ramp start from I guess the street edge? It's quite a ways back. It's yeah five or six feet back from the edge It's a very shallow ramp because the site actually slopes up to the door from the street All right, yeah Reasonable to me distance What is the distance between the door and? The street and how many would it only be one truck at a time and? Yes, it's it's basically a single dock to access that one single door and Put my glasses on It's the that wall is actually 52 feet back from the property line Thank you. I believe we had a correspondence from board member Garrett Hey, but we could go ahead miss Marianne. I am unable to reach her and there was a question about business relationship and So I'm going to err on the side of caution and assume that she would want to recuse herself And I am not going to read board member Garrett's comments I tried to text her to find out if she would still like me to read them And I'm just going to be err on the side of caution because your comments may influence or will like very likely influence the decision makers Decision okay, thank you I've got just a couple of things and So that probably the most important thing to me is the fact that there's no changes to the building if you were Coming to us today and and wanting to create an opening with a roll-up door or something like that it would be in a Probably a major landmark alteration situation that but in this situation I do support that it's a minor landmark alteration With that and I think it's Important that the city received good engineering to ensure that the foundation of the existing building isn't compromised in any way With the addition to the ramp because you will be digging close to the foundation and and I think there should be some engineering done Just to make sure that brick building is properly supported And this is just it would be nice if the safety rails that you're going to build You know to keep you from falling into the ramp if they could complement the building as as much as possible if maybe an architect could Could look at those rails and do something that's attractive and nice and looks like maybe it was always there because Even a building of that year to you know might have had you know ramps like that So the idea is to try to make it look like it's always always been there The fact that the driveway the existing driveway is just concrete There's nothing significant about it if it was pavers old you know or or a brick or something That was original to the building we'd probably be in a different situation, but it's just a concrete slab I drove by there today. It's there's nothing special about the ground and So anyway that those are my only comments I support you know the project I support it being a minor landmark alteration and Hopefully it can be done in a way that won't compromise the building and will Be done tastefully so it looks like it. Maybe it's always been there as much as possible Any other thoughts or comments from board? Okay, so just to recap. I think the only comments you got are just what what I had to say so Good to go I Just want to ask any questions from you. Mr. Bartley. No, I have some questions for you Susie tomorrow Thank you, okay seeing no other items on our agenda today This meeting the cultural errors board is now adjourned


Certainly, I think so. I mean, if you think about communications, first of all, the ability to communicate whatever the messaging is. You have people on machinery. You have people in plants.  They're not all easy accessible. So trying to cascade important messaging and, you know, business basics is often a challenge. And even though we have the technology, the iPads, you know, and cell phones and things, sometimes parts of the plant or parts of, you know, if you're operating a piece of machinery, it's not practical or safe to be doing it that way. So that's one of the challenges. The fact that we operate 24-7, and particularly as we move into not just increased women, but increased appearance, you know, who need to be at home or who... So daycare, for example. Daycare for a 12-hour shift is one thing. Daycare for a 24-hour shift is a completely different thing. So there are some unique challenges. It is remote. And oftentimes we are able to recruit one of, you know, if there are two partners, we can recruit one into the business, but because it's a small region and a small area, the question is, can the second person find that same career opportunity? And so, you know, in the good old days, I think companies were able to create jobs for that second person. Those good old days are long gone. And so that's another one I think that is unique in terms of probably not just mining but remote, and generally mining is a remote, and they come together.