Lecture 13 - Disk Drives

Let's look at expanding Dijkstra's Algorithm.

Multi-Dimensional Banker's Alg.

Just like the 1-D version we keep a table of how many of each resource is:

In Use table:

R0 R1 R2 R3
A 3 0 1 1
B 0 1 0 0
C 1 1 1 0
D 1 1 0 1
E 0 0 0 0
Allocated 5 3 2 2
Resources Left (remaining need):
R0 R1 R2 R3
A 1 1 0 0
B 0 1 1 2
C 3 1 0 0
D 0 0 1 0
E 2 1 1 0
Exists 6 3 4 2
R0 R1 R2 R3
Free 1 0 2 0

To determine the safety:

do {
	pick a process all of whose needs can bee satisfied
	pretend it finishes & releases
} until (all done or stuck)

For this the processes is:

  1. D is the only process where the free vector agrees with it running. It runs and gives the following free: (2,1,21)
  2. Now A can run (it's vector is smaller for each element) so run it. free(5,1,3,2)
  3. Now E can run so run it. free(5,2,3,2)
  4. Now B can run ...

Now say that B asks for more resources, asking for another R2:

In Use table:

R0 R1 R2 R3
A 3 0 1 1
B 0 1 1 0
C 1 1 1 0
D 1 1 0 1
E 0 0 0 0
Allocated 5 3 3 2
Resources Left (remaining need):
R0 R1 R2 R3
A 1 1 0 0
B 0 1 0 2
C 3 1 0 0
D 0 0 1 0
E 2 1 1 0
Exists 6 3 4 2
R0 R1 R2 R3
Free 1 0 1 0
Doing the algorithm:
  1. D is our only hope: free(2,1,1,1)
  2. A is the only free one: free(5,1,2,2)
  3. We can satisfy B. free(5,2,3,2)
  4. E: ... (the rest are easily satisfied).

Consider another example where E has nothing. Can we help little old E?

In Use table:

R0 R1 R2 R3
A 3 0 1 1
B 0 1 1 0
C 1 1 1 0
D 1 1 0 1
E 0 0 1 0
Allocated 5 3 4 2
Resources Left (remaining need):
R0 R1 R2 R3
A 1 1 0 0
B 0 1 0 2
C 3 1 0 0
D 0 0 1 0
E 2 1 0 0
Exists 6 3 1 2
R0 R1 R2 R3
Free 1 0 1 0
...

... uh we were talking about Devices

Here's the problem with devices; they are real things. They literally are numbered with sectors:

But of course unless you're actually using the device itself, we're not actually talking to the device. We're talking to some control register that acts as an intermediary between the programmer and the data itself.

The programmer can then read the status registers to see what data is there, and when it's valid.

How do we talk to one? There's a few ways to do that:

  1. Memory-Mapped IO (MMIO): memory addresses are written to via the device, and then we can read from that address.
    • Pros: It works (and is simple at that).
    • Cons: If you have cache systems, then they won't be up-to-date with the memory itself (since the disk writes directly to memory, not through the cache line).
2. *IO Ports*: have special instructions to do IO. - Pros: Solves the MMIO problems we saw before. - Cons: You may not be able to add these instructions. It requires the CPU is designed around it.

How to Interact with the Device

It's simple:

  1. Write something to the control register (see the docs for what specifically to write. It's device dependent)
  2. Wait a while (keep checking the status register to see if it's done)
  3. Check status register (again)
  4. Respond appropriately

To check when it's done, just lock (poll) until the status register says it's ready. The problem is that:

It's better to use interrupts/signals to solve this issue (Programmed IO):

  1. Issue a command
  2. Device interrupts when it's done
  3. OS deals with the interrupt and returns to normal operation.

Okay wait this is pretty annoying. Look at how many avenues it has to take to get that data to memory! It'd be better if it we could write directly to it:
3. Direct Memory Access (DMA): device controller itself does the data transfer

We'll have to talk more about how we'll use DMA and write software using it.