UnixOperatingSystem.st
changeset 6340 65183f0db451
parent 6334 cbb0e8c8c1a5
child 6343 3e35a55af7c5
--- a/UnixOperatingSystem.st	Tue Dec 18 21:49:04 2001 +0100
+++ b/UnixOperatingSystem.st	Wed Dec 19 13:01:26 2001 +0100
@@ -3555,11 +3555,11 @@
             __HANDLE_INTERRUPTS__;
             goto again;
         } else {
-            error = __MKSMALLINT(errno);
+            error = __mkSmallInteger(errno);
             goto err;
         }
     }
-    fileDescriptor = __MKSMALLINT(fd);
+    fileDescriptor = __mkSmallInteger(fd);
 err:;
 %}.
     ^ fileDescriptor notNil ifTrue:[
@@ -9284,7 +9284,7 @@
 
 !UnixOperatingSystem::FileDescriptorHandle methodsFor:'misc functions'!
 
-readCheck
+canReadWithoutBlocking
     "return true, if data is available on a filedescriptor 
      (i.e. read is possible without blocking).
      This depends on a working select or FIONREAD to be provided by the OS."
@@ -9349,12 +9349,78 @@
         ^ true
     ].
 
-    (OperatingSystem selectOnAnyReadable:(Array with:fd)
-                     writable:nil
-                    exception:nil
-                  withTimeOut:0) == fd
-        ifTrue:[^ true].
-    ^ false
+    ^ (OperatingSystem selectOnAnyReadable:(Array with:fd)
+                       writable:nil
+                       exception:nil
+                       withTimeOut:0) == fd
+!
+
+seekTo:newPosition from:whence
+    "seek to newPosition
+     whence is one of: #begin #current #end.
+     Return the new position.
+
+     TODO: 64 bit handling"
+
+    |error|
+
+%{
+    INT fd, pos, ret;
+    INT __whence;
+    __uint64__ pos64;
+
+    if (! __isSmallInteger(__INST(fd))) {
+        error = @symbol(errorNotOpen);
+        goto bad;
+    }
+    if (__isSmallInteger(newPosition)) {
+        pos = __smallIntegerVal(newPosition);
+    } else if (__signedLong64IntVal(newPosition, &pos64) == 0) {
+        error = @symbol(badArgument1);
+        goto bad;
+    }
+    fd = __smallIntegerVal(__INST(fd));
+    if (fd < 0) {
+        error = @symbol(internalError);
+        goto bad;
+    }
+    if (whence == @symbol(begin)) {
+        __whence = SEEK_SET;    
+    } else if (whence == @symbol(current)) {
+        __whence = SEEK_CUR;    
+    } else if (whence == @symbol(end)) {
+        __whence = SEEK_END;    
+    } else {
+        error = @symbol(badArgument2);
+        goto bad;
+    }
+
+again:
+    ret = lseek(fd, pos, __whence);
+    if (ret < 0) {
+        if (errno == EINTR) {
+            __HANDLE_INTERRUPTS__;
+            goto again;
+        }
+        error = __mkSmallInteger(errno);
+        goto bad;
+    }
+    /* RETURN (__mkInteger(ret)); */
+    RETURN (__mkSmallInteger(ret));
+
+bad: ;   
+%}.
+    ^ self error:error.
+
+    "
+     |h buff n|
+
+     h := OperatingSystem openFileForRead:'/etc/hosts'.
+     h seekTo:10 from:#begin.
+     buff := ByteArray new:1000. buff inspect.
+     n := h readBytes:1000 into:buff startingAt:1.
+     Transcript show:n; space; showCR:buff asString.
+    "
 !
 
 selectWithTimeOut:millis
@@ -9421,28 +9487,6 @@
     ^ self primitiveFailed
 
 
-!
-
-writeCheck
-    "return true, if filedescriptor can be written without blocking"
-
-    OperatingSystem supportsSelect ifFalse:[
-        "/ mhmh - what should we do then ?
-        "/ For now, return true as if data was present,
-        "/ and let the thread fall into the write.
-        "/ It will then (hopefully) be desceduled there and
-        "/ effectively polling for output.
-        ^ true
-    ].
-
-    (OperatingSystem selectOnAnyReadable:nil
-                     writable:(Array with:fd)
-                    exception:nil
-                  withTimeOut:0) == fd
-        ifTrue:[^ true].
-    ^ false
-
-    "Created: 1.10.1997 / 08:49:24 / stefan"
 ! !
 
 !UnixOperatingSystem::FileDescriptorHandle methodsFor:'private accessing'!
@@ -9460,6 +9504,24 @@
 
 !UnixOperatingSystem::FileDescriptorHandle methodsFor:'queries'!
 
+canWriteWithoutBlocking
+    "return true, if filedescriptor can be written without blocking"
+
+    OperatingSystem supportsSelect ifFalse:[
+        "/ mhmh - what should we do then ?
+        "/ For now, return true as if data was present,
+        "/ and let the thread fall into the write.
+        "/ It will then (hopefully) be desceduled there and
+        "/ effectively polling for output.
+        ^ true
+    ].
+
+    ^ (OperatingSystem selectOnAnyReadable:nil
+                       writable:(Array with:fd)
+                       exception:nil
+                       withTimeOut:0) == fd
+!
+
 isValid
     "answer true, if the handle is valid, i.e. connected to
      a file or some other OS object"
@@ -9506,10 +9568,78 @@
     "Modified: 30.9.1997 / 12:42:16 / stefan"
 ! !
 
+!UnixOperatingSystem::FileDescriptorHandle methodsFor:'waiting'!
+
+readWaitWithTimeoutMs:timeout 
+    "suspend the current process, until the receiver
+     becomes ready for reading or a timeout (in milliseconds) expired. 
+     If data is already available, return immediate. 
+     Return true if a timeout occured (i.e. false, if data is available).
+     The other threads are not affected by the wait."
+
+    |inputSema hasData wasBlocked|
+
+    fd isNil ifTrue:[^ self error:#errorNotOpen].
+
+    wasBlocked := OperatingSystem blockInterrupts.
+    hasData := self canReadWithoutBlocking.
+    hasData ifFalse:[
+        inputSema := Semaphore new name:'readWait'.
+        [
+            timeout notNil ifTrue:[
+                Processor signal:inputSema afterMilliseconds:timeout 
+            ].
+            Processor signal:inputSema onInput:fd.
+            Processor activeProcess state:#ioWait.
+            inputSema wait.
+            Processor disableSemaphore:inputSema.
+            hasData := self canReadWithoutBlocking.
+        ] ifCurtailed:[
+            Processor disableSemaphore:inputSema.
+            wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
+        ]
+    ].
+    wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
+    ^ hasData not
+!
+
+writeWaitWithTimeoutMs:timeout
+    "suspend the current process, until the receiver
+     becomes ready for writing or a timeout (in seconds) expired. 
+     Return true if a timeout occured (i.e. false, if data is available).
+     Return immediate if the receiver is already ready. 
+     The other threads are not affected by the wait."
+
+    |fd outputSema canWrite wasBlocked|
+
+    fd isNil ifTrue:[^ self error:#errorNotOpen].
+
+    wasBlocked := OperatingSystem blockInterrupts.
+    canWrite := self canWriteWithoutBlocking.
+    canWrite ifFalse:[
+        outputSema := Semaphore new name:'writeWait'.
+        [
+            timeout notNil ifTrue:[
+                Processor signal:outputSema afterMilliseconds:timeout
+            ].
+            Processor signal:outputSema onOutput:fd.
+            Processor activeProcess state:#ioWait.
+            outputSema wait.
+            Processor disableSemaphore:outputSema.
+            canWrite := self canWriteWithoutBlocking.
+        ] ifCurtailed:[
+            Processor disableSemaphore:outputSema.
+            wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
+        ]
+    ].
+    wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
+    ^ canWrite not
+! !
+
 !UnixOperatingSystem::FilePointerHandle class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libbasic/UnixOperatingSystem.st,v 1.105 2001-12-18 13:12:38 stefan Exp $'
+    ^ '$Header: /cvs/stx/stx/libbasic/UnixOperatingSystem.st,v 1.106 2001-12-19 12:01:26 stefan Exp $'
 ! !
 
 !UnixOperatingSystem::FilePointerHandle methodsFor:'release'!
@@ -9821,6 +9951,6 @@
 !UnixOperatingSystem class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libbasic/UnixOperatingSystem.st,v 1.105 2001-12-18 13:12:38 stefan Exp $'
+    ^ '$Header: /cvs/stx/stx/libbasic/UnixOperatingSystem.st,v 1.106 2001-12-19 12:01:26 stefan Exp $'
 ! !
 UnixOperatingSystem initialize!