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

Generated on Thu Sep 16 12:33:45 2004 for NachOS by doxygen 1.3.8