001/*
002 *  This file is part of the Jikes RVM project (http://jikesrvm.org).
003 *
004 *  This file is licensed to You under the Eclipse Public License (EPL);
005 *  You may not use this file except in compliance with the License. You
006 *  may obtain a copy of the License at
007 *
008 *      http://www.opensource.org/licenses/eclipse-1.0.php
009 *
010 *  See the COPYRIGHT.txt file distributed with this work for information
011 *  regarding copyright ownership.
012 */
013package org.jikesrvm.runtime;
014
015import java.io.BufferedInputStream;
016import java.io.BufferedOutputStream;
017import java.io.FileDescriptor;
018import java.io.FileInputStream;
019import java.io.FileOutputStream;
020import java.io.PrintStream;
021import org.jikesrvm.VM;
022import org.jikesrvm.scheduler.RVMThread;
023import static org.jikesrvm.runtime.SysCall.sysCall;
024import org.vmmagic.pragma.NoInline;
025import org.vmmagic.pragma.NoOptCompile;
026import org.vmmagic.pragma.BaselineSaveLSRegisters;
027import org.vmmagic.pragma.Unpreemptible;
028
029/**
030 * Interface to filesystem of underlying operating system.  Historically
031 * this has provided a blocking IO abstraction on top of non-blocking IO,
032 * which was necessary for green threads.  The current code contains only
033 * abstractions for dealing with things like file status.
034 */
035public class FileSystem {
036
037  /**
038   * Read single byte from file.
039   *
040   * @param fd file descriptor
041   * @return byte that was read (< -2: i/o error, -2: timeout, -1: eof, >= 0: data)
042   */
043  @NoInline
044  @NoOptCompile
045  @BaselineSaveLSRegisters
046  @Unpreemptible
047  public static int readByte(int fd) {
048    RVMThread.saveThreadState();
049    RVMThread.enterNative();
050    int result = sysCall.sysReadByte(fd);
051    RVMThread.leaveNative();
052    return result;
053  }
054
055  /**
056   * Write single byte to file
057   *
058   * @param fd file descriptor
059   * @param b  byte to be written
060   * @return  -2: i/o error, -1: timeout, 0: ok
061   */
062  @NoInline
063  @NoOptCompile
064  @BaselineSaveLSRegisters
065  @Unpreemptible
066  public static int writeByte(int fd, int b) {
067    RVMThread.saveThreadState();
068    RVMThread.enterNative();
069    int result = sysCall.sysWriteByte(fd,b);
070    RVMThread.leaveNative();
071    return result;
072  }
073
074  /**
075   * Reads multiple bytes.
076   *
077   * @param fd the file descriptor for the file that should be read from
078   * @param buf a pinned byte array to read into
079   * @param off the offset in the buffer to read into
080   * @param cnt the number of bytes to read
081   * @return -2: i/o error, -1: timeout, >=0: number of bytes read
082   */
083  @NoInline
084  @NoOptCompile
085  @BaselineSaveLSRegisters
086  @Unpreemptible
087  public static int readBytes(int fd, byte[] buf, int off, int cnt) {
088    RVMThread.saveThreadState();
089    RVMThread.enterNative();
090    int result = sysCall.sysReadBytes(fd,Magic.objectAsAddress(buf).plus(off),cnt);
091    RVMThread.leaveNative();
092    return result;
093  }
094
095  /**
096   * Writes multiple bytes.
097   *
098   * @param fd the file descriptor for the file that should be written to
099   * @param buf a pinned byte array to write from
100   * @param off the offset in the buffer to start writing from
101   * @param cnt the number of bytes to write
102   * @return -2: i/o error, -1: timeout, >=0: number of bytes written
103   */
104  @NoInline
105  @NoOptCompile
106  @BaselineSaveLSRegisters
107  @Unpreemptible
108  public static int writeBytes(int fd, byte[] buf, int off, int cnt) {
109    RVMThread.saveThreadState();
110    RVMThread.enterNative();
111    int result = sysCall.sysWriteBytes(fd,Magic.objectAsAddress(buf).plus(off),cnt);
112    RVMThread.leaveNative();
113    return result;
114  }
115
116  // not sure if this is the right place to have this.
117  /**
118   * Called from VM.boot to set up java.lang.System.in, java.lang.System.out,
119   * and java.lang.System.err
120   */
121  public static void initializeStandardStreams() {
122    FileInputStream fdIn = new FileInputStream(FileDescriptor.in);
123    FileOutputStream fdOut = new FileOutputStream(FileDescriptor.out);
124    FileOutputStream fdErr = new FileOutputStream(FileDescriptor.err);
125    System.setIn(new BufferedInputStream(fdIn));
126    System.setOut(new PrintStream(new BufferedOutputStream(fdOut, 128), true));
127    System.setErr(new PrintStream(new BufferedOutputStream(fdErr, 128), true));
128    Callbacks.addExitMonitor(new Callbacks.ExitMonitor() {
129      @Override
130      public void notifyExit(int value) {
131        try {
132          System.err.flush();
133          System.out.flush();
134        } catch (Throwable e) {
135          VM.sysWriteln("vm: error flushing stdout, stderr");
136          e.printStackTrace();
137        }
138      }
139    });
140  }
141}
142
143