⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 post.cc

📁 美国加州大学操作系统课程实验平台Nachos
💻 CC
字号:
// 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-1996 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"//----------------------------------------------------------------------// 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, char *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<Mail *>(); }//----------------------------------------------------------------------// 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; }//----------------------------------------------------------------------// 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){    cout << "From (" << pktHdr.from << ", " << mailHdr.from << ") to (" << 	pktHdr.to << ", " << mailHdr.to << ") bytes " << mailHdr.length << "\n";}//----------------------------------------------------------------------// 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, char *data){     Mail *mail = new Mail(pktHdr, mailHdr, data);     messages->Append(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, char *data) {     DEBUG(dbgNet, "Waiting for mail in mailbox");    Mail *mail = messages->RemoveFront();	// remove message from list;						// will wait if list is empty    *pktHdr = mail->pktHdr;    *mailHdr = mail->mailHdr;    if (debug->IsEnabled('n')) {	cout << "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}//----------------------------------------------------------------------// PostOfficeInput::PostOfficeInput// 	Initialize the post office input queues 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.////	"nBoxes" is the number of mail boxes in this Post Office//----------------------------------------------------------------------PostOfficeInput::PostOfficeInput(int nBoxes){    messageAvailable = new Semaphore("message available", 0);    numBoxes = nBoxes;    boxes = new MailBox[nBoxes];    network = new NetworkInput(this);    Thread *t = new Thread("postal worker");    t->Fork(PostOfficeInput::PostalDelivery, this);}//----------------------------------------------------------------------// PostOfficeInput::~PostOfficeInput// 	De-allocate the post office data structures.//	//	Since the postal helper is waiting on the "messageAvail" semaphore,//	we don't deallocate it!  This leaves garbage lying about,//	but the alternative is worse!//----------------------------------------------------------------------PostOfficeInput::~PostOfficeInput(){    delete network;    delete [] boxes;}//----------------------------------------------------------------------// 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.//----------------------------------------------------------------------voidPostOfficeInput::PostalDelivery(void* data){    PostOfficeInput* _this = (PostOfficeInput*)data;    PacketHeader pktHdr;    MailHeader mailHdr;    char *buffer = new char[MaxPacketSize];    for (;;) {        // first, wait for a message        _this->messageAvailable->P();	        pktHdr = _this->network->Receive(buffer);        mailHdr = *(MailHeader *)buffer;        if (debug->IsEnabled('n')) {	    cout << "Putting mail into mailbox: ";	    PrintHeader(pktHdr, mailHdr);        }	// check that arriving message is legal!	ASSERT(0 <= mailHdr.to && mailHdr.to < _this->numBoxes);	ASSERT(mailHdr.length <= MaxMailSize);	// put into mailbox        _this->boxes[mailHdr.to].Put(pktHdr, mailHdr, buffer + sizeof(MailHeader));    }}//----------------------------------------------------------------------// PostOfficeInput::Receive// 	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//----------------------------------------------------------------------voidPostOfficeInput::Receive(int box, PacketHeader *pktHdr, 				MailHeader *mailHdr, char* data){    ASSERT((box >= 0) && (box < numBoxes));    boxes[box].Get(pktHdr, mailHdr, data);    ASSERT(mailHdr->length <= MaxMailSize);}//----------------------------------------------------------------------// PostOffice::CallBack// 	Interrupt handler, called when a packet arrives from the network.////	Signal the PostalDelivery routine that it is time to get to work!//----------------------------------------------------------------------voidPostOfficeInput::CallBack(){     messageAvailable->V(); }//----------------------------------------------------------------------// PostOfficeOutput::PostOfficeOutput// 	Initialize the post office output queue.////	"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)//----------------------------------------------------------------------PostOfficeOutput::PostOfficeOutput(double reliability){    messageSent = new Semaphore("message sent", 0);    sendLock = new Lock("message send lock");    network = new NetworkOutput(reliability, this);}//----------------------------------------------------------------------// PostOfficeOutput::~PostOfficeOutput// 	De-allocate the post office data structures.//----------------------------------------------------------------------PostOfficeOutput::~PostOfficeOutput(){    delete network;    delete messageSent;    delete sendLock;}//----------------------------------------------------------------------// PostOfficeOutput::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//----------------------------------------------------------------------voidPostOfficeOutput::Send(PacketHeader pktHdr, MailHeader mailHdr, char* data){    char* buffer = new char[MaxPacketSize];	// space to hold concatenated						// mailHdr + data    if (debug->IsEnabled('n')) {	cout << "Post send: ";	PrintHeader(pktHdr, mailHdr);    }    ASSERT(mailHdr.length <= MaxMailSize);    ASSERT(0 <= mailHdr.to);        // fill in pktHdr, for the Network layer    pktHdr.from = kernel->hostName;    pktHdr.length = mailHdr.length + sizeof(MailHeader);    // concatenate MailHeader and data    bcopy((char *)&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}//----------------------------------------------------------------------// PostOfficeOutput::CallBack// 	Interrupt handler, called when the next packet can be put onto the //	network.////	Called even if the previous packet was dropped.//----------------------------------------------------------------------void PostOfficeOutput::CallBack(){     messageSent->V();}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -