Beispiel #1
0
/*! Sends BYTE to the serial port. */
void serial_putc(uint8_t byte) {
    enum intr_level old_level = intr_disable();

    if (mode != QUEUE) {
        /* If we're not set up for interrupt-driven I/O yet,
           use dumb polling to transmit a byte. */
        if (mode == UNINIT)
            init_poll();
        putc_poll(byte); 
    }
    else {
        /* Otherwise, queue a byte and update the interrupt enable register. */
        if (old_level == INTR_OFF && intq_full(&txq)) {
            /* Interrupts are off and the transmit queue is full.
               If we wanted to wait for the queue to empty,
               we'd have to reenable interrupts.
               That's impolite, so we'll send a character via
               polling instead. */
            putc_poll(intq_getc (&txq)); 
        }

        intq_putc(&txq, byte); 
        write_ier();
    }

    intr_set_level(old_level);
}
Beispiel #2
0
/* Adds BYTE to the end of Q.
   Q must not be full if called from an interrupt handler.
   Otherwise, if Q is full, first sleeps until a byte is
   removed. */
void
intq_putc (struct intq *q, uint8_t byte) 
{
  ASSERT (intr_get_level () == INTR_OFF);
  while (intq_full (q))
    {
      ASSERT (!intr_context ());
      lock_acquire (&q->lock);
      wait (q, &q->not_full);
      lock_release_with_preemption (&q->lock);
    }

  q->buf[q->head] = byte;
  q->head = next (q->head);
  signal (q, &q->not_empty);
}
Beispiel #3
0
/* Returns the position after POS within an intq. */
static int
next (int pos) 
{
  return (pos + 1) % INTQ_BUFSIZE;
}

/* WAITER must be the address of Q's not_empty or not_full
   member.  Waits until the given condition is true. */
static void
wait (struct intq *q UNUSED, struct thread **waiter) 
{
  ASSERT (!intr_context ());
  ASSERT (intr_get_level () == INTR_OFF);
  ASSERT ((waiter == &q->not_empty && intq_empty (q))
          || (waiter == &q->not_full && intq_full (q)));

  *waiter = thread_current ();
  thread_block ();
}

/* WAITER must be the address of Q's not_empty or not_full
   member, and the associated condition must be true.  If a
   thread is waiting for the condition, wakes it up and resets
   the waiting thread. */
static void
signal (struct intq *q UNUSED, struct thread **waiter) 
{
  ASSERT (intr_get_level () == INTR_OFF);
  ASSERT ((waiter == &q->not_empty && !intq_empty (q))
          || (waiter == &q->not_full && !intq_full (q)));