Upload
shonda-wright
View
218
Download
0
Tags:
Embed Size (px)
Citation preview
Project 2CS-502 Fall 2007 1
Programming Project #2Message Passing System
CS 502 Operating SystemsFall 2007
Project 2CS-502 Fall 2007 2
Project
• To build and test a message-passing system for Inter-process Communication among separate address spaces– Implement API for message-passing functions– Kernel system calls to handle messages– Test program to exercise the message passing
system
Project 2CS-502 Fall 2007 3
Objective
• To gain experience programming and testing synchronization and IPC operations
• To gain experience with synchronization & memory management in the Linux Kernel
Project 2CS-502 Fall 2007 4
Overview
• Add a mailbox to each process– Abstract object capable of holding messages
– Messages are of bounded length, undefined structure
– Mailboxes may be of bounded size
• All threads of a process share a mailbox• Any Linux task can send a message to any
mailbox– Including own mailbox– Addressed by pid_t
Project 2CS-502 Fall 2007 5
Overview (continued)
• Task may receive message only from “own” mailbox– Any thread of task may receive!
• Mailbox created during fork
• Mailbox deleted during process termination
• Mailbox may be “stopped”– I.e., no more message are accepted– Optionally, mailbox may be flushed
Project 2CS-502 Fall 2007 6
This Project
• Predefined API (Application Program Interface) at– mailbox.h in this directory
• All students must implement same API– User space interface program– Kernel implementation– Test program
Project 2CS-502 Fall 2007 7
APIint SendMsg(pid_t dest, void *msg, int len, bool block)
• Sends a message body at *msg to process dest• Length = len; not more than MAX_MSG_SIZE• Blocks if mailbox full and block = TRUE• Returns zero if successful, error code if not
int RcvMsg(pid_t *sender, void *msg,int *len, bool block)
• Gets a message from own mailbox, puts in *msg• Sender process ID returned in *sender• Blocks if mailbox empty and block = TRUE• Returns zero if successful, error code if not
• Messages in FIFO order
Project 2CS-502 Fall 2007 8
API (continued)int ManageMailbox(bool stop, int *count)
• Gets number of message currently queued in mailbox
• If stop = TRUE, prevents mailbox from receiving more messages
– Unblocks all waiting SendMsg and RcvMsg
– Future RcvMsg calls can still retrieve remaining queued messages
• Returns zero if successful, error code if not
Project 2CS-502 Fall 2007 9
API — Documented Error Codes
• MAILBOX_FULL• Non-blocking send
• MAILBOX_EMPTY• Non-blocking receive
• MAILBOX_STOPPED• On any send
• Also after blocked send or receive
• MAILBOX_INVALID• On any call
• MSG_TOO_LONG• On send
• MSG_ARG_ERROR• Invalid argument or
pointer• copy_to_user or copy_from_user fails
• MAILBOX_ERROR• Any other kind of error
• You may add other error codes as needed
Project 2CS-502 Fall 2007 10
Kernel Implementation
• Start with prePatch-Project2• I.e., so we all have same task_struct and header files
• Three system calls.long sys_mailbox_send.long sys_mailbox_rcv.long sys_mailbox_manage
• Create and delete mailboxes• Memory allocation within kernel
• All messages of fixed size
• Synchronization within kernel• Suggest simulating a monitor per mailbox
Project 2CS-502 Fall 2007 11
Kernel Implementation
• Start with prePatch-Project2• I.e., so we all have same task_struct
• Three system calls.long sys_mailbox_send.long sys_mailbox_rcv.long sys_mailbox_manage
• Create and delete mailboxes• Memory allocation within kernel
• All messages of fixed size
• Synchronization within kernel
Project 2CS-502 Fall 2007 12
Pre-Patch your Kernel
• Apply prePatch-Project2 to a clean kernel tree• Adds to task_struct
• struct *mailbox mailbox
• Defines syscalls in syscall.S and unistd.h
.long sys_mailbox_send /* 318 */
.long sys_mailbox_rcv /* 319 */
.long sys_mailbox_manage /* 320 */
• Reason• Instructor’s time in grading
• Don’t modify other commonly used header files!
Project 2CS-502 Fall 2007 13
Kernel Implementation
• Start with prePatch-Project2• I.e., so we all have same task_struct
• Three system calls.long sys_mailbox_send.long sys_mailbox_rcv.long sys_mailbox_manage
• Create and delete mailboxes• Memory allocation within kernel
• All messages of fixed size
• Synchronization within kernel
Project 2CS-502 Fall 2007 14
Creating a Mailbox
• During do_fork()• In kernel/fork.c
• If this is a new process• Use kmalloc() to allocate a new data structure for a
new mailbox
• Initialize• Set pointer in task_struct->mailbox
• If this is just a new thread• Keep existing mailbox of process
• Indicated by CLONE_THREAD argument to do_fork()
Project 2CS-502 Fall 2007 15
Creating a Mailbox (continued)
• No mailbox for kernel threads, etc.• Be sure task_struct->mailbox is null
Project 2CS-502 Fall 2007 16
Kernel Implementation of Mailbox Operations
• Monitor model per mailbox– Three system calls for user-visible functions
sys_mailbox_sendsys_mailbox_rcvsys_mailbox_manage
– Two other functions for kernel supportmailbox_createmailbox_destroy
• Contents of monitor data structure– Monitor lock
• spinlock_t initialized SPIN_LOCK_UNLOCKED
– Semaphore and count to simulate condition variable• Both initialized to zero
– List head for linked list of messages; flag for stopped mailbox– Other fields as needed
Project 2CS-502 Fall 2007 17
Kernel Implementation (continued)
• RcvMsg• Grab monitor lock• While linked list is empty
– Simulate wait on condition variable
• Unlink first message from mailbox linked list• Release monitor lock• copy_to_user to copy message body and other
information to caller• Free kernel space for unlinked message (see below)
• Non-blocking receive• Exercise for student
Project 2CS-502 Fall 2007 18
Kernel Implementation (continued)
• RcvMsg• Grab monitor lock• While linked list is empty
– Simulate wait on condition variable
• Unlink first message from mailbox linked list• Release monitor lock• copy_to_user to copy message body and other
information to caller• Free kernel space for unlinked message (see below)
• Non-blocking receive• Exercise for student
Need to check if
mailbox is stopped
Project 2CS-502 Fall 2007 19
Kernel Implementation (continued)
• RcvMsg• Grab monitor lock• While linked list is empty
– Simulate wait on condition variable
• Unlink first message from mailbox linked list• Release monitor lock• copy_to_user to copy message body and other
information to caller• Free kernel space for unlinked message (see below)
• Non-blocking receive• Exercise for student
Note order of
operations here
Project 2CS-502 Fall 2007 20
Kernel Implementation (continued)
• RcvMsg• Grab monitor lock• While linked list is empty
– Simulate wait on condition variable
• Unlink first message from mailbox linked list• Release monitor lock• copy_to_user to copy message body and other
information to caller• Free kernel space for unlinked message (see below)
• Non-blocking receive• Exercise for student
Wha
t kind
of fa
ilure
can o
ccur
here?
Project 2CS-502 Fall 2007 21
Kernel Implementation (continued)
• SendMsg• Allocate kernel space for new message (see below)• copy_from_user to copy message body into kernel• Fill in other details (sender, length, etc.)
• Grab monitor lock
• Link new message to end of mailbox linked list
• Simulate signal to condition variable if any receivers waiting
• Release monitor lock
• Blocking send• Exercise for student
• Must simulate wait on condition variable if mailbox is full
Project 2CS-502 Fall 2007 22
Kernel Implementation (continued)
• ManageMailbox• Grab monitor lock
• Counter number of messages
• If stop = TRUE, determine if any tasks waiting
• If so, trick them into “unblocking” and returning error
• Release monitor lock
• Revisit blocking SendMsg, RcvMsg• When unblocked, be sure mailbox has not been
stopped in meantime.
Project 2CS-502 Fall 2007 23
Deleting a Mailbox
• In do_exit()
• Only if the task group is dead!
• Stop the mailbox to be sure that blocked send operations can complete!– Flush messages (to free their space)
• Free the mailbox data structure– kfree()
• Zero out task_struct->mailbox
Project 2CS-502 Fall 2007 24
Memory Allocation Resources
• kmalloc(), kfree()• linux/slab.h
• Similar to malloc() & free(), but with flags• Also vmalloc()
– slight performance hit but does not require physically contiguous pages
• Slab allocator• kmem_cache_t* kmem_cache_create()• void* kmem_cache_alloc()• void kmem_cache_free()• int kmem_cache_destroy()
Project 2CS-502 Fall 2007 25
Memory Allocation Resources (continued)
• Use slab allocator– All message bodies the same size in kernel– Highly optimized for rapid allocation and free– Low fragmentation
• Initialization– Establish cache and any static variables during init.c
Project 2CS-502 Fall 2007 26
Locking Tools in the Kernel
• Mailbox• Needs to be locked to link and unlink messages• Also to change state (START, STOP)
• Remember – the Linux Kernel is fully preemptive!
• System call may be preempted before completion• Interrupt may schedule another process at any time• Interrupt may manage shared resources• But not while holding a spinlock
– Due to support for symmetric multi-processing
Project 2CS-502 Fall 2007 27
Robert Love says …
• It is a major bug if …– An interrupt occurs to access a resource while
kernel code is also manipulating that resource– Kernel code is preempted while accessing a
shared resource– Kernel code sleeps while in the middle of a
critical section– Two processors access same data at same time
• Implementing locking is not hard• Tricky part is identifying what to lock.
Project 2CS-502 Fall 2007 28
Tools for Simulating Monitors
• Spin locks (for monitor locking)• spin_lock_init()
• spin_lock(), spin_unlock()• See linux/spinlock.h
• Must be used to provide mutual exclusion for all monitor functions
• Also to release and acquire lock around condition variable waits
Project 2CS-502 Fall 2007 29
Condition Variable (simulated)
• Condition variable representation• Struct semaphore, int wait_count, both initialized to zero• See asm/semaphore.h
• Wait on condition variable/* while holding the monitor lock */wait_count++; /* incr # of waiting tasks */spin_unlock(&mr_lock); /*release lock */down_interruptible(&sem); /* wait */spin_lock(&mr_lock); /* reacquire lock */
• Signal condition variable/* while holding the monitor lock */if (wait_count > 0)
up(&sem); /* unblock a task */wait_count--; /* decr # of waiting tasks */
Project 2CS-502 Fall 2007 30
/* function implementations */
FIFOMessageQueue(void) {
/* constructor*/head = tail = NULL;
};
void addMsg(msg_t newMsg) {
qItem *new = malloc(qItem);newprev = tail;newnext = NULL;
if (tail==NULL) head = new;else tailnext = new;
tail = new;
signal nonEmpty;
};
Monitor Example*
monitor FIFOMessageQueue {
struct qItem {struct qItem *next,*prev;msg_t msg;
};
/* internal data of queue*/
struct qItem *head, *tail;condition nonEmpty;
/* function prototypes */
void addMsg(msg_t newMsg);msg_t removeMsg(void);
/* constructor/destructor */
FIFOMessageQueue(void);~FIFOMessageQueue(void);
};
* Adapted from Kleiman, Shah, and Smaalders
Project 2CS-502 Fall 2007 31
/* function implementations concluded*/
~FIFOMessageQueue(void) {
/* destructor*/while (head <> NULL) {
struct qItem * top = head;head = topnext;free(top);
};
/* what is missing here? */
Monitor Example/* function implementations
continued*/
msg_t removeMsg(void) {
while (head == NULL)wait(nonEmpty);
struct qItem *old = head;
if (oldnext == NULL)tail = NULL; /*last
element*/else
oldnextprev = NULL;
head = oldnext;
msg_t msg = oldmsg;
free(old);
return(msg);
};
Project 2CS-502 Fall 2007 32
/* function implementations concluded*/
~FIFOMessageQueue(void) {
/* destructor*/while (head <> NULL) {
struct qItem * top = head;head = topnext;free(top);
};
/* what is missing here? *//* Answer:- need to unblock waiting threads in destructor! */
Monitor Example/* function implementations
continued*/
msg_t removeMsg(void) {
while (head == NULL)wait(nonEmpty);
struct qItem *old = head;
if (oldnext == NULL)tail = NULL; /*last
element*/else
oldnextprev = NULL;
head = oldnext;
msg_t msg = oldmsg;
free(old);
return(msg);
};
Project 2CS-502 Fall 2007 33
Deleting mailbox
• Must stop mailbox first
• In loop, unblock all waiting tasks
• Be sure any waiting task has had time to complete operation
• Potential race condition
• Flush remaining messages
• Delete mailbox data structure
Project 2CS-502 Fall 2007 34
Testing
• Fork multiple processes• Create mailboxes, exchange mailbox IDs
• Randomly send messages to each other• Payload must be self identifying
• Acknowledge received messages
• Test extreme conditions• E.g., fill up mailbox
Project 2CS-502 Fall 2007 35
Due Dates
• Project due at start of class, Monday, October 22• Pace yourself:–
– October 8:–• Creation & deletion of mailboxes in do_fork(), do_exit()
• Design of mailbox data structure for producer-consumer
– October 15:–• Sending and receiving messages
• User space support and test program
– October 22:–• Stopping mailbox with blocked calls on SendMsg or RcvMsg
• Flushing messages
Project 2CS-502 Fall 2007 36
Submission
• Submit using web-based turnin program– http://turnin.cs.wpi.edu:8088/servlets/turnin.ss
• Include – One patch file for kernel implementation
• Difference from prePatch-Project2 and your implementation
– User space implementation of mailbox.h interface– Test program(s) and results– Makefile
– Write up explaining implementation and testing
• Put your name on all documents and at top of every edited file!
Project 2CS-502 Fall 2007 37
Questions?