4 #include "threads/interrupt.h"
5 #include "threads/synch.h"
7 /* An "interrupt queue", a circular buffer shared between
8 kernel threads and external interrupt handlers.
10 A kernel thread that touches an interrupt queue must bracket
11 its accesses with calls to intq_lock() and intq_unlock().
12 These functions take a lock associated with the queue (which
13 locks out other kernel threads) and disable interrupts (which
14 locks out interrupt handlers).
16 An external interrupt handler that touches an interrupt queue
17 need not take any special precautions. Interrupts are
18 disabled in an external interrupt handler, so other code will
19 not interfere. The interrupt cannot occur during an update to
20 the interrupt queue by a kernel thread because kernel threads
21 disable interrupts while touching interrupt queues.
23 Incidentally, this has the structure of a "monitor". Normally
24 we'd use locks and condition variables from threads/synch.h to
25 implement a monitor. Unfortunately, those are intended only
26 to protect kernel threads from one another, not from interrupt
29 /* Queue buffer size, in bytes. */
30 #define INTQ_BUFSIZE 8
32 /* A circular queue of bytes. */
35 /* Mutual exclusion. */
36 enum intr_level old_level; /* Excludes interrupt handlers. */
37 struct lock lock; /* Excludes kernel threads. */
39 /* Waiting threads. */
40 struct thread *not_full; /* Thread waiting for not-full condition. */
41 struct thread *not_empty; /* Thread waiting for not-empty condition. */
44 uint8_t buf[INTQ_BUFSIZE]; /* Buffer. */
45 int head; /* New data is written here. */
46 int tail; /* Old data is read here. */
49 void intq_init (struct intq *, const char *);
50 void intq_lock (struct intq *);
51 void intq_unlock (struct intq *);
52 bool intq_empty (const struct intq *);
53 bool intq_full (const struct intq *);
54 uint8_t intq_getc (struct intq *);
55 void intq_putc (struct intq *, uint8_t);
57 #endif /* devices/intq.h */