1 00:00:00,520 --> 00:00:05,819 So far in constructing our timesharing system, we've worked hard to build an execution environment 2 00:00:05,819 --> 00:00:11,490 that gives each process the illusion of running on its own independent virtual machine. 3 00:00:11,490 --> 00:00:16,079 The processes appear to run concurrently although we're really quickly switching between running 4 00:00:16,079 --> 00:00:22,250 processes on a single hardware system. This often leads to better overall utilization 5 00:00:22,250 --> 00:00:27,780 since if a particular process is waiting for an I/O event, we can devote the unneeded cycles 6 00:00:27,780 --> 00:00:33,190 to running other processes. The downside of timesharing is that it can 7 00:00:33,190 --> 00:00:39,300 be hard to predict exactly how long a process will take to complete since the CPU time it 8 00:00:39,300 --> 00:00:44,399 will receive depends on how much time the other processes are using. 9 00:00:44,399 --> 00:00:48,739 So we'd need to know how many other processes there are, whether they're waiting for I/O 10 00:00:48,739 --> 00:00:52,660 events, etc. In a timesharing system we can't make any 11 00:00:52,660 --> 00:00:58,900 guarantees on completion times. And we chose to have the OS play the intermediary 12 00:00:58,900 --> 00:01:03,579 between interrupt events triggered by the outside world and the user-mode programs where 13 00:01:03,579 --> 00:01:08,810 the event processing occurs. In other words, we've separated event handling 14 00:01:08,810 --> 00:01:14,249 (where the data is stored by the OS) and event processing (where the data is passed 15 00:01:14,249 --> 00:01:20,829 to user-mode programs via SVCs). This means that using a conventional timesharing 16 00:01:20,829 --> 00:01:27,270 system, it's hard to ensure that event processing will be complete by a specified event deadline, 17 00:01:27,270 --> 00:01:33,658 i.e., before the end of a specified time period after the event was triggered. 18 00:01:33,658 --> 00:01:38,679 Since modern CPU chips provide inexpensive, high-performance, general-purpose computing, 19 00:01:38,679 --> 00:01:44,549 they are often used as the "brains" of control systems where deadlines are a fact of life. 20 00:01:44,549 --> 00:01:49,908 For example, consider the electronic stability control (ESC) system on modern cars. 21 00:01:49,908 --> 00:01:54,700 This system helps drivers maintain control of their vehicle during steering and braking 22 00:01:54,700 --> 00:02:00,429 maneuvers by keeping the car headed in the driver's intended direction. 23 00:02:00,429 --> 00:02:04,920 The computer at the heart of the system measures the forces on the car, the direction of steering, 24 00:02:04,920 --> 00:02:08,560 and the rotation of the wheels to determine if there's been a loss of control 25 00:02:08,560 --> 00:02:13,620 due to a loss of traction, i.e., is the car "spinning out"? 26 00:02:13,620 --> 00:02:20,510 If so, the ESC uses rapid automatic braking of individual wheels to prevent the car's 27 00:02:20,510 --> 00:02:24,310 heading from veering from the driver's intended heading. 28 00:02:24,310 --> 00:02:31,020 With ESC you can slam on your brakes or swerve to avoid an obstacle and not worry that the 29 00:02:31,020 --> 00:02:36,380 car will suddenly fishtail out of control. You can feel the system working as a chatter 30 00:02:36,380 --> 00:02:42,840 in the brakes. To be effective, the ESC system has to guarantee 31 00:02:42,840 --> 00:02:48,460 the correct braking action at each wheel within a certain time of receiving dangerous sensor 32 00:02:48,460 --> 00:02:51,840 settings. This means that it has to be able to guarantee 33 00:02:51,840 --> 00:02:56,960 that certain subroutines will run to completion within some predetermined time of a sensor 34 00:02:56,960 --> 00:03:00,800 event. To be able to make these guarantees we'll 35 00:03:00,800 --> 00:03:04,870 have to come up with a better way to schedule process execution - 36 00:03:04,870 --> 00:03:10,570 round-robin scheduling won't get the job done! Systems that can make such guarantees are 37 00:03:10,570 --> 00:03:15,200 called "real-time systems". One measure of performance in a real-time 38 00:03:15,200 --> 00:03:20,300 system is the interrupt latency L, the amount of time that elapses between a request to 39 00:03:20,300 --> 00:03:24,560 run some code and when that code actually starts executing. 40 00:03:24,560 --> 00:03:29,880 If there's a deadline D associated with servicing the request, we can compute the maximum allowable 41 00:03:29,880 --> 00:03:34,720 latency that still permits the service routine to complete by the deadline. 42 00:03:34,720 --> 00:03:39,410 In other words, what's the largest L such that L_max+S = D? 43 00:03:39,410 --> 00:03:45,160 Bad things can happen if we miss certain deadlines. Maybe that's why we call them "dead"-lines 44 00:03:45,160 --> 00:03:48,310 :) In those cases we want our real time system 45 00:03:48,310 --> 00:03:54,930 to guarantee that the actual latency is always less than the maximum allowable latency. 46 00:03:54,930 --> 00:04:00,390 These critical deadlines give rise to what we call "hard real-time constraints". 47 00:04:00,390 --> 00:04:05,880 What factors contribute to interrupt latency? Well, while handling an interrupt it takes 48 00:04:05,880 --> 00:04:11,160 times to save the process state, switch to the kernel context, and dispatch to the correct 49 00:04:11,160 --> 00:04:15,270 interrupt handler. When writing our OS, we can work to minimize 50 00:04:15,270 --> 00:04:19,858 the amount of code involved in the setup phase of an interrupt handler. 51 00:04:19,858 --> 00:04:24,270 We also have to avoid long periods of time when the processor cannot be interrupted. 52 00:04:24,270 --> 00:04:30,490 Some ISAs have complex multi-cycle instructions, e.g., block move instructions where a single 53 00:04:30,490 --> 00:04:35,870 instruction makes many memory accesses as it moves a block of data from one location 54 00:04:35,870 --> 00:04:39,270 to another. In designing the ISA, we need to avoid such 55 00:04:39,270 --> 00:04:43,520 instructions or design them so that they can be interrupted and restarted. 56 00:04:43,520 --> 00:04:48,759 The biggest problem comes when we're executing another interrupt handler in kernel mode. 57 00:04:48,759 --> 00:04:53,560 In kernel mode, interrupts are disabled, so the actual latency will be determined by the 58 00:04:53,560 --> 00:04:58,230 time it takes to complete the current interrupt handler in addition to the other costs mentioned 59 00:04:58,230 --> 00:05:02,490 above. This latency is not under the control of the 60 00:05:02,490 --> 00:05:07,479 CPU designer and will depend on the particular application. 61 00:05:07,479 --> 00:05:12,710 Writing programs with hard real-time constraints can get complicated! 62 00:05:12,710 --> 00:05:15,960 Our goal is to bound and minimize interrupt latency. 63 00:05:15,960 --> 00:05:20,650 We'll do this by optimizing the cost of taking an interrupt and dispatching to the correct 64 00:05:20,650 --> 00:05:24,729 handler code. We'll avoid instructions whose execution time 65 00:05:24,729 --> 00:05:28,389 is data dependent. And we'll work to minimize the time spent 66 00:05:28,389 --> 00:05:32,490 in kernel mode. But even with all these measures, we'll see 67 00:05:32,490 --> 00:05:37,460 that in some cases we'll have to modify our system to allow interrupts even in kernel 68 00:05:37,460 --> 00:05:41,460 mode. Next we'll look at some concrete examples 69 00:05:41,460 --> 00:05:46,819 and see what mechanisms are required to make guarantees about hard real-time constraints.