1 #include "devices/intq.h"
3 #include "threads/thread.h"
5 static int next (int pos
);
6 static void wait (struct intq
*q
, struct thread
**waiter
);
7 static void signal (struct intq
*q
, struct thread
**waiter
);
9 /* Initializes interrupt queue Q. */
11 intq_init (struct intq
*q
)
14 q
->not_full
= q
->not_empty
= NULL
;
15 q
->head
= q
->tail
= 0;
18 /* Returns true if Q is empty, false otherwise. */
20 intq_empty (const struct intq
*q
)
22 ASSERT (intr_get_level () == INTR_OFF
);
23 return q
->head
== q
->tail
;
26 /* Returns true if Q is full, false otherwise. */
28 intq_full (const struct intq
*q
)
30 ASSERT (intr_get_level () == INTR_OFF
);
31 return next (q
->head
) == q
->tail
;
34 /* Removes a byte from Q and returns it.
35 Q must not be empty if called from an interrupt handler.
36 Otherwise, if Q is empty, first sleeps until a byte is
39 intq_getc (struct intq
*q
)
43 ASSERT (intr_get_level () == INTR_OFF
);
44 while (intq_empty (q
))
46 ASSERT (!intr_context ());
47 lock_acquire (&q
->lock
);
48 wait (q
, &q
->not_empty
);
49 lock_release (&q
->lock
);
52 byte
= q
->buf
[q
->tail
];
53 q
->tail
= next (q
->tail
);
54 signal (q
, &q
->not_full
);
58 /* Adds BYTE to the end of Q.
59 Q must not be full if called from an interrupt handler.
60 Otherwise, if Q is full, first sleeps until a byte is
63 intq_putc (struct intq
*q
, uint8_t byte
)
65 ASSERT (intr_get_level () == INTR_OFF
);
68 ASSERT (!intr_context ());
69 lock_acquire (&q
->lock
);
70 wait (q
, &q
->not_full
);
71 lock_release (&q
->lock
);
74 q
->buf
[q
->head
] = byte
;
75 q
->head
= next (q
->head
);
76 signal (q
, &q
->not_empty
);
79 /* Returns the position after POS within an intq. */
83 return (pos
+ 1) % INTQ_BUFSIZE
;
86 /* WAITER must be the address of Q's not_empty or not_full
87 member. Waits until the given condition is true. */
89 wait (struct intq
*q UNUSED
, struct thread
**waiter
)
91 ASSERT (!intr_context ());
92 ASSERT (intr_get_level () == INTR_OFF
);
93 ASSERT ((waiter
== &q
->not_empty
&& intq_empty (q
))
94 || (waiter
== &q
->not_full
&& intq_full (q
)));
96 *waiter
= thread_current ();
100 /* WAITER must be the address of Q's not_empty or not_full
101 member, and the associated condition must be true. If a
102 thread is waiting for the condition, wakes it up and resets
103 the waiting thread. */
105 signal (struct intq
*q UNUSED
, struct thread
**waiter
)
107 ASSERT (intr_get_level () == INTR_OFF
);
108 ASSERT ((waiter
== &q
->not_empty
&& !intq_empty (q
))
109 || (waiter
== &q
->not_full
&& !intq_full (q
)));
113 thread_unblock (*waiter
);