CS111 Scribe notes for lecture on 11/1/05

Authors: Mark Gin, Ka Leung

 

 

 

Wait-free data structures

 

-         Use atomic instructions (like compare_and_swap), so there is no race conditions or deadlock (since it never needs locking).

-         No locking overhead, which yields better performance.

-         Avoid concurrency issues by design

-         Difficult to design (possibly more complex).

-         May not always be possible due to limitations.

 

Wait-free queues coding example:

 

queue_t *queue_init(int capacity)

{

            queue_t *q = malloc(sizeof(queue_t));

            q->queue = malloc(sizeof(queuedata_t) * (capacity+1));

            q->head = 0;

            q->tail = 0;

            q->capacity = capacity;

            return q;

}

 

void queue_enq(queue_t *q, queuedata_t data)

{

            while( (q->tail+1) % (q->capacity+1) == q->head )

                        yield();

            q->queue[q->tail] = data;

            q->tail = (q->tail+1) % (q->capacity+1);

}

 

queuedata_t queue_deq(queue_t *q)

{

            queuedata_t data;

            while(q->head == q->tail)

                        yield();

            data = q->queue[q->head];

            q->head = (q->head+1) % (q->capacity+1);

            return data;

}

 

Note that there is no critical section in the code. Also, there is a limit of only one reader and one writer at a time for this to work.

 

How does I/O interface work inside the kernel?

 

-         Input / Output is an interface to hardware, such as: disks, network devices, printers, displays.

 

 

è    “Code bloat” occurs if each interface has to know how to talk to every type of disk.

 

 

-         Alternative: use a multi-layer interface

 

 

 

-         Device driver is software in kernel that communicates with the device controllers to send commands and read results.

 

-         Goals:        

·        Throughput, number of request per second the device can handle

·        Latency, time it takes to respond to any request

 

-         Factors affecting them:

·        Overhead – How much costs to communicate with a device

·        Functionality – What device can handle

 

Costs of machine operations (example)

Cycle = 10^(-9)s

Programmed IO 10^(-6)s or 10000 cycles

 

Let’s read 40 bytes from a device:

Simples and oldest interaction mechanism is Programmed IO

Special Instructions to read/write to devices (not memory)

            on x86: inb, outb, inw, outw

 

Controller Registers

            *status register indicates if disk is done

                                    while (inb(status) != 0)

                                                //yield

                                    result = inb(result);

outb(data1, 0);

outb(data2, 0);

outb(data3, 0);

outb(data4, 0);

outb(command, 32);

 

The costs of Programmed IO is very expensive: uses BUS, synchronization and lock issues

 

To read 40 bytes from a disk

            1) Write command:                                           5 PIO Instructions

            2) Wait for command to complete                     50 microseconds to complete

            3) Read results:                                     40 PIO

                        Overhead:        95 microseconds

                        Latency:           95 microseconds (busy waiting)

                        Throughput:      10500/s (inverse of overhead)