Project #9: Asynchronous Serial Driver

Submit: Turn in your entire xinu-hw9 directory source files using the turnin command on morbius.mscsnet.mu.edu or one of the other Systems Lab machines. Please run "make clean" in the compile/ subdirectory just before submission to reduce unnecessary space consumption.

Work should be completed in pairs. Be certain to include both names in the comment block at the top of all source code files, with a TA-BOT:MAILTO comment line including any addresses that should automatically receive results. It would be courteous to confirm with your partner when submitting the assignment.

Device Drivers

Preparation

Make a fresh copy of your work thus far.
      cp -R xinu-hw8 xinu-hw9

Then, untar the new project files on top of it:
      tar xvzf ~brylow/os/Projects/xinu-hw9.tgz

Be certain to make clean before compiling for the first time.

Semaphores

Step one of this project is the completion of a classic semaphores system. An implementation of classic semaphores with waiting queues has been partially provided for you, and can be found across several files including include/semaphore.h, system/semcreate.c, system/semfree.c, system/signal.c, system/signaln.c, and system/wait.c.. See the TODO comments in these files for details on completing the semaphore implementation. In essence, a process/thread calling wait() decrements the semaphore count. If the count becomes less than zero, the wait() call should block the thread, putting it into a new PRWAIT state, and enqueing it on a waiting list for that semaphore. Note that the absolute value of a negative count indicates how many threads are waiting on that semaphore. When another thread calls signal(), the semaphore count is incremented and a waiting thread can be awakened. The signaln() call is a shortcut for signalling a semaphore 'n' times, which can happen when counting semaphores are used to track many buffer slots.

The Asynchronous Serial Driver

You already have implemented a Synchronous Serial Driver for your operating system. Recall from Assignment 3: "The driver is synchronous because it waits for the slow I/O device to do its work, rather than using interrupts to communicate with the hardware."

Now, you will implement an Asynchronous Serial Driver (for an interrupt-driven UART) using semaphores across multiple cores. A proper asynchronous driver does not wait needlessly for the hardware, but instead only communicates with the UART when a hardware interrupt indicates to the system that it is ready for the next batch of work.

As discussed in lecture, there are two parts to the asynchronous serial driver: the Lower Half and the Upper Half.

The Upper Half of the driver consists of the functions called by various user-level processes, such as getc, putc, and printf. As much as possible, the upper half functions shield the user from the intricate details of the hardware.

The Lower Half of the driver consists of the handler functions run when hardware interrupt requests arrive. Lower half functions must do their work quickly, and deal with data that has been buffered up by the upper half functions.

The Lower half has been implemented for you in device/uart/uartHandler.c. You will be working on the upper half functions in device/uart/uartPutc.c and device/uart/uartGetc.c.

To implement your asynchronous driver, follow these steps:

  1. Begin by completing the given implementation of semaphores in system/signal.c, system/signaln.c, and system/wait.c.
  2. Implement the Upper Half driver functions in device/uart/
  3. Write testcases that demonstrate your working implementation, as well as your understanding of the assignment, in testcases.c.


[back]

[Revised 2022 May 06 09:45 DWB]