// sysdep.cc
// Implementation of system-dependent interface. Nachos uses the
// routines defined here, rather than directly calling the UNIX library,
// to simplify porting between versions of UNIX, and even to
// other systems, such as MSDOS.
//
// On UNIX, almost all of these routines are simple wrappers
// for the underlying UNIX system calls.
//
// NOTE: all of these routines refer to operations on the underlying
// host machine (e.g., the DECstation, SPARC, etc.), supporting the
// Nachos simulation code. Nachos implements similar operations,
// (such as opening a file), but those are implemented in terms
// of hardware devices, which are simulated by calls to the underlying
// routines in the host workstation OS.
//
// This file includes lots of calls to C routines. C++ requires
// us to wrap all C definitions with a "extern "C" block".
// This prevents the internal forms of the names from being
// changed by the C++ compiler.
//
// 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"
extern "C" {
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <sys/file.h>
#include <sys/un.h>
#include <sys/mman.h>
#ifdef HOST_i386
#include <sys/time.h>
#endif
#ifdef HOST_SPARC
#include <sys/time.h>
#endif
// UNIX routines called by procedures in this file
#if 1
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#else
#ifdef HOST_SNAKE
// int creat(char *name, unsigned short mode);
// int open(const char *name, int flags, ...);
#else
int creat(const char *name, unsigned short mode);
int open(const char *name, int flags, ...);
// void signal(int sig, VoidFunctionPtr func); -- this may work now!
#ifdef HOST_i386
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
struct timeval *timeout);
#else
int select(int numBits, void *readFds, void *writeFds, void *exceptFds,
struct timeval *timeout);
#endif
#endif
int unlink(char *name);
int read(int filedes, char *buf, int numBytes);
int write(int filedes, char *buf, int numBytes);
int lseek(int filedes, int offset, int whence);
int tell(int filedes);
int close(int filedes);
int unlink(char *name);
// definition varies slightly from platform to platform, so don't
// define unless gcc complains
// extern int recvfrom(int s, void *buf, int len, int flags, void *from, int *fromlen);
// extern int sendto(int s, void *msg, int len, int flags, void *to, int tolen);
void srand(unsigned seed);
int rand(void);
unsigned sleep(unsigned);
void abort();
void exit();
int mprotect(char *addr, int len, int prot);
int socket(int, int, int);
int bind (int, const void*, int);
int recvfrom (int, void*, int, int, void*, int *);
int sendto (int, const void*, int, int, void*, int);
#endif
}
#include "interrupt.h"
#include "system.h"
//----------------------------------------------------------------------
// PollFile
// Check open file or open socket to see if there are any
// characters that can be read immediately. If so, read them
// in, and return TRUE.
//
// In the network case, if there are no threads for us to run,
// and no characters to be read,
// we need to give the other side a chance to get our host's CPU
// (otherwise, we'll go really slowly, since UNIX time-slices
// infrequently, and this would be like busy-waiting). So we
// delay for a short fixed time, before allowing ourselves to be
// re-scheduled (sort of like a Yield, but cast in terms of UNIX).
//
// "fd" -- the file descriptor of the file to be polled
//----------------------------------------------------------------------
bool PollFile(int fd)
{
int rfd = (1 << fd), wfd = 0, xfd = 0, retVal;
struct timeval pollTime;
// decide how long to wait if there are no characters on the file
pollTime.tv_sec = 0;
if (interrupt->getStatus() == IdleMode)
pollTime.tv_usec = 20000; // delay to let other nachos run
else
pollTime.tv_usec = 0; // no delay
// poll file or socket
#ifdef HOST_i386
retVal = select(32, (fd_set*)&rfd, (fd_set*)&wfd, (fd_set*)&xfd, &pollTime);
#else
retVal = select(32, &rfd, &wfd, &xfd, &pollTime);
#endif
ASSERT((retVal == 0) || (retVal == 1));
if (retVal == 0)
return FALSE; // no char waiting to be read
return TRUE;
}
//----------------------------------------------------------------------
// OpenForWrite
// Open a file for writing. Create it if it doesn't exist; truncate it
// if it does already exist. Return the file descriptor.
//
// "name" -- file name
//----------------------------------------------------------------------
int OpenForWrite(char *name)
{
int fd = open(name, O_RDWR|O_CREAT|O_TRUNC, 0666);
ASSERT(fd >= 0);
return fd;
}
//----------------------------------------------------------------------
// OpenForReadWrite
// Open a file for reading or writing.
// Return the file descriptor, or error if it doesn't exist.
//
// "name" -- file name
//----------------------------------------------------------------------
int OpenForReadWrite(char *name, bool crashOnError)
{
int fd = open(name, O_RDWR, 0);
ASSERT(!crashOnError || fd >= 0);
return fd;
}
//----------------------------------------------------------------------
// Read
// Read characters from an open file. Abort if read fails.
//----------------------------------------------------------------------
void Read(int fd, char *buffer, int nBytes)
{
int retVal = read(fd, buffer, nBytes);
ASSERT(retVal == nBytes);
}
//----------------------------------------------------------------------
// ReadPartial
// Read characters from an open file, returning as many as are
// available.
//----------------------------------------------------------------------
int ReadPartial(int fd, char *buffer, int nBytes)
{
return read(fd, buffer, nBytes);
}
//----------------------------------------------------------------------
// WriteFile
// Write characters to an open file. Abort if write fails.
//----------------------------------------------------------------------
void WriteFile(int fd, char *buffer, int nBytes)
{
int retVal = write(fd, buffer, nBytes);
ASSERT(retVal == nBytes);
}
//----------------------------------------------------------------------
// Lseek
// Change the location within an open file. Abort on error.
//----------------------------------------------------------------------
void Lseek(int fd, int offset, int whence)
{
int retVal = lseek(fd, offset, whence);
ASSERT(retVal >= 0);
}
//----------------------------------------------------------------------
// Tell
// Report the current location within an open file.
//----------------------------------------------------------------------
int Tell(int fd)
{
#ifdef HOST_i386
return lseek(fd,0,SEEK_CUR); // 386BSD doesn't have the tell() system call
#else
return tell(fd);
#endif
}
//----------------------------------------------------------------------