Submit: Turn in your source code using the
turnin command on the lab machines. Please turn in only the files spinlock_util.S and spinlock.c.
Work should be completed in pairs. Be certain to include both
names in the comment block at the top of all source code files. It
would be courteous to confirm with your partner when submitting the
assignment. You may modify any files in the operating system, but
only changes to system/spinlock_util.S and system/spinlock.c will be graded for this assignment.
Raspberry Pi 3 B+:
In the coming multicore assignments, you will be running your kernel on the
Raspberry Pi 3 Model B+ platform, which has four cores within its processor.
All previous variants of this course have used single-core platforms
(i.e., Linksys MIPS router, Raspberry Pi 1) to run students' code.
This is the first Operating Systems course at Marquette (and in the world, as far as we know)
that make use of real multicore hardware (as opposed to a virtual machine) to teach multicore concepts.
Your previous UART driver assignment ran on the Pi 3, but you only used one core for that.
Now that your embedded O/S will be taking advantage of this multicore architecture, you need to know
the multicore functions built in for you to use.
Unparkcore():
Although this concept is general to multicore platforms, the specific implementations vary from
one platform to another.
When the Pi 3 B+ boots, only Core 0 is powered up, and Cores 1-3 are put in a sleep state.
To wake up, or "unpark," a core, you send it an event to "wake it up," then the core will check the value in special location known
as its "mailbox." The core then begins execution at the address that it finds in its mailbox.
In this example, core 3 is unparked and sent to execute a given test_procedure with no arguments (NULL).
See the "Testing" section below for information about how to use this function.
unparkcore() is already implemented for you and can be found in system/unparkcore.c
unparkcore(int core, void* address, void* argument);
In the implementation of unparkcore, you will see that it will unpark the core to an assembly
routine called setupCore (found in system/setupCore.S). setupCore is necessary because the core
needs to undergo specific initializations before any of your code can run.
unparkcore.c and setupCore.S are already implemented for you.
Preparation
NOTICE: Because you will be using your own kprintf.c
file in this assignment, to keep TA-Bot in sync on our end, the method for untarring
this project is slightly different from Project 3.
First, make a copy of your Project 3 directory:
cp -R xinu-hw3 xinu-hw4
Then, untar the new project files on top of it:
tar xvzf ~brylow/os/Projects/xinu-hw4.tgz
New files:
- system/
- spinlock.c
- spinlock_util.S
- unparkcore.c
- setupCore.S
- mmu.c
- mmu_util.S
- include/
Copy your synchronous serial driver file (kprintf.c) into the
system/ directory.
Like with any programming task, it is important to understand the concepts before
jumping into the code. Before beginning this assignment, refer to Chapter 5 of your book.
Make sure you understand approaches of critical sections and mutual exclusion.
Further, please read this
ARM document
explaining LDREX and STREX atomic operations which you will use in your implementation of _lock_acquire.
Objective: Enforcing mutual exclusion across multiple cores
What happens when multiple cores attempt to print over the UART at the same time -- without mutual exclusion?
Undesirable behavior.
Currently, your embedded operating system does not support mutual exclusion across
multiple cores. Refer to system/testcases.c. In its current state, unparking
cores 1, 2, and 3 to a function that prints "Hello World from core n" yields a
distorted mess of characters.
To amend this behavior, you will implemente a spin-lock for XINU's serial port.
For this assignment, you will have to complete the spin lock
acquire (_lock_acquire) function in system/spinlock_util.S.
You will also have to complete lock_acquire and lock_release in system/spinlock.c
Make sure:
- You have followed the "Preparation" steps above
- You use your serial_lock in kprintf (refer to include/spinlock.h)
Testing
Refer to the testcases() function within system/testcases.c.
By default, the testcases function unparks cores 1, 2, and 3 to a function called
core_print(). Since core_print() does not take parameters,
unparkcore() passes it NULL arguments.
If the cores print out neatly, then you will know that your _lock_acquire
function works correctly (and that you properly called lock_acquire and
lock_release in your kprintf function).
|