Page principale | Liste des namespaces | Hiérarchie des classes | Liste des classes | Répertoires | Liste des fichiers | Membres de namespace | Membres de classe | Membres de fichier

sysdep.cc

Aller à la documentation de ce fichier.
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-1996 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 #include "debug.h"
00028 #include "sysdep.h"
00029 #include "stdlib.h"
00030 #include "unistd.h"
00031 #include "sys/time.h"
00032 #include "sys/file.h"
00033 #include <sys/socket.h>
00034 #include <sys/un.h>
00035 
00036 #ifdef SOLARIS
00037 // KMS
00038 // for open()
00039 #include <fcntl.h>
00040 #endif
00041 
00042 #ifdef LINUX     // at this point, linux doesn't support mprotect 
00043 #define NO_MPROT     
00044 #endif
00045 #ifdef DOS      // neither does DOS
00046 #define NO_MPROT
00047 #endif
00048 
00049 extern "C" {
00050 #include <signal.h>
00051 #include <sys/types.h>
00052 
00053 #ifndef NO_MPROT 
00054 #include <sys/mman.h>
00055 #endif
00056 
00057 // UNIX routines called by procedures in this file 
00058 
00059 #if defined CYGWIN
00060   size_t getpagesize(void);
00061 #else
00062  int getpagesize(void);
00063 #endif
00064 unsigned sleep(unsigned);
00065 //#ifdef SOLARIS
00066 //int usleep(useconds_t);
00067 //#else
00068 //void usleep(unsigned int);  // rcgood - to avoid spinning processes.
00069 //#endif
00070 
00071 
00072 #ifndef NO_MPROT        
00073 
00074 #ifdef OSF
00075 #define OSF_OR_AIX
00076 #endif
00077 #ifdef AIX
00078 #define OSF_OR_AIX
00079 #endif
00080 
00081 #ifdef OSF_OR_AIX
00082 int mprotect(const void *, long unsigned int, int);
00083 #else
00084 int mprotect(char *, unsigned int, int);
00085 #endif
00086 #endif
00087 
00088 #if defined(BSD) || defined(SOLARIS) || defined(LINUX)
00089 //KMS
00090 // added Solaris and LINUX
00091 int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
00092              struct timeval *timeout);
00093 #else
00094 int select(int numBits, void *readFds, void *writeFds, void *exceptFds, 
00095         struct timeval *timeout);
00096 #endif
00097 
00098 int socket(int, int, int);
00099 
00100 #if defined(SUNOS) || defined(ULTRIX)
00101 long tell(int);
00102 int bind (int, const void*, int);
00103 int recvfrom (int, void*, int, int, void*, int *);
00104 int sendto (int, const void*, int, int, void*, int);
00105 #endif
00106 
00107 }
00108 
00109 //----------------------------------------------------------------------
00110 // CallOnUserAbort
00111 //      Arrange that "func" will be called when the user aborts (e.g., by
00112 //      hitting ctl-C.
00113 //----------------------------------------------------------------------
00114 
00115 void 
00116 CallOnUserAbort(void (*func)(int))
00117 {
00118     (void)signal(SIGINT, func);
00119 }
00120 
00121 //----------------------------------------------------------------------
00122 // RegisterSignal
00123 //      Arrange that "func" will be called when NachOS get a signal from
00124 //      the host operating system.
00125 //----------------------------------------------------------------------
00126 
00127 void 
00128 RegisterSignalHandler(void (*func)(int), int sig)
00129 {
00130     (void)signal(sig, func);
00131 }
00132 
00133 //----------------------------------------------------------------------
00134 // Delay
00135 //      Put the UNIX process running Nachos to sleep for x seconds,
00136 //      to give the user time to start up another invocation of Nachos
00137 //      in a different UNIX shell.
00138 //----------------------------------------------------------------------
00139 
00140 void 
00141 Delay(int seconds)
00142 {
00143     (void) sleep((unsigned) seconds);
00144 }
00145 
00146 //----------------------------------------------------------------------
00147 // UDelay
00148 //      Put the UNIX process running Nachos to sleep for x microseconds,
00149 //      to prevent an idle Nachos process from spinning...
00150 //----------------------------------------------------------------------
00151 
00152 void 
00153 UDelay(unsigned int useconds)
00154 {
00155 //#ifdef SOLARIS
00156 //   usleep(useconds_t useconds);
00157 //#else
00158 //   usleep(useconds);
00159 //#endif /* SOLARIS */
00160 
00161 }
00162 
00163 //----------------------------------------------------------------------
00164 // Abort
00165 //      Quit and drop core.
00166 //----------------------------------------------------------------------
00167 
00168 void 
00169 Abort()
00170 {
00171     abort();
00172 }
00173 
00174 //----------------------------------------------------------------------
00175 // Exit
00176 //      Quit without dropping core.
00177 //----------------------------------------------------------------------
00178 
00179 void 
00180 Exit(int exitCode)
00181 {
00182     exit(exitCode);
00183 }
00184 
00185 //----------------------------------------------------------------------
00186 // RandomInit
00187 //      Initialize the pseudo-random number generator.  We use the
00188 //      now obsolete "srand" and "rand" because they are more portable!
00189 //----------------------------------------------------------------------
00190 
00191 void 
00192 RandomInit(unsigned seed)
00193 {
00194     srand(seed);
00195 }
00196 
00197 //----------------------------------------------------------------------
00198 // RandomNumber
00199 //      Return a pseudo-random number.
00200 //----------------------------------------------------------------------
00201 
00202 unsigned int 
00203 RandomNumber()
00204 {
00205     return rand();
00206 }
00207 
00208 //----------------------------------------------------------------------
00209 // AllocBoundedArray
00210 //      Return an array, with the two pages just before 
00211 //      and after the array unmapped, to catch illegal references off
00212 //      the end of the array.  Particularly useful for catching overflow
00213 //      beyond fixed-size thread execution stacks.
00214 //
00215 //      Note: Just return the useful part!
00216 //
00217 //      "size" -- amount of useful space needed (in bytes)
00218 //----------------------------------------------------------------------
00219 
00220 char * 
00221 AllocBoundedArray(int size)
00222 {
00223 #ifdef NO_MPROT
00224     return new char[size];
00225 #else
00226     int pgSize = getpagesize();
00227     char *ptr = new char[pgSize * 2 + size];
00228 
00229     mprotect(ptr, pgSize, 0);
00230     mprotect(ptr + pgSize + size, pgSize, 0);
00231     return ptr + pgSize;
00232 #endif
00233 }
00234 
00235 //----------------------------------------------------------------------
00236 // DeallocBoundedArray
00237 //      Deallocate an array of integers, unprotecting its two boundary pages.
00238 //
00239 //      "ptr" -- the array to be deallocated
00240 //      "size" -- amount of useful space in the array (in bytes)
00241 //----------------------------------------------------------------------
00242 
00243 #ifdef NO_MPROT
00244 void 
00245 DeallocBoundedArray(char *ptr, int /* size */)
00246 {
00247     delete [] ptr;
00248 }
00249 #else
00250 void 
00251 DeallocBoundedArray(char *ptr, int size)
00252 {
00253     int pgSize = getpagesize();
00254 
00255     mprotect(ptr - pgSize, pgSize, PROT_READ | PROT_WRITE | PROT_EXEC);
00256     mprotect(ptr + size, pgSize, PROT_READ | PROT_WRITE | PROT_EXEC);
00257     delete [] (ptr - pgSize);
00258 }
00259 #endif
00260 
00261 //----------------------------------------------------------------------
00262 // PollFile
00263 //      Check open file or open socket to see if there are any 
00264 //      characters that can be read immediately.  If so, read them
00265 //      in, and return TRUE.
00266 //
00267 //      "fd" -- the file descriptor of the file to be polled
00268 //----------------------------------------------------------------------
00269 
00270 bool
00271 PollFile(int fd)
00272 {
00273 #if defined(SOLARIS) || defined(LINUX)
00274 // KMS
00275     fd_set rfd,wfd,xfd;
00276 #else
00277     int rfd = (1 << fd), wfd = 0, xfd = 0;
00278 #endif
00279     int retVal;
00280     struct timeval pollTime;
00281 
00282 #if defined(SOLARIS) || defined(LINUX)
00283 // KMS
00284     FD_ZERO(&rfd);
00285     FD_ZERO(&wfd);
00286     FD_ZERO(&xfd);
00287     FD_SET(fd,&rfd);
00288 #endif
00289 
00290 // don't wait if there are no characters on the file
00291     pollTime.tv_sec = 0;
00292     pollTime.tv_usec = 0;
00293 
00294 // poll file or socket
00295 #if defined(BSD)
00296     retVal = select(32, (fd_set*)&rfd, (fd_set*)&wfd, (fd_set*)&xfd, &pollTime);
00297 #elif defined(SOLARIS) || defined(LINUX)
00298     // KMS
00299     retVal = select(32, &rfd, &wfd, &xfd, &pollTime);
00300 #else
00301     retVal = select(32, &rfd, &wfd, &xfd, &pollTime);
00302 #endif
00303 
00304     ASSERT((retVal == 0) || (retVal == 1));
00305     if (retVal == 0)
00306         return FALSE;                           // no char waiting to be read
00307     return TRUE;
00308 }
00309 
00310 //----------------------------------------------------------------------
00311 // OpenForWrite
00312 //      Open a file for writing.  Create it if it doesn't exist; truncate it 
00313 //      if it does already exist.  Return the file descriptor.
00314 //
00315 //      "name" -- file name
00316 //----------------------------------------------------------------------
00317 
00318 int
00319 OpenForWrite(char *name)
00320 {
00321     int fd = open(name, O_RDWR|O_CREAT|O_TRUNC, 0666);
00322 
00323     ASSERT(fd >= 0); 
00324     return fd;
00325 }
00326 
00327 //----------------------------------------------------------------------
00328 // OpenForReadWrite
00329 //      Open a file for reading or writing.
00330 //      Return the file descriptor, or error if it doesn't exist.
00331 //
00332 //      "name" -- file name
00333 //----------------------------------------------------------------------
00334 
00335 int
00336 OpenForReadWrite(char *name, bool crashOnError)
00337 {
00338     int fd = open(name, O_RDWR, 0);
00339 
00340     ASSERT(!crashOnError || fd >= 0);
00341     return fd;
00342 }
00343 
00344 //----------------------------------------------------------------------
00345 // Read
00346 //      Read characters from an open file.  Abort if read fails.
00347 //----------------------------------------------------------------------
00348 
00349 void
00350 Read(int fd, char *buffer, int nBytes)
00351 {
00352     int retVal = read(fd, buffer, nBytes);
00353     ASSERT(retVal == nBytes);
00354 }
00355 
00356 //----------------------------------------------------------------------
00357 // ReadPartial
00358 //      Read characters from an open file, returning as many as are
00359 //      available.
00360 //----------------------------------------------------------------------
00361 
00362 int
00363 ReadPartial(int fd, char *buffer, int nBytes)
00364 {
00365     return read(fd, buffer, nBytes);
00366 }
00367 
00368 
00369 //----------------------------------------------------------------------
00370 // WriteFile
00371 //      Write characters to an open file.  Abort if write fails.
00372 //----------------------------------------------------------------------
00373 
00374 void
00375 WriteFile(int fd, char *buffer, int nBytes)
00376 {
00377     int retVal = write(fd, buffer, nBytes);
00378     ASSERT(retVal == nBytes);
00379 }
00380 
00381 //----------------------------------------------------------------------
00382 // Lseek
00383 //      Change the location within an open file.  Abort on error.
00384 //----------------------------------------------------------------------
00385 
00386 void 
00387 Lseek(int fd, int offset, int whence)
00388 {
00389     int retVal = lseek(fd, offset, whence);
00390     ASSERT(retVal >= 0);
00391 }
00392 
00393 //----------------------------------------------------------------------
00394 // Tell
00395 //      Report the current location within an open file.
00396 //----------------------------------------------------------------------
00397 
00398 int 
00399 Tell(int fd)
00400 {
00401 #if defined(BSD) || defined(SOLARIS) || defined(LINUX)
00402     return lseek(fd,0,SEEK_CUR); // 386BSD doesn't have the tell() system call
00403                                  // neither do Solaris and Linux  -KMS
00404 #else
00405     return tell(fd);
00406 #endif
00407 }
00408 
00409 
00410 //----------------------------------------------------------------------
00411 // Close
00412 //      Close a file.  Abort on error.
00413 //----------------------------------------------------------------------
00414 
00415 int 
00416 Close(int fd)
00417 {
00418     int retVal = close(fd);
00419     ASSERT(retVal >= 0); 
00420     return retVal;
00421 }
00422 
00423 //----------------------------------------------------------------------
00424 // Unlink
00425 //      Delete a file.
00426 //----------------------------------------------------------------------
00427 
00428 bool 
00429 Unlink(char *name)
00430 {
00431     return unlink(name);
00432 }
00433 
00434 //----------------------------------------------------------------------
00435 // OpenSocket
00436 //      Open an interprocess communication (IPC) connection.  For now, 
00437 //      just open a datagram port where other Nachos (simulating 
00438 //      workstations on a network) can send messages to this Nachos.
00439 //----------------------------------------------------------------------
00440 
00441 int
00442 OpenSocket()
00443 {
00444     int sockID;
00445     
00446     sockID = socket(AF_UNIX, SOCK_DGRAM, 0);
00447     ASSERT(sockID >= 0);
00448 
00449     return sockID;
00450 }
00451 
00452 //----------------------------------------------------------------------
00453 // CloseSocket
00454 //      Close the IPC connection. 
00455 //----------------------------------------------------------------------
00456 
00457 void
00458 CloseSocket(int sockID)
00459 {
00460     (void) close(sockID);
00461 }
00462 
00463 //----------------------------------------------------------------------
00464 // InitSocketName
00465 //      Initialize a UNIX socket address -- magical!
00466 //----------------------------------------------------------------------
00467 
00468 static void 
00469 InitSocketName(struct sockaddr_un *uname, char *name)
00470 {
00471     uname->sun_family = AF_UNIX;
00472     strcpy(uname->sun_path, name);
00473 }
00474 
00475 //----------------------------------------------------------------------
00476 // AssignNameToSocket
00477 //      Give a UNIX file name to the IPC port, so other instances of Nachos
00478 //      can locate the port. 
00479 //----------------------------------------------------------------------
00480 
00481 void
00482 AssignNameToSocket(char *socketName, int sockID)
00483 {
00484     struct sockaddr_un uName;
00485     int retVal;
00486 
00487     (void) unlink(socketName);    // in case it's still around from last time
00488 
00489     InitSocketName(&uName, socketName);
00490     retVal = bind(sockID, (struct sockaddr *) &uName, sizeof(uName));
00491     ASSERT(retVal >= 0);
00492     DEBUG(dbgNet, "Created socket " << socketName);
00493 }
00494 
00495 //----------------------------------------------------------------------
00496 // DeAssignNameToSocket
00497 //      Delete the UNIX file name we assigned to our IPC port, on cleanup.
00498 //----------------------------------------------------------------------
00499 void
00500 DeAssignNameToSocket(char *socketName)
00501 {
00502     (void) unlink(socketName);
00503 }
00504 
00505 //----------------------------------------------------------------------
00506 // PollSocket
00507 //      Return TRUE if there are any messages waiting to arrive on the
00508 //      IPC port.
00509 //----------------------------------------------------------------------
00510 bool
00511 PollSocket(int sockID)
00512 {
00513     return PollFile(sockID);    // on UNIX, socket ID's are just file ID's
00514 }
00515 
00516 //----------------------------------------------------------------------
00517 // ReadFromSocket
00518 //      Read a fixed size packet off the IPC port.  Abort on error.
00519 //----------------------------------------------------------------------
00520 void
00521 ReadFromSocket(int sockID, char *buffer, int packetSize)
00522 {
00523     int retVal;
00524 #if defined(__GNUC__) && __GNUC__ < 3
00525     extern int errno;
00526 #endif
00527     struct sockaddr_un uName;
00528 #ifdef LINUX
00529     socklen_t size = sizeof(uName);
00530 #else
00531     int size = sizeof(uName);
00532 #endif
00533    
00534     retVal = recvfrom(sockID, buffer, packetSize, 0,
00535                                    (struct sockaddr *) &uName, &size);
00536 
00537     if (retVal != packetSize) {
00538         perror("in recvfrom");
00539 #if defined (CYGWIN) || (__GNUC__ >= 3)
00540         cerr << "called with " << packetSize << ", got back " << retVal 
00541                                                 << ", and " << "\n";
00542 #else   
00543         cerr << "called with " << packetSize << ", got back " << retVal 
00544                                                 << ", and " << errno << "\n";
00545 #endif 
00546     }
00547     ASSERT(retVal == packetSize);
00548 }
00549 
00550 //----------------------------------------------------------------------
00551 //    modified by KMS to add retry...
00552 // SendToSocket
00553 //      Transmit a fixed size packet to another Nachos' IPC port.
00554 //      Try 10 times with a one second delay between attempts.
00555 //      This is useful, e.g., to give the other socket a chance
00556 //      to get set up.
00557 //      Terminate if we still fail after 10 tries.
00558 //----------------------------------------------------------------------
00559 void
00560 SendToSocket(int sockID, char *buffer, int packetSize, char *toName)
00561 {
00562     struct sockaddr_un uName;
00563     int retVal;
00564     int retryCount;
00565 
00566     InitSocketName(&uName, toName);
00567 
00568     for(retryCount=0;retryCount < 10;retryCount++) {
00569       retVal = sendto(sockID, buffer, packetSize, 0, 
00570                         (struct sockaddr *) &uName, sizeof(uName));
00571       if (retVal == packetSize) return;
00572       // if we did not succeed, we should see a negative
00573       // return value indicating complete failure.  If we
00574       // don't, something fishy is going on...
00575       ASSERT(retVal < 0);
00576       // wait a second before trying again
00577       Delay(1);
00578     }
00579     // At this point, we have failed many times
00580     // The most common reason for this is that the target machine
00581     // has halted and its socket no longer exists.
00582     // We simply do nothing (drop the packet).
00583     // This may mask other kinds of failures, but it is the
00584     // right thing to do in the common case.
00585 }

Généré le Sun Jan 15 00:45:46 2006 pour Système NachOS : par  doxygen 1.4.4