Main Page   Compound List   File List   Compound Members   File Members  

sysdep.cc

Go to the documentation of this file.
00001 // sysdep.cc
00002 //      Implementation of system-dependent interface.  Nachos uses the 
00003 //      routines defined here, rather than directly calling the UNIX library,
00004 //      to simplify porting between versions of UNIX, and even to
00005 //      other systems, such as MSDOS.
00006 //
00007 //      On UNIX, almost all of these routines are simple wrappers
00008 //      for the underlying UNIX system calls.
00009 //
00010 //      NOTE: all of these routines refer to operations on the underlying
00011 //      host machine (e.g., the DECstation, SPARC, etc.), supporting the 
00012 //      Nachos simulation code.  Nachos implements similar operations,
00013 //      (such as opening a file), but those are implemented in terms
00014 //      of hardware devices, which are simulated by calls to the underlying
00015 //      routines in the host workstation OS.
00016 //
00017 //      This file includes lots of calls to C routines.  C++ requires
00018 //      us to wrap all C definitions with a "extern "C" block".
00019 //      This prevents the internal forms of the names from being
00020 //      changed by the C++ compiler.
00021 //
00022 // Copyright (c) 1992-1993 The Regents of the University of California.
00023 // All rights reserved.  See copyright.h for copyright notice and limitation 
00024 // of liability and disclaimer of warranty provisions.
00025 
00026 #include "copyright.h"
00027 
00028 extern "C" {
00029 #include <stdio.h>
00030 #include <string.h>
00031 #include <signal.h>
00032 #include <sys/types.h>
00033 #include <sys/time.h>
00034 #include <sys/socket.h>
00035 #include <sys/file.h>
00036 #include <sys/un.h>
00037 #include <sys/mman.h>
00038 #ifdef HOST_i386
00039 #include <sys/time.h>
00040 #endif
00041 #ifdef HOST_SPARC
00042 #include <sys/time.h>
00043 #endif
00044 #ifdef        HOST_SVR4
00045 #include      <fcntl.h>
00046 #endif
00047 
00048 // UNIX routines called by procedures in this file 
00049 
00050 #if   defined(HOST_SNAKE) || defined(HOST_SVR4)
00051 // int creat(char *name, unsigned short mode);
00052 // int open(const char *name, int flags, ...);
00053 #else
00054 int creat(const char *name, unsigned short mode);
00055 int open(const char *name, int flags, ...);
00056 // void signal(int sig, VoidFunctionPtr func); -- this may work now!
00057 #ifdef HOST_i386
00058 int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
00059              struct timeval *timeout);
00060 #else
00061 int select(int numBits, void *readFds, void *writeFds, void *exceptFds, 
00062         struct timeval *timeout);
00063 #endif
00064 #endif
00065 
00066 int unlink(char *name);
00067 int read(int filedes, char *buf, int numBytes);
00068 int write(int filedes, char *buf, int numBytes);
00069 int lseek(int filedes, int offset, int whence);
00070 int tell(int filedes);
00071 int close(int filedes);
00072 int unlink(char *name);
00073 
00074 // definition varies slightly from platform to platform, so don't 
00075 // define unless gcc complains
00076 // extern int recvfrom(int s, void *buf, int len, int flags, void *from, int *fromlen);
00077 // extern int sendto(int s, void *msg, int len, int flags, void *to, int tolen);
00078 
00079 void srand(unsigned seed);
00080 int rand(void);
00081 unsigned sleep(unsigned);
00082 void abort();
00083 void exit();
00084 #if !defined(HOST_SVR4)
00085 int mprotect(char *addr, int len, int prot);
00086 #endif
00087 
00088 #if !defined(HOST_SVR4) 
00089 int socket(int, int, int);
00090 int bind (int, const void*, int);
00091 // int recvfrom (int, void*, int, int, void*, int *);
00092 // int sendto (int, const void*, int, int, void*, int);
00093 int getpagesize();
00094 #else
00095 int socket(int, int, int);
00096 int bind(int, const struct sockaddr *, unsigned int);
00097 // int recvfrom(int, char *, int, int, struct sockaddr *, int *);
00098 // int sendto(int, const char *, int, int, struct sockaddr *, int);
00099 int getpagesize();
00100 #endif 
00101 }
00102 
00103 #include "interrupt.h"
00104 #include "system.h"
00105 
00106 //----------------------------------------------------------------------
00107 // PollFile
00108 //      Check open file or open socket to see if there are any 
00109 //      characters that can be read immediately.  If so, read them
00110 //      in, and return TRUE.
00111 //
00112 //      In the network case, if there are no threads for us to run,
00113 //      and no characters to be read,
00114 //      we need to give the other side a chance to get our host's CPU
00115 //      (otherwise, we'll go really slowly, since UNIX time-slices
00116 //      infrequently, and this would be like busy-waiting).  So we
00117 //      delay for a short fixed time, before allowing ourselves to be
00118 //      re-scheduled (sort of like a Yield, but cast in terms of UNIX).
00119 //
00120 //      "fd" -- the file descriptor of the file to be polled
00121 //----------------------------------------------------------------------
00122 
00123 bool
00124 PollFile(int fd)
00125 {
00126     int rfd = (1 << fd), wfd = 0, xfd = 0, retVal;
00127     struct timeval pollTime;
00128 
00129 // decide how long to wait if there are no characters on the file
00130     pollTime.tv_sec = 0;
00131     if (interrupt->getStatus() == IdleMode)
00132         pollTime.tv_usec = 20000;               // delay to let other nachos run
00133     else
00134         pollTime.tv_usec = 0;                   // no delay
00135 
00136 // poll file or socket
00137 #if   defined(HOST_i386) || defined(HOST_SVR4)
00138     retVal = select(32, (fd_set*)&rfd, (fd_set*)&wfd, (fd_set*)&xfd, &pollTime);
00139 #else
00140     retVal = select(32, &rfd, &wfd, &xfd, &pollTime);
00141 #endif
00142 
00143     ASSERT((retVal == 0) || (retVal == 1));
00144     if (retVal == 0)
00145         return FALSE;                           // no char waiting to be read
00146     return TRUE;
00147 }
00148 
00149 //----------------------------------------------------------------------
00150 // OpenForWrite
00151 //      Open a file for writing.  Create it if it doesn't exist; truncate it 
00152 //      if it does already exist.  Return the file descriptor.
00153 //
00154 //      "name" -- file name
00155 //----------------------------------------------------------------------
00156 
00157 int
00158 OpenForWrite(char *name)
00159 {
00160     int fd = open(name, O_RDWR|O_CREAT|O_TRUNC, 0666);
00161 
00162     ASSERT(fd >= 0); 
00163     return fd;
00164 }
00165 
00166 //----------------------------------------------------------------------
00167 // OpenForReadWrite
00168 //      Open a file for reading or writing.
00169 //      Return the file descriptor, or error if it doesn't exist.
00170 //
00171 //      "name" -- file name
00172 //----------------------------------------------------------------------
00173 
00174 int
00175 OpenForReadWrite(char *name, bool crashOnError)
00176 {
00177     int fd = open(name, O_RDWR, 0);
00178 
00179     ASSERT(!crashOnError || fd >= 0);
00180     return fd;
00181 }
00182 
00183 //----------------------------------------------------------------------
00184 // Read
00185 //      Read characters from an open file.  Abort if read fails.
00186 //----------------------------------------------------------------------
00187 
00188 void
00189 Read(int fd, char *buffer, int nBytes)
00190 {
00191     int retVal = read(fd, buffer, nBytes);
00192     ASSERT(retVal == nBytes);
00193 }
00194 
00195 //----------------------------------------------------------------------
00196 // ReadPartial
00197 //      Read characters from an open file, returning as many as are
00198 //      available.
00199 //----------------------------------------------------------------------
00200 
00201 int
00202 ReadPartial(int fd, char *buffer, int nBytes)
00203 {
00204     return read(fd, buffer, nBytes);
00205 }
00206 
00207 
00208 //----------------------------------------------------------------------
00209 // WriteFile
00210 //      Write characters to an open file.  Abort if write fails.
00211 //----------------------------------------------------------------------
00212 
00213 void
00214 WriteFile(int fd, char *buffer, int nBytes)
00215 {
00216     int retVal = write(fd, buffer, nBytes);
00217     ASSERT(retVal == nBytes);
00218 }
00219 
00220 //----------------------------------------------------------------------
00221 // Lseek
00222 //      Change the location within an open file.  Abort on error.
00223 //----------------------------------------------------------------------
00224 
00225 void 
00226 Lseek(int fd, int offset, int whence)
00227 {
00228     int retVal = lseek(fd, offset, whence);
00229     ASSERT(retVal >= 0);
00230 }
00231 
00232 //----------------------------------------------------------------------
00233 // Tell
00234 //      Report the current location within an open file.
00235 //----------------------------------------------------------------------
00236 
00237 int 
00238 Tell(int fd)
00239 {
00240 #ifdef HOST_i386
00241     return lseek(fd,0,SEEK_CUR); // 386BSD doesn't have the tell() system call
00242 #else
00243     return tell(fd);
00244 #endif
00245 }
00246 
00247 
00248 //----------------------------------------------------------------------
00249 // Close
00250 //      Close a file.  Abort on error.
00251 //----------------------------------------------------------------------
00252 
00253 void 
00254 Close(int fd)
00255 {
00256     int retVal = close(fd);
00257     ASSERT(retVal >= 0); 
00258 }
00259 
00260 //----------------------------------------------------------------------
00261 // Unlink
00262 //      Delete a file.
00263 //----------------------------------------------------------------------
00264 
00265 bool 
00266 Unlink(char *name)
00267 {
00268     return unlink(name);
00269 }
00270 
00271 //----------------------------------------------------------------------
00272 // OpenSocket
00273 //      Open an interprocess communication (IPC) connection.  For now, 
00274 //      just open a datagram port where other Nachos (simulating 
00275 //      workstations on a network) can send messages to this Nachos.
00276 //----------------------------------------------------------------------
00277 
00278 int
00279 OpenSocket()
00280 {
00281     int sockID;
00282     
00283     sockID = socket(AF_UNIX, SOCK_DGRAM, 0);
00284     ASSERT(sockID >= 0);
00285 
00286     return sockID;
00287 }
00288 
00289 //----------------------------------------------------------------------
00290 // CloseSocket
00291 //      Close the IPC connection. 
00292 //----------------------------------------------------------------------
00293 
00294 void
00295 CloseSocket(int sockID)
00296 {
00297     (void) close(sockID);
00298 }
00299 
00300 //----------------------------------------------------------------------
00301 // InitSocketName
00302 //      Initialize a UNIX socket address -- magical!
00303 //----------------------------------------------------------------------
00304 
00305 static void 
00306 InitSocketName(struct sockaddr_un *uname, char *name)
00307 {
00308     uname->sun_family = AF_UNIX;
00309     strcpy(uname->sun_path, name);
00310 }
00311 
00312 //----------------------------------------------------------------------
00313 // AssignNameToSocket
00314 //      Give a UNIX file name to the IPC port, so other instances of Nachos
00315 //      can locate the port. 
00316 //----------------------------------------------------------------------
00317 
00318 void
00319 AssignNameToSocket(char *socketName, int sockID)
00320 {
00321     struct sockaddr_un uName;
00322     int retVal;
00323 
00324     (void) unlink(socketName);    // in case it's still around from last time
00325 
00326     InitSocketName(&uName, socketName);
00327     retVal = bind(sockID, (struct sockaddr *) &uName, sizeof(uName));
00328     ASSERT(retVal >= 0);
00329     DEBUG('n', "Created socket %s\n", socketName);
00330 }
00331 
00332 //----------------------------------------------------------------------
00333 // DeAssignNameToSocket
00334 //      Delete the UNIX file name we assigned to our IPC port, on cleanup.
00335 //----------------------------------------------------------------------
00336 void
00337 DeAssignNameToSocket(char *socketName)
00338 {
00339     (void) unlink(socketName);
00340 }
00341 
00342 //----------------------------------------------------------------------
00343 // PollSocket
00344 //      Return TRUE if there are any messages waiting to arrive on the
00345 //      IPC port.
00346 //----------------------------------------------------------------------
00347 bool
00348 PollSocket(int sockID)
00349 {
00350     return PollFile(sockID);    // on UNIX, socket ID's are just file ID's
00351 }
00352 
00353 //----------------------------------------------------------------------
00354 // ReadFromSocket
00355 //      Read a fixed size packet off the IPC port.  Abort on error.
00356 //----------------------------------------------------------------------
00357 void
00358 ReadFromSocket(int sockID, char *buffer, int packetSize)
00359 {
00360     int retVal;
00361     extern int errno;
00362     struct sockaddr_un uName;
00363     int size = sizeof(uName);
00364    
00365     retVal = recvfrom(sockID, buffer, packetSize, 0,
00366                                    (struct sockaddr *) &uName, &size);
00367 
00368     if (retVal != packetSize) {
00369         perror("in recvfrom");
00370         printf("called: %x, got back %d, %d\n", (unsigned int) buffer, 
00371                retVal, errno);
00372     }
00373     ASSERT(retVal == packetSize);
00374 }
00375 
00376 //----------------------------------------------------------------------
00377 // SendToSocket
00378 //      Transmit a fixed size packet to another Nachos' IPC port.
00379 //      Abort on error.
00380 //----------------------------------------------------------------------
00381 void
00382 SendToSocket(int sockID, char *buffer, int packetSize, char *toName)
00383 {
00384     struct sockaddr_un uName;
00385     int retVal;
00386 
00387     InitSocketName(&uName, toName);
00388     retVal = sendto(sockID, buffer, packetSize, 0,
00389 #ifdef        HOST_SVR4
00390                     (sockaddr *) &uName, 
00391 #else
00392                     (char *) &uName, 
00393 #endif        /* HOST_SVR4 */
00394                     sizeof(uName));
00395     ASSERT(retVal == packetSize);
00396 }
00397 
00398 
00399 //----------------------------------------------------------------------
00400 // CallOnUserAbort
00401 //      Arrange that "func" will be called when the user aborts (e.g., by
00402 //      hitting ctl-C.
00403 //----------------------------------------------------------------------
00404 
00405 void 
00406 CallOnUserAbort(VoidNoArgFunctionPtr func)
00407 {
00408     (void)signal(SIGINT, (VoidFunctionPtr) func);
00409 }
00410 
00411 //----------------------------------------------------------------------
00412 // Sleep
00413 //      Put the UNIX process running Nachos to sleep for x seconds,
00414 //      to give the user time to start up another invocation of Nachos
00415 //      in a different UNIX shell.
00416 //----------------------------------------------------------------------
00417 
00418 void 
00419 Delay(int seconds)
00420 {
00421     (void) sleep((unsigned) seconds);
00422 }
00423 
00424 //----------------------------------------------------------------------
00425 // Abort
00426 //      Quit and drop core.
00427 //----------------------------------------------------------------------
00428 
00429 void 
00430 Abort()
00431 {
00432     abort();
00433 }
00434 
00435 //----------------------------------------------------------------------
00436 // Exit
00437 //      Quit without dropping core.
00438 //----------------------------------------------------------------------
00439 
00440 void 
00441 Exit(int exitCode)
00442 {
00443     exit(exitCode);
00444 }
00445 
00446 //----------------------------------------------------------------------
00447 // RandomInit
00448 //      Initialize the pseudo-random number generator.  We use the
00449 //      now obsolete "srand" and "rand" because they are more portable!
00450 //----------------------------------------------------------------------
00451 
00452 void 
00453 RandomInit(unsigned seed)
00454 {
00455     srand(seed);
00456 }
00457 
00458 //----------------------------------------------------------------------
00459 // Random
00460 //      Return a pseudo-random number.
00461 //----------------------------------------------------------------------
00462 
00463 int 
00464 Random()
00465 {
00466     return rand();
00467 }
00468 
00469 //----------------------------------------------------------------------
00470 // AllocBoundedArray
00471 //      Return an array, with the two pages just before 
00472 //      and after the array unmapped, to catch illegal references off
00473 //      the end of the array.  Particularly useful for catching overflow
00474 //      beyond fixed-size thread execution stacks.
00475 //
00476 //      Note: Just return the useful part!
00477 //
00478 //      "size" -- amount of useful space needed (in bytes)
00479 //----------------------------------------------------------------------
00480 
00481 char * 
00482 AllocBoundedArray(int size)
00483 {
00484     int pgSize = getpagesize();
00485     char *ptr = new char[pgSize * 2 + size];
00486 
00487     mprotect(ptr, pgSize, 0);
00488     mprotect(ptr + pgSize + size, pgSize, 0);
00489     return ptr + pgSize;
00490 }
00491 
00492 //----------------------------------------------------------------------
00493 // DeallocBoundedArray
00494 //      Deallocate an array of integers, unprotecting its two boundary pages.
00495 //
00496 //      "ptr" -- the array to be deallocated
00497 //      "size" -- amount of useful space in the array (in bytes)
00498 //----------------------------------------------------------------------
00499 
00500 void 
00501 DeallocBoundedArray(char *ptr, int size)
00502 {
00503     int pgSize = getpagesize();
00504 
00505     mprotect(ptr - pgSize, pgSize, PROT_READ | PROT_WRITE | PROT_EXEC);
00506     mprotect(ptr + size, pgSize, PROT_READ | PROT_WRITE | PROT_EXEC);
00507     delete [] (ptr - pgSize);
00508 }

Generated on Mon Feb 10 09:54:47 2003 for nachos by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002
The University of Southern California does not screen or control the content on this website and thus does not guarantee the accuracy, integrity, or quality of such content. All content on this website is provided by and is the sole responsibility of the person from which such content originated, and such content does not necessarily reflect the opinions of the University administration or the Board of Trustees