CS 452/652 Winter 2024 - Kernel (Part 4)

(Version: 1)

Due Date: Thu, Feb 29, 2024, 9:00am

Introduction

In this final kernel assignment, you use the interrupt processing capabilities of your kernel to create tasks that provide interrupt driven input/output. User programs will then be able to call Getc(), Putc() and any other primitives you choose to implement to access input and output streams on either of the two UARTs. It is also expected that during this final stage of development you polish the code of your kernel, integrating tightly the functionality you have implemented and thereby making the code robust.

To demonstrate your serial I/O you are to redo the functionality of Assignment 0, but using interrupt-mediated I/O and task-structured application code. As well as testing your I/O this provides you with a valuable capability that you will certainly use when developing your train application. We explicitly expect that you will have these capabilities available for later demos. The documentation you provide with this assignment should document your kernel completely, and will be evaluated with this in mind. If you have been providing good documentation as you went along, most of what you need to submit has already been written.

Description

I/O Interface

This assignment does not require the implementation of any new system calls. However, you should implement I/O servers which offer an API like this:

int Getc(int tid, int channel)
int Putc(int tid, int channel, unsigned char ch)

See the kernel description for more detail on how these primitives should operate.

Server Tasks

Putc() and Getc() should be implemented as wrappers around Send-Receive-Reply communication to one or more I/O server tasks. The servers' task ids should be obtained by the client using a call to the name server. Your I/O servers are expected to implement this API without busy-waiting, using interrupts.

There is more than one way to design your I/O server tasks. You need to create at least one I/O server, but possibly more: do what you think is best. Describe the task structure you chose, and why you chose it, in your documentation.

Hint

There is not a unique 'best' task structure, but some task structures are better than others. As mentioned in class, servers should never use Send() or AwaitEvent() and mostly be blocked waiting on Receive(). Notifiers should almost always be in AwaitEvent(). Keep in mind that the two serial devices (UARTs) play very different roles in train applications. One is much more performance-limiting than the other.

Serial I/O

To test your serial I/O you are asked to redo the functionality of Assignment 0, this time Getc and Putc. What collection of tasks you use is implementation-dependent, but you should describe and explain your design decisions.

Once your UART implementation is complete you do not need to do much more than connecting terminal commands to output for the train controller, and connecting train input to the terminal display. In doing so please remember to retain features such as the display of idle time, which you added earlier in your kernel development.

Also, remember that typing a command at the terminal does not test either terminal or train controller I/O very rigorously: human typing is way slower than a machine sending at full bandwidth.

Implementation Comments

Until now you have been using busy-wait I/O for debugging. In class we discussed that it might be possible to mix busy-wait I/O with interrupt-mediated I/O. Please make sure to
  1. clearly document your approach to busy-wait debug I/O, if at all, and
  2. make sure that all workarounds can be removed from compilation via preprocessor switch, and
  3. submit a version without busy-wait debug I/O.

Submission

Your readable and documented source code should be in your repository at https://git.uwaterloo.ca. The repository must be set to 'Private' with instructor and TAs added as 'Reporter'. Your repo should include a README-K4 file, which describes how to make and operate your program. Each group should be working from a single repository.

Each group should submit a single PDF file into the K4 dropbox for this course in Learn. The PDF should include the following information:

  1. The names, userids, and student IDs of your group members.
  2. The name of your group's code repository on git.uwaterloo.ca and the SHA of the commit that we should be using for this assignment. The commit must be dated before the assignment deadline.
  3. The final comprehensive description of your kernel, including tasks, scheduling, and message and event handling. If you added any additional kernel functionality, be sure to describe that as well. Aside from testing, we will judge your program primarily on the basis of this description. Describe which algorithms and data structures you use and why you chose them. Describe your choices for critical system parameters and limitations, such as stack size, maximum number of tasks, etc.
  4. The I/O interface description should describe what I/O servers you've created and what they do.
  5. If appplicable, a description of unimplemented aspects of the assignment. Also, if you know of bugs in your implementation describe them explicitly.

We may perform code reviews with students, in which case a TA/instructor and will contact you to set up a meeting.