Initial version
This commit is contained in:
commit
6f405265a5
102 changed files with 14486 additions and 0 deletions
23
code/network/Makefile
Normal file
23
code/network/Makefile
Normal file
|
@ -0,0 +1,23 @@
|
|||
# NOTE: this is a GNU Makefile. You must use "gmake" rather than "make".
|
||||
#
|
||||
# Makefile for the network assignment
|
||||
# Defines set up assuming this assignment is done last
|
||||
# If not, use the "bare bones" defines below.
|
||||
#
|
||||
# Copyright (c) 1992 The Regents of the University of California.
|
||||
# All rights reserved. See copyright.h for copyright notice and limitation
|
||||
# of liability and disclaimer of warranty provisions.
|
||||
|
||||
DEFINES = -DUSER_PROGRAM -DVM -DFILESYS_NEEDED -DFILESYS -DNETWORK
|
||||
INCPATH = -I../network -I../bin -I../filesys -I../vm -I../userprog -I../threads -I../machine
|
||||
C_OFILES = $(THREAD_O) $(USERPROG_O) $(VM_O) $(FILESYS_O) $(NETWORK_O)
|
||||
|
||||
# bare bones version
|
||||
# DEFINES =-DTHREADS -DNETWORK
|
||||
# INCPATH = -I../network -I../threads -I../machine
|
||||
# C_OFILES = $(THREAD_O) $(NETWORK_O)
|
||||
|
||||
include ../Makefile.common
|
||||
include ../Makefile.dep
|
||||
|
||||
|
59
code/network/README
Normal file
59
code/network/README
Normal file
|
@ -0,0 +1,59 @@
|
|||
From: cs162@po.EECS.Berkeley.EDU (Class Master)
|
||||
Subject: Answer to problems running assignment 5
|
||||
|
||||
Some people have been having problems running assignment 5.
|
||||
Unfortunately, the way the network gets initialized, if things
|
||||
don't get done in exactly the right order, you can get an error
|
||||
in sending the first packet to the socket.
|
||||
|
||||
I have modified synch.h and synch.cc in code/, and re-compiled
|
||||
the contents of code/network. I was then able to run the
|
||||
test case successfully, at least one out of two times. See below.
|
||||
So, be careful out there!
|
||||
|
||||
tom
|
||||
-----------
|
||||
po.EECS.Berkeley.EDU:network>!19
|
||||
./nachos -m 0 -o 1 > & log & ; ./nachos -m 1 -o 0 > & log2 &
|
||||
[1] 10882
|
||||
[2] 10883
|
||||
po.EECS.Berkeley.EDU:network>
|
||||
[2] Illegal instruction ./nachos -m 1 -o 0 >& log2 (core dumped)
|
||||
|
||||
[1] Illegal instruction ./nachos -m 0 -o 1 >& log (core dumped)
|
||||
|
||||
po.EECS.Berkeley.EDU:network>rm -f log* SOCKET*
|
||||
po.EECS.Berkeley.EDU:network>!19
|
||||
./nachos -m 0 -o 1 > & log & ; ./nachos -m 1 -o 0 > & log2 &
|
||||
[1] 10895
|
||||
[2] 10896
|
||||
po.EECS.Berkeley.EDU:network>
|
||||
[1] Done ./nachos -m 0 -o 1 >& log
|
||||
|
||||
[2] Done ./nachos -m 1 -o 0 >& log2
|
||||
more log
|
||||
Got "Hello there!" from 1, box 1
|
||||
Got "Got it!" from 1, box 1
|
||||
Machine halting!
|
||||
|
||||
Ticks: total 57080, idle 56810, system 270, user 0
|
||||
Disk I/O: reads 2, writes 0
|
||||
Console I/O: reads 0, writes 0
|
||||
Paging: faults 0
|
||||
Network I/O: packets received 2, sent 2
|
||||
|
||||
|
||||
|
||||
Cleaning up...
|
||||
po.EECS.Berkeley.EDU:network>more log2
|
||||
Got "Hello there!" from 0, box 1
|
||||
Got "Got it!" from 0, box 1
|
||||
Machine halting!
|
||||
|
||||
Ticks: total 58530, idle 58260, system 270, user 0
|
||||
Disk I/O: reads 2, writes 0
|
||||
Console I/O: reads 0, writes 0
|
||||
Paging: faults 0
|
||||
Network I/O: packets received 2, sent 2
|
||||
|
||||
Cleaning up...
|
72
code/network/nettest.cc
Normal file
72
code/network/nettest.cc
Normal file
|
@ -0,0 +1,72 @@
|
|||
// nettest.cc
|
||||
// Test out message delivery between two "Nachos" machines,
|
||||
// using the Post Office to coordinate delivery.
|
||||
//
|
||||
// Two caveats:
|
||||
// 1. Two copies of Nachos must be running, with machine ID's 0 and 1:
|
||||
// ./nachos -m 0 -o 1 &
|
||||
// ./nachos -m 1 -o 0 &
|
||||
//
|
||||
// 2. You need an implementation of condition variables,
|
||||
// which is *not* provided as part of the baseline threads
|
||||
// implementation. The Post Office won't work without
|
||||
// a correct implementation of condition variables.
|
||||
//
|
||||
// Copyright (c) 1992-1993 The Regents of the University of California.
|
||||
// All rights reserved. See copyright.h for copyright notice and limitation
|
||||
// of liability and disclaimer of warranty provisions.
|
||||
|
||||
#include "copyright.h"
|
||||
|
||||
#include "system.h"
|
||||
#include "network.h"
|
||||
#include "post.h"
|
||||
#include "interrupt.h"
|
||||
|
||||
// Test out message delivery, by doing the following:
|
||||
// 1. send a message to the machine with ID "farAddr", at mail box #0
|
||||
// 2. wait for the other machine's message to arrive (in our mailbox #0)
|
||||
// 3. send an acknowledgment for the other machine's message
|
||||
// 4. wait for an acknowledgement from the other machine to our
|
||||
// original message
|
||||
|
||||
void
|
||||
MailTest(int farAddr)
|
||||
{
|
||||
PacketHeader outPktHdr, inPktHdr;
|
||||
MailHeader outMailHdr, inMailHdr;
|
||||
const char *data = "Hello there!";
|
||||
const char *ack = "Got it!";
|
||||
char buffer[MaxMailSize];
|
||||
|
||||
// construct packet, mail header for original message
|
||||
// To: destination machine, mailbox 0
|
||||
// From: our machine, reply to: mailbox 1
|
||||
outPktHdr.to = farAddr;
|
||||
outMailHdr.to = 0;
|
||||
outMailHdr.from = 1;
|
||||
outMailHdr.length = strlen(data) + 1;
|
||||
|
||||
// Send the first message
|
||||
postOffice->Send(outPktHdr, outMailHdr, data);
|
||||
|
||||
// Wait for the first message from the other machine
|
||||
postOffice->Receive(0, &inPktHdr, &inMailHdr, buffer);
|
||||
printf("Got \"%s\" from %d, box %d\n",buffer,inPktHdr.from,inMailHdr.from);
|
||||
fflush(stdout);
|
||||
|
||||
// Send acknowledgement to the other machine (using "reply to" mailbox
|
||||
// in the message that just arrived
|
||||
outPktHdr.to = inPktHdr.from;
|
||||
outMailHdr.to = inMailHdr.from;
|
||||
outMailHdr.length = strlen(ack) + 1;
|
||||
postOffice->Send(outPktHdr, outMailHdr, ack);
|
||||
|
||||
// Wait for the ack from the other machine to the first message we sent.
|
||||
postOffice->Receive(1, &inPktHdr, &inMailHdr, buffer);
|
||||
printf("Got \"%s\" from %d, box %d\n",buffer,inPktHdr.from,inMailHdr.from);
|
||||
fflush(stdout);
|
||||
|
||||
// Then we're done!
|
||||
interrupt->Powerdown();
|
||||
}
|
347
code/network/post.cc
Normal file
347
code/network/post.cc
Normal file
|
@ -0,0 +1,347 @@
|
|||
// post.cc
|
||||
// Routines to deliver incoming network messages to the correct
|
||||
// "address" -- a mailbox, or a holding area for incoming messages.
|
||||
// This module operates just like the US postal service (in other
|
||||
// words, it works, but it's slow, and you can't really be sure if
|
||||
// your mail really got through!).
|
||||
//
|
||||
// Note that once we prepend the MailHdr to the outgoing message data,
|
||||
// the combination (MailHdr plus data) looks like "data" to the Network
|
||||
// device.
|
||||
//
|
||||
// The implementation synchronizes incoming messages with threads
|
||||
// waiting for those messages.
|
||||
//
|
||||
// Copyright (c) 1992-1993 The Regents of the University of California.
|
||||
// All rights reserved. See copyright.h for copyright notice and limitation
|
||||
// of liability and disclaimer of warranty provisions.
|
||||
|
||||
#include "copyright.h"
|
||||
#include "post.h"
|
||||
|
||||
#include <strings.h> /* for bzero */
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Mail::Mail
|
||||
// Initialize a single mail message, by concatenating the headers to
|
||||
// the data.
|
||||
//
|
||||
// "pktH" -- source, destination machine ID's
|
||||
// "mailH" -- source, destination mailbox ID's
|
||||
// "data" -- payload data
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
Mail::Mail(PacketHeader pktH, MailHeader mailH, const void *msgData)
|
||||
{
|
||||
ASSERT(mailH.length <= MaxMailSize);
|
||||
|
||||
pktHdr = pktH;
|
||||
mailHdr = mailH;
|
||||
bcopy(msgData, data, mailHdr.length);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// MailBox::MailBox
|
||||
// Initialize a single mail box within the post office, so that it
|
||||
// can receive incoming messages.
|
||||
//
|
||||
// Just initialize a list of messages, representing the mailbox.
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
|
||||
MailBox::MailBox()
|
||||
{
|
||||
messages = new SynchList();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// MailBox::~MailBox
|
||||
// De-allocate a single mail box within the post office.
|
||||
//
|
||||
// Just delete the mailbox, and throw away all the queued messages
|
||||
// in the mailbox.
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
MailBox::~MailBox()
|
||||
{
|
||||
delete messages;
|
||||
messages = NULL;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// PrintHeader
|
||||
// Print the message header -- the destination machine ID and mailbox
|
||||
// #, source machine ID and mailbox #, and message length.
|
||||
//
|
||||
// "pktHdr" -- source, destination machine ID's
|
||||
// "mailHdr" -- source, destination mailbox ID's
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
static void
|
||||
PrintHeader(PacketHeader pktHdr, MailHeader mailHdr)
|
||||
{
|
||||
printf("From (%d, %d) to (%d, %d) bytes %d\n",
|
||||
pktHdr.from, mailHdr.from, pktHdr.to, mailHdr.to, mailHdr.length);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// MailBox::Put
|
||||
// Add a message to the mailbox. If anyone is waiting for message
|
||||
// arrival, wake them up!
|
||||
//
|
||||
// We need to reconstruct the Mail message (by concatenating the headers
|
||||
// to the data), to simplify queueing the message on the SynchList.
|
||||
//
|
||||
// "pktHdr" -- source, destination machine ID's
|
||||
// "mailHdr" -- source, destination mailbox ID's
|
||||
// "data" -- payload message data
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
void
|
||||
MailBox::Put(PacketHeader pktHdr, MailHeader mailHdr, const void *data)
|
||||
{
|
||||
Mail *mail = new Mail(pktHdr, mailHdr, data);
|
||||
|
||||
messages->Append((void *)mail); // put on the end of the list of
|
||||
// arrived messages, and wake up
|
||||
// any waiters
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// MailBox::Get
|
||||
// Get a message from a mailbox, parsing it into the packet header,
|
||||
// mailbox header, and data.
|
||||
//
|
||||
// The calling thread waits if there are no messages in the mailbox.
|
||||
//
|
||||
// "pktHdr" -- address to put: source, destination machine ID's
|
||||
// "mailHdr" -- address to put: source, destination mailbox ID's
|
||||
// "data" -- address to put: payload message data
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
void
|
||||
MailBox::Get(PacketHeader *pktHdr, MailHeader *mailHdr, void *data)
|
||||
{
|
||||
DEBUG('n', "Waiting for mail in mailbox\n");
|
||||
Mail *mail = (Mail *) messages->Remove(); // remove message from list;
|
||||
// will wait if list is empty
|
||||
|
||||
*pktHdr = mail->pktHdr;
|
||||
*mailHdr = mail->mailHdr;
|
||||
if (DebugIsEnabled('n')) {
|
||||
printf("Got mail from mailbox: ");
|
||||
PrintHeader(*pktHdr, *mailHdr);
|
||||
}
|
||||
bcopy(mail->data, data, mail->mailHdr.length);
|
||||
// copy the message data into
|
||||
// the caller's buffer
|
||||
delete mail; // we've copied out the stuff we
|
||||
// need, we can now discard the message
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// PostalHelper, ReadAvailHandler, WriteDoneHandler
|
||||
// Dummy functions because C++ can't indirectly invoke member functions
|
||||
// The first is forked as part of the "postal worker thread; the
|
||||
// later two are called by the network interrupt handler.
|
||||
//
|
||||
// "arg" -- pointer to the Post Office managing the Network
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
static void PostalHelper(void *arg)
|
||||
{ PostOffice* po = (PostOffice *) arg; po->PostalDelivery(); }
|
||||
static void ReadAvailHandler(void *arg)
|
||||
{ PostOffice* po = (PostOffice *) arg; po->IncomingPacket(); }
|
||||
static void WriteDoneHandler(void *arg)
|
||||
{ PostOffice* po = (PostOffice *) arg; po->PacketSent(); }
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// PostOffice::PostOffice
|
||||
// Initialize a post office as a collection of mailboxes.
|
||||
// Also initialize the network device, to allow post offices
|
||||
// on different machines to deliver messages to one another.
|
||||
//
|
||||
// We use a separate thread "the postal worker" to wait for messages
|
||||
// to arrive, and deliver them to the correct mailbox. Note that
|
||||
// delivering messages to the mailboxes can't be done directly
|
||||
// by the interrupt handlers, because it requires a Lock.
|
||||
//
|
||||
// "addr" is this machine's network ID
|
||||
// "reliability" is the probability that a network packet will
|
||||
// be delivered (e.g., reliability = 1 means the network never
|
||||
// drops any packets; reliability = 0 means the network never
|
||||
// delivers any packets)
|
||||
// "nBoxes" is the number of mail boxes in this Post Office
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
PostOffice::PostOffice(NetworkAddress addr, double reliability, int nBoxes)
|
||||
{
|
||||
// First, initialize the synchronization with the interrupt handlers
|
||||
messageAvailable = new Semaphore("message available", 0);
|
||||
messageSent = new Semaphore("message sent", 0);
|
||||
sendLock = new Lock("message send lock");
|
||||
|
||||
// Second, initialize the mailboxes
|
||||
netAddr = addr;
|
||||
numBoxes = nBoxes;
|
||||
boxes = new MailBox[nBoxes];
|
||||
|
||||
// Third, initialize the network; tell it which interrupt handlers to call
|
||||
network = new Network(addr, reliability, ReadAvailHandler, WriteDoneHandler, this);
|
||||
|
||||
|
||||
// Finally, create a thread whose sole job is to wait for incoming messages,
|
||||
// and put them in the right mailbox.
|
||||
Thread *t = new Thread("postal worker");
|
||||
|
||||
t->Start(PostalHelper, this);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// PostOffice::~PostOffice
|
||||
// De-allocate the post office data structures.
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
PostOffice::~PostOffice()
|
||||
{
|
||||
delete network;
|
||||
delete [] boxes;
|
||||
delete messageAvailable;
|
||||
delete messageSent;
|
||||
delete sendLock;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// PostOffice::PostalDelivery
|
||||
// Wait for incoming messages, and put them in the right mailbox.
|
||||
//
|
||||
// Incoming messages have had the PacketHeader stripped off,
|
||||
// but the MailHeader is still tacked on the front of the data.
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
void
|
||||
PostOffice::PostalDelivery()
|
||||
{
|
||||
PacketHeader pktHdr;
|
||||
MailHeader mailHdr;
|
||||
char *buffer = new char[MaxPacketSize];
|
||||
|
||||
for (;;) {
|
||||
// first, wait for a message
|
||||
messageAvailable->P();
|
||||
pktHdr = network->Receive(buffer);
|
||||
|
||||
mailHdr = *(MailHeader *)buffer;
|
||||
if (DebugIsEnabled('n')) {
|
||||
printf("Putting mail into mailbox: ");
|
||||
PrintHeader(pktHdr, mailHdr);
|
||||
}
|
||||
|
||||
// check that arriving message is legal!
|
||||
ASSERT(0 <= mailHdr.to && mailHdr.to < numBoxes);
|
||||
ASSERT(mailHdr.length <= MaxMailSize);
|
||||
|
||||
// put into mailbox
|
||||
boxes[mailHdr.to].Put(pktHdr, mailHdr, buffer + sizeof(MailHeader));
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// PostOffice::Send
|
||||
// Concatenate the MailHeader to the front of the data, and pass
|
||||
// the result to the Network for delivery to the destination machine.
|
||||
//
|
||||
// Note that the MailHeader + data looks just like normal payload
|
||||
// data to the Network.
|
||||
//
|
||||
// "pktHdr" -- source, destination machine ID's
|
||||
// "mailHdr" -- source, destination mailbox ID's
|
||||
// "data" -- payload message data
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
void
|
||||
PostOffice::Send(PacketHeader pktHdr, MailHeader mailHdr, const void* data)
|
||||
{
|
||||
char* buffer = new char[MaxPacketSize]; // space to hold concatenated
|
||||
// mailHdr + data
|
||||
|
||||
if (DebugIsEnabled('n')) {
|
||||
printf("Post send: ");
|
||||
PrintHeader(pktHdr, mailHdr);
|
||||
}
|
||||
ASSERT(mailHdr.length <= MaxMailSize);
|
||||
ASSERT(0 <= mailHdr.to && mailHdr.to < numBoxes);
|
||||
|
||||
// fill in pktHdr, for the Network layer
|
||||
pktHdr.from = netAddr;
|
||||
pktHdr.length = mailHdr.length + sizeof(MailHeader);
|
||||
|
||||
// concatenate MailHeader and data
|
||||
bcopy(&mailHdr, buffer, sizeof(MailHeader));
|
||||
bcopy(data, buffer + sizeof(MailHeader), mailHdr.length);
|
||||
|
||||
sendLock->Acquire(); // only one message can be sent
|
||||
// to the network at any one time
|
||||
network->Send(pktHdr, buffer);
|
||||
messageSent->P(); // wait for interrupt to tell us
|
||||
// ok to send the next message
|
||||
sendLock->Release();
|
||||
|
||||
delete [] buffer; // we've sent the message, so
|
||||
// we can delete our buffer
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// PostOffice::Send
|
||||
// Retrieve a message from a specific box if one is available,
|
||||
// otherwise wait for a message to arrive in the box.
|
||||
//
|
||||
// Note that the MailHeader + data looks just like normal payload
|
||||
// data to the Network.
|
||||
//
|
||||
//
|
||||
// "box" -- mailbox ID in which to look for message
|
||||
// "pktHdr" -- address to put: source, destination machine ID's
|
||||
// "mailHdr" -- address to put: source, destination mailbox ID's
|
||||
// "data" -- address to put: payload message data
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
void
|
||||
PostOffice::Receive(int box, PacketHeader *pktHdr,
|
||||
MailHeader *mailHdr, void* data)
|
||||
{
|
||||
ASSERT((box >= 0) && (box < numBoxes));
|
||||
|
||||
boxes[box].Get(pktHdr, mailHdr, data);
|
||||
ASSERT(mailHdr->length <= MaxMailSize);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// PostOffice::IncomingPacket
|
||||
// Interrupt handler, called when a packet arrives from the network.
|
||||
//
|
||||
// Signal the PostalDelivery routine that it is time to get to work!
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
void
|
||||
PostOffice::IncomingPacket()
|
||||
{
|
||||
messageAvailable->V();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// PostOffice::PacketSent
|
||||
// Interrupt handler, called when the next packet can be put onto the
|
||||
// network.
|
||||
//
|
||||
// The name of this routine is a misnomer; if "reliability < 1",
|
||||
// the packet could have been dropped by the network, so it won't get
|
||||
// through.
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
void
|
||||
PostOffice::PacketSent()
|
||||
{
|
||||
messageSent->V();
|
||||
}
|
||||
|
141
code/network/post.h
Normal file
141
code/network/post.h
Normal file
|
@ -0,0 +1,141 @@
|
|||
// post.h
|
||||
// Data structures for providing the abstraction of unreliable,
|
||||
// ordered, fixed-size message delivery to mailboxes on other
|
||||
// (directly connected) machines. Messages can be dropped by
|
||||
// the network, but they are never corrupted.
|
||||
//
|
||||
// The US Post Office delivers mail to the addressed mailbox.
|
||||
// By analogy, our post office delivers packets to a specific buffer
|
||||
// (MailBox), based on the mailbox number stored in the packet header.
|
||||
// Mail waits in the box until a thread asks for it; if the mailbox
|
||||
// is empty, threads can wait for mail to arrive in it.
|
||||
//
|
||||
// Thus, the service our post office provides is to de-multiplex
|
||||
// incoming packets, delivering them to the appropriate thread.
|
||||
//
|
||||
// With each message, you get a return address, which consists of a "from
|
||||
// address", which is the id of the machine that sent the message, and
|
||||
// a "from box", which is the number of a mailbox on the sending machine
|
||||
// to which you can send an acknowledgement, if your protocol requires
|
||||
// this.
|
||||
//
|
||||
// Copyright (c) 1992-1993 The Regents of the University of California.
|
||||
// All rights reserved. See copyright.h for copyright notice and limitation
|
||||
// of liability and disclaimer of warranty provisions.
|
||||
|
||||
#include "copyright.h"
|
||||
|
||||
#ifndef POST_H
|
||||
#define POST_H
|
||||
|
||||
#include "network.h"
|
||||
#include "synchlist.h"
|
||||
|
||||
// Mailbox address -- uniquely identifies a mailbox on a given machine.
|
||||
// A mailbox is just a place for temporary storage for messages.
|
||||
typedef int MailBoxAddress;
|
||||
|
||||
// The following class defines part of the message header.
|
||||
// This is prepended to the message by the PostOffice, before the message
|
||||
// is sent to the Network.
|
||||
|
||||
class MailHeader {
|
||||
public:
|
||||
MailBoxAddress to; // Destination mail box
|
||||
MailBoxAddress from; // Mail box to reply to
|
||||
unsigned length; // Bytes of message data (excluding the
|
||||
// mail header)
|
||||
};
|
||||
|
||||
// Maximum "payload" -- real data -- that can included in a single message
|
||||
// Excluding the MailHeader and the PacketHeader
|
||||
|
||||
#define MaxMailSize (MaxPacketSize - sizeof(MailHeader))
|
||||
|
||||
|
||||
// The following class defines the format of an incoming/outgoing
|
||||
// "Mail" message. The message format is layered:
|
||||
// network header (PacketHeader)
|
||||
// post office header (MailHeader)
|
||||
// data
|
||||
|
||||
class Mail {
|
||||
public:
|
||||
Mail(PacketHeader pktH, MailHeader mailH, const void *msgData);
|
||||
// Initialize a mail message by
|
||||
// concatenating the headers to the data
|
||||
|
||||
PacketHeader pktHdr; // Header appended by Network
|
||||
MailHeader mailHdr; // Header appended by PostOffice
|
||||
char data[MaxMailSize]; // Payload -- message data
|
||||
};
|
||||
|
||||
// The following class defines a single mailbox, or temporary storage
|
||||
// for messages. Incoming messages are put by the PostOffice into the
|
||||
// appropriate mailbox, and these messages can then be retrieved by
|
||||
// threads on this machine.
|
||||
|
||||
class MailBox:public dontcopythis {
|
||||
public:
|
||||
MailBox(); // Allocate and initialize mail box
|
||||
~MailBox(); // De-allocate mail box
|
||||
|
||||
void Put(PacketHeader pktHdr, MailHeader mailHdr, const void *data);
|
||||
// Atomically put a message into the mailbox
|
||||
void Get(PacketHeader *pktHdr, MailHeader *mailHdr, void *data);
|
||||
// Atomically get a message out of the
|
||||
// mailbox (and wait if there is no message
|
||||
// to get!)
|
||||
private:
|
||||
SynchList *messages; // A mailbox is just a list of arrived messages
|
||||
};
|
||||
|
||||
// The following class defines a "Post Office", or a collection of
|
||||
// mailboxes. The Post Office is a synchronization object that provides
|
||||
// two main operations: Send -- send a message to a mailbox on a remote
|
||||
// machine, and Receive -- wait until a message is in the mailbox,
|
||||
// then remove and return it.
|
||||
//
|
||||
// Incoming messages are put by the PostOffice into the
|
||||
// appropriate mailbox, waking up any threads waiting on Receive.
|
||||
|
||||
class PostOffice:public dontcopythis {
|
||||
public:
|
||||
PostOffice(NetworkAddress addr, double reliability, int nBoxes);
|
||||
// Allocate and initialize Post Office
|
||||
// "reliability" is how many packets
|
||||
// get dropped by the underlying network
|
||||
~PostOffice(); // De-allocate Post Office data
|
||||
|
||||
void Send(PacketHeader pktHdr, MailHeader mailHdr, const void *data);
|
||||
// Send a message to a mailbox on a remote
|
||||
// machine. The fromBox in the MailHeader is
|
||||
// the return box for ack's.
|
||||
|
||||
void Receive(int box, PacketHeader *pktHdr,
|
||||
MailHeader *mailHdr, void *data);
|
||||
// Retrieve a message from "box". Wait if
|
||||
// there is no message in the box.
|
||||
|
||||
void PostalDelivery(); // Wait for incoming messages,
|
||||
// and then put them in the correct mailbox
|
||||
|
||||
void PacketSent(); // Interrupt handler, called when outgoing
|
||||
// packet has been put on network; next
|
||||
// packet can now be sent
|
||||
void IncomingPacket(); // Interrupt handler, called when incoming
|
||||
// packet has arrived and can be pulled
|
||||
// off of network (i.e., time to call
|
||||
// PostalDelivery)
|
||||
|
||||
private:
|
||||
Network *network; // Physical network connection
|
||||
NetworkAddress netAddr; // Network address of this machine
|
||||
MailBox *boxes; // Table of mail boxes to hold incoming mail
|
||||
int numBoxes; // Number of mail boxes
|
||||
Semaphore *messageAvailable;// V'ed when message has arrived from network
|
||||
Semaphore *messageSent; // V'ed when next message can be sent to network
|
||||
Lock *sendLock; // Only one outgoing message at a time
|
||||
};
|
||||
|
||||
#endif
|
Loading…
Add table
Add a link
Reference in a new issue