CS 354 Spring 2021

TA Notes

General Help

Macro Use

The XINUTEST and XINUDEBUG macros are simply for ease of enabling/disabling the various kprintf calls, sanity checks, etc. that you add throughout a lab.

Use of the XINUDEBUG macro is optional. You may choose to use this macro anywhere you need to utilize kprintf() for print statement debugging. Prior to submitting, the graders will expect that your program has no extraneous output beyond what is asked for in the lab problems, so debugging output will need to be disabled, commented out, or removed completely. The XINUDEBUG macro aims to make this process easier

Use of the XINUTEST macro is required. You will need to use this macro any time a lab problem explicitly asks you to output using kprintf(). This will provide the TAs with an easy way of enabling and disabling the kprintf() calls that you make during grading.

Here is a snippet of example code that can be added to include/process.h in order to use XINUDEBUG and XINUTEST for calling kprintf()

    #define XINUTEST  1 /* set to 1 */
    #define XINUDEBUG 0 /* User debug. should be 0 in final turnin */

    /* for print required for labs */
    #if XINUTEST
    #define XTEST_KPRINTF(...) kprintf(__VA_ARGS__)
    #define XTEST_KPRINTF(...)

    /* User debug */
    #define XDEBUG_KPRINTF(...) kprintf(__VA_ARGS__)
    #define XDEBUG_KPRINTF(...)

Lab 1

Bonus Problem

For those students who elect to implement the bonus problem, you will notice that calling haltnull() inside nulluser()'s infinite loop will conflict with the work you already did in Problem 3.4, where you were instructed to add the inline assembly 'asm("hlt")'.

If you do choose to solve the bonus problem, please do the following:

  1. Write your haltnull() function in system/haltnull.S and make any other additional modifications necessary to allow calling haltnull() from nulluser()
  2. Test and verity that your haltnull() implementation works as intended by replacing the asm("hlt") instruction with your haltnull() function call.
  3. After validating your haltnull() implementation, remove your haltnull() function call from nulluser(), and re-insert the asm("hlt") instruction as directed in Problem 3.4
  4. Re-validate your Xinu build, ensuring that it compiles and everything still functions as intended
  5. Turn in your Lab 1 as directed when ready

When grading the bonus question, the TAs will replace your nulluser() function with their own, and call your haltnull() implementation to ensure it works

Lab 4

Problem 4

As specified in the handout, when implementing qsenb() and qreceiveb(), you will want to ensure that shared variables are not corrupted by the interleaving of multiple processes by the scheduler.

We want to be clear that there are multiple approaches to this problem, and you are free to choose your own approach so long as it works. The original release of the handout was worded to make it sound like resched() must be modified, but this is not the case. Modifying resched() is just one potential solution to this problem. As a few keen students have pointed out, it is possible to program qsendb() and qreceiveb() carefully such that shared variables are safe without actually having to modify reched()

Lab 5

Problem 3.1

Many students have had issues with implementing 3.1, particularly with the step in the handout that says "use extended in-line assembly to add code that pushes the original return address of ctxsw() stored in origretaddr onto the stack so that ESP points to this address".

Here, we do not want to take the use of the word "push" too literally. Remember that `malwareIa()` is a function written in c, and is therefore generated by gcc. Although we know by CDECL that when `malwareIa()` goes to return, it will interpret the top of the stack as the return address, there is no guarantee that other stack operations done by gcc-generated code are not also modifying the stack both before and after our extended in-line assembly gets executed.

Recall that in the case of Xinu's build configuration, the compiled c code of `malwareIa()` likely looks like the following:

             *function prologue*
             *local variables*
             *extended in-line assembly*
             *function epilogue*

With this in mind, there may be slightly more involved than simply "pushing" the return address to the top of the stack