--- a/ProcessorScheduler.st Tue Jul 15 14:19:45 2003 +0200
+++ b/ProcessorScheduler.st Tue Jul 15 16:03:28 2003 +0200
@@ -626,7 +626,7 @@
handle all timeout actions
"
anyTimeouts ifTrue:[
- self evaluateTimeouts
+ self evaluateTimeouts
].
"first do a quick check for semaphores using checkActions - this is needed for
@@ -639,42 +639,42 @@
any := false.
nActions := readCheckArray size.
1 to:nActions do:[:index |
- checkBlock := readCheckArray at:index.
- (checkBlock notNil and:[checkBlock value]) ifTrue:[
- sema := readSemaphoreArray at:index.
- sema notNil ifTrue:[
- sema signalOnce.
- ].
- any := true.
- ]
+ checkBlock := readCheckArray at:index.
+ (checkBlock notNil and:[checkBlock value]) ifTrue:[
+ sema := readSemaphoreArray at:index.
+ sema notNil ifTrue:[
+ sema signalOnce.
+ ].
+ any := true.
+ ]
].
nActions := writeCheckArray size.
1 to:nActions do:[:index |
- checkBlock := writeCheckArray at:index.
- (checkBlock notNil and:[checkBlock value]) ifTrue:[
- sema := writeSemaphoreArray at:index.
- sema notNil ifTrue:[
- sema signalOnce.
- ].
- any := true.
- ]
+ checkBlock := writeCheckArray at:index.
+ (checkBlock notNil and:[checkBlock value]) ifTrue:[
+ sema := writeSemaphoreArray at:index.
+ sema notNil ifTrue:[
+ sema signalOnce.
+ ].
+ any := true.
+ ]
].
"now, someone might be runnable ..."
p := self highestPriorityRunnableProcess.
p isNil ifTrue:[
- "/ no one runnable, hard wait for event or timeout
-
- self waitForEventOrTimeout.
-
- "/ check for OS process termination
- gotChildSignalInterrupt ifTrue:[
- gotChildSignalInterrupt := false.
- self handleChildSignalInterrupt
- ].
- wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
- ^ self
+ "/ no one runnable, hard wait for event or timeout
+
+ self waitForEventOrTimeout.
+
+ "/ check for OS process termination
+ gotChildSignalInterrupt ifTrue:[
+ gotChildSignalInterrupt := false.
+ self handleChildSignalInterrupt
+ ].
+ wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
+ ^ self
].
pri := p priority.
@@ -705,13 +705,13 @@
"
pri < TimingPriority ifTrue:[
- anyTimeouts ifTrue:[
- millis := self timeToNextTimeout.
- millis == 0 ifTrue:[
- wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
- ^ self
- ]
- ]
+ anyTimeouts ifTrue:[
+ millis := self timeToNextTimeout.
+ millis == 0 ifTrue:[
+ wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
+ ^ self
+ ]
+ ]
].
"
@@ -724,37 +724,37 @@
pri < UserInterruptPriority ifTrue:[
"comment out this if above is uncommented"
- anyTimeouts ifTrue:[
- millis := self timeToNextTimeout.
- millis == 0 ifTrue:[
- wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
- ^ self
- ].
- ].
+ anyTimeouts ifTrue:[
+ millis := self timeToNextTimeout.
+ millis == 0 ifTrue:[
+ wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
+ ^ self
+ ].
+ ].
"---"
- useIOInterrupts ifTrue:[
+ useIOInterrupts ifTrue:[
"/ readFdArray do:[:fd |
"/ (fd notNil and:[fd >= 0]) ifTrue:[
"/ OperatingSystem enableIOInterruptsOn:fd
"/ ].
"/ ].
- ] ifFalse:[
- millis notNil ifTrue:[
- millis := millis min:EventPollingInterval
- ] ifFalse:[
- millis := EventPollingInterval
- ]
- ]
+ ] ifFalse:[
+ millis notNil ifTrue:[
+ millis := millis min:EventPollingInterval
+ ] ifFalse:[
+ millis := EventPollingInterval
+ ]
+ ]
].
millis notNil ifTrue:[
- "schedule a clock interrupt after millis milliseconds"
- OperatingSystem enableTimer:millis rounded.
+ "schedule a clock interrupt after millis milliseconds"
+ OperatingSystem enableTimer:millis rounded.
].
scheduledProcesses notNil ifTrue:[
- scheduledProcesses add:p
+ scheduledProcesses add:p
].
"
@@ -764,17 +764,17 @@
self threadSwitch:p.
"... when we arrive here, we are back on stage.
- Either by an ALARM or IO signal, or by a suspend of another process
+ Either by an ALARM or IO signal, or by a suspend of another process
"
millis notNil ifTrue:[
- OperatingSystem disableTimer.
+ OperatingSystem disableTimer.
].
"/ check for OS process termination
gotChildSignalInterrupt ifTrue:[
- gotChildSignalInterrupt := false.
- self handleChildSignalInterrupt
+ gotChildSignalInterrupt := false.
+ self handleChildSignalInterrupt
].
"/ check for new input
@@ -782,8 +782,8 @@
OperatingSystem unblockInterrupts.
(gotIOInterrupt or:[useIOInterrupts not]) ifTrue:[
- gotIOInterrupt := false.
- self checkForInputWithTimeout:0.
+ gotIOInterrupt := false.
+ self checkForIOWithTimeout:0.
].
wasBlocked ifTrue:[OperatingSystem blockInterrupts].
@@ -2909,11 +2909,13 @@
!ProcessorScheduler methodsFor:'waiting'!
-checkForInputWithTimeout:millis
+checkForIOWithTimeout:millis
"this is called, when there is absolutely nothing to do;
- hard wait for either input to arrive or a timeout to occur."
-
- |nSelected index sema action wasBlocked err resultFdArray newProcessMaybeReady|
+ hard wait for either input to arrive, or output to be possible
+ or a timeout to occur."
+
+ |nReady index sema action wasBlocked err fd readyIndex
+ readableResultFdArray writableResultFdArray newProcessMaybeReady|
"/ must enable interrupts, to be able to get out of a
"/ long wait (especially, to handle sigChild in the meantime)
@@ -2923,19 +2925,23 @@
].
newProcessMaybeReady := false.
- resultFdArray := Array new:40.
- nSelected := OperatingSystem
- selectOnAnyReadable:readFdArray
- writable:writeFdArray
- exception:nil
- into:resultFdArray
- withTimeOut:millis.
+ readableResultFdArray := Array new:40.
+ writableResultFdArray := Array new:40.
+
+ nReady := OperatingSystem
+ selectOnAnyReadable:readFdArray
+ writable:writeFdArray
+ exception:nil
+ readableInto:readableResultFdArray
+ writableInto:writableResultFdArray
+ exceptionInto:nil
+ withTimeOut:millis.
wasBlocked ifTrue:[
OperatingSystem blockInterrupts.
].
- nSelected == 0 ifTrue:[
+ nReady == 0 ifTrue:[
"/ either still nothing to do,
"/ or error (which should not happen)
@@ -2960,12 +2966,11 @@
].
]
] ifFalse:[
- nSelected > resultFdArray size ifTrue:[
- nSelected := resultFdArray size.
- ].
- 1 to:nSelected do:[:fdIndex| |fd|
- fd := resultFdArray at:fdIndex.
-
+ readyIndex := 1.
+ [nReady > 0
+ and:[ readyIndex <= readableResultFdArray size
+ and:[ (fd := readableResultFdArray at:readyIndex) notNil ]]]
+ whileTrue:[
index := readFdArray identityIndexOf:fd.
index ~~ 0 ifTrue:[
sema := readSemaphoreArray at:index.
@@ -2979,6 +2984,15 @@
newProcessMaybeReady := true
]
].
+ nReady := nReady - 1.
+ index := index + 1.
+ ].
+
+ readyIndex := 1.
+ [nReady > 0
+ and:[ readyIndex <= writableResultFdArray size
+ and:[ (fd := writableResultFdArray at:readyIndex) notNil ]]]
+ whileTrue:[
index := writeFdArray identityIndexOf:fd.
index ~~ 0 ifTrue:[
sema := writeSemaphoreArray at:index.
@@ -2992,6 +3006,8 @@
newProcessMaybeReady := true
]
].
+ nReady := nReady - 1.
+ index := index + 1.
].
].
^ newProcessMaybeReady
@@ -3173,7 +3189,7 @@
].
doingGC ifTrue:[
- (self checkForInputWithTimeout:0) ifTrue:[
+ (self checkForIOWithTimeout:0) ifTrue:[
^ self "go back checking"
]
]
@@ -3211,7 +3227,7 @@
waiting always 1 sec in the select - therefore we delay a bit and
return - effectively polling in 50ms cycles
"
- (self checkForInputWithTimeout:0) ifTrue:[
+ (self checkForIOWithTimeout:0) ifTrue:[
^ self "go back checking"
].
OperatingSystem millisecondDelay:EventPollingInterval.
@@ -3230,7 +3246,7 @@
millis := millis rounded min:dT.
].
- self checkForInputWithTimeout:millis
+ self checkForIOWithTimeout:millis
"Modified: 14.12.1995 / 13:37:46 / stefan"
"Modified: 18.7.1996 / 20:42:17 / cg"
@@ -3239,7 +3255,7 @@
!ProcessorScheduler class methodsFor:'documentation'!
version
- ^ '$Header: /cvs/stx/stx/libbasic/ProcessorScheduler.st,v 1.211 2003-07-12 08:25:04 stefan Exp $'
+ ^ '$Header: /cvs/stx/stx/libbasic/ProcessorScheduler.st,v 1.212 2003-07-15 14:03:17 cg Exp $'
! !
ProcessorScheduler initialize!
--- a/UnixOperatingSystem.st Tue Jul 15 14:19:45 2003 +0200
+++ b/UnixOperatingSystem.st Tue Jul 15 16:03:28 2003 +0200
@@ -9050,25 +9050,32 @@
!
selectOnAnyReadable:readFdArray writable:writeFdArray exception:exceptFdArray
- into:resultFdArray withTimeOut:millis
- "wait for any fd in readFdArray (an Array of integers) to become ready for
- reading, writeFdArray to become ready for writing, or exceptFdArray to
- arrive exceptional data (i.e. out-of-band data).
- Timeout after t milliseconds or, if the timeout time is 0, immediately..
+ readableInto:readableResultFdArray writableInto:writableResultFdArray
+ exceptionInto:exceptionResultFdArray
+ withTimeOut:millis
+
+ "wait for any fd in readFdArray (an Array of integers) to become ready for reading,
+ writeFdArray to become ready for writing,
+ or exceptFdArray to arrive exceptional data (i.e. out-of-band data).
+ Timeout after t milliseconds or - if the timeout time is 0 - immediately..
Empty fd-sets will always wait. Zero time can be used to poll file-
descriptors (i.e. to check if I/O possible without blocking).
- The filedescriptors which are ready are returned in resultArray.
-
- Return the number of selected filedescriptors"
+ The corresponding filedescriptors which are ready are returned in readableResultFdArray,
+ writableResultFdArray and exceptionResultFdArray respectively.
+
+ Return the (overall) number of selected filedescriptors.
+ readableResultFdArray, writableResultFdArray and exceptionResultFdArray will
+ get a nil-value stored into the slot after the last valid fileDescriptor;
+ Thus, the caller can simply scan these arrays upTo the end or a nil value."
%{
fd_set rset, wset, eset;
struct timeval wt, et;
- int f, maxF, i, lX, bX;
+ int maxF;
INT t;
- OBJ fd, retFd;
int ret;
- int count, resultCount;
+ int cntR = 0, cntW = 0, cntE = 0;
+ int resultSizeReadable = 0, resultSizeWritable = 0, resultSizeException = 0;
int numFds = 0;
#ifndef __isArrayLike
# define __isArrayLike __isArray
@@ -9077,10 +9084,25 @@
if (!__isSmallInteger(millis)) {
goto fail;
}
- if (! __isArrayLike(resultFdArray)) {
- goto fail;
- }
- resultCount = __arraySize(resultFdArray);
+
+ if (readableResultFdArray != nil) {
+ if (! __isArrayLike(readableResultFdArray)) {
+ goto fail;
+ }
+ resultSizeReadable = __arraySize(readableResultFdArray);
+ }
+ if (writableResultFdArray != nil) {
+ if (! __isArrayLike(writableResultFdArray)) {
+ goto fail;
+ }
+ resultSizeWritable = __arraySize(writableResultFdArray);
+ }
+ if (exceptionResultFdArray != nil) {
+ if (! __isArrayLike(exceptionResultFdArray)) {
+ goto fail;
+ }
+ resultSizeException = __arraySize(exceptionResultFdArray);
+ }
FD_ZERO(&rset);
FD_ZERO(&wset);
@@ -9088,12 +9110,16 @@
maxF = -1;
if (__isNonNilObject(readFdArray)) {
+ int i, count;
+
if (! __isArrayLike(readFdArray)) {
goto fail;
}
count = __arraySize(readFdArray);
for (i=0; i<count;i++) {
+ OBJ fd;
+
fd = __ArrayInstPtr(readFdArray)->a_element[i];
if (fd != nil) {
if (! __isSmallInteger(fd)) {
@@ -9101,6 +9127,8 @@
fprintf(stderr, "[OS] warning: funny read-fd (0x%x) given to select\n", fd);
}
} else {
+ int f;
+
f = __intVal(fd);
if ((unsigned)f < FD_SETSIZE) {
FD_SET(f, &rset);
@@ -9117,11 +9145,15 @@
}
if (__isNonNilObject(writeFdArray)) {
+ int i, count;
+
if (! __isArrayLike(writeFdArray)) {
goto fail;
}
count = __arraySize(writeFdArray);
for (i=0; i<count;i++) {
+ OBJ fd;
+
fd = __ArrayInstPtr(writeFdArray)->a_element[i];
if (fd != nil) {
if (! __isSmallInteger(fd)) {
@@ -9129,6 +9161,8 @@
fprintf(stderr, "[OS] warning: funny write-fd (0x%x) given to select\n", fd);
}
} else {
+ int f;
+
f = __intVal(fd);
if ((unsigned)f < FD_SETSIZE) {
FD_SET(f, &wset);
@@ -9145,11 +9179,15 @@
}
if (__isNonNilObject(exceptFdArray)) {
+ int i, count;
+
if (! __isArrayLike(exceptFdArray)) {
goto fail;
}
count = __arraySize(exceptFdArray);
for (i=0; i<count;i++) {
+ OBJ fd;
+
fd = __ArrayInstPtr(exceptFdArray)->a_element[i];
if (fd != nil) {
if (! __isSmallInteger(fd)) {
@@ -9157,6 +9195,8 @@
fprintf(stderr, "[OS] warning: funny except-fd (0x%x) given to select\n", fd);
}
} else {
+ int f;
+
f = __intVal(fd);
if ((unsigned)f < FD_SETSIZE) {
FD_SET(f, &eset);
@@ -9208,20 +9248,45 @@
__END_INTERRUPTABLE__
if (ret > 0) {
- int cnt = 0;
- OBJ *__result = __arrayVal(resultFdArray);
+ OBJ *__resultR = __arrayVal(readableResultFdArray);
+ OBJ *__resultW = __arrayVal(writableResultFdArray);
+ OBJ *__resultE = __arrayVal(exceptionResultFdArray);
+ int i;
for (i=0; i <= maxF; i++) {
- if (FD_ISSET(i, &rset)
- || FD_ISSET(i, &wset)
- || FD_ISSET(i, &eset)) {
- if (cnt < resultCount) {
- __result[cnt] = __MKSMALLINT(i);
+ if (FD_ISSET(i, &rset)) {
+ if (cntR < resultSizeReadable) {
+ __resultR[cntR] = __MKSMALLINT(i);
}
- cnt++;
+ cntR++;
+ }
+
+ if (FD_ISSET(i, &wset)) {
+ if (cntW < resultSizeWritable) {
+ __resultW[cntW] = __MKSMALLINT(i);
+ }
+ cntW++;
+ }
+
+ if (FD_ISSET(i, &eset)) {
+ if (cntE < resultSizeException) {
+ __resultE[cntE] = __MKSMALLINT(i);
+ }
+ cntE++;
}
}
- RETURN (__MKSMALLINT(cnt));
+ /* add a delimiter */
+ if (cntR < resultSizeReadable) {
+ __resultR[cntR] = nil;
+ }
+ if (cntW < resultSizeWritable) {
+ __resultW[cntW] = nil;
+ }
+ if (cntE < resultSizeException) {
+ __resultE[cntE] = nil;
+ }
+
+ RETURN (__MKSMALLINT(cntR+cntW+cntE));
} else {
if (ret < 0) {
if (errno == EINTR) {
@@ -9242,8 +9307,6 @@
* Return 0 (no filedescriptor ready)
*/
RETURN (__MKSMALLINT(0));
-
-
fail: ;
%}.
"
@@ -9255,13 +9318,13 @@
!
selectOnAnyReadable:readFdArray writable:writeFdArray exception:exceptFdArray withTimeOut:millis
- "wait for any fd in readFdArray (an Array of integers) to become ready for
- reading, writeFdArray to become ready for writing, or exceptFdArray to
- arrive exceptional data (i.e. out-of-band data).
+ "wait for any fd in readFdArray (an Array of integers) to become ready for reading,
+ writeFdArray to become ready for writing,
+ or exceptFdArray to arrive exceptional data (i.e. out-of-band data).
Timeout after t milliseconds or, if the timeout time is 0, immediately..
Empty fd-sets will always wait. Zero time can be used to poll file-
descriptors (i.e. to check if I/O possible without blocking).
- Return first ready fd if I/O ok, nil if timed-out or interrupted."
+ Return the first ready fd if I/O ok, nil if timed-out or interrupted."
%{
fd_set rset, wset, eset;
@@ -9277,159 +9340,159 @@
#endif
if (__isSmallInteger(millis)) {
- FD_ZERO(&rset);
- FD_ZERO(&wset);
- FD_ZERO(&eset);
-
- maxF = -1;
- if (__isNonNilObject(readFdArray)) {
- if (! __isArrayLike(readFdArray)) {
- goto fail;
- }
- count = __arraySize(readFdArray);
-
- for (i=0; i<count;i++) {
- fd = __ArrayInstPtr(readFdArray)->a_element[i];
- if (fd != nil) {
- if (! __isSmallInteger(fd)) {
- if (@global(InfoPrinting) == true) {
- fprintf(stderr, "[OS] warning: funny read-fd (0x%x) given to select\n", fd);
- }
- } else {
- f = __intVal(fd);
- if ((unsigned)f < FD_SETSIZE) {
- FD_SET(f, &rset);
- if (f > maxF) maxF = f;
- numFds++;
- } else {
- if (@global(InfoPrinting) == true) {
- fprintf(stderr, "[OS] warning: huge read-fd (0x%x) given to select\n", fd);
- }
- }
- }
- }
- }
- }
-
- if (__isNonNilObject(writeFdArray)) {
- if (! __isArrayLike(writeFdArray)) {
- goto fail;
- }
- count = __arraySize(writeFdArray);
- for (i=0; i<count;i++) {
- fd = __ArrayInstPtr(writeFdArray)->a_element[i];
- if (fd != nil) {
- if (! __isSmallInteger(fd)) {
- if (@global(InfoPrinting) == true) {
- fprintf(stderr, "[OS] warning: funny write-fd (0x%x) given to select\n", fd);
- }
- } else {
- f = __intVal(fd);
- if ((unsigned)f < FD_SETSIZE) {
- FD_SET(f, &wset);
- if (f > maxF) maxF = f;
- numFds++;
- } else {
- if (@global(InfoPrinting) == true) {
- fprintf(stderr, "[OS] warning: huge write-fd (0x%x) given to select\n", fd);
- }
- }
- }
- }
- }
- }
-
- if (__isNonNilObject(exceptFdArray)) {
- if (! __isArrayLike(exceptFdArray)) {
- goto fail;
- }
- count = __arraySize(exceptFdArray);
- for (i=0; i<count;i++) {
- fd = __ArrayInstPtr(exceptFdArray)->a_element[i];
- if (fd != nil) {
- if (! __isSmallInteger(fd)) {
- if (@global(InfoPrinting) == true) {
- fprintf(stderr, "[OS] warning: funny except-fd (0x%x) given to select\n", fd);
- }
- } else {
- f = __intVal(fd);
- if ((unsigned)f < FD_SETSIZE) {
- FD_SET(f, &eset);
- if (f > maxF) maxF = f;
- numFds++;
- } else {
- if (@global(InfoPrinting) == true) {
- fprintf(stderr, "[OS] warning: huge except-fd (0x%x) given to select\n", fd);
- }
- }
- }
- }
- }
- }
-
- t = __intVal(millis);
- if (t) {
- wt.tv_sec = t / 1000;
- wt.tv_usec = (t % 1000) * 1000;
- } else {
- wt.tv_sec = wt.tv_usec = 0;
- }
-
- /*
- * make certain, that interrupt gets us out of the select
- * However, we must then care for moved objects.
- */
- __BEGIN_INTERRUPTABLE__
- errno = 0;
-
- if (t == 0) {
- /*
- * if there is no timeout time, we can stay here interruptable.
- */
- do {
- ret = select(maxF+1, &rset, &wset, &eset, &wt);
- } while ((ret < 0) && (errno == EINTR));
- } else {
- do {
- ret = select(maxF+1, &rset, &wset, &eset, &wt);
- /*
- * for now: dont loop; if we did, we had to adjust the vt-timeval;
- * could otherwise stay in this loop forever ...
- * Premature ret (before the time expired) must be handled by the caller.
- * A good solution is to update the wt-timeval and redo the select.
- */
- } while (0 /* (ret < 0) && (errno == EINTR) */ );
- }
- __END_INTERRUPTABLE__
-
- if (ret > 0) {
- for (i=0; i <= maxF; i++) {
- if (FD_ISSET(i, &rset)
- || FD_ISSET(i, &wset)
- || FD_ISSET(i, &eset)) {
- RETURN ( __MKSMALLINT(i) );
- }
- }
- } else {
- if (ret < 0) {
- if (errno == EINTR) {
- errno = 0;
- @global(LastErrorNumber) = nil;
- } else {
- if (@global(InfoPrinting) == true) {
- fprintf(stderr, "OS [info]: select errno = %d\n", errno);
- }
- @global(LastErrorNumber) = __MKSMALLINT(errno);
- }
- } else {
- @global(LastErrorNumber) = nil;
- }
- }
-
- /*
- * Return nil (means time expired or interrupted)
- */
- RETURN ( nil );
+ FD_ZERO(&rset);
+ FD_ZERO(&wset);
+ FD_ZERO(&eset);
+
+ maxF = -1;
+ if (__isNonNilObject(readFdArray)) {
+ if (! __isArrayLike(readFdArray)) {
+ goto fail;
+ }
+ count = __arraySize(readFdArray);
+
+ for (i=0; i<count;i++) {
+ fd = __ArrayInstPtr(readFdArray)->a_element[i];
+ if (fd != nil) {
+ if (! __isSmallInteger(fd)) {
+ if (@global(InfoPrinting) == true) {
+ fprintf(stderr, "[OS] warning: funny read-fd (0x%x) given to select\n", fd);
+ }
+ } else {
+ f = __intVal(fd);
+ if ((unsigned)f < FD_SETSIZE) {
+ FD_SET(f, &rset);
+ if (f > maxF) maxF = f;
+ numFds++;
+ } else {
+ if (@global(InfoPrinting) == true) {
+ fprintf(stderr, "[OS] warning: huge read-fd (0x%x) given to select\n", fd);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (__isNonNilObject(writeFdArray)) {
+ if (! __isArrayLike(writeFdArray)) {
+ goto fail;
+ }
+ count = __arraySize(writeFdArray);
+ for (i=0; i<count;i++) {
+ fd = __ArrayInstPtr(writeFdArray)->a_element[i];
+ if (fd != nil) {
+ if (! __isSmallInteger(fd)) {
+ if (@global(InfoPrinting) == true) {
+ fprintf(stderr, "[OS] warning: funny write-fd (0x%x) given to select\n", fd);
+ }
+ } else {
+ f = __intVal(fd);
+ if ((unsigned)f < FD_SETSIZE) {
+ FD_SET(f, &wset);
+ if (f > maxF) maxF = f;
+ numFds++;
+ } else {
+ if (@global(InfoPrinting) == true) {
+ fprintf(stderr, "[OS] warning: huge write-fd (0x%x) given to select\n", fd);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (__isNonNilObject(exceptFdArray)) {
+ if (! __isArrayLike(exceptFdArray)) {
+ goto fail;
+ }
+ count = __arraySize(exceptFdArray);
+ for (i=0; i<count;i++) {
+ fd = __ArrayInstPtr(exceptFdArray)->a_element[i];
+ if (fd != nil) {
+ if (! __isSmallInteger(fd)) {
+ if (@global(InfoPrinting) == true) {
+ fprintf(stderr, "[OS] warning: funny except-fd (0x%x) given to select\n", fd);
+ }
+ } else {
+ f = __intVal(fd);
+ if ((unsigned)f < FD_SETSIZE) {
+ FD_SET(f, &eset);
+ if (f > maxF) maxF = f;
+ numFds++;
+ } else {
+ if (@global(InfoPrinting) == true) {
+ fprintf(stderr, "[OS] warning: huge except-fd (0x%x) given to select\n", fd);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ t = __intVal(millis);
+ if (t) {
+ wt.tv_sec = t / 1000;
+ wt.tv_usec = (t % 1000) * 1000;
+ } else {
+ wt.tv_sec = wt.tv_usec = 0;
+ }
+
+ /*
+ * make certain, that interrupt gets us out of the select
+ * However, we must then care for moved objects.
+ */
+ __BEGIN_INTERRUPTABLE__
+ errno = 0;
+
+ if (t == 0) {
+ /*
+ * if there is no timeout time, we can stay here interruptable.
+ */
+ do {
+ ret = select(maxF+1, &rset, &wset, &eset, &wt);
+ } while ((ret < 0) && (errno == EINTR));
+ } else {
+ do {
+ ret = select(maxF+1, &rset, &wset, &eset, &wt);
+ /*
+ * for now: dont loop; if we did, we had to adjust the vt-timeval;
+ * could otherwise stay in this loop forever ...
+ * Premature ret (before the time expired) must be handled by the caller.
+ * A good solution is to update the wt-timeval and redo the select.
+ */
+ } while (0 /* (ret < 0) && (errno == EINTR) */ );
+ }
+ __END_INTERRUPTABLE__
+
+ if (ret > 0) {
+ for (i=0; i <= maxF; i++) {
+ if (FD_ISSET(i, &rset)
+ || FD_ISSET(i, &wset)
+ || FD_ISSET(i, &eset)) {
+ RETURN ( __MKSMALLINT(i) );
+ }
+ }
+ } else {
+ if (ret < 0) {
+ if (errno == EINTR) {
+ errno = 0;
+ @global(LastErrorNumber) = nil;
+ } else {
+ if (@global(InfoPrinting) == true) {
+ fprintf(stderr, "OS [info]: select errno = %d\n", errno);
+ }
+ @global(LastErrorNumber) = __MKSMALLINT(errno);
+ }
+ } else {
+ @global(LastErrorNumber) = nil;
+ }
+ }
+
+ /*
+ * Return nil (means time expired or interrupted)
+ */
+ RETURN ( nil );
}
fail: ;
@@ -12152,7 +12215,7 @@
!UnixOperatingSystem class methodsFor:'documentation'!
version
- ^ '$Header: /cvs/stx/stx/libbasic/UnixOperatingSystem.st,v 1.174 2003-07-15 12:19:45 cg Exp $'
+ ^ '$Header: /cvs/stx/stx/libbasic/UnixOperatingSystem.st,v 1.175 2003-07-15 14:03:04 cg Exp $'
! !
UnixOperatingSystem initialize!