ProcessorScheduler.st
changeset 18295 17324d5bb9cc
parent 17412 ef9b82b8ce77
child 18301 d0a478542bbf
child 18620 b4e9f25d6ce6
equal deleted inserted replaced
18294:5c7b472ab445 18295:17324d5bb9cc
     1 "
     1 "
     2  COPYRIGHT (c) 1993 by Claus Gittinger
     2  COPYRIGHT (c) 1993 by Claus Gittinger
     3               All Rights Reserved
     3 	      All Rights Reserved
     4 
     4 
     5  This software is furnished under a license and may be used
     5  This software is furnished under a license and may be used
     6  only in accordance with the terms of that license and with the
     6  only in accordance with the terms of that license and with the
     7  inclusion of the above copyright notice.   This software may not
     7  inclusion of the above copyright notice.   This software may not
     8  be provided or otherwise made available to, or used by, any
     8  be provided or otherwise made available to, or used by, any
    37 !ProcessorScheduler class methodsFor:'documentation'!
    37 !ProcessorScheduler class methodsFor:'documentation'!
    38 
    38 
    39 copyright
    39 copyright
    40 "
    40 "
    41  COPYRIGHT (c) 1993 by Claus Gittinger
    41  COPYRIGHT (c) 1993 by Claus Gittinger
    42               All Rights Reserved
    42 	      All Rights Reserved
    43 
    43 
    44  This software is furnished under a license and may be used
    44  This software is furnished under a license and may be used
    45  only in accordance with the terms of that license and with the
    45  only in accordance with the terms of that license and with the
    46  inclusion of the above copyright notice.   This software may not
    46  inclusion of the above copyright notice.   This software may not
    47  be provided or otherwise made available to, or used by, any
    47  be provided or otherwise made available to, or used by, any
    77 
    77 
    78     This pure-event mode may not be supported in the future
    78     This pure-event mode may not be supported in the future
    79     (actually, it is no longer maintained, so dont run the system without Processes).
    79     (actually, it is no longer maintained, so dont run the system without Processes).
    80 
    80 
    81     [instance variables:]
    81     [instance variables:]
    82         quiescentProcessLists           - list of waiting processes
    82 	quiescentProcessLists           - list of waiting processes
    83         scheduler                       - the scheduler process itself
    83 	scheduler                       - the scheduler process itself
    84         zombie                          - internal temporary (recently died process)
    84 	zombie                          - internal temporary (recently died process)
    85         activeProcess                   - the current process
    85 	activeProcess                   - the current process
    86         activeProcessId                 - the current processes id
    86 	activeProcessId                 - the current processes id
    87         currentPriority                 - the current processes priority
    87 	currentPriority                 - the current processes priority
    88         readFdArray                     - fd-sema-checkBlock triple-association
    88 	readFdArray                     - fd-sema-checkBlock triple-association
    89         readSemaphoreArray                (stupid historic 3-separate arrays for hi-speed-optimization reasons)
    89 	readSemaphoreArray                (stupid historic 3-separate arrays for hi-speed-optimization reasons)
    90         readCheckArray
    90 	readCheckArray
    91         writeFdArray                    - fd-sema-checkBlock triple-association
    91 	writeFdArray                    - fd-sema-checkBlock triple-association
    92         writeSemaphoreArray               (stupid historic 3-separate arrays for hi-speed-optimization reasons)
    92 	writeSemaphoreArray               (stupid historic 3-separate arrays for hi-speed-optimization reasons)
    93         writeCheckArray
    93 	writeCheckArray
    94         timeoutArray                    - time-action-process-sema quadruple-association
    94 	timeoutArray                    - time-action-process-sema quadruple-association
    95         timeoutActionArray                (stupid historic 3-separate arrays for hi-speed-optimization reasons)
    95 	timeoutActionArray                (stupid historic 3-separate arrays for hi-speed-optimization reasons)
    96         timeoutProcessArray
    96 	timeoutProcessArray
    97         timeoutSemaphoreArray
    97 	timeoutSemaphoreArray
    98         idleActions                     - actions to be executed when idle
    98 	idleActions                     - actions to be executed when idle
    99         preWaitActions                  - actions to be executed BEFORE going into an OS-wait
    99 	preWaitActions                  - actions to be executed BEFORE going into an OS-wait
   100         anyTimeouts                     - flag if any timeouts are pending
   100 	anyTimeouts                     - flag if any timeouts are pending
   101         dispatching                     - flag if dispatch process is running (i.e. NOT initializing)
   101 	dispatching                     - flag if dispatch process is running (i.e. NOT initializing)
   102         interruptedProcess              - the currently interrupted process.
   102 	interruptedProcess              - the currently interrupted process.
   103         useIOInterrupts                 - flag if the OS supports I/O interrupts and if they are used (to get me out of an OS wait)
   103 	useIOInterrupts                 - flag if the OS supports I/O interrupts and if they are used (to get me out of an OS wait)
   104         gotIOInterrupt                  - flag if I came out of a wait due to an I/O interrupt
   104 	gotIOInterrupt                  - flag if I came out of a wait due to an I/O interrupt
   105         osChildExitActions              - OS chid process actions
   105 	osChildExitActions              - OS chid process actions
   106         gotChildSignalInterrupt         - flag if I came out of a wait due to an OS child interrupt
   106 	gotChildSignalInterrupt         - flag if I came out of a wait due to an OS child interrupt
   107         exitWhenNoMoreUserProcesses     - flag which controls if ST/X should exit when the last process dies (for standalone apps)
   107 	exitWhenNoMoreUserProcesses     - flag which controls if ST/X should exit when the last process dies (for standalone apps)
   108         suspendScheduler                - internal use
   108 	suspendScheduler                - internal use
   109         timeSliceProcess                - the timeSlicer process
   109 	timeSliceProcess                - the timeSlicer process
   110         supportDynamicPriorities        - flag if dynamic priorities should be supported by the timeSlicer
   110 	supportDynamicPriorities        - flag if dynamic priorities should be supported by the timeSlicer
   111         scheduledProcesses              - list of scheduled processes for the timeSlicers dynamic prio handling
   111 	scheduledProcesses              - list of scheduled processes for the timeSlicers dynamic prio handling
   112 
   112 
   113     [class variables:]
   113     [class variables:]
   114 
   114 
   115         KnownProcesses          <WeakArray>     all known processes
   115 	KnownProcesses          <WeakArray>     all known processes
   116         KnownProcessIds         <Collection>    and their IDs
   116 	KnownProcessIds         <Collection>    and their IDs
   117 
   117 
   118         PureEventDriven         <Boolean>       true, if no process support
   118 	PureEventDriven         <Boolean>       true, if no process support
   119                                                 is available
   119 						is available
   120 
   120 
   121         UserSchedulingPriority  <Integer>       the priority at which normal
   121 	UserSchedulingPriority  <Integer>       the priority at which normal
   122                                                 user interfaces run
   122 						user interfaces run
   123 
   123 
   124         UserInterruptPriority                   the priority at which user-
   124 	UserInterruptPriority                   the priority at which user-
   125                                                 interrupts (Cntl-C) processing
   125 						interrupts (Cntl-C) processing
   126                                                 takes place. Processes with
   126 						takes place. Processes with
   127                                                 a greater or equal priority are
   127 						a greater or equal priority are
   128                                                 not interruptable.
   128 						not interruptable.
   129 
   129 
   130         TimingPriority                          the priority used for timing.
   130 	TimingPriority                          the priority used for timing.
   131                                                 Processes with a greater or
   131 						Processes with a greater or
   132                                                 equal priority are not interrupted
   132 						equal priority are not interrupted
   133                                                 by timers.
   133 						by timers.
   134 
   134 
   135         HighestPriority                         The highest allowed prio for processes
   135 	HighestPriority                         The highest allowed prio for processes
   136 
   136 
   137         SchedulingPriority                      The priority of the scheduler (must
   137 	SchedulingPriority                      The priority of the scheduler (must
   138                                                 me higher than any other).
   138 						me higher than any other).
   139 
   139 
   140         MaxNumberOfProcesses                    if non-nil, no more than this
   140 	MaxNumberOfProcesses                    if non-nil, no more than this
   141                                                 number of processes are allowed
   141 						number of processes are allowed
   142                                                 (for debugging)
   142 						(for debugging)
   143 
   143 
   144         TimeSliceInterval                       for preemptive priority scheduling only:
   144 	TimeSliceInterval                       for preemptive priority scheduling only:
   145                                                 the time interval in millis, at which processes
   145 						the time interval in millis, at which processes
   146                                                 are timesliced
   146 						are timesliced
   147 
   147 
   148         TimeSlicingPriorityLimit                for preemptive priority scheduling only:
   148 	TimeSlicingPriorityLimit                for preemptive priority scheduling only:
   149                                                 processes are only timesliced, if running
   149 						processes are only timesliced, if running
   150                                                 at or below this priority.
   150 						at or below this priority.
   151 
   151 
   152         EventPollingInterval                    for systems which do not support select on
   152 	EventPollingInterval                    for systems which do not support select on
   153                                                 a fileDescriptor: the polling interval in millis.
   153 						a fileDescriptor: the polling interval in millis.
   154 
   154 
   155     most interesting methods:
   155     most interesting methods:
   156 
   156 
   157         Processor>>suspend:                  (see also Process>>suspend)
   157 	Processor>>suspend:                  (see also Process>>suspend)
   158         Processor>>resume:                   (see also Process>>resume)
   158 	Processor>>resume:                   (see also Process>>resume)
   159         Processor>>terminate:                (see also Process>>terminate)
   159 	Processor>>terminate:                (see also Process>>terminate)
   160         Processor>>yield
   160 	Processor>>yield
   161         Processor>>changePriority:for:       (see also Process>>priority:
   161 	Processor>>changePriority:for:       (see also Process>>priority:
   162 
   162 
   163         Processor>>signal:afterSeconds:      (see also Delay>>forSeconds:)
   163 	Processor>>signal:afterSeconds:      (see also Delay>>forSeconds:)
   164         Processor>>signal:afterMilliseconds: (see also Delay>>forMilliseconds:)
   164 	Processor>>signal:afterMilliseconds: (see also Delay>>forMilliseconds:)
   165         Processor>>signal:onInput:           (see also ExternalStream>>readWait)
   165 	Processor>>signal:onInput:           (see also ExternalStream>>readWait)
   166         Processor>>signal:onOutput:          (see also ExternalStream>>writeWait)
   166 	Processor>>signal:onOutput:          (see also ExternalStream>>writeWait)
   167         Processor>>disableSemaphore:
   167 	Processor>>disableSemaphore:
   168 
   168 
   169 
   169 
   170     [see also:]
   170     [see also:]
   171         Process
   171 	Process
   172         Delay Semaphore SemaphoreSet SharedQueue
   172 	Delay Semaphore SemaphoreSet SharedQueue
   173         WindowGroup
   173 	WindowGroup
   174         (``Working with processes'': programming/processes.html)
   174 	(``Working with processes'': programming/processes.html)
   175 
   175 
   176     [author:]
   176     [author:]
   177         Claus Gittinger
   177 	Claus Gittinger
   178 "
   178 "
   179 !
   179 !
   180 
   180 
   181 scheduling
   181 scheduling
   182 "
   182 "
   210     event.
   210     event.
   211     Timeslicing will not be done for processes running above TimeSlicingPriorityLimit, which
   211     Timeslicing will not be done for processes running above TimeSlicingPriorityLimit, which
   212     allows for critical processes to run unaffected to completion.
   212     allows for critical processes to run unaffected to completion.
   213 
   213 
   214     WARNING:
   214     WARNING:
   215         timesliced priority scheduling is an experimental feature. There is no warranty,
   215 	timesliced priority scheduling is an experimental feature. There is no warranty,
   216         (at the moment), that the system runs reliable in this mode.
   216 	(at the moment), that the system runs reliable in this mode.
   217         The problem is, that shared collections may now be easily modified by other
   217 	The problem is, that shared collections may now be easily modified by other
   218         processes, running at the same time.
   218 	processes, running at the same time.
   219         The class library has being investigated for such possible trouble spots
   219 	The class library has being investigated for such possible trouble spots
   220         (we have eliminated many weak spots, and added critical regions at many places,
   220 	(we have eliminated many weak spots, and added critical regions at many places,
   221          but cannot guarantee that all of them have been found so far ...)
   221 	 but cannot guarantee that all of them have been found so far ...)
   222         We found that many existing public domain programs are not prepared for
   222 	We found that many existing public domain programs are not prepared for
   223         being interrupted by a same-prio process and therefore may corrupt their
   223 	being interrupted by a same-prio process and therefore may corrupt their
   224         data. If in doubt, disable this fefature.
   224 	data. If in doubt, disable this fefature.
   225 
   225 
   226     We think, that the timeSlicer is a useful add-on and that the system is fit enough
   226     We think, that the timeSlicer is a useful add-on and that the system is fit enough
   227     for it to be evaluated, therefore, its included.
   227     for it to be evaluated, therefore, its included.
   228     However, use it at your own risk.
   228     However, use it at your own risk.
   229 
   229 
   230     To demonstrate the effect of timeSlicing, do the following:
   230     To demonstrate the effect of timeSlicing, do the following:
   231 
   231 
   232         - disable timeSlicing (in the launchers misc-settings menu)
   232 	- disable timeSlicing (in the launchers misc-settings menu)
   233         - open a workSpace
   233 	- open a workSpace
   234         - in the workspace, evaluate:
   234 	- in the workspace, evaluate:
   235                 [true] whileTrue:[1000 factorial]
   235 		[true] whileTrue:[1000 factorial]
   236 
   236 
   237     now, (since the workSpace runs at the same prio as other window-processes),
   237     now, (since the workSpace runs at the same prio as other window-processes),
   238     other views do no longer react - all CPU is used up by the workSpace.
   238     other views do no longer react - all CPU is used up by the workSpace.
   239     However, CTRL-C in the workspace is still possible to stop the endless loop,
   239     However, CTRL-C in the workspace is still possible to stop the endless loop,
   240     since that is handled by the (higher prio) event dispatcher process.
   240     since that is handled by the (higher prio) event dispatcher process.
   260     TimeSlicingPriorityLimit := 26.
   260     TimeSlicingPriorityLimit := 26.
   261     HighestPriority := 30.
   261     HighestPriority := 30.
   262     SchedulingPriority := 31.
   262     SchedulingPriority := 31.
   263 
   263 
   264     InvalidProcessSignal isNil ifTrue:[
   264     InvalidProcessSignal isNil ifTrue:[
   265         InvalidProcessSignal := Error newSignalMayProceed:true.
   265 	InvalidProcessSignal := Error newSignalMayProceed:true.
   266         InvalidProcessSignal nameClass:self message:#invalidProcessSignal.
   266 	InvalidProcessSignal nameClass:self message:#invalidProcessSignal.
   267         InvalidProcessSignal notifierString:'invalid process'.
   267 	InvalidProcessSignal notifierString:'invalid process'.
   268     ].
   268     ].
   269 
   269 
   270     Processor isNil ifTrue:[
   270     Processor isNil ifTrue:[
   271         "create the one and only processor"
   271 	"create the one and only processor"
   272 
   272 
   273         Processor := self basicNew initialize.
   273 	Processor := self basicNew initialize.
   274     ].
   274     ].
   275 
   275 
   276     "
   276     "
   277      allow configurations without processes
   277      allow configurations without processes
   278      (but such configurations are no longer distributed)
   278      (but such configurations are no longer distributed)
   279     "
   279     "
   280     PureEventDriven := self threadsAvailable not.
   280     PureEventDriven := self threadsAvailable not.
   281     PureEventDriven ifTrue:[
   281     PureEventDriven ifTrue:[
   282         'Processor [error]: no process support - running event driven' errorPrintCR
   282 	'Processor [error]: no process support - running event driven' errorPrintCR
   283     ].
   283     ].
   284 
   284     self initializeVMMaxProcessId
   285 %{
       
   286 #ifndef MAX_PROCESS_ID
       
   287 # define MAX_PROCESS_ID _MAX_INT
       
   288 #endif
       
   289     @global(ProcessorScheduler:MaxProcessId) = __MKSMALLINT(MAX_PROCESS_ID);    
       
   290 %}
       
   291 
   285 
   292     "Modified: / 23-09-1996 / 14:24:50 / stefan"
   286     "Modified: / 23-09-1996 / 14:24:50 / stefan"
   293     "Modified: / 10-01-1997 / 18:03:03 / cg"
   287     "Modified: / 10-01-1997 / 18:03:03 / cg"
   294     "Modified: / 19-09-2014 / 12:47:51 / Jan Vrany <jan.vrany@fit.cvut.cz>"
   288     "Modified: / 19-09-2014 / 12:47:51 / Jan Vrany <jan.vrany@fit.cvut.cz>"
       
   289 !
       
   290 
       
   291 initializeVMMaxProcessId
       
   292 
       
   293     "/ for java locks, the VM may reserve some bits
       
   294     "/ and reduce the maximum processID to be able to
       
   295     "/ encode the id in an object's header field.
       
   296 %{
       
   297 #ifndef __SCHTEAM__
       
   298 
       
   299 # ifndef MAX_PROCESS_ID
       
   300 #  define MAX_PROCESS_ID _MAX_INT
       
   301 # endif
       
   302 
       
   303     @global(ProcessorScheduler:MaxProcessId) = __MKSMALLINT(MAX_PROCESS_ID);
       
   304     RETURN (self);
       
   305 #endif /* not SCHTEAM */
       
   306 %}.
       
   307     MaxProcessId := SmallInteger maxVal.
   295 ! !
   308 ! !
   296 
   309 
   297 !ProcessorScheduler class methodsFor:'instance creation'!
   310 !ProcessorScheduler class methodsFor:'instance creation'!
   298 
   311 
   299 new
   312 new
   319      by sending #terminate."
   332      by sending #terminate."
   320 
   333 
   321     |id sz "{ Class: SmallInteger }"|
   334     |id sz "{ Class: SmallInteger }"|
   322 
   335 
   323     something == #ElementExpired ifTrue:[
   336     something == #ElementExpired ifTrue:[
   324         sz := KnownProcessIds size.
   337 	sz := KnownProcessIds size.
   325         1 to:sz do:[:index |
   338 	1 to:sz do:[:index |
   326             "/ (KnownProcesses at:index) isNil ifTrue:[
   339 	    "/ (KnownProcesses at:index) isNil ifTrue:[
   327             (KnownProcesses at:index) == 0 ifTrue:[
   340 	    (KnownProcesses at:index) == 0 ifTrue:[
   328                 id := KnownProcessIds at:index.
   341 		id := KnownProcessIds at:index.
   329                 id notNil ifTrue:[
   342 		id notNil ifTrue:[
   330                     'Processor [warning]: terminating thread ' errorPrint.
   343 		    'Processor [warning]: terminating thread ' errorPrint.
   331                     id errorPrint.
   344 		    id errorPrint.
   332                     ' (no longer refd)' errorPrintCR.
   345 		    ' (no longer refd)' errorPrintCR.
   333 
   346 
   334                     self threadDestroy:id.
   347 		    self threadDestroy:id.
   335                     KnownProcessIds at:index put:nil.
   348 		    KnownProcessIds at:index put:nil.
   336                 ].
   349 		].
   337                 KnownProcesses at:index put:nil.
   350 		KnownProcesses at:index put:nil.
   338             ]
   351 	    ]
   339         ]
   352 	]
   340     ]
   353     ]
   341 
   354 
   342     "Created: 7.1.1997 / 16:45:42 / stefan"
   355     "Created: 7.1.1997 / 16:45:42 / stefan"
   343     "Modified: 10.1.1997 / 19:10:48 / cg"
   356     "Modified: 10.1.1997 / 19:10:48 / cg"
   344 ! !
   357 ! !
   349     "physical creation of a process.
   362     "physical creation of a process.
   350      (warning: low level entry, no administration done).
   363      (warning: low level entry, no administration done).
   351      This may raise an exception, if a VM process could not be created."
   364      This may raise an exception, if a VM process could not be created."
   352 
   365 
   353     MaxNumberOfProcesses notNil ifTrue:[
   366     MaxNumberOfProcesses notNil ifTrue:[
   354         KnownProcessIds size >= MaxNumberOfProcesses ifTrue:[
   367 	KnownProcessIds size >= MaxNumberOfProcesses ifTrue:[
   355             (KnownProcessIds count:[:el | el notNil]) >= MaxNumberOfProcesses ifTrue:[
   368 	    (KnownProcessIds count:[:el | el notNil]) >= MaxNumberOfProcesses ifTrue:[
   356                 "
   369 		"
   357                  the number of processes has reached the (soft) limit.
   370 		 the number of processes has reached the (soft) limit.
   358                  This limit prevents runaway programs from creating too many
   371 		 This limit prevents runaway programs from creating too many
   359                  processes. If you continue in the debugger, the process will be
   372 		 processes. If you continue in the debugger, the process will be
   360                  created as usual. If you dont want this, abort or terminate.
   373 		 created as usual. If you dont want this, abort or terminate.
   361                 "
   374 		"
   362                 self error:'too many processes'.
   375 		self error:'too many processes'.
   363             ]
   376 	    ]
   364         ]
   377 	]
   365     ].
   378     ].
   366 
   379 
   367 %{
   380 %{
   368     int tid;
   381     int tid;
   369     extern int __threadCreate();
   382     extern int __threadCreate();
   370 
   383 
   371     tid = __threadCreate(aProcess,
   384     tid = __threadCreate(aProcess,
   372                          0   /* stackSize: no longer needed */,
   385 			 0   /* stackSize: no longer needed */,
   373                          __isSmallInteger(id) ? __intVal(id)     /* assign id */
   386 			 __isSmallInteger(id) ? __intVal(id)     /* assign id */
   374                                               : -1              /* let VM assign one */  );
   387 					      : -1              /* let VM assign one */  );
   375     if (tid) {
   388     if (tid) {
   376         RETURN ( __mkSmallInteger(tid));
   389 	RETURN ( __mkSmallInteger(tid));
   377     }
   390     }
   378 %}
   391 %}
   379 .
   392 .
   380     "
   393     "
   381      arrive here, if creation of process in VM failed.
   394      arrive here, if creation of process in VM failed.
   391      (warning: low level entry, no administration done)"
   404      (warning: low level entry, no administration done)"
   392 
   405 
   393 %{  /* NOCONTEXT */
   406 %{  /* NOCONTEXT */
   394 
   407 
   395     if (__isSmallInteger(id)) {
   408     if (__isSmallInteger(id)) {
   396         __threadDestroy(__intVal(id));
   409 	__threadDestroy(__intVal(id));
   397     }
   410     }
   398 %}
   411 %}
   399 !
   412 !
   400 
   413 
   401 threadInterrupt:id
   414 threadInterrupt:id
   405      interrupt (currently, it looks for interruptBlocks to evaluate)."
   418      interrupt (currently, it looks for interruptBlocks to evaluate)."
   406 
   419 
   407 %{  /* NOCONTEXT */
   420 %{  /* NOCONTEXT */
   408 
   421 
   409     if (__isSmallInteger(id)) {
   422     if (__isSmallInteger(id)) {
   410         __threadInterrupt(__intVal(id));
   423 	__threadInterrupt(__intVal(id));
   411     }
   424     }
   412 %}
   425 %}
   413 !
   426 !
   414 
   427 
   415 threadsAvailable
   428 threadsAvailable
   447 
   460 
   448 knownProcessesDo:aBlock
   461 knownProcessesDo:aBlock
   449     "evaluate aBlock for each (living) processes in the system"
   462     "evaluate aBlock for each (living) processes in the system"
   450 
   463 
   451     KnownProcesses do:[:p |
   464     KnownProcesses do:[:p |
   452         (p notNil and:[p ~~ 0]) ifTrue:[aBlock value:p]
   465 	(p notNil and:[p ~~ 0]) ifTrue:[aBlock value:p]
   453     ]
   466     ]
   454 
   467 
   455     "Created: / 26-10-2012 / 13:02:33 / cg"
   468     "Created: / 26-10-2012 / 13:02:33 / cg"
   456 !
   469 !
   457 
   470 
   501     |idx "{Class: SmallInteger }"
   514     |idx "{Class: SmallInteger }"
   502      wasBlocked|
   515      wasBlocked|
   503 
   516 
   504     wasBlocked := OperatingSystem blockInterrupts.
   517     wasBlocked := OperatingSystem blockInterrupts.
   505     useIOInterrupts ifTrue:[
   518     useIOInterrupts ifTrue:[
   506         OperatingSystem disableIOInterruptsOn:aFileDescriptor
   519 	OperatingSystem disableIOInterruptsOn:aFileDescriptor
   507     ].
   520     ].
   508 
   521 
   509     idx := readFdArray identityIndexOf:aFileDescriptor startingAt:1.
   522     idx := readFdArray identityIndexOf:aFileDescriptor startingAt:1.
   510     idx ~~ 0 ifTrue:[
   523     idx ~~ 0 ifTrue:[
   511         readFdArray at:idx put:nil.
   524 	readFdArray at:idx put:nil.
   512         readCheckArray at:idx put:nil.
   525 	readCheckArray at:idx put:nil.
   513         readSemaphoreArray at:idx put:nil
   526 	readSemaphoreArray at:idx put:nil
   514     ].
   527     ].
   515     idx := writeFdArray identityIndexOf:aFileDescriptor startingAt:1.
   528     idx := writeFdArray identityIndexOf:aFileDescriptor startingAt:1.
   516     idx ~~ 0 ifTrue:[
   529     idx ~~ 0 ifTrue:[
   517         writeFdArray at:idx put:nil.
   530 	writeFdArray at:idx put:nil.
   518         writeCheckArray at:idx put:nil.
   531 	writeCheckArray at:idx put:nil.
   519         writeSemaphoreArray at:idx put:nil
   532 	writeSemaphoreArray at:idx put:nil
   520     ].
   533     ].
   521     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
   534     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
   522 
   535 
   523     "Modified: 4.8.1997 / 15:16:00 / cg"
   536     "Modified: 4.8.1997 / 15:16:00 / cg"
   524 !
   537 !
   530 
   543 
   531     |idx "{Class: SmallInteger }"
   544     |idx "{Class: SmallInteger }"
   532      wasBlocked|
   545      wasBlocked|
   533 
   546 
   534     aFileDescriptor < 0 ifTrue:[
   547     aFileDescriptor < 0 ifTrue:[
   535         'Processor [warning]: ignored invalid fd for IO action.' errorPrintCR.
   548 	'Processor [warning]: ignored invalid fd for IO action.' errorPrintCR.
   536         thisContext fullPrintAll.
   549 	thisContext fullPrintAll.
   537         ^ self
   550 	^ self
   538     ].
   551     ].
   539 
   552 
   540     wasBlocked := OperatingSystem blockInterrupts.
   553     wasBlocked := OperatingSystem blockInterrupts.
   541     (readFdArray identityIndexOf:aFileDescriptor startingAt:1) == 0 ifTrue:[
   554     (readFdArray identityIndexOf:aFileDescriptor startingAt:1) == 0 ifTrue:[
   542         idx := readFdArray identityIndexOf:nil startingAt:1.
   555 	idx := readFdArray identityIndexOf:nil startingAt:1.
   543         idx ~~ 0 ifTrue:[
   556 	idx ~~ 0 ifTrue:[
   544             readFdArray at:idx put:aFileDescriptor.
   557 	    readFdArray at:idx put:aFileDescriptor.
   545             readCheckArray at:idx put:aBlock.
   558 	    readCheckArray at:idx put:aBlock.
   546             readSemaphoreArray at:idx put:nil
   559 	    readSemaphoreArray at:idx put:nil
   547         ] ifFalse:[
   560 	] ifFalse:[
   548             readFdArray := readFdArray copyWith:aFileDescriptor.
   561 	    readFdArray := readFdArray copyWith:aFileDescriptor.
   549             readCheckArray := readCheckArray copyWith:aBlock.
   562 	    readCheckArray := readCheckArray copyWith:aBlock.
   550             readSemaphoreArray := readSemaphoreArray copyWith:nil.
   563 	    readSemaphoreArray := readSemaphoreArray copyWith:nil.
   551         ].
   564 	].
   552         useIOInterrupts ifTrue:[
   565 	useIOInterrupts ifTrue:[
   553             OperatingSystem enableIOInterruptsOn:aFileDescriptor
   566 	    OperatingSystem enableIOInterruptsOn:aFileDescriptor
   554         ].
   567 	].
   555 
   568 
   556     ].
   569     ].
   557     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
   570     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
   558 
   571 
   559     "Modified: 4.8.1997 / 15:17:28 / cg"
   572     "Modified: 4.8.1997 / 15:17:28 / cg"
   624 
   637 
   625     |wasBlocked|
   638     |wasBlocked|
   626 
   639 
   627     wasBlocked := OperatingSystem blockInterrupts.
   640     wasBlocked := OperatingSystem blockInterrupts.
   628     idleActions isNil ifTrue:[
   641     idleActions isNil ifTrue:[
   629         idleActions := OrderedCollection new
   642 	idleActions := OrderedCollection new
   630     ].
   643     ].
   631     idleActions add:aBlock.
   644     idleActions add:aBlock.
   632     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
   645     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
   633 !
   646 !
   634 
   647 
   659 
   672 
   660     "
   673     "
   661      handle all timeout actions
   674      handle all timeout actions
   662     "
   675     "
   663     anyTimeouts ifTrue:[
   676     anyTimeouts ifTrue:[
   664         self evaluateTimeouts
   677 	self evaluateTimeouts
   665     ].
   678     ].
   666 
   679 
   667     "first do a quick check for semaphores using checkActions - this is needed for
   680     "first do a quick check for semaphores using checkActions - this is needed for
   668      devices like the X-connection, where some events might be in the event
   681      devices like the X-connection, where some events might be in the event
   669      queue but the sockets input queue is empty.
   682      queue but the sockets input queue is empty.
   672      sockets and pipes (sigh)
   685      sockets and pipes (sigh)
   673     "
   686     "
   674     any := false.
   687     any := false.
   675     nActions := readCheckArray size.
   688     nActions := readCheckArray size.
   676     1 to:nActions do:[:index |
   689     1 to:nActions do:[:index |
   677         checkBlock := readCheckArray at:index.
   690 	checkBlock := readCheckArray at:index.
   678         (checkBlock notNil and:[checkBlock value]) ifTrue:[
   691 	(checkBlock notNil and:[checkBlock value]) ifTrue:[
   679             sema := readSemaphoreArray at:index.
   692 	    sema := readSemaphoreArray at:index.
   680             sema notNil ifTrue:[
   693 	    sema notNil ifTrue:[
   681                 sema signalOnce.
   694 		sema signalOnce.
   682             ].
   695 	    ].
   683             any := true.
   696 	    any := true.
   684         ]
   697 	]
   685     ].
   698     ].
   686     nActions := writeCheckArray size.
   699     nActions := writeCheckArray size.
   687     1 to:nActions do:[:index |
   700     1 to:nActions do:[:index |
   688         checkBlock := writeCheckArray at:index.
   701 	checkBlock := writeCheckArray at:index.
   689         (checkBlock notNil and:[checkBlock value]) ifTrue:[
   702 	(checkBlock notNil and:[checkBlock value]) ifTrue:[
   690             sema := writeSemaphoreArray at:index.
   703 	    sema := writeSemaphoreArray at:index.
   691             sema notNil ifTrue:[
   704 	    sema notNil ifTrue:[
   692                 sema signalOnce.
   705 		sema signalOnce.
   693             ].
   706 	    ].
   694             any := true.
   707 	    any := true.
   695         ]
   708 	]
   696     ].
   709     ].
   697 
   710 
   698     "now, someone might be runnable ..."
   711     "now, someone might be runnable ..."
   699 
   712 
   700     p := self highestPriorityRunnableProcess.
   713     p := self highestPriorityRunnableProcess.
   701     p isNil ifTrue:[
   714     p isNil ifTrue:[
   702         "/ no one runnable, hard wait for event or timeout
   715 	"/ no one runnable, hard wait for event or timeout
   703         "/ Trace ifTrue:['w' printCR.].
   716 	"/ Trace ifTrue:['w' printCR.].
   704         self waitForEventOrTimeout.
   717 	self waitForEventOrTimeout.
   705 
   718 
   706         "/ check for OS process termination
   719 	"/ check for OS process termination
   707         gotChildSignalInterrupt ifTrue:[
   720 	gotChildSignalInterrupt ifTrue:[
   708             gotChildSignalInterrupt := false.
   721 	    gotChildSignalInterrupt := false.
   709             self handleChildSignalInterrupt
   722 	    self handleChildSignalInterrupt
   710         ].
   723 	].
   711         wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
   724 	wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
   712         ^ self
   725 	^ self
   713     ].
   726     ].
   714 
   727 
   715     pri := p priority.
   728     pri := p priority.
   716 
   729 
   717     "
   730     "
   738  (a future version will have a process running to handle a timeout queue)
   751  (a future version will have a process running to handle a timeout queue)
   739 "
   752 "
   740 
   753 
   741 "
   754 "
   742     pri < TimingPriority ifTrue:[
   755     pri < TimingPriority ifTrue:[
   743         anyTimeouts ifTrue:[
   756 	anyTimeouts ifTrue:[
   744             millis := self timeToNextTimeout.
   757 	    millis := self timeToNextTimeout.
   745             millis == 0 ifTrue:[
   758 	    millis == 0 ifTrue:[
   746                 wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
   759 		wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
   747                 ^ self
   760 		^ self
   748             ]
   761 	    ]
   749         ]
   762 	]
   750     ].
   763     ].
   751 "
   764 "
   752 
   765 
   753     "
   766     "
   754      if the process to run has a lower than UserInterruptPriority,
   767      if the process to run has a lower than UserInterruptPriority,
   757      or by installing a poll-interrupt after 50ms (if the OS does not).
   770      or by installing a poll-interrupt after 50ms (if the OS does not).
   758     "
   771     "
   759     pri < UserInterruptPriority ifTrue:[
   772     pri < UserInterruptPriority ifTrue:[
   760 
   773 
   761 "comment out this if above is uncommented"
   774 "comment out this if above is uncommented"
   762         anyTimeouts ifTrue:[
   775 	anyTimeouts ifTrue:[
   763             millis := self timeToNextTimeout.
   776 	    millis := self timeToNextTimeout.
   764             millis == 0 ifTrue:[
   777 	    millis == 0 ifTrue:[
   765                 wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
   778 		wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
   766                 ^ self
   779 		^ self
   767             ].
   780 	    ].
   768         ].
   781 	].
   769 "---"
   782 "---"
   770 
   783 
   771         useIOInterrupts ifTrue:[
   784 	useIOInterrupts ifTrue:[
   772 "/            readFdArray do:[:fd |
   785 "/            readFdArray do:[:fd |
   773 "/                (fd notNil and:[fd >= 0]) ifTrue:[
   786 "/                (fd notNil and:[fd >= 0]) ifTrue:[
   774 "/                    OperatingSystem enableIOInterruptsOn:fd
   787 "/                    OperatingSystem enableIOInterruptsOn:fd
   775 "/                ].
   788 "/                ].
   776 "/            ].
   789 "/            ].
   777         ] ifFalse:[
   790 	] ifFalse:[
   778             millis notNil ifTrue:[
   791 	    millis notNil ifTrue:[
   779                 millis := millis min:EventPollingInterval
   792 		millis := millis min:EventPollingInterval
   780             ] ifFalse:[
   793 	    ] ifFalse:[
   781                 millis := EventPollingInterval
   794 		millis := EventPollingInterval
   782             ]
   795 	    ]
   783         ]
   796 	]
   784     ].
   797     ].
   785 
   798 
   786     millis notNil ifTrue:[
   799     millis notNil ifTrue:[
   787         "/ Trace ifTrue:['C' print. millis printCR.].
   800 	"/ Trace ifTrue:['C' print. millis printCR.].
   788         "schedule a clock interrupt after millis milliseconds"
   801 	"schedule a clock interrupt after millis milliseconds"
   789         OperatingSystem enableTimer:millis rounded.
   802 	OperatingSystem enableTimer:millis rounded.
   790     ].
   803     ].
   791 
   804 
   792     scheduledProcesses notNil ifTrue:[
   805     scheduledProcesses notNil ifTrue:[
   793         scheduledProcesses add:p
   806 	scheduledProcesses add:p
   794     ].
   807     ].
   795 
   808 
   796     "
   809     "
   797      now let the process run - will come back here by reschedule
   810      now let the process run - will come back here by reschedule
   798      from ioInterrupt, scheduler or timerInterrupt ... (running at max+1)
   811      from ioInterrupt, scheduler or timerInterrupt ... (running at max+1)
   800     "/ Trace ifTrue:['->' print. p printCR.].
   813     "/ Trace ifTrue:['->' print. p printCR.].
   801     self threadSwitch:p.
   814     self threadSwitch:p.
   802     "/ Trace ifTrue:['<-' printCR.].
   815     "/ Trace ifTrue:['<-' printCR.].
   803 
   816 
   804     "... when we arrive here, we are back on stage.
   817     "... when we arrive here, we are back on stage.
   805          Either by an ALARM or IO signal, or by a suspend of another process
   818 	 Either by an ALARM or IO signal, or by a suspend of another process
   806     "
   819     "
   807 
   820 
   808     millis notNil ifTrue:[
   821     millis notNil ifTrue:[
   809         OperatingSystem disableTimer.
   822 	OperatingSystem disableTimer.
   810     ].
   823     ].
   811 
   824 
   812     "/ check for OS process termination
   825     "/ check for OS process termination
   813     gotChildSignalInterrupt ifTrue:[
   826     gotChildSignalInterrupt ifTrue:[
   814         gotChildSignalInterrupt := false.
   827 	gotChildSignalInterrupt := false.
   815         self handleChildSignalInterrupt
   828 	self handleChildSignalInterrupt
   816     ].
   829     ].
   817 
   830 
   818     "/ check for new input
   831     "/ check for new input
   819 
   832 
   820     OperatingSystem unblockInterrupts.
   833     OperatingSystem unblockInterrupts.
   821 
   834 
   822     (gotIOInterrupt or:[useIOInterrupts not]) ifTrue:[
   835     (gotIOInterrupt or:[useIOInterrupts not]) ifTrue:[
   823         gotIOInterrupt := false.
   836 	gotIOInterrupt := false.
   824         self checkForIOWithTimeout:0.
   837 	self checkForIOWithTimeout:0.
   825     ].
   838     ].
   826 
   839 
   827     wasBlocked ifTrue:[OperatingSystem blockInterrupts].
   840     wasBlocked ifTrue:[OperatingSystem blockInterrupts].
   828 
   841 
   829     "Modified: / 12.4.1996 / 10:14:18 / stefan"
   842     "Modified: / 12.4.1996 / 10:14:18 / stefan"
   837     |dispatchAction handlerAction ignoredSignals|
   850     |dispatchAction handlerAction ignoredSignals|
   838 
   851 
   839     "avoid confusion if entered twice"
   852     "avoid confusion if entered twice"
   840 
   853 
   841     dispatching == true ifTrue:[
   854     dispatching == true ifTrue:[
   842         'Processor [info]: already in dispatch' infoPrintCR.
   855 	'Processor [info]: already in dispatch' infoPrintCR.
   843         ^ self
   856 	^ self
   844     ].
   857     ].
   845     dispatching := true.
   858     dispatching := true.
   846 
   859 
   847     "/ create the relevant blocks & signalSet outside of the
   860     "/ create the relevant blocks & signalSet outside of the
   848     "/ while-loop
   861     "/ while-loop
   850     "/  this safes a bit of memory allocation in the scheduler)
   863     "/  this safes a bit of memory allocation in the scheduler)
   851 
   864 
   852     dispatchAction := [ [dispatching] whileTrue:[ self dispatch ] ].
   865     dispatchAction := [ [dispatching] whileTrue:[ self dispatch ] ].
   853 
   866 
   854     handlerAction := [:ex |
   867     handlerAction := [:ex |
   855                         (HaltInterrupt accepts:ex creator) ifTrue:[
   868 			(HaltInterrupt accepts:ex creator) ifTrue:[
   856                             "/ in a standalone application, we do not want those
   869 			    "/ in a standalone application, we do not want those
   857                             Smalltalk isStandAloneApp ifTrue:[
   870 			    Smalltalk isStandAloneApp ifTrue:[
   858                                 Smalltalk isStandAloneDebug ifFalse:[
   871 				Smalltalk isStandAloneDebug ifFalse:[
   859                                     ('Processor [info]: ignored (', ex creator printString, ')') infoPrintCR.
   872 				    ('Processor [info]: ignored (', ex creator printString, ')') infoPrintCR.
   860                                     ex proceed.
   873 				    ex proceed.
   861                                 ]
   874 				]
   862                             ].
   875 			    ].
   863                         ].
   876 			].
   864 
   877 
   865                         ('Processor [info]: caught (and ignored) signal (', ex creator printString, ')') infoPrintCR.
   878 			('Processor [info]: caught (and ignored) signal (', ex creator printString, ')') infoPrintCR.
   866                         ex return
   879 			ex return
   867                      ].
   880 		     ].
   868 
   881 
   869     ignoredSignals := SignalSet
   882     ignoredSignals := SignalSet
   870                         with:HaltInterrupt
   883 			with:HaltInterrupt
   871                         with:TerminateProcessRequest
   884 			with:TerminateProcessRequest
   872                         with:RecursionError
   885 			with:RecursionError
   873                         with:AbortAllOperationRequest.
   886 			with:AbortAllOperationRequest.
   874 
   887 
   875     "/
   888     "/
   876     "/ I made this an extra call to dispatch; this allows recompilation
   889     "/ I made this an extra call to dispatch; this allows recompilation
   877     "/  of the dispatch-handling code in the running system.
   890     "/  of the dispatch-handling code in the running system.
   878     "/
   891     "/
   879     [dispatching] whileTrue:[
   892     [dispatching] whileTrue:[
   880         ignoredSignals handle:handlerAction do:dispatchAction
   893 	ignoredSignals handle:handlerAction do:dispatchAction
   881     ].
   894     ].
   882 
   895 
   883     "/ we arrive here in standalone Apps,
   896     "/ we arrive here in standalone Apps,
   884     "/ when the last process at or above UserSchedulingPriority process died.
   897     "/ when the last process at or above UserSchedulingPriority process died.
   885     "/ regular ST/X stays in above loop forever
   898     "/ regular ST/X stays in above loop forever
   907 
   920 
   908     |nPrios "{ Class: SmallInteger }"
   921     |nPrios "{ Class: SmallInteger }"
   909      p l|
   922      p l|
   910 
   923 
   911     KnownProcesses isNil ifTrue:[
   924     KnownProcesses isNil ifTrue:[
   912         KnownProcesses := WeakArray new:30.
   925 	KnownProcesses := WeakArray new:30.
   913         KnownProcesses addDependent:self class.
   926 	KnownProcesses addDependent:self class.
   914         KnownProcessIds := OrderedCollection new:30.
   927 	KnownProcessIds := OrderedCollection new:30.
   915     ].
   928     ].
   916 
   929 
   917     "
   930     "
   918      create a collection with process lists; accessed using the priority as key
   931      create a collection with process lists; accessed using the priority as key
   919     "
   932     "
   938     osChildExitActions := Dictionary new.
   951     osChildExitActions := Dictionary new.
   939     gotChildSignalInterrupt := false.
   952     gotChildSignalInterrupt := false.
   940 
   953 
   941     supportDynamicPriorities := false.
   954     supportDynamicPriorities := false.
   942     exitWhenNoMoreUserProcesses isNil ifTrue:[
   955     exitWhenNoMoreUserProcesses isNil ifTrue:[
   943         exitWhenNoMoreUserProcesses := false. "/ mhmh - how about true ?
   956 	exitWhenNoMoreUserProcesses := false. "/ mhmh - how about true ?
   944     ].
   957     ].
   945 
   958 
   946     "
   959     "
   947      handcraft the first (dispatcher-) process - this one will never
   960      handcraft the first (dispatcher-) process - this one will never
   948      block, but go into a select if there is nothing to do.
   961      block, but go into a select if there is nothing to do.
   949      Also, it has a prio of max+1 - thus, it comes first when looking
   962      Also, it has a prio of max+1 - thus, it comes first when looking
   950      for a runnable process.
   963      for a runnable process.
   951     "
   964     "
   952     currentPriority := SchedulingPriority.
   965     currentPriority := SchedulingPriority.
   953     p := Process basicNew.
   966     p := Process basicNew.
   954     p 
   967     p
   955         setId:0 state:#run;
   968 	setId:0 state:#run;
   956         setPriority:currentPriority;
   969 	setPriority:currentPriority;
   957         name:'scheduler';
   970 	name:'scheduler';
   958         beSystemProcess.
   971 	beSystemProcess.
   959 
   972 
   960     scheduler := activeProcess := p.
   973     scheduler := activeProcess := p.
   961     activeProcessId := 0.
   974     activeProcessId := 0.
   962 
   975 
   963     quiescentProcessLists at:currentPriority put:(l := LinkedList new).
   976     quiescentProcessLists at:currentPriority put:(l := LinkedList new).
   965 
   978 
   966     "
   979     "
   967      let me handle IO and timer interrupts
   980      let me handle IO and timer interrupts
   968     "
   981     "
   969     useIOInterrupts ifTrue:[ObjectMemory ioInterruptHandler:self].
   982     useIOInterrupts ifTrue:[ObjectMemory ioInterruptHandler:self].
   970     ObjectMemory 
   983     ObjectMemory
   971         timerInterruptHandler:self;
   984 	timerInterruptHandler:self;
   972         childSignalInterruptHandler:self.
   985 	childSignalInterruptHandler:self.
   973 
   986 
   974     "Modified: / 7.1.1997 / 16:48:26 / stefan"
   987     "Modified: / 7.1.1997 / 16:48:26 / stefan"
   975     "Modified: / 4.2.1999 / 13:08:39 / cg"
   988     "Modified: / 4.2.1999 / 13:08:39 / cg"
   976 !
   989 !
   977 
   990 
   993     "
  1006     "
   994      lay all processes to rest, collect restartable ones
  1007      lay all processes to rest, collect restartable ones
   995     "
  1008     "
   996     processesToRestart := OrderedCollection new.
  1009     processesToRestart := OrderedCollection new.
   997     KnownProcesses do:[:p |
  1010     KnownProcesses do:[:p |
   998         (p notNil and:[p ~~ 0]) ifTrue:[
  1011 	(p notNil and:[p ~~ 0]) ifTrue:[
   999             "how, exactly should this be done ?"
  1012 	    "how, exactly should this be done ?"
  1000 
  1013 
  1001             p isRestartable == true ifTrue:[
  1014 	    p isRestartable == true ifTrue:[
  1002                 p nextLink:nil.
  1015 		p nextLink:nil.
  1003                 processesToRestart add:p
  1016 		processesToRestart add:p
  1004             ] ifFalse:[
  1017 	    ] ifFalse:[
  1005                 p setId:nil state:#dead
  1018 		p setId:nil state:#dead
  1006             ]
  1019 	    ]
  1007         ].
  1020 	].
  1008     ].
  1021     ].
  1009     scheduler setId:nil state:#dead.
  1022     scheduler setId:nil state:#dead.
  1010 
  1023 
  1011     "
  1024     "
  1012      now, start from scratch
  1025      now, start from scratch
  1013     "
  1026     "
  1014     KnownProcesses := nil.
  1027     KnownProcesses := nil.
  1015     self initialize.
  1028     self initialize.
  1016 
  1029 
  1017     processesToRestart do:[:p |
  1030     processesToRestart do:[:p |
  1018         p imageRestart
  1031 	p imageRestart
  1019     ]
  1032     ]
  1020 
  1033 
  1021     "Modified: / 7.6.1998 / 02:23:56 / cg"
  1034     "Modified: / 7.6.1998 / 02:23:56 / cg"
  1022 ! !
  1035 ! !
  1023 
  1036 
  1031     <context: #return>
  1044     <context: #return>
  1032 
  1045 
  1033     |index pri aProcess l|
  1046     |index pri aProcess l|
  1034 
  1047 
  1035     OperatingSystem interruptsBlocked ifFalse:[
  1048     OperatingSystem interruptsBlocked ifFalse:[
  1036         MiniDebugger
  1049 	MiniDebugger
  1037             enterWithMessage:'vmResumeInterrupt with no interruptsBlocked'
  1050 	    enterWithMessage:'vmResumeInterrupt with no interruptsBlocked'
  1038             mayProceed:true.
  1051 	    mayProceed:true.
  1039     ].
  1052     ].
  1040 
  1053 
  1041     index := KnownProcessIds identityIndexOf:id.
  1054     index := KnownProcessIds identityIndexOf:id.
  1042     index ~~ 0 ifTrue:[
  1055     index ~~ 0 ifTrue:[
  1043         aProcess := KnownProcesses at:index.
  1056 	aProcess := KnownProcesses at:index.
  1044         pri := aProcess priority.
  1057 	pri := aProcess priority.
  1045         l := quiescentProcessLists at:pri.
  1058 	l := quiescentProcessLists at:pri.
  1046         l notNil ifTrue:[
  1059 	l notNil ifTrue:[
  1047             (l includesIdentical:aProcess) ifTrue:[
  1060 	    (l includesIdentical:aProcess) ifTrue:[
  1048                 "/ aProcess is on a run queue.
  1061 		"/ aProcess is on a run queue.
  1049                 "/ CG: this situation may happen, if the wrapCall
  1062 		"/ CG: this situation may happen, if the wrapCall
  1050                 "/ finishes before the process was layed to sleep
  1063 		"/ finishes before the process was layed to sleep
  1051                 "/ (i.e. schedulerIRQ arrives before the threadSwitch was finished).
  1064 		"/ (i.e. schedulerIRQ arrives before the threadSwitch was finished).
  1052                 "/ In that case, simply resume it and everything is OK.
  1065 		"/ In that case, simply resume it and everything is OK.
  1053                 "/ If the process is state running, ignore.
  1066 		"/ If the process is state running, ignore.
  1054 
  1067 
  1055                 |state|
  1068 		|state|
  1056 
  1069 
  1057                 state := aProcess state.
  1070 		state := aProcess state.
  1058                 (state == #wrapWait or:[state == #osWait] or:[state == #stopped]) ifTrue:[
  1071 		(state == #wrapWait or:[state == #osWait] or:[state == #stopped]) ifTrue:[
  1059                     aProcess state:#run.
  1072 		    aProcess state:#run.
  1060                 ].
  1073 		].
  1061                 'ProcSched [info]: resumeIRQ ignored for process: ' infoPrint.
  1074 		'ProcSched [info]: resumeIRQ ignored for process: ' infoPrint.
  1062                 aProcess id infoPrint. ' in state: ' infoPrint. state infoPrintCR.
  1075 		aProcess id infoPrint. ' in state: ' infoPrint. state infoPrintCR.
  1063                 ^ self
  1076 		^ self
  1064             ]
  1077 	    ]
  1065         ] ifFalse:[
  1078 	] ifFalse:[
  1066             l := LinkedList new.
  1079 	    l := LinkedList new.
  1067             quiescentProcessLists at:pri put:l.
  1080 	    quiescentProcessLists at:pri put:l.
  1068         ].
  1081 	].
  1069         l addLast:aProcess.
  1082 	l addLast:aProcess.
  1070         aProcess state:#run.
  1083 	aProcess state:#run.
  1071     ] ifFalse:[
  1084     ] ifFalse:[
  1072         'ProcSched [info]: resumeIRQ for unknown process: ' infoPrint.
  1085 	'ProcSched [info]: resumeIRQ for unknown process: ' infoPrint.
  1073         id infoPrintCR.
  1086 	id infoPrintCR.
  1074     ]
  1087     ]
  1075 
  1088 
  1076     "Modified: / 28.9.1998 / 11:36:53 / cg"
  1089     "Modified: / 28.9.1998 / 11:36:53 / cg"
  1077 !
  1090 !
  1078 
  1091 
  1085     <context: #return>
  1098     <context: #return>
  1086 
  1099 
  1087     |pri l newState|
  1100     |pri l newState|
  1088 
  1101 
  1089     OperatingSystem interruptsBlocked ifFalse:[
  1102     OperatingSystem interruptsBlocked ifFalse:[
  1090         MiniDebugger
  1103 	MiniDebugger
  1091             enterWithMessage:'immediateInterrupt with no interruptsBlocked'
  1104 	    enterWithMessage:'immediateInterrupt with no interruptsBlocked'
  1092             mayProceed:true.
  1105 	    mayProceed:true.
  1093     ].
  1106     ].
  1094 
  1107 
  1095     (whyCode == 2) ifTrue:[
  1108     (whyCode == 2) ifTrue:[
  1096          newState := #wrapWait.
  1109 	 newState := #wrapWait.
  1097     ] ifFalse:[
  1110     ] ifFalse:[
  1098         (whyCode == 3) ifTrue:[
  1111 	(whyCode == 3) ifTrue:[
  1099             newState := #osWait.
  1112 	    newState := #osWait.
  1100         ] ifFalse:[
  1113 	] ifFalse:[
  1101             newState := #stopped.
  1114 	    newState := #stopped.
  1102         ].
  1115 	].
  1103     ].
  1116     ].
  1104     activeProcess setStateTo:newState if:#active.
  1117     activeProcess setStateTo:newState if:#active.
  1105 
  1118 
  1106     pri := activeProcess priority.
  1119     pri := activeProcess priority.
  1107     l := quiescentProcessLists at:pri.
  1120     l := quiescentProcessLists at:pri.
  1108 
  1121 
  1109     "notice: this is slightly faster than putting the if-code into
  1122     "notice: this is slightly faster than putting the if-code into
  1110      the ifAbsent block, because [] is a shared cheap block, created at compile time
  1123      the ifAbsent block, because [] is a shared cheap block, created at compile time
  1111     "
  1124     "
  1112     (l isNil or:[(l removeIdentical:activeProcess ifAbsent:nil) isNil]) ifTrue:[
  1125     (l isNil or:[(l removeIdentical:activeProcess ifAbsent:nil) isNil]) ifTrue:[
  1113         "/ 'Processor [warning]: bad vmSuspendInterrupt: not on run list' errorPrintCR.
  1126 	"/ 'Processor [warning]: bad vmSuspendInterrupt: not on run list' errorPrintCR.
  1114         MiniDebugger enterWithMessage:'bad vmSuspendInterrupt: not on run list' mayProceed:true.
  1127 	MiniDebugger enterWithMessage:'bad vmSuspendInterrupt: not on run list' mayProceed:true.
  1115         ^ self
  1128 	^ self
  1116     ].
  1129     ].
  1117 ! !
  1130 ! !
  1118 
  1131 
  1119 !ProcessorScheduler methodsFor:'os process handling'!
  1132 !ProcessorScheduler methodsFor:'os process handling'!
  1120 
  1133 
  1124     "child changed state - switch to scheduler process which will decide
  1137     "child changed state - switch to scheduler process which will decide
  1125      what to do now."
  1138      what to do now."
  1126 
  1139 
  1127     gotChildSignalInterrupt := true.
  1140     gotChildSignalInterrupt := true.
  1128     activeProcess ~~ scheduler ifTrue:[
  1141     activeProcess ~~ scheduler ifTrue:[
  1129         interruptedProcess := activeProcess.
  1142 	interruptedProcess := activeProcess.
  1130         self threadSwitch:scheduler
  1143 	self threadSwitch:scheduler
  1131     ]
  1144     ]
  1132 
  1145 
  1133     "Modified: 12.4.1996 / 10:12:18 / stefan"
  1146     "Modified: 12.4.1996 / 10:12:18 / stefan"
  1134 !
  1147 !
  1135 
  1148 
  1142     blocking := OperatingSystem blockingChildProcessWait.
  1155     blocking := OperatingSystem blockingChildProcessWait.
  1143 
  1156 
  1144     "/ no interrupt processing, to avoid races with monitorPid
  1157     "/ no interrupt processing, to avoid races with monitorPid
  1145     wasBlocked := OperatingSystem blockInterrupts.
  1158     wasBlocked := OperatingSystem blockInterrupts.
  1146     [
  1159     [
  1147         [
  1160 	[
  1148             osProcessStatus := OperatingSystem childProcessWait:blocking pid:nil.
  1161 	    osProcessStatus := OperatingSystem childProcessWait:blocking pid:nil.
  1149             osProcessStatus notNil ifTrue:[
  1162 	    osProcessStatus notNil ifTrue:[
  1150                 |pid action|
  1163 		|pid action|
  1151 
  1164 
  1152                 pid := osProcessStatus pid.
  1165 		pid := osProcessStatus pid.
  1153                 osProcessStatus stillAlive ifTrue:[
  1166 		osProcessStatus stillAlive ifTrue:[
  1154                     action := osChildExitActions at:pid ifAbsent:nil.
  1167 		    action := osChildExitActions at:pid ifAbsent:nil.
  1155                 ] ifFalse:[
  1168 		] ifFalse:[
  1156                     action := osChildExitActions removeKey:pid ifAbsent:nil.
  1169 		    action := osChildExitActions removeKey:pid ifAbsent:nil.
  1157                 ].
  1170 		].
  1158                 action notNil ifTrue:[
  1171 		action notNil ifTrue:[
  1159                     action value:osProcessStatus
  1172 		    action value:osProcessStatus
  1160                 ].
  1173 		].
  1161             ].
  1174 	    ].
  1162 
  1175 
  1163             "/ if pollChildProcesses does block, poll only one status change.
  1176 	    "/ if pollChildProcesses does block, poll only one status change.
  1164             "/ we will get another SIGCHLD for other status changes.
  1177 	    "/ we will get another SIGCHLD for other status changes.
  1165 
  1178 
  1166             osProcessStatus notNil and:[blocking not]
  1179 	    osProcessStatus notNil and:[blocking not]
  1167         ] whileTrue.
  1180 	] whileTrue.
  1168 
  1181 
  1169         "/ if there are no more waiters, disable SIGCHILD handler.
  1182 	"/ if there are no more waiters, disable SIGCHILD handler.
  1170         "/ this helps us with synchronous waiters (e.g. pclose),
  1183 	"/ this helps us with synchronous waiters (e.g. pclose),
  1171         "/ But they should block SIGCHLD anyway.
  1184 	"/ But they should block SIGCHLD anyway.
  1172 
  1185 
  1173         osChildExitActions isEmpty ifTrue:[
  1186 	osChildExitActions isEmpty ifTrue:[
  1174             OperatingSystem disableChildSignalInterrupts.
  1187 	    OperatingSystem disableChildSignalInterrupts.
  1175         ].
  1188 	].
  1176     ] ensure:[
  1189     ] ensure:[
  1177         wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  1190 	wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  1178     ]
  1191     ]
  1179 
  1192 
  1180     "Modified: 5.1.1996 / 16:56:11 / stefan"
  1193     "Modified: 5.1.1996 / 16:56:11 / stefan"
  1181     "Modified: 28.2.1996 / 21:36:31 / cg"
  1194     "Modified: 28.2.1996 / 21:36:31 / cg"
  1182     "Created: 12.4.1996 / 10:08:21 / stefan"
  1195     "Created: 12.4.1996 / 10:08:21 / stefan"
  1201     OperatingSystem enableChildSignalInterrupts.        "/ no-op in windows
  1214     OperatingSystem enableChildSignalInterrupts.        "/ no-op in windows
  1202     wasBlocked := OperatingSystem blockInterrupts.
  1215     wasBlocked := OperatingSystem blockInterrupts.
  1203     "/ start the OS-Process
  1216     "/ start the OS-Process
  1204     pid := aBlockReturningPid value.
  1217     pid := aBlockReturningPid value.
  1205     pid notNil ifTrue:[
  1218     pid notNil ifTrue:[
  1206         osChildExitActions at:pid put:actionBlock.
  1219 	osChildExitActions at:pid put:actionBlock.
  1207     ].
  1220     ].
  1208     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  1221     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  1209     ^ pid
  1222     ^ pid
  1210 
  1223 
  1211     "Created: / 25.3.1997 / 10:54:56 / stefan"
  1224     "Created: / 25.3.1997 / 10:54:56 / stefan"
  1227 scheduleForInterrupt:aProcess
  1240 scheduleForInterrupt:aProcess
  1228     "make aProcess evaluate its pushed interrupt block(s)"
  1241     "make aProcess evaluate its pushed interrupt block(s)"
  1229 
  1242 
  1230     self scheduleInterruptActionsOf:aProcess.
  1243     self scheduleInterruptActionsOf:aProcess.
  1231     aProcess state ~~ #stopped ifTrue:[
  1244     aProcess state ~~ #stopped ifTrue:[
  1232         "
  1245 	"
  1233          make the process runnable
  1246 	 make the process runnable
  1234         "
  1247 	"
  1235         self resume:aProcess
  1248 	self resume:aProcess
  1236     ]
  1249     ]
  1237 
  1250 
  1238     "Modified: / 24.8.1998 / 18:31:32 / cg"
  1251     "Modified: / 24.8.1998 / 18:31:32 / cg"
  1239 !
  1252 !
  1240 
  1253 
  1284 "/    ok := self threadSwitchFrom:oldProcess to:aProcess id:id singleStep:singleStep.
  1297 "/    ok := self threadSwitchFrom:oldProcess to:aProcess id:id singleStep:singleStep.
  1285 %{
  1298 %{
  1286     extern OBJ ___threadSwitch();
  1299     extern OBJ ___threadSwitch();
  1287 
  1300 
  1288     if (__isSmallInteger(id)) {
  1301     if (__isSmallInteger(id)) {
  1289         ok = ___threadSwitch(__context, __intVal(id), (singleStep == true) ? 1 : 0, 0);
  1302 	ok = ___threadSwitch(__context, __intVal(id), (singleStep == true) ? 1 : 0, 0);
  1290     } else {
  1303     } else {
  1291         ok = false;
  1304 	ok = false;
  1292     }
  1305     }
  1293 %}.
  1306 %}.
  1294 
  1307 
  1295     "time passes spent in some other process ...
  1308     "time passes spent in some other process ...
  1296      ... here again"
  1309      ... here again"
  1299     activeProcess := oldProcess.
  1312     activeProcess := oldProcess.
  1300     activeProcessId := oldId.
  1313     activeProcessId := oldId.
  1301     currentPriority := oldProcess priority.
  1314     currentPriority := oldProcess priority.
  1302 
  1315 
  1303     ok == true ifFalse:[
  1316     ok == true ifFalse:[
  1304         "
  1317 	"
  1305          switch failed for some reason -
  1318 	 switch failed for some reason -
  1306          destroy (hard-terminate) the bad process.
  1319 	 destroy (hard-terminate) the bad process.
  1307          This happens when:
  1320 	 This happens when:
  1308          - the stack went above the absolute limit
  1321 	 - the stack went above the absolute limit
  1309            (VM switches back to scheduler)
  1322 	   (VM switches back to scheduler)
  1310          - a halted process cannot execute its interrupt
  1323 	 - a halted process cannot execute its interrupt
  1311            actions (win32 only)
  1324 	   actions (win32 only)
  1312         "
  1325 	"
  1313         (id := p id) ~~ 0 ifTrue:[
  1326 	(id := p id) ~~ 0 ifTrue:[
  1314             id notNil ifTrue:[
  1327 	    id notNil ifTrue:[
  1315                 'Processor [warning]: problem with process ' errorPrint.
  1328 		'Processor [warning]: problem with process ' errorPrint.
  1316                 id errorPrint.
  1329 		id errorPrint.
  1317                 (nm := p name) notNil ifTrue:[
  1330 		(nm := p name) notNil ifTrue:[
  1318                     ' (' errorPrint. nm errorPrint. ')' errorPrint.
  1331 		    ' (' errorPrint. nm errorPrint. ')' errorPrint.
  1319                 ].
  1332 		].
  1320 
  1333 
  1321                 ok == #halted ifTrue:[
  1334 		ok == #halted ifTrue:[
  1322                     "/ that process was halted (win32 only)
  1335 		    "/ that process was halted (win32 only)
  1323                     p state:#halted.
  1336 		    p state:#halted.
  1324                    '; stopped it.' errorPrintCR.
  1337 		   '; stopped it.' errorPrintCR.
  1325                    self suspend:p.
  1338 		   self suspend:p.
  1326                 ] ifFalse:[
  1339 		] ifFalse:[
  1327                    '; hard-terminate it.' errorPrintCR.
  1340 		   '; hard-terminate it.' errorPrintCR.
  1328                    'Processor [info]: cleanup may take a while if stack is huge' infoPrintCR.
  1341 		   'Processor [info]: cleanup may take a while if stack is huge' infoPrintCR.
  1329                    p state:#cleanup.
  1342 		   p state:#cleanup.
  1330                    self terminateNoSignal:p.
  1343 		   self terminateNoSignal:p.
  1331                 ]
  1344 		]
  1332             ]
  1345 	    ]
  1333         ]
  1346 	]
  1334     ].
  1347     ].
  1335     zombie notNil ifTrue:[
  1348     zombie notNil ifTrue:[
  1336         self class threadDestroy:zombie.
  1349 	self class threadDestroy:zombie.
  1337         zombie := nil
  1350 	zombie := nil
  1338     ].
  1351     ].
  1339     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  1352     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  1340 
  1353 
  1341     "Modified: / 23-07-2010 / 10:32:11 / cg"
  1354     "Modified: / 23-07-2010 / 10:32:11 / cg"
  1342 ! !
  1355 ! !
  1446 
  1459 
  1447     wasBlocked := OperatingSystem blockInterrupts.
  1460     wasBlocked := OperatingSystem blockInterrupts.
  1448     index := 1.
  1461     index := 1.
  1449     sz := KnownProcessIds size.
  1462     sz := KnownProcessIds size.
  1450     [index <= sz] whileTrue:[
  1463     [index <= sz] whileTrue:[
  1451         (KnownProcesses at:index) isNil ifTrue:[
  1464 	(KnownProcesses at:index) isNil ifTrue:[
  1452             oldId := KnownProcessIds at:index.
  1465 	    oldId := KnownProcessIds at:index.
  1453             oldId notNil ifTrue:[
  1466 	    oldId notNil ifTrue:[
  1454                 self class threadDestroy:oldId.
  1467 		self class threadDestroy:oldId.
  1455             ].
  1468 	    ].
  1456             KnownProcesses at:index put:aProcess.
  1469 	    KnownProcesses at:index put:aProcess.
  1457             KnownProcessIds at:index put:aProcess id.
  1470 	    KnownProcessIds at:index put:aProcess id.
  1458             wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  1471 	    wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  1459             ^ self
  1472 	    ^ self
  1460         ].
  1473 	].
  1461         index := index + 1
  1474 	index := index + 1
  1462     ].
  1475     ].
  1463 
  1476 
  1464     KnownProcessIds grow:index.
  1477     KnownProcessIds grow:index.
  1465     KnownProcessIds at:index put:aProcess id.
  1478     KnownProcessIds at:index put:aProcess id.
  1466 
  1479 
  1467     oldSize := KnownProcesses size.
  1480     oldSize := KnownProcesses size.
  1468     (index > oldSize) ifTrue:[
  1481     (index > oldSize) ifTrue:[
  1469         newShadow := WeakArray new:(oldSize * 2).
  1482 	newShadow := WeakArray new:(oldSize * 2).
  1470         newShadow addDependent:self class.
  1483 	newShadow addDependent:self class.
  1471         newShadow replaceFrom:1 with:KnownProcesses.
  1484 	newShadow replaceFrom:1 with:KnownProcesses.
  1472         KnownProcesses := newShadow
  1485 	KnownProcesses := newShadow
  1473     ].
  1486     ].
  1474     KnownProcesses at:index put:aProcess.
  1487     KnownProcesses at:index put:aProcess.
  1475     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  1488     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  1476 
  1489 
  1477     "Modified: 7.1.1997 / 16:48:39 / stefan"
  1490     "Modified: 7.1.1997 / 16:48:39 / stefan"
  1483     |index wasBlocked|
  1496     |index wasBlocked|
  1484 
  1497 
  1485     wasBlocked := OperatingSystem blockInterrupts.
  1498     wasBlocked := OperatingSystem blockInterrupts.
  1486     index := KnownProcesses identityIndexOf:aProcess.
  1499     index := KnownProcesses identityIndexOf:aProcess.
  1487     index ~~ 0 ifTrue:[
  1500     index ~~ 0 ifTrue:[
  1488         KnownProcessIds at:index put:nil.
  1501 	KnownProcessIds at:index put:nil.
  1489         KnownProcesses at:index put:nil.
  1502 	KnownProcesses at:index put:nil.
  1490     ].
  1503     ].
  1491     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  1504     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  1492 ! !
  1505 ! !
  1493 
  1506 
  1494 !ProcessorScheduler methodsFor:'process creation'!
  1507 !ProcessorScheduler methodsFor:'process creation'!
  1509 
  1522 
  1510 newProcessFor:aProcess withId:idWant
  1523 newProcessFor:aProcess withId:idWant
  1511     "private entry for Process restart - do not use in your program"
  1524     "private entry for Process restart - do not use in your program"
  1512 
  1525 
  1513     idWant isNil ifTrue:[
  1526     idWant isNil ifTrue:[
  1514         self newProcessFor:aProcess.
  1527 	self newProcessFor:aProcess.
  1515         ^ true.
  1528 	^ true.
  1516     ].
  1529     ].
  1517 
  1530 
  1518     (self class threadCreate:aProcess withId:idWant) ~~ idWant ifTrue:[
  1531     (self class threadCreate:aProcess withId:idWant) ~~ idWant ifTrue:[
  1519         ^ false
  1532 	^ false
  1520     ].
  1533     ].
  1521 
  1534 
  1522     aProcess state:#light.   "meaning: has no stack yet"
  1535     aProcess state:#light.   "meaning: has no stack yet"
  1523     self remember:aProcess.
  1536     self remember:aProcess.
  1524     ^ true
  1537     ^ true
  1555     wasBlocked := OperatingSystem blockInterrupts.
  1568     wasBlocked := OperatingSystem blockInterrupts.
  1556 
  1569 
  1557     listArray := quiescentProcessLists.
  1570     listArray := quiescentProcessLists.
  1558 
  1571 
  1559     [prio >= 1] whileTrue:[
  1572     [prio >= 1] whileTrue:[
  1560         l := listArray at:prio.
  1573 	l := listArray at:prio.
  1561         l notNil ifTrue:[
  1574 	l notNil ifTrue:[
  1562             l linksDo:[:aProcess |
  1575 	    l linksDo:[:aProcess |
  1563                 aProcess isUserProcess ifTrue:[
  1576 		aProcess isUserProcess ifTrue:[
  1564                     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  1577 		    wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  1565                     ^ true.
  1578 		    ^ true.
  1566                 ]
  1579 		]
  1567             ]
  1580 	    ]
  1568         ].
  1581 	].
  1569         prio := prio - 1
  1582 	prio := prio - 1
  1570     ].
  1583     ].
  1571     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  1584     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  1572     ^ false
  1585     ^ false
  1573 
  1586 
  1574     "
  1587     "
  1587     prio := HighestPriority.
  1600     prio := HighestPriority.
  1588     wasBlocked := OperatingSystem blockInterrupts.
  1601     wasBlocked := OperatingSystem blockInterrupts.
  1589 
  1602 
  1590     listArray := quiescentProcessLists.
  1603     listArray := quiescentProcessLists.
  1591     [prio >= 1] whileTrue:[
  1604     [prio >= 1] whileTrue:[
  1592         l := listArray at:prio.
  1605 	l := listArray at:prio.
  1593         l notNil ifTrue:[
  1606 	l notNil ifTrue:[
  1594             l notEmpty ifTrue:[
  1607 	    l notEmpty ifTrue:[
  1595                 p := l firstLink.
  1608 		p := l firstLink.
  1596                 "
  1609 		"
  1597                  if it got corrupted somehow ...
  1610 		 if it got corrupted somehow ...
  1598                 "
  1611 		"
  1599                 p isDead ifTrue:[
  1612 		p isDead ifTrue:[
  1600                     'Processor [warning]: dead process removed' errorPrintCR.
  1613 		    'Processor [warning]: dead process removed' errorPrintCR.
  1601                     l removeFirst.
  1614 		    l removeFirst.
  1602                     p := nil.
  1615 		    p := nil.
  1603                 ].
  1616 		].
  1604                 wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  1617 		wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  1605                 ^ p
  1618 		^ p
  1606             ]
  1619 	    ]
  1607         ].
  1620 	].
  1608         prio := prio - 1
  1621 	prio := prio - 1
  1609     ].
  1622     ].
  1610     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  1623     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  1611     ^ nil
  1624     ^ nil
  1612 
  1625 
  1613     "Modified: 12.2.1997 / 12:41:49 / cg"
  1626     "Modified: 12.2.1997 / 12:41:49 / cg"
  1653 
  1666 
  1654     wasBlocked := OperatingSystem blockInterrupts.
  1667     wasBlocked := OperatingSystem blockInterrupts.
  1655 
  1668 
  1656     slot := KnownProcessIds indexOf:anInteger.
  1669     slot := KnownProcessIds indexOf:anInteger.
  1657     slot ~~ 0 ifTrue:[
  1670     slot ~~ 0 ifTrue:[
  1658         process := KnownProcesses at:slot ifAbsent:[].
  1671 	process := KnownProcesses at:slot ifAbsent:[].
  1659     ].
  1672     ].
  1660 
  1673 
  1661     wasBlocked ifFalse:[
  1674     wasBlocked ifFalse:[
  1662         OperatingSystem unblockInterrupts.
  1675 	OperatingSystem unblockInterrupts.
  1663     ].
  1676     ].
  1664 
  1677 
  1665     "Take care, the process may already have been collected"
  1678     "Take care, the process may already have been collected"
  1666     process == 0 ifTrue:[
  1679     process == 0 ifTrue:[
  1667         ^ nil.
  1680 	^ nil.
  1668     ].
  1681     ].
  1669     ^ process.
  1682     ^ process.
  1670 
  1683 
  1671     "
  1684     "
  1672         Processor processWithId:4
  1685 	Processor processWithId:4
  1673         Processor processWithId:4711
  1686 	Processor processWithId:4711
  1674     "
  1687     "
  1675 ! !
  1688 ! !
  1676 
  1689 
  1677 !ProcessorScheduler methodsFor:'scheduling'!
  1690 !ProcessorScheduler methodsFor:'scheduling'!
  1678 
  1691 
  1688     "
  1701     "
  1689      check for valid argument
  1702      check for valid argument
  1690     "
  1703     "
  1691     newPrio := prio.
  1704     newPrio := prio.
  1692     newPrio < 1 ifTrue:[
  1705     newPrio < 1 ifTrue:[
  1693         newPrio := 1.
  1706 	newPrio := 1.
  1694     ] ifFalse:[
  1707     ] ifFalse:[
  1695         newPrio > HighestPriority ifTrue:[
  1708 	newPrio > HighestPriority ifTrue:[
  1696             newPrio := HighestPriority
  1709 	    newPrio := HighestPriority
  1697         ]
  1710 	]
  1698     ].
  1711     ].
  1699 
  1712 
  1700     [
  1713     [
  1701         wasBlocked := OperatingSystem blockInterrupts.
  1714 	wasBlocked := OperatingSystem blockInterrupts.
  1702 
  1715 
  1703         aProcess setPriority:newPrio.
  1716 	aProcess setPriority:newPrio.
  1704 
  1717 
  1705         oldList := quiescentProcessLists at:oldPrio.
  1718 	oldList := quiescentProcessLists at:oldPrio.
  1706         oldList notNil ifTrue:[
  1719 	oldList notNil ifTrue:[
  1707             (oldList removeIdentical:aProcess ifAbsent:nil) notNil ifTrue:[
  1720 	    (oldList removeIdentical:aProcess ifAbsent:nil) notNil ifTrue:[
  1708                 newList := quiescentProcessLists at:newPrio.
  1721 		newList := quiescentProcessLists at:newPrio.
  1709                 newList isNil ifTrue:[
  1722 		newList isNil ifTrue:[
  1710                     quiescentProcessLists at:newPrio put:(newList := LinkedList new).
  1723 		    quiescentProcessLists at:newPrio put:(newList := LinkedList new).
  1711                 ].
  1724 		].
  1712                 newList addLast:aProcess.
  1725 		newList addLast:aProcess.
  1713 
  1726 
  1714                 "if its the current process lowering its prio
  1727 		"if its the current process lowering its prio
  1715                  or another one raising, we have to reschedule"
  1728 		 or another one raising, we have to reschedule"
  1716 
  1729 
  1717                 aProcess == activeProcess ifTrue:[
  1730 		aProcess == activeProcess ifTrue:[
  1718                     currentPriority := newPrio.
  1731 		    currentPriority := newPrio.
  1719                     newPrio < oldPrio ifTrue:[
  1732 		    newPrio < oldPrio ifTrue:[
  1720                         self threadSwitch:scheduler.
  1733 			self threadSwitch:scheduler.
  1721                     ]
  1734 		    ]
  1722                 ] ifFalse:[
  1735 		] ifFalse:[
  1723                     newPrio > currentPriority ifTrue:[
  1736 		    newPrio > currentPriority ifTrue:[
  1724                         self threadSwitch:aProcess.
  1737 			self threadSwitch:aProcess.
  1725                     ]
  1738 		    ]
  1726                 ].
  1739 		].
  1727                 timeSliceNeededSemaphore notNil ifTrue:[
  1740 		timeSliceNeededSemaphore notNil ifTrue:[
  1728                     "/ tell timeslicer, that some work might be needed...
  1741 		    "/ tell timeslicer, that some work might be needed...
  1729                     timeSliceNeededSemaphore signalIf.
  1742 		    timeSliceNeededSemaphore signalIf.
  1730                 ]
  1743 		]
  1731             ]
  1744 	    ]
  1732         ]
  1745 	]
  1733     ] ensure:[
  1746     ] ensure:[
  1734         wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  1747 	wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  1735     ]
  1748     ]
  1736 
  1749 
  1737     "Modified: / 4.8.1998 / 00:08:54 / cg"
  1750     "Modified: / 4.8.1998 / 00:08:54 / cg"
  1738 !
  1751 !
  1739 
  1752 
  1751     "/ the interrupt block should think it was called right
  1764     "/ the interrupt block should think it was called right
  1752     "/ from the originally interrupted context
  1765     "/ from the originally interrupted context
  1753 
  1766 
  1754     s := thisContext sender.
  1767     s := thisContext sender.
  1755     s selector == #threadSwitchFrom:to:id:singleStep: ifTrue:[
  1768     s selector == #threadSwitchFrom:to:id:singleStep: ifTrue:[
  1756         s := s sender.
  1769 	s := s sender.
  1757         s selector == #threadSwitch: ifTrue:[
  1770 	s selector == #threadSwitch: ifTrue:[
  1758             s := s sender.
  1771 	    s := s sender.
  1759             s selector == #timerInterrupt ifTrue:[
  1772 	    s selector == #timerInterrupt ifTrue:[
  1760                 s := s sender
  1773 		s := s sender
  1761             ]
  1774 	    ]
  1762         ]
  1775 	]
  1763     ].
  1776     ].
  1764 
  1777 
  1765     "/ the returned value here has a subtle effect:
  1778     "/ the returned value here has a subtle effect:
  1766     "/ if false, the interrupt is assumed to be not taken,
  1779     "/ if false, the interrupt is assumed to be not taken,
  1767     "/ and will be redelivered.
  1780     "/ and will be redelivered.
  1779     "ignore, if process is already dead"
  1792     "ignore, if process is already dead"
  1780     (aProcess isNil or:[aProcess isDead]) ifTrue:[^ false].
  1793     (aProcess isNil or:[aProcess isDead]) ifTrue:[^ false].
  1781 
  1794 
  1782     s := aProcess state.
  1795     s := aProcess state.
  1783     s == #osWait ifTrue:[
  1796     s == #osWait ifTrue:[
  1784         'Processor [warning]: bad resume: #osWait' errorPrintCR.
  1797 	'Processor [warning]: bad resume: #osWait' errorPrintCR.
  1785         "/ MiniDebugger enterWithMessage:'bad resume: state osWait'.
  1798 	"/ MiniDebugger enterWithMessage:'bad resume: state osWait'.
  1786         ^ false.
  1799 	^ false.
  1787     ].
  1800     ].
  1788     s == #stopped ifTrue:[
  1801     s == #stopped ifTrue:[
  1789         "by definition, stopped processes cannot be resumed"
  1802 	"by definition, stopped processes cannot be resumed"
  1790         ^ false.
  1803 	^ false.
  1791     ].
  1804     ].
  1792 
  1805 
  1793     aProcess == activeProcess ifTrue:[
  1806     aProcess == activeProcess ifTrue:[
  1794         "special handling for waiting schedulers"
  1807 	"special handling for waiting schedulers"
  1795         aProcess == scheduler ifTrue:[
  1808 	aProcess == scheduler ifTrue:[
  1796             suspendScheduler := false.
  1809 	    suspendScheduler := false.
  1797         ].
  1810 	].
  1798         ^ false
  1811 	^ false
  1799     ].
  1812     ].
  1800 
  1813 
  1801     wasBlocked := OperatingSystem blockInterrupts.
  1814     wasBlocked := OperatingSystem blockInterrupts.
  1802 
  1815 
  1803     pri := aProcess priority.
  1816     pri := aProcess priority.
  1804 
  1817 
  1805     l := quiescentProcessLists at:pri.
  1818     l := quiescentProcessLists at:pri.
  1806     "if already running, ignore"
  1819     "if already running, ignore"
  1807     l notNil ifTrue:[
  1820     l notNil ifTrue:[
  1808         (l identityIndexOf:aProcess) ~~ 0 ifTrue:[
  1821 	(l identityIndexOf:aProcess) ~~ 0 ifTrue:[
  1809             wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  1822 	    wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  1810             ^ false
  1823 	    ^ false
  1811         ]
  1824 	]
  1812     ] ifFalse:[
  1825     ] ifFalse:[
  1813         l := LinkedList new.
  1826 	l := LinkedList new.
  1814         quiescentProcessLists at:pri put:l.
  1827 	quiescentProcessLists at:pri put:l.
  1815     ].
  1828     ].
  1816     l addLast:aProcess.
  1829     l addLast:aProcess.
  1817     aProcess state:#run.
  1830     aProcess state:#run.
  1818     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  1831     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  1819 
  1832 
  1820     pri > currentPriority ifTrue:[
  1833     pri > currentPriority ifTrue:[
  1821         "must reschedule"
  1834 	"must reschedule"
  1822         ^ true.
  1835 	^ true.
  1823     ].
  1836     ].
  1824 
  1837 
  1825     timeSliceNeededSemaphore notNil ifTrue:[
  1838     timeSliceNeededSemaphore notNil ifTrue:[
  1826         "/ tell timeslicer, that some work might be needed...
  1839 	"/ tell timeslicer, that some work might be needed...
  1827         timeSliceNeededSemaphore signalIf.
  1840 	timeSliceNeededSemaphore signalIf.
  1828     ].
  1841     ].
  1829     ^ false.
  1842     ^ false.
  1830 
  1843 
  1831     "Modified: / 29.7.1996 / 12:07:37 / cg"
  1844     "Modified: / 29.7.1996 / 12:07:37 / cg"
  1832     "Created: / 4.2.1998 / 20:58:28 / cg"
  1845     "Created: / 4.2.1998 / 20:58:28 / cg"
  1854 resume:aProcess
  1867 resume:aProcess
  1855     "set aProcess runnable -
  1868     "set aProcess runnable -
  1856      if its prio is higher than the currently running prio, switch to it."
  1869      if its prio is higher than the currently running prio, switch to it."
  1857 
  1870 
  1858     (self makeRunnable:aProcess) ifTrue:[
  1871     (self makeRunnable:aProcess) ifTrue:[
  1859         "aProcess prio is higher; immediately transfer control to it"
  1872 	"aProcess prio is higher; immediately transfer control to it"
  1860         self threadSwitch:aProcess.
  1873 	self threadSwitch:aProcess.
  1861     ].
  1874     ].
  1862 !
  1875 !
  1863 
  1876 
  1864 resumeForSingleSend:aProcess
  1877 resumeForSingleSend:aProcess
  1865     "like resume, but let the process execute a single send only.
  1878     "like resume, but let the process execute a single send only.
  1875 suspend:aProcess
  1888 suspend:aProcess
  1876     "remove the argument, aProcess from the list of runnable processes.
  1889     "remove the argument, aProcess from the list of runnable processes.
  1877      If the process is the current one, reschedule.
  1890      If the process is the current one, reschedule.
  1878 
  1891 
  1879      Notice:
  1892      Notice:
  1880          This method should only be called by Process>>suspend or
  1893 	 This method should only be called by Process>>suspend or
  1881          Process>>suspendWithState:"
  1894 	 Process>>suspendWithState:"
  1882 
  1895 
  1883     |pri l p wasBlocked|
  1896     |pri l p wasBlocked|
  1884 
  1897 
  1885     "
  1898     "
  1886      some debugging stuff
  1899      some debugging stuff
  1887     "
  1900     "
  1888     aProcess isNil ifTrue:[
  1901     aProcess isNil ifTrue:[
  1889         InvalidProcessSignal raiseRequestWith:aProcess errorString:'nil suspend'.
  1902 	InvalidProcessSignal raiseRequestWith:aProcess errorString:'nil suspend'.
  1890         ^ self
  1903 	^ self
  1891     ].
  1904     ].
  1892     aProcess isDead ifTrue:[
  1905     aProcess isDead ifTrue:[
  1893         InvalidProcessSignal raiseRequestWith:aProcess errorString:'bad suspend: already dead'.
  1906 	InvalidProcessSignal raiseRequestWith:aProcess errorString:'bad suspend: already dead'.
  1894         self threadSwitch:scheduler.
  1907 	self threadSwitch:scheduler.
  1895         ^ self
  1908 	^ self
  1896     ].
  1909     ].
  1897     aProcess == scheduler ifTrue:[
  1910     aProcess == scheduler ifTrue:[
  1898         "only the scheduler may suspend itself"
  1911 	"only the scheduler may suspend itself"
  1899         activeProcess == scheduler ifTrue:[
  1912 	activeProcess == scheduler ifTrue:[
  1900             suspendScheduler := true.
  1913 	    suspendScheduler := true.
  1901             [suspendScheduler] whileTrue:[
  1914 	    [suspendScheduler] whileTrue:[
  1902                 self dispatch.
  1915 		self dispatch.
  1903             ].
  1916 	    ].
  1904             ^ self
  1917 	    ^ self
  1905         ].
  1918 	].
  1906 
  1919 
  1907         InvalidProcessSignal raiseRequestWith:aProcess errorString:'attempt to suspend scheduler'.
  1920 	InvalidProcessSignal raiseRequestWith:aProcess errorString:'attempt to suspend scheduler'.
  1908         ^ self
  1921 	^ self
  1909     ].
  1922     ].
  1910 
  1923 
  1911     aProcess hasInterruptActions ifTrue:[
  1924     aProcess hasInterruptActions ifTrue:[
  1912         aProcess interrupt.
  1925 	aProcess interrupt.
  1913     ].
  1926     ].
  1914 
  1927 
  1915     wasBlocked := OperatingSystem blockInterrupts.
  1928     wasBlocked := OperatingSystem blockInterrupts.
  1916 
  1929 
  1917     pri := aProcess priority.
  1930     pri := aProcess priority.
  1919 
  1932 
  1920     "notice: this is slightly faster than putting the if-code into
  1933     "notice: this is slightly faster than putting the if-code into
  1921      the ifAbsent block, because [] is a shared cheap block, created at compile time
  1934      the ifAbsent block, because [] is a shared cheap block, created at compile time
  1922     "
  1935     "
  1923     (l isNil or:[(l removeIdentical:aProcess ifAbsent:nil) isNil]) ifTrue:[
  1936     (l isNil or:[(l removeIdentical:aProcess ifAbsent:nil) isNil]) ifTrue:[
  1924         "/ 'Processor [warning]: bad suspend: process is not running' errorPrintCR.
  1937 	"/ 'Processor [warning]: bad suspend: process is not running' errorPrintCR.
  1925         "/ MiniDebugger enterWithMessage:'bad suspend: process is not running'.
  1938 	"/ MiniDebugger enterWithMessage:'bad suspend: process is not running'.
  1926         aProcess == activeProcess ifTrue:[
  1939 	aProcess == activeProcess ifTrue:[
  1927             self threadSwitch:scheduler.
  1940 	    self threadSwitch:scheduler.
  1928         ].
  1941 	].
  1929         wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  1942 	wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  1930         ^ self
  1943 	^ self
  1931     ].
  1944     ].
  1932 
  1945 
  1933     (aProcess == activeProcess) ifTrue:[
  1946     (aProcess == activeProcess) ifTrue:[
  1934         "we can immediately switch sometimes"
  1947 	"we can immediately switch sometimes"
  1935         l isEmpty ifTrue:[
  1948 	l isEmpty ifTrue:[
  1936             p := scheduler
  1949 	    p := scheduler
  1937         ] ifFalse:[
  1950 	] ifFalse:[
  1938             p := l firstLink
  1951 	    p := l firstLink
  1939         ].
  1952 	].
  1940         self threadSwitch:p
  1953 	self threadSwitch:p
  1941     ].
  1954     ].
  1942 
  1955 
  1943     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  1956     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  1944 
  1957 
  1945     "Modified: / 23.9.1996 / 13:49:24 / stefan"
  1958     "Modified: / 23.9.1996 / 13:49:24 / stefan"
  1982 
  1995 
  1983     |pri id l wasBlocked|
  1996     |pri id l wasBlocked|
  1984 
  1997 
  1985     aProcess isNil ifTrue:[^ self].
  1998     aProcess isNil ifTrue:[^ self].
  1986     aProcess == scheduler ifTrue:[
  1999     aProcess == scheduler ifTrue:[
  1987         InvalidProcessSignal raiseWith:aProcess errorString:'attempt to terminate scheduler'.
  2000 	InvalidProcessSignal raiseWith:aProcess errorString:'attempt to terminate scheduler'.
  1988         ^ self
  2001 	^ self
  1989     ].
  2002     ].
  1990 
  2003 
  1991     wasBlocked := OperatingSystem blockInterrupts.
  2004     wasBlocked := OperatingSystem blockInterrupts.
  1992 
  2005 
  1993     id := aProcess id.
  2006     id := aProcess id.
  1994     id isNil ifTrue:[   "already dead"
  2007     id isNil ifTrue:[   "already dead"
  1995         wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  2008 	wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  1996         ^ self
  2009 	^ self
  1997     ].
  2010     ].
  1998 
  2011 
  1999     aProcess setId:nil state:#dead.
  2012     aProcess setId:nil state:#dead.
  2000 
  2013 
  2001     "remove the process from the runnable list"
  2014     "remove the process from the runnable list"
  2002 
  2015 
  2003     pri := aProcess priority.
  2016     pri := aProcess priority.
  2004     l := quiescentProcessLists at:pri.
  2017     l := quiescentProcessLists at:pri.
  2005     l notNil ifTrue:[
  2018     l notNil ifTrue:[
  2006         (l removeIdentical:aProcess ifAbsent:nil) "notNil ifTrue:[
  2019 	(l removeIdentical:aProcess ifAbsent:nil) "notNil ifTrue:[
  2007             l isEmpty ifTrue:[
  2020 	    l isEmpty ifTrue:[
  2008                 quiescentProcessLists at:pri put:nil
  2021 		quiescentProcessLists at:pri put:nil
  2009             ]
  2022 	    ]
  2010         ]."
  2023 	]."
  2011     ].
  2024     ].
  2012 
  2025 
  2013     aProcess == activeProcess ifTrue:[
  2026     aProcess == activeProcess ifTrue:[
  2014         "
  2027 	"
  2015          hard case - it's the currently running process
  2028 	 hard case - it's the currently running process
  2016          we must have the next active process destroy this one
  2029 	 we must have the next active process destroy this one
  2017          (we cannot destroy the chair we are sitting on ... :-)
  2030 	 (we cannot destroy the chair we are sitting on ... :-)
  2018         "
  2031 	"
  2019         zombie notNil ifTrue:[
  2032 	zombie notNil ifTrue:[
  2020             self error:'active process is zombie' mayProceed:true.
  2033 	    self error:'active process is zombie' mayProceed:true.
  2021             self class threadDestroy:zombie.
  2034 	    self class threadDestroy:zombie.
  2022         ].
  2035 	].
  2023 
  2036 
  2024         self unRemember:aProcess.
  2037 	self unRemember:aProcess.
  2025         zombie := id.
  2038 	zombie := id.
  2026 
  2039 
  2027         wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  2040 	wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  2028         self threadSwitch:scheduler.
  2041 	self threadSwitch:scheduler.
  2029         "not reached"
  2042 	"not reached"
  2030         ^ self
  2043 	^ self
  2031     ].
  2044     ].
  2032 
  2045 
  2033     self unRemember:aProcess.
  2046     self unRemember:aProcess.
  2034     self class threadDestroy:id.
  2047     self class threadDestroy:id.
  2035 
  2048 
  2048     |l sz wasBlocked|
  2061     |l sz wasBlocked|
  2049 
  2062 
  2050     wasBlocked := OperatingSystem blockInterrupts.
  2063     wasBlocked := OperatingSystem blockInterrupts.
  2051 
  2064 
  2052     activeProcess == scheduler ifTrue:[
  2065     activeProcess == scheduler ifTrue:[
  2053         'Processor [warning]: scheduler tries to yield' errorPrintCR.
  2066 	'Processor [warning]: scheduler tries to yield' errorPrintCR.
  2054         ^ self
  2067 	^ self
  2055     ].
  2068     ].
  2056 
  2069 
  2057     "
  2070     "
  2058      debugging consistency check - will be removed later
  2071      debugging consistency check - will be removed later
  2059     "
  2072     "
  2060     activeProcess priority ~~ currentPriority ifTrue:[
  2073     activeProcess priority ~~ currentPriority ifTrue:[
  2061         'Processor [warning]: process changed its priority' errorPrintCR.
  2074 	'Processor [warning]: process changed its priority' errorPrintCR.
  2062         currentPriority := activeProcess priority.
  2075 	currentPriority := activeProcess priority.
  2063     ].
  2076     ].
  2064 
  2077 
  2065     l := quiescentProcessLists at:currentPriority.
  2078     l := quiescentProcessLists at:currentPriority.
  2066     sz := l size.
  2079     sz := l size.
  2067 
  2080 
  2068     "
  2081     "
  2069      debugging consistency checks - will be removed later
  2082      debugging consistency checks - will be removed later
  2070     "
  2083     "
  2071     sz == 0 ifTrue:[
  2084     sz == 0 ifTrue:[
  2072         wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  2085 	wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  2073         'Processor [warning]: empty runnable list' errorPrintCR.
  2086 	'Processor [warning]: empty runnable list' errorPrintCR.
  2074         ^ self
  2087 	^ self
  2075     ].
  2088     ].
  2076 
  2089 
  2077     "
  2090     "
  2078      check if the running process is not the only one
  2091      check if the running process is not the only one
  2079     "
  2092     "
  2080     sz ~~ 1 ifTrue:[
  2093     sz ~~ 1 ifTrue:[
  2081         "
  2094 	"
  2082          bring running process to the end
  2095 	 bring running process to the end
  2083         "
  2096 	"
  2084         l removeFirst.
  2097 	l removeFirst.
  2085         l addLast:activeProcess.
  2098 	l addLast:activeProcess.
  2086 
  2099 
  2087         "
  2100 	"
  2088          and switch to first in the list
  2101 	 and switch to first in the list
  2089         "
  2102 	"
  2090         self threadSwitch:(l firstLink).
  2103 	self threadSwitch:(l firstLink).
  2091     ].
  2104     ].
  2092     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  2105     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  2093 
  2106 
  2094     "Modified: / 02-08-2010 / 13:36:25 / cg"
  2107     "Modified: / 02-08-2010 / 13:36:25 / cg"
  2095 ! !
  2108 ! !
  2100     "recompute dynamic priorities."
  2113     "recompute dynamic priorities."
  2101 
  2114 
  2102     |processesToDecrease processesToIncrease|
  2115     |processesToDecrease processesToIncrease|
  2103 
  2116 
  2104     scheduledProcesses notNil ifTrue:[
  2117     scheduledProcesses notNil ifTrue:[
  2105         "/ this is written a bit cryptic - to avoid creation
  2118 	"/ this is written a bit cryptic - to avoid creation
  2106         "/ of garbage objects (Id'sets) if possible.
  2119 	"/ of garbage objects (Id'sets) if possible.
  2107         "/ since this runs 50 times a second and most of the
  2120 	"/ since this runs 50 times a second and most of the
  2108         "/ time, no rescheduling is req'd
  2121 	"/ time, no rescheduling is req'd
  2109 
  2122 
  2110         scheduledProcesses do:[:aProcess |
  2123 	scheduledProcesses do:[:aProcess |
  2111             |range|
  2124 	    |range|
  2112 
  2125 
  2113             "/ decrease priority of processes that did run
  2126 	    "/ decrease priority of processes that did run
  2114             (range := aProcess priorityRange) notNil ifTrue:[
  2127 	    (range := aProcess priorityRange) notNil ifTrue:[
  2115                 aProcess priority > range start ifTrue:[
  2128 		aProcess priority > range start ifTrue:[
  2116                     processesToDecrease isNil ifTrue:[
  2129 		    processesToDecrease isNil ifTrue:[
  2117                         processesToDecrease := IdentitySet new.
  2130 			processesToDecrease := IdentitySet new.
  2118                     ].
  2131 		    ].
  2119                     processesToDecrease add:aProcess.
  2132 		    processesToDecrease add:aProcess.
  2120                 ]
  2133 		]
  2121             ]
  2134 	    ]
  2122         ].
  2135 	].
  2123 
  2136 
  2124         processesToDecrease notNil ifTrue:[
  2137 	processesToDecrease notNil ifTrue:[
  2125             processesToDecrease do:[:aProcess |
  2138 	    processesToDecrease do:[:aProcess |
  2126                 |newPri|
  2139 		|newPri|
  2127 
  2140 
  2128                 "/ newPri := aProcess priority - 1.
  2141 		"/ newPri := aProcess priority - 1.
  2129                 newPri := aProcess priorityRange start.
  2142 		newPri := aProcess priorityRange start.
  2130                 self changePriority:newPri for:aProcess.
  2143 		self changePriority:newPri for:aProcess.
  2131             ].
  2144 	    ].
  2132         ].
  2145 	].
  2133 
  2146 
  2134         "/ and increase all prios of those that did not run, but are runnable
  2147 	"/ and increase all prios of those that did not run, but are runnable
  2135 
  2148 
  2136         TimeSlicingPriorityLimit to:1 by:-1 do:[:i |
  2149 	TimeSlicingPriorityLimit to:1 by:-1 do:[:i |
  2137             |list|
  2150 	    |list|
  2138 
  2151 
  2139             (list := quiescentProcessLists at:i) size > 0 ifTrue:[
  2152 	    (list := quiescentProcessLists at:i) size > 0 ifTrue:[
  2140                 list linksDo:[:aProcess |
  2153 		list linksDo:[:aProcess |
  2141                     |range prio|
  2154 		    |range prio|
  2142 
  2155 
  2143                     (range := aProcess priorityRange) notNil ifTrue:[
  2156 		    (range := aProcess priorityRange) notNil ifTrue:[
  2144                         (processesToDecrease isNil
  2157 			(processesToDecrease isNil
  2145                         or:[(processesToDecrease includes:aProcess) not]) ifTrue:[
  2158 			or:[(processesToDecrease includes:aProcess) not]) ifTrue:[
  2146                             aProcess priority < range stop ifTrue:[
  2159 			    aProcess priority < range stop ifTrue:[
  2147                                 processesToIncrease isNil ifTrue:[
  2160 				processesToIncrease isNil ifTrue:[
  2148                                     processesToIncrease := OrderedCollection new.
  2161 				    processesToIncrease := OrderedCollection new.
  2149                                 ].
  2162 				].
  2150                                 processesToIncrease add:aProcess
  2163 				processesToIncrease add:aProcess
  2151                             ]
  2164 			    ]
  2152                         ]
  2165 			]
  2153                     ]
  2166 		    ]
  2154                 ]
  2167 		]
  2155             ]
  2168 	    ]
  2156         ].
  2169 	].
  2157         processesToIncrease notNil ifTrue:[
  2170 	processesToIncrease notNil ifTrue:[
  2158             processesToIncrease do:[:aProcess |
  2171 	    processesToIncrease do:[:aProcess |
  2159                 self changePriority:(aProcess priority + 1) for:aProcess.
  2172 		self changePriority:(aProcess priority + 1) for:aProcess.
  2160             ].
  2173 	    ].
  2161         ].
  2174 	].
  2162     ].
  2175     ].
  2163 
  2176 
  2164     "Modified: / 30-07-2013 / 19:33:14 / cg"
  2177     "Modified: / 30-07-2013 / 19:33:14 / cg"
  2165 !
  2178 !
  2166 
  2179 
  2185     wasBlocked := OperatingSystem blockInterrupts.
  2198     wasBlocked := OperatingSystem blockInterrupts.
  2186 
  2199 
  2187     i := TimeSlicingPriorityLimit.
  2200     i := TimeSlicingPriorityLimit.
  2188     [(i > 0) and:[(list := quiescentProcessLists at:i) size <= 1]] whileTrue: [i := i - 1].
  2201     [(i > 0) and:[(list := quiescentProcessLists at:i) size <= 1]] whileTrue: [i := i - 1].
  2189     i ~~ 0 ifTrue: [
  2202     i ~~ 0 ifTrue: [
  2190         "/ shuffle that list
  2203 	"/ shuffle that list
  2191         list addLast:(list removeFirst).
  2204 	list addLast:(list removeFirst).
  2192         anyShuffle := true.
  2205 	anyShuffle := true.
  2193     ].
  2206     ].
  2194     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  2207     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  2195     anyShuffle ifFalse:[
  2208     anyShuffle ifFalse:[
  2196         "/ wait for the scheduler to make some process runnable...
  2209 	"/ wait for the scheduler to make some process runnable...
  2197         timeSliceNeededSemaphore wait.
  2210 	timeSliceNeededSemaphore wait.
  2198     ].
  2211     ].
  2199 
  2212 
  2200     "Modified: / 4.8.1998 / 00:13:32 / cg"
  2213     "Modified: / 4.8.1998 / 00:13:32 / cg"
  2201 !
  2214 !
  2202 
  2215 
  2206     timeSliceProcess notNil ifTrue: [^ self].
  2219     timeSliceProcess notNil ifTrue: [^ self].
  2207 
  2220 
  2208     timeSliceNeededSemaphore := Semaphore new name:'timeSlice needed'.
  2221     timeSliceNeededSemaphore := Semaphore new name:'timeSlice needed'.
  2209 
  2222 
  2210     timeSliceProcess := [
  2223     timeSliceProcess := [
  2211         [
  2224 	[
  2212             self timeSlicingLoop.
  2225 	    self timeSlicingLoop.
  2213         ] ifCurtailed:[
  2226 	] ifCurtailed:[
  2214             timeSliceProcess := nil.
  2227 	    timeSliceProcess := nil.
  2215             'Processor [info]: timeslicer finished' infoPrintCR.
  2228 	    'Processor [info]: timeslicer finished' infoPrintCR.
  2216         ]
  2229 	]
  2217     ] newProcess.
  2230     ] newProcess.
  2218     timeSliceProcess 
  2231     timeSliceProcess
  2219         priority:HighestPriority;
  2232 	priority:HighestPriority;
  2220         name:'time slicer';
  2233 	name:'time slicer';
  2221         restartable:true;
  2234 	restartable:true;
  2222         beSystemProcess;
  2235 	beSystemProcess;
  2223         resume.
  2236 	resume.
  2224 
  2237 
  2225     "
  2238     "
  2226      Processor stopTimeSlicing.
  2239      Processor stopTimeSlicing.
  2227      Processor startTimeSlicing.
  2240      Processor startTimeSlicing.
  2228     "
  2241     "
  2233 
  2246 
  2234 stopTimeSlicing
  2247 stopTimeSlicing
  2235     "stop preemptive scheduling (timeSlicing)"
  2248     "stop preemptive scheduling (timeSlicing)"
  2236 
  2249 
  2237     timeSliceProcess notNil ifTrue: [
  2250     timeSliceProcess notNil ifTrue: [
  2238         timeSliceProcess terminate.
  2251 	timeSliceProcess terminate.
  2239         timeSliceProcess := nil.
  2252 	timeSliceProcess := nil.
  2240         scheduledProcesses := nil.
  2253 	scheduledProcesses := nil.
  2241         timeSliceNeededSemaphore := nil.
  2254 	timeSliceNeededSemaphore := nil.
  2242     ]
  2255     ]
  2243 
  2256 
  2244     "
  2257     "
  2245      Processor stopTimeSlicing
  2258      Processor stopTimeSlicing
  2246     "
  2259     "
  2277     myDelay := Delay forMilliseconds:(t := TimeSliceInterval).
  2290     myDelay := Delay forMilliseconds:(t := TimeSliceInterval).
  2278     flipFlop := true.
  2291     flipFlop := true.
  2279 
  2292 
  2280     'Processor [info]: timeslicer started' infoPrintCR.
  2293     'Processor [info]: timeslicer started' infoPrintCR.
  2281     [
  2294     [
  2282         t ~~ TimeSliceInterval ifTrue:[
  2295 	t ~~ TimeSliceInterval ifTrue:[
  2283             "/ interval changed -> need a new delay
  2296 	    "/ interval changed -> need a new delay
  2284             myDelay delay:(t := TimeSliceInterval).
  2297 	    myDelay delay:(t := TimeSliceInterval).
  2285         ].
  2298 	].
  2286         myDelay wait.
  2299 	myDelay wait.
  2287         self slice.
  2300 	self slice.
  2288 
  2301 
  2289         "/ every other tick, recompute priorities.
  2302 	"/ every other tick, recompute priorities.
  2290         flipFlop := flipFlop not.
  2303 	flipFlop := flipFlop not.
  2291         flipFlop ifTrue:[
  2304 	flipFlop ifTrue:[
  2292             scheduledProcesses notNil ifTrue:[
  2305 	    scheduledProcesses notNil ifTrue:[
  2293                 supportDynamicPriorities ifTrue:[
  2306 		supportDynamicPriorities ifTrue:[
  2294                     self recomputeDynamicPriorities.
  2307 		    self recomputeDynamicPriorities.
  2295                 ].
  2308 		].
  2296                 scheduledProcesses clearContents.
  2309 		scheduledProcesses clearContents.
  2297             ] ifFalse:[
  2310 	    ] ifFalse:[
  2298                 scheduledProcesses := IdentitySet new.
  2311 		scheduledProcesses := IdentitySet new.
  2299             ].
  2312 	    ].
  2300         ].
  2313 	].
  2301     ] loop.
  2314     ] loop.
  2302 ! !
  2315 ! !
  2303 
  2316 
  2304 !ProcessorScheduler methodsFor:'semaphore signalling'!
  2317 !ProcessorScheduler methodsFor:'semaphore signalling'!
  2305 
  2318 
  2310      wasBlocked fd|
  2323      wasBlocked fd|
  2311 
  2324 
  2312     wasBlocked := OperatingSystem blockInterrupts.
  2325     wasBlocked := OperatingSystem blockInterrupts.
  2313     idx := readSemaphoreArray identityIndexOf:aSemaphore startingAt:1.
  2326     idx := readSemaphoreArray identityIndexOf:aSemaphore startingAt:1.
  2314     [idx ~~ 0] whileTrue:[
  2327     [idx ~~ 0] whileTrue:[
  2315         useIOInterrupts ifTrue:[
  2328 	useIOInterrupts ifTrue:[
  2316             fd := readFdArray at:idx.
  2329 	    fd := readFdArray at:idx.
  2317             fd notNil ifTrue:[
  2330 	    fd notNil ifTrue:[
  2318                 OperatingSystem disableIOInterruptsOn:fd
  2331 		OperatingSystem disableIOInterruptsOn:fd
  2319             ].
  2332 	    ].
  2320         ].
  2333 	].
  2321         readFdArray at:idx put:nil.
  2334 	readFdArray at:idx put:nil.
  2322         readSemaphoreArray at:idx put:nil.
  2335 	readSemaphoreArray at:idx put:nil.
  2323         readCheckArray at:idx put:nil.
  2336 	readCheckArray at:idx put:nil.
  2324         idx := readSemaphoreArray identityIndexOf:aSemaphore startingAt:idx+1.
  2337 	idx := readSemaphoreArray identityIndexOf:aSemaphore startingAt:idx+1.
  2325     ].
  2338     ].
  2326     idx := writeSemaphoreArray identityIndexOf:aSemaphore startingAt:1.
  2339     idx := writeSemaphoreArray identityIndexOf:aSemaphore startingAt:1.
  2327     [idx ~~ 0] whileTrue:[
  2340     [idx ~~ 0] whileTrue:[
  2328         useIOInterrupts ifTrue:[
  2341 	useIOInterrupts ifTrue:[
  2329             fd := writeFdArray at:idx.
  2342 	    fd := writeFdArray at:idx.
  2330             fd notNil ifTrue:[
  2343 	    fd notNil ifTrue:[
  2331                 OperatingSystem disableIOInterruptsOn:fd
  2344 		OperatingSystem disableIOInterruptsOn:fd
  2332             ].
  2345 	    ].
  2333         ].
  2346 	].
  2334         writeFdArray at:idx put:nil.
  2347 	writeFdArray at:idx put:nil.
  2335         writeSemaphoreArray at:idx put:nil.
  2348 	writeSemaphoreArray at:idx put:nil.
  2336         writeCheckArray at:idx put:nil.
  2349 	writeCheckArray at:idx put:nil.
  2337         idx := writeSemaphoreArray identityIndexOf:aSemaphore startingAt:idx+1.
  2350 	idx := writeSemaphoreArray identityIndexOf:aSemaphore startingAt:idx+1.
  2338     ].
  2351     ].
  2339     idx := timeoutSemaphoreArray identityIndexOf:aSemaphore startingAt:1.
  2352     idx := timeoutSemaphoreArray identityIndexOf:aSemaphore startingAt:1.
  2340     [idx ~~ 0] whileTrue:[
  2353     [idx ~~ 0] whileTrue:[
  2341         timeoutArray at:idx put:nil.
  2354 	timeoutArray at:idx put:nil.
  2342         timeoutSemaphoreArray at:idx put:nil.
  2355 	timeoutSemaphoreArray at:idx put:nil.
  2343         timeoutActionArray at:idx put:nil.
  2356 	timeoutActionArray at:idx put:nil.
  2344         timeoutProcessArray at:idx put:nil.
  2357 	timeoutProcessArray at:idx put:nil.
  2345         idx := timeoutSemaphoreArray identityIndexOf:aSemaphore startingAt:idx+1.
  2358 	idx := timeoutSemaphoreArray identityIndexOf:aSemaphore startingAt:idx+1.
  2346     ].
  2359     ].
  2347     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  2360     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  2348 
  2361 
  2349     "Modified: 4.8.1997 / 15:19:33 / cg"
  2362     "Modified: 4.8.1997 / 15:19:33 / cg"
  2350 !
  2363 !
  2399      wasBlocked|
  2412      wasBlocked|
  2400 
  2413 
  2401     wasBlocked := OperatingSystem blockInterrupts.
  2414     wasBlocked := OperatingSystem blockInterrupts.
  2402     index := timeoutSemaphoreArray identityIndexOf:aSemaphore startingAt:1.
  2415     index := timeoutSemaphoreArray identityIndexOf:aSemaphore startingAt:1.
  2403     index ~~ 0 ifTrue:[
  2416     index ~~ 0 ifTrue:[
  2404         timeoutArray at:index put:aMillisecondTime
  2417 	timeoutArray at:index put:aMillisecondTime
  2405     ] ifFalse:[
  2418     ] ifFalse:[
  2406         index := timeoutArray identityIndexOf:nil startingAt:1.
  2419 	index := timeoutArray identityIndexOf:nil startingAt:1.
  2407         index ~~ 0 ifTrue:[
  2420 	index ~~ 0 ifTrue:[
  2408             timeoutSemaphoreArray at:index put:aSemaphore.
  2421 	    timeoutSemaphoreArray at:index put:aSemaphore.
  2409             timeoutArray at:index put:aMillisecondTime.
  2422 	    timeoutArray at:index put:aMillisecondTime.
  2410             timeoutActionArray at:index put:nil.
  2423 	    timeoutActionArray at:index put:nil.
  2411             timeoutProcessArray at:index put:nil
  2424 	    timeoutProcessArray at:index put:nil
  2412         ] ifFalse:[
  2425 	] ifFalse:[
  2413             timeoutSemaphoreArray := timeoutSemaphoreArray copyWith:aSemaphore.
  2426 	    timeoutSemaphoreArray := timeoutSemaphoreArray copyWith:aSemaphore.
  2414             timeoutArray := timeoutArray copyWith:aMillisecondTime.
  2427 	    timeoutArray := timeoutArray copyWith:aMillisecondTime.
  2415             timeoutActionArray := timeoutActionArray copyWith:nil.
  2428 	    timeoutActionArray := timeoutActionArray copyWith:nil.
  2416             timeoutProcessArray := timeoutProcessArray copyWith:nil
  2429 	    timeoutProcessArray := timeoutProcessArray copyWith:nil
  2417         ].
  2430 	].
  2418     ].
  2431     ].
  2419 
  2432 
  2420     anyTimeouts := true.
  2433     anyTimeouts := true.
  2421     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  2434     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  2422 !
  2435 !
  2446 
  2459 
  2447     "Here we assume, that for every triple (aSemaphore, aFileDescriptor, aBlock)
  2460     "Here we assume, that for every triple (aSemaphore, aFileDescriptor, aBlock)
  2448      aSemphore is never nil, but one of aFileDescriptor, aBlock may be nil"
  2461      aSemphore is never nil, but one of aFileDescriptor, aBlock may be nil"
  2449 
  2462 
  2450     aFileDescriptor isNil ifTrue:[
  2463     aFileDescriptor isNil ifTrue:[
  2451         idx := readSemaphoreArray identityIndexOf:aSemaphore or:nil.
  2464 	idx := readSemaphoreArray identityIndexOf:aSemaphore or:nil.
  2452         idx == 0 ifTrue:[
  2465 	idx == 0 ifTrue:[
  2453             "aSemaphore is not registered yet, have to create a new slot"
  2466 	    "aSemaphore is not registered yet, have to create a new slot"
  2454             readFdArray := readFdArray copyWith:nil.
  2467 	    readFdArray := readFdArray copyWith:nil.
  2455             readSemaphoreArray := readSemaphoreArray copyWith:aSemaphore.
  2468 	    readSemaphoreArray := readSemaphoreArray copyWith:aSemaphore.
  2456             readCheckArray := readCheckArray copyWith:aBlock.
  2469 	    readCheckArray := readCheckArray copyWith:aBlock.
  2457         ] ifFalse:[
  2470 	] ifFalse:[
  2458             slot := readSemaphoreArray at:idx.
  2471 	    slot := readSemaphoreArray at:idx.
  2459             slot isNil ifTrue:[
  2472 	    slot isNil ifTrue:[
  2460                 readSemaphoreArray at:idx put:aSemaphore.
  2473 		readSemaphoreArray at:idx put:aSemaphore.
  2461                 readCheckArray at:idx put:aBlock
  2474 		readCheckArray at:idx put:aBlock
  2462             ] ifFalse:[
  2475 	    ] ifFalse:[
  2463                 "/ someone has already registered aSemaphore.
  2476 		"/ someone has already registered aSemaphore.
  2464                 "/ Check if it is the block changes...
  2477 		"/ Check if it is the block changes...
  2465                 (readCheckArray at:idx) notNil ifTrue:[
  2478 		(readCheckArray at:idx) notNil ifTrue:[
  2466                     (readCheckArray at:idx) ~~ aBlock ifTrue:[
  2479 		    (readCheckArray at:idx) ~~ aBlock ifTrue:[
  2467                         'Processor [info]: checkblock changed for read-check' infoPrintCR.
  2480 			'Processor [info]: checkblock changed for read-check' infoPrintCR.
  2468                         readCheckArray at:idx put:aBlock.
  2481 			readCheckArray at:idx put:aBlock.
  2469                     ].
  2482 		    ].
  2470                 ].
  2483 		].
  2471             ].
  2484 	    ].
  2472         ]
  2485 	]
  2473     ] ifFalse:[
  2486     ] ifFalse:[
  2474         idx := readFdArray identityIndexOf:aFileDescriptor or:nil.
  2487 	idx := readFdArray identityIndexOf:aFileDescriptor or:nil.
  2475         idx == 0 ifTrue:[
  2488 	idx == 0 ifTrue:[
  2476             "aFileDescriptor is not registered yet, have to create a new slot"
  2489 	    "aFileDescriptor is not registered yet, have to create a new slot"
  2477             readFdArray := readFdArray copyWith:aFileDescriptor.
  2490 	    readFdArray := readFdArray copyWith:aFileDescriptor.
  2478             readSemaphoreArray := readSemaphoreArray copyWith:aSemaphore.
  2491 	    readSemaphoreArray := readSemaphoreArray copyWith:aSemaphore.
  2479             readCheckArray := readCheckArray copyWith:aBlock.
  2492 	    readCheckArray := readCheckArray copyWith:aBlock.
  2480         ] ifFalse:[
  2493 	] ifFalse:[
  2481             slot := readFdArray at:idx.
  2494 	    slot := readFdArray at:idx.
  2482             slot isNil ifTrue:[
  2495 	    slot isNil ifTrue:[
  2483                 readFdArray at:idx put:aFileDescriptor.
  2496 		readFdArray at:idx put:aFileDescriptor.
  2484                 readSemaphoreArray at:idx put:aSemaphore.
  2497 		readSemaphoreArray at:idx put:aSemaphore.
  2485                 readCheckArray at:idx put:aBlock
  2498 		readCheckArray at:idx put:aBlock
  2486             ] ifFalse:[
  2499 	    ] ifFalse:[
  2487                 "/ someone has already registered aFileDescriptor.
  2500 		"/ someone has already registered aFileDescriptor.
  2488                 "/ Check if it is the semaphore or block changes...
  2501 		"/ Check if it is the semaphore or block changes...
  2489                 (readSemaphoreArray at:idx) ~~ aSemaphore ifTrue:[
  2502 		(readSemaphoreArray at:idx) ~~ aSemaphore ifTrue:[
  2490                     'Processor [info]: sema changed for read-check' infoPrintCR.
  2503 		    'Processor [info]: sema changed for read-check' infoPrintCR.
  2491                     readSemaphoreArray at:idx put:aSemaphore.
  2504 		    readSemaphoreArray at:idx put:aSemaphore.
  2492                 ].
  2505 		].
  2493                 (readCheckArray at:idx) ~~ aBlock ifTrue:[
  2506 		(readCheckArray at:idx) ~~ aBlock ifTrue:[
  2494                     'Processor [info]: checkblock changed for read-check' infoPrintCR.
  2507 		    'Processor [info]: checkblock changed for read-check' infoPrintCR.
  2495                     readCheckArray at:idx put:aBlock.
  2508 		    readCheckArray at:idx put:aBlock.
  2496                 ].
  2509 		].
  2497             ].
  2510 	    ].
  2498         ].
  2511 	].
  2499         (useIOInterrupts and:[slot isNil]) ifTrue:[
  2512 	(useIOInterrupts and:[slot isNil]) ifTrue:[
  2500             OperatingSystem enableIOInterruptsOn:aFileDescriptor
  2513 	    OperatingSystem enableIOInterruptsOn:aFileDescriptor
  2501         ].
  2514 	].
  2502     ].
  2515     ].
  2503     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  2516     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  2504 
  2517 
  2505     "Modified: 4.8.1997 / 15:20:45 / cg"
  2518     "Modified: 4.8.1997 / 15:20:45 / cg"
  2506 !
  2519 !
  2509     "arrange for a semaphore to be triggered when input on aStream arrives.
  2522     "arrange for a semaphore to be triggered when input on aStream arrives.
  2510      This will do a select, if the OS supports selecting on that filedescriptor,
  2523      This will do a select, if the OS supports selecting on that filedescriptor,
  2511      otherwise, it will be polled every few milliseconds (MSDOS)."
  2524      otherwise, it will be polled every few milliseconds (MSDOS)."
  2512 
  2525 
  2513     aStream canBeSelected ifTrue:[
  2526     aStream canBeSelected ifTrue:[
  2514         "/ can this stream be selected on ?
  2527 	"/ can this stream be selected on ?
  2515         self signal:aSemaphore onInput:aStream fileDescriptor orCheck:nil
  2528 	self signal:aSemaphore onInput:aStream fileDescriptor orCheck:nil
  2516     ] ifFalse:[
  2529     ] ifFalse:[
  2517         "/ nope - must poll ...
  2530 	"/ nope - must poll ...
  2518         self signal:aSemaphore onInput:nil orCheck:[aStream canReadWithoutBlocking]
  2531 	self signal:aSemaphore onInput:nil orCheck:[aStream canReadWithoutBlocking]
  2519     ]
  2532     ]
  2520 
  2533 
  2521     "Modified: / 14.12.1999 / 23:58:50 / cg"
  2534     "Modified: / 14.12.1999 / 23:58:50 / cg"
  2522 !
  2535 !
  2523 
  2536 
  2547 
  2560 
  2548     "Here we assume, that for every triple (aSemaphore, aFileDescriptor, aBlock)
  2561     "Here we assume, that for every triple (aSemaphore, aFileDescriptor, aBlock)
  2549      aSemphore is never nil, but one of aFileDescriptor, aBlock may be nil"
  2562      aSemphore is never nil, but one of aFileDescriptor, aBlock may be nil"
  2550 
  2563 
  2551     aFileDescriptor isNil ifTrue:[
  2564     aFileDescriptor isNil ifTrue:[
  2552         idx := writeSemaphoreArray identityIndexOf:aSemaphore or:nil.
  2565 	idx := writeSemaphoreArray identityIndexOf:aSemaphore or:nil.
  2553         idx == 0 ifTrue:[
  2566 	idx == 0 ifTrue:[
  2554             "aSemaphore is not registered yet, have to create a new slot"
  2567 	    "aSemaphore is not registered yet, have to create a new slot"
  2555             writeFdArray := writeFdArray copyWith:nil.
  2568 	    writeFdArray := writeFdArray copyWith:nil.
  2556             writeSemaphoreArray := writeSemaphoreArray copyWith:aSemaphore.
  2569 	    writeSemaphoreArray := writeSemaphoreArray copyWith:aSemaphore.
  2557             writeCheckArray := writeCheckArray copyWith:aBlock.
  2570 	    writeCheckArray := writeCheckArray copyWith:aBlock.
  2558         ] ifFalse:[
  2571 	] ifFalse:[
  2559             slot := writeSemaphoreArray at:idx.
  2572 	    slot := writeSemaphoreArray at:idx.
  2560             slot isNil ifTrue:[
  2573 	    slot isNil ifTrue:[
  2561                 writeSemaphoreArray at:idx put:aSemaphore.
  2574 		writeSemaphoreArray at:idx put:aSemaphore.
  2562                 writeCheckArray at:idx put:aBlock
  2575 		writeCheckArray at:idx put:aBlock
  2563             ] ifFalse:[
  2576 	    ] ifFalse:[
  2564                 "/ someone has already registered aSemaphore.
  2577 		"/ someone has already registered aSemaphore.
  2565                 "/ Check if it is the block changes...
  2578 		"/ Check if it is the block changes...
  2566                 (writeCheckArray at:idx) notNil ifTrue:[
  2579 		(writeCheckArray at:idx) notNil ifTrue:[
  2567                     (writeCheckArray at:idx) ~~ aBlock ifTrue:[
  2580 		    (writeCheckArray at:idx) ~~ aBlock ifTrue:[
  2568                         'Processor [info]: checkblock changed for write-check' infoPrintCR.
  2581 			'Processor [info]: checkblock changed for write-check' infoPrintCR.
  2569                         writeCheckArray at:idx put:aBlock.
  2582 			writeCheckArray at:idx put:aBlock.
  2570                     ].
  2583 		    ].
  2571                 ].
  2584 		].
  2572             ].
  2585 	    ].
  2573         ]
  2586 	]
  2574     ] ifFalse:[
  2587     ] ifFalse:[
  2575         idx := writeFdArray identityIndexOf:aFileDescriptor or:nil.
  2588 	idx := writeFdArray identityIndexOf:aFileDescriptor or:nil.
  2576         idx == 0 ifTrue:[
  2589 	idx == 0 ifTrue:[
  2577             "aFileDescriptor is not registered yet, have to create a new slot"
  2590 	    "aFileDescriptor is not registered yet, have to create a new slot"
  2578             writeFdArray := writeFdArray copyWith:aFileDescriptor.
  2591 	    writeFdArray := writeFdArray copyWith:aFileDescriptor.
  2579             writeSemaphoreArray := writeSemaphoreArray copyWith:aSemaphore.
  2592 	    writeSemaphoreArray := writeSemaphoreArray copyWith:aSemaphore.
  2580             writeCheckArray := writeCheckArray copyWith:aBlock.
  2593 	    writeCheckArray := writeCheckArray copyWith:aBlock.
  2581         ] ifFalse:[
  2594 	] ifFalse:[
  2582             slot := writeFdArray at:idx.
  2595 	    slot := writeFdArray at:idx.
  2583             slot isNil ifTrue:[
  2596 	    slot isNil ifTrue:[
  2584                 writeFdArray at:idx put:aFileDescriptor.
  2597 		writeFdArray at:idx put:aFileDescriptor.
  2585                 writeSemaphoreArray at:idx put:aSemaphore.
  2598 		writeSemaphoreArray at:idx put:aSemaphore.
  2586                 writeCheckArray at:idx put:aBlock
  2599 		writeCheckArray at:idx put:aBlock
  2587             ] ifFalse:[
  2600 	    ] ifFalse:[
  2588                 "/ someone has already registered aFileDescriptor.
  2601 		"/ someone has already registered aFileDescriptor.
  2589                 "/ Check if it is the semaphore or block changes...
  2602 		"/ Check if it is the semaphore or block changes...
  2590                 (writeSemaphoreArray at:idx) ~~ aSemaphore ifTrue:[
  2603 		(writeSemaphoreArray at:idx) ~~ aSemaphore ifTrue:[
  2591                     'Processor [info]: sema changed for write-check' infoPrintCR.
  2604 		    'Processor [info]: sema changed for write-check' infoPrintCR.
  2592                     writeSemaphoreArray at:idx put:aSemaphore.
  2605 		    writeSemaphoreArray at:idx put:aSemaphore.
  2593                 ].
  2606 		].
  2594                 (writeCheckArray at:idx) ~~ aBlock ifTrue:[
  2607 		(writeCheckArray at:idx) ~~ aBlock ifTrue:[
  2595                     'Processor [info]: checkblock changed for write-check' infoPrintCR.
  2608 		    'Processor [info]: checkblock changed for write-check' infoPrintCR.
  2596                     writeCheckArray at:idx put:aBlock.
  2609 		    writeCheckArray at:idx put:aBlock.
  2597                 ].
  2610 		].
  2598             ].
  2611 	    ].
  2599         ].
  2612 	].
  2600         (useIOInterrupts and:[slot isNil]) ifTrue:[
  2613 	(useIOInterrupts and:[slot isNil]) ifTrue:[
  2601             OperatingSystem enableIOInterruptsOn:aFileDescriptor
  2614 	    OperatingSystem enableIOInterruptsOn:aFileDescriptor
  2602         ].
  2615 	].
  2603     ].
  2616     ].
  2604     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  2617     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  2605 
  2618 
  2606     "Modified: 4.8.1997 / 15:21:49 / cg"
  2619     "Modified: 4.8.1997 / 15:21:49 / cg"
  2607 !
  2620 !
  2610     "arrange for a semaphore to be triggered when output on aStream is possible.
  2623     "arrange for a semaphore to be triggered when output on aStream is possible.
  2611      This will do a select, if the OS supports selecting on that filedescriptor,
  2624      This will do a select, if the OS supports selecting on that filedescriptor,
  2612      otherwise, it will be polled every few milliseconds (MSDOS)."
  2625      otherwise, it will be polled every few milliseconds (MSDOS)."
  2613 
  2626 
  2614     aStream canBeSelected ifTrue:[
  2627     aStream canBeSelected ifTrue:[
  2615         "/ can this stream be selected on ?
  2628 	"/ can this stream be selected on ?
  2616         self signal:aSemaphore onOutput:aStream fileDescriptor orCheck:nil
  2629 	self signal:aSemaphore onOutput:aStream fileDescriptor orCheck:nil
  2617     ] ifFalse:[
  2630     ] ifFalse:[
  2618         "/ nope - must poll ...
  2631 	"/ nope - must poll ...
  2619         self signal:aSemaphore onOutput:nil orCheck:[aStream canWriteWithoutBlocking]
  2632 	self signal:aSemaphore onOutput:nil orCheck:[aStream canWriteWithoutBlocking]
  2620     ]
  2633     ]
  2621 
  2634 
  2622     "Modified: / 14.12.1999 / 23:59:19 / cg"
  2635     "Modified: / 14.12.1999 / 23:59:19 / cg"
  2623 ! !
  2636 ! !
  2624 
  2637 
  2631      If enabled, arrangements are made for data-availability to trigger an
  2644      If enabled, arrangements are made for data-availability to trigger an
  2632      interrupt.
  2645      interrupt.
  2633      Using IO interrupts reduces the idle CPU usage of ST/X by some percent
  2646      Using IO interrupts reduces the idle CPU usage of ST/X by some percent
  2634      (typically 2-7%).
  2647      (typically 2-7%).
  2635      Notice:
  2648      Notice:
  2636         some systems do not support IO-interrupts (or have a broken stdio-lib),
  2649 	some systems do not support IO-interrupts (or have a broken stdio-lib),
  2637         and this feature is always disabled;
  2650 	and this feature is always disabled;
  2638      Also notice:
  2651      Also notice:
  2639         we found that in some Xlib-implementations, interrupted reads are not
  2652 	we found that in some Xlib-implementations, interrupted reads are not
  2640         handled correctly (especially in multi-headed applications), and this
  2653 	handled correctly (especially in multi-headed applications), and this
  2641         feature should be disabled to avoid a blocking XPending.
  2654 	feature should be disabled to avoid a blocking XPending.
  2642 
  2655 
  2643      If this method is used to disable IO interrupts in multi-headed apps,
  2656      If this method is used to disable IO interrupts in multi-headed apps,
  2644      it should be invoked BEFORE the display event dispatcher processes are started."
  2657      it should be invoked BEFORE the display event dispatcher processes are started."
  2645 
  2658 
  2646     OperatingSystem supportsIOInterrupts ifTrue:[
  2659     OperatingSystem supportsIOInterrupts ifTrue:[
  2647         useIOInterrupts := aBoolean
  2660 	useIOInterrupts := aBoolean
  2648     ].
  2661     ].
  2649 
  2662 
  2650     "Created: / 15.7.1998 / 13:32:29 / cg"
  2663     "Created: / 15.7.1998 / 13:32:29 / cg"
  2651 ! !
  2664 ! !
  2652 
  2665 
  2790      wasBlocked|
  2803      wasBlocked|
  2791 
  2804 
  2792     wasBlocked := OperatingSystem blockInterrupts.
  2805     wasBlocked := OperatingSystem blockInterrupts.
  2793     index := timeoutActionArray identityIndexOf:aBlock startingAt:1.
  2806     index := timeoutActionArray identityIndexOf:aBlock startingAt:1.
  2794     index ~~ 0 ifTrue:[
  2807     index ~~ 0 ifTrue:[
  2795         timeoutArray at:index put:aMillisecondTime
  2808 	timeoutArray at:index put:aMillisecondTime
  2796     ] ifFalse:[
  2809     ] ifFalse:[
  2797         index := timeoutArray indexOf:nil.
  2810 	index := timeoutArray indexOf:nil.
  2798         index ~~ 0 ifTrue:[
  2811 	index ~~ 0 ifTrue:[
  2799             timeoutArray at:index put:aMillisecondTime.
  2812 	    timeoutArray at:index put:aMillisecondTime.
  2800             timeoutActionArray at:index put:aBlock.
  2813 	    timeoutActionArray at:index put:aBlock.
  2801             timeoutSemaphoreArray at:index put:nil.
  2814 	    timeoutSemaphoreArray at:index put:nil.
  2802             timeoutProcessArray at:index put:aProcess
  2815 	    timeoutProcessArray at:index put:aProcess
  2803         ] ifFalse:[
  2816 	] ifFalse:[
  2804             timeoutArray := timeoutArray copyWith:aMillisecondTime.
  2817 	    timeoutArray := timeoutArray copyWith:aMillisecondTime.
  2805             timeoutActionArray := timeoutActionArray copyWith:aBlock.
  2818 	    timeoutActionArray := timeoutActionArray copyWith:aBlock.
  2806             timeoutSemaphoreArray := timeoutSemaphoreArray copyWith:nil.
  2819 	    timeoutSemaphoreArray := timeoutSemaphoreArray copyWith:nil.
  2807             timeoutProcessArray := timeoutProcessArray copyWith:aProcess.
  2820 	    timeoutProcessArray := timeoutProcessArray copyWith:aProcess.
  2808             index := timeoutArray size.
  2821 	    index := timeoutArray size.
  2809         ].
  2822 	].
  2810     ].
  2823     ].
  2811 
  2824 
  2812     anyTimeouts := true.
  2825     anyTimeouts := true.
  2813     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  2826     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  2814     ^ index
  2827     ^ index
  2831     wasBlocked := OperatingSystem blockInterrupts.
  2844     wasBlocked := OperatingSystem blockInterrupts.
  2832     now := OperatingSystem getMillisecondTime.
  2845     now := OperatingSystem getMillisecondTime.
  2833     then := OperatingSystem millisecondTimeAdd:now and:delta.
  2846     then := OperatingSystem millisecondTimeAdd:now and:delta.
  2834 
  2847 
  2835     id := self
  2848     id := self
  2836         addTimeoutFunctionCall:anExternalFunction
  2849 	addTimeoutFunctionCall:anExternalFunction
  2837         for:aProcess
  2850 	for:aProcess
  2838         atMilliseconds:then
  2851 	atMilliseconds:then
  2839         with:argument.
  2852 	with:argument.
  2840 
  2853 
  2841     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  2854     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  2842     ^ id
  2855     ^ id
  2843 
  2856 
  2844     "Created: 23.9.1996 / 14:28:27 / cg"
  2857     "Created: 23.9.1996 / 14:28:27 / cg"
  2857 
  2870 
  2858     |action|
  2871     |action|
  2859 
  2872 
  2860     action := [anExternalFunction callWith:argument].
  2873     action := [anExternalFunction callWith:argument].
  2861     ^ self
  2874     ^ self
  2862         addTimedBlock:action
  2875 	addTimedBlock:action
  2863         for:aProcess
  2876 	for:aProcess
  2864         atMilliseconds:milliTime.
  2877 	atMilliseconds:milliTime.
  2865 
  2878 
  2866     "Created: 23.9.1996 / 14:29:30 / cg"
  2879     "Created: 23.9.1996 / 14:29:30 / cg"
  2867     "Modified: 23.9.1996 / 14:34:57 / cg"
  2880     "Modified: 23.9.1996 / 14:34:57 / cg"
  2868 !
  2881 !
  2869 
  2882 
  2870 evaluateTimeouts
  2883 evaluateTimeouts
  2871     "walk through timeouts and evaluate blocks or signal semas that need to be .."
  2884     "walk through timeouts and evaluate blocks or signal semas that need to be .."
  2872 
  2885 
  2873     |sema now aTime block blocksAndProcessesToEvaluate
  2886     |sema now aTime block blocksAndProcessesToEvaluate
  2874      firstBlockToEvaluate firstProcess 
  2887      firstBlockToEvaluate firstProcess
  2875      n "{ Class: SmallInteger }"
  2888      n "{ Class: SmallInteger }"
  2876      indexOfLastTimeout "{ Class: SmallInteger }"
  2889      indexOfLastTimeout "{ Class: SmallInteger }"
  2877      halfSize "{ Class: SmallInteger }"
  2890      halfSize "{ Class: SmallInteger }"
  2878      wasBlocked p|
  2891      wasBlocked p|
  2879 
  2892 
  2880 
  2893 
  2881     anyTimeouts ifFalse:[ ^ self].
  2894     anyTimeouts ifFalse:[ ^ self].
  2882     anyTimeouts := false.
  2895     anyTimeouts := false.
  2883 
  2896 
  2884     "have to collect the blocks first, then evaluate them. 
  2897     "have to collect the blocks first, then evaluate them.
  2885      This avoids problems due to newly inserted blocks."
  2898      This avoids problems due to newly inserted blocks."
  2886 
  2899 
  2887     "/ notice: the code looks uglier than seems to be required;
  2900     "/ notice: the code looks uglier than seems to be required;
  2888     "/ the observation is that in almost all cases, only a single block (or no block at all)
  2901     "/ the observation is that in almost all cases, only a single block (or no block at all)
  2889     "/ is found in the loops below.
  2902     "/ is found in the loops below.
  2893     "/ looks ugly, but as this is called very often, reduces idle allocation by a lot.
  2906     "/ looks ugly, but as this is called very often, reduces idle allocation by a lot.
  2894 
  2907 
  2895     now := OperatingSystem getMillisecondTime.
  2908     now := OperatingSystem getMillisecondTime.
  2896     n := timeoutArray size.
  2909     n := timeoutArray size.
  2897     1 to:n do:[:index |
  2910     1 to:n do:[:index |
  2898         aTime := timeoutArray at:index.
  2911 	aTime := timeoutArray at:index.
  2899         aTime notNil ifTrue:[
  2912 	aTime notNil ifTrue:[
  2900             (OperatingSystem millisecondTime:now isAfter:aTime) ifTrue:[
  2913 	    (OperatingSystem millisecondTime:now isAfter:aTime) ifTrue:[
  2901                 "this one should be triggered"
  2914 		"this one should be triggered"
  2902 
  2915 
  2903                 sema := timeoutSemaphoreArray at:index.
  2916 		sema := timeoutSemaphoreArray at:index.
  2904                 sema notNil ifTrue:[
  2917 		sema notNil ifTrue:[
  2905                     timeoutSemaphoreArray at:index put:nil.
  2918 		    timeoutSemaphoreArray at:index put:nil.
  2906                     sema signalOnce.
  2919 		    sema signalOnce.
  2907                 ] ifFalse:[
  2920 		] ifFalse:[
  2908                     "to support pure-events"
  2921 		    "to support pure-events"
  2909                     block := timeoutActionArray at:index.
  2922 		    block := timeoutActionArray at:index.
  2910                     block notNil ifTrue:[
  2923 		    block notNil ifTrue:[
  2911                         firstBlockToEvaluate isNil ifTrue:[
  2924 			firstBlockToEvaluate isNil ifTrue:[
  2912                             firstBlockToEvaluate := block.
  2925 			    firstBlockToEvaluate := block.
  2913                             firstProcess := timeoutProcessArray at:index.
  2926 			    firstProcess := timeoutProcessArray at:index.
  2914                         ] ifFalse:[
  2927 			] ifFalse:[
  2915                             blocksAndProcessesToEvaluate isNil ifTrue:[
  2928 			    blocksAndProcessesToEvaluate isNil ifTrue:[
  2916                                 blocksAndProcessesToEvaluate := OrderedCollection 
  2929 				blocksAndProcessesToEvaluate := OrderedCollection
  2917                                                                     with:firstBlockToEvaluate
  2930 								    with:firstBlockToEvaluate
  2918                                                                     with:firstProcess.
  2931 								    with:firstProcess.
  2919                             ].
  2932 			    ].
  2920                             blocksAndProcessesToEvaluate add:block.
  2933 			    blocksAndProcessesToEvaluate add:block.
  2921                             blocksAndProcessesToEvaluate add:(timeoutProcessArray at:index).
  2934 			    blocksAndProcessesToEvaluate add:(timeoutProcessArray at:index).
  2922                         ].
  2935 			].
  2923                         timeoutActionArray at:index put:nil.
  2936 			timeoutActionArray at:index put:nil.
  2924                         timeoutProcessArray at:index put:nil.
  2937 			timeoutProcessArray at:index put:nil.
  2925                     ]
  2938 		    ]
  2926                 ].
  2939 		].
  2927                 timeoutArray at:index put:nil.
  2940 		timeoutArray at:index put:nil.
  2928             ] ifFalse:[
  2941 	    ] ifFalse:[
  2929                 "there are still pending timeouts"
  2942 		"there are still pending timeouts"
  2930                 anyTimeouts := true.
  2943 		anyTimeouts := true.
  2931                 indexOfLastTimeout := index.
  2944 		indexOfLastTimeout := index.
  2932             ]
  2945 	    ]
  2933         ]
  2946 	]
  2934     ].
  2947     ].
  2935 
  2948 
  2936     "shrink the arrays, if they are 50% free"
  2949     "shrink the arrays, if they are 50% free"
  2937     n > 20 ifTrue:[
  2950     n > 20 ifTrue:[
  2938         halfSize := n // 2.
  2951 	halfSize := n // 2.
  2939         indexOfLastTimeout < halfSize ifTrue:[
  2952 	indexOfLastTimeout < halfSize ifTrue:[
  2940             wasBlocked := OperatingSystem blockInterrupts.
  2953 	    wasBlocked := OperatingSystem blockInterrupts.
  2941             (timeoutArray at:indexOfLastTimeout+1) isNil ifTrue:[   "/ no new timeouts arrived
  2954 	    (timeoutArray at:indexOfLastTimeout+1) isNil ifTrue:[   "/ no new timeouts arrived
  2942                 timeoutArray := timeoutArray copyTo:halfSize.
  2955 		timeoutArray := timeoutArray copyTo:halfSize.
  2943                 timeoutSemaphoreArray := timeoutSemaphoreArray copyTo:halfSize.
  2956 		timeoutSemaphoreArray := timeoutSemaphoreArray copyTo:halfSize.
  2944                 timeoutActionArray := timeoutActionArray copyTo:halfSize.
  2957 		timeoutActionArray := timeoutActionArray copyTo:halfSize.
  2945                 timeoutProcessArray := timeoutProcessArray copyTo:halfSize.
  2958 		timeoutProcessArray := timeoutProcessArray copyTo:halfSize.
  2946             ].
  2959 	    ].
  2947             wasBlocked ifFalse:[ OperatingSystem unblockInterrupts ].
  2960 	    wasBlocked ifFalse:[ OperatingSystem unblockInterrupts ].
  2948         ].
  2961 	].
  2949     ].
  2962     ].
  2950 
  2963 
  2951     blocksAndProcessesToEvaluate isNil ifTrue:[
  2964     blocksAndProcessesToEvaluate isNil ifTrue:[
  2952         firstBlockToEvaluate notNil ifTrue:[
  2965 	firstBlockToEvaluate notNil ifTrue:[
  2953             (firstProcess isNil or:[firstProcess == scheduler or:[PureEventDriven]]) ifTrue:[
  2966 	    (firstProcess isNil or:[firstProcess == scheduler or:[PureEventDriven]]) ifTrue:[
  2954                 firstBlockToEvaluate value
  2967 		firstBlockToEvaluate value
  2955             ] ifFalse:[
  2968 	    ] ifFalse:[
  2956                 firstProcess isDead ifTrue:[
  2969 		firstProcess isDead ifTrue:[
  2957                     "/ a timedBlock for a process which has already terminated
  2970 		    "/ a timedBlock for a process which has already terminated
  2958                     "/ issue a warning and do not execute it.
  2971 		    "/ issue a warning and do not execute it.
  2959                     "/ (exeuting here may be dangerous, since it would run at scheduler priority here,
  2972 		    "/ (exeuting here may be dangerous, since it would run at scheduler priority here,
  2960                     "/  and thereby could block the whole smalltalk system.
  2973 		    "/  and thereby could block the whole smalltalk system.
  2961                     "/  For this reason is it IGNORED here.)
  2974 		    "/  For this reason is it IGNORED here.)
  2962 "/ Could handle it in timeoutProcess, but we don't,
  2975 "/ Could handle it in timeoutProcess, but we don't,
  2963 "/ because otherwise timeouts might be reissued forever...
  2976 "/ because otherwise timeouts might be reissued forever...
  2964 "/                    (timeoutHandlerProcess notNil and:[timeoutHandlerProcess isDead not]) ifTrue:[
  2977 "/                    (timeoutHandlerProcess notNil and:[timeoutHandlerProcess isDead not]) ifTrue:[
  2965 "/                        timeoutHandlerProcess interruptWith:block.
  2978 "/                        timeoutHandlerProcess interruptWith:block.
  2966 "/                    ] ifFalse:[
  2979 "/                    ] ifFalse:[
  2967                         ('ProcessorScheduler [warning]: cannot evaluate timedBlock for dead process: ''' , firstProcess name , '''') infoPrintCR.
  2980 			('ProcessorScheduler [warning]: cannot evaluate timedBlock for dead process: ''' , firstProcess name , '''') infoPrintCR.
  2968                         ('ProcessorScheduler [warning]: the timedBlock is: ' , firstBlockToEvaluate displayString) infoPrintCR.
  2981 			('ProcessorScheduler [warning]: the timedBlock is: ' , firstBlockToEvaluate displayString) infoPrintCR.
  2969 "/                    ].
  2982 "/                    ].
  2970                 ] ifFalse:[
  2983 		] ifFalse:[
  2971                     firstProcess interruptWith:firstBlockToEvaluate
  2984 		    firstProcess interruptWith:firstBlockToEvaluate
  2972                 ]
  2985 		]
  2973             ]             
  2986 	    ]
  2974         ].
  2987 	].
  2975     ] ifFalse:[
  2988     ] ifFalse:[
  2976         n := blocksAndProcessesToEvaluate size.
  2989 	n := blocksAndProcessesToEvaluate size.
  2977         1 to:n by:2 do:[:index |
  2990 	1 to:n by:2 do:[:index |
  2978             block := blocksAndProcessesToEvaluate at:index.
  2991 	    block := blocksAndProcessesToEvaluate at:index.
  2979             p := blocksAndProcessesToEvaluate at:index+1.
  2992 	    p := blocksAndProcessesToEvaluate at:index+1.
  2980             (p isNil or:[p == scheduler or:[PureEventDriven]]) ifTrue:[
  2993 	    (p isNil or:[p == scheduler or:[PureEventDriven]]) ifTrue:[
  2981                 block value
  2994 		block value
  2982             ] ifFalse:[
  2995 	    ] ifFalse:[
  2983                 p isDead ifTrue:[
  2996 		p isDead ifTrue:[
  2984                     "/ a timedBlock for a process which has already terminated
  2997 		    "/ a timedBlock for a process which has already terminated
  2985                     "/ issue a warning and do not execute it.
  2998 		    "/ issue a warning and do not execute it.
  2986                     "/ (exeuting here may be dangerous, since it would run at scheduler priority here,
  2999 		    "/ (exeuting here may be dangerous, since it would run at scheduler priority here,
  2987                     "/  and thereby could block the whole smalltalk system.
  3000 		    "/  and thereby could block the whole smalltalk system.
  2988                     "/  For this reason is it IGNORED here.)
  3001 		    "/  For this reason is it IGNORED here.)
  2989 "/ Could handle it in timeoutProcess, but we don't,
  3002 "/ Could handle it in timeoutProcess, but we don't,
  2990 "/ because otherwise timeouts might be reissued forever...
  3003 "/ because otherwise timeouts might be reissued forever...
  2991 "/                    (timeoutHandlerProcess notNil and:[timeoutHandlerProcess isDead not]) ifTrue:[
  3004 "/                    (timeoutHandlerProcess notNil and:[timeoutHandlerProcess isDead not]) ifTrue:[
  2992 "/                        timeoutHandlerProcess interruptWith:block.
  3005 "/                        timeoutHandlerProcess interruptWith:block.
  2993 "/                    ] ifFalse:[
  3006 "/                    ] ifFalse:[
  2994                         ('ProcessorScheduler [warning]: cannot evaluate timedBlock for dead process: ''' , p name , '''') infoPrintCR.
  3007 			('ProcessorScheduler [warning]: cannot evaluate timedBlock for dead process: ''' , p name , '''') infoPrintCR.
  2995                         ('ProcessorScheduler [warning]: the timedBlock is: ' , block displayString) infoPrintCR.
  3008 			('ProcessorScheduler [warning]: the timedBlock is: ' , block displayString) infoPrintCR.
  2996 "/                    ].
  3009 "/                    ].
  2997                 ] ifFalse:[
  3010 		] ifFalse:[
  2998                     p interruptWith:block
  3011 		    p interruptWith:block
  2999                 ]
  3012 		]
  3000             ]
  3013 	    ]
  3001         ]
  3014 	]
  3002     ].
  3015     ].
  3003 
  3016 
  3004     "Modified: / 30-07-2013 / 19:33:24 / cg"
  3017     "Modified: / 30-07-2013 / 19:33:24 / cg"
  3005 !
  3018 !
  3006 
  3019 
  3013     aBlock isNil ifTrue:[^ self].
  3026     aBlock isNil ifTrue:[^ self].
  3014 
  3027 
  3015     wasBlocked := OperatingSystem blockInterrupts.
  3028     wasBlocked := OperatingSystem blockInterrupts.
  3016     index := timeoutActionArray identityIndexOf:aBlock startingAt:1.
  3029     index := timeoutActionArray identityIndexOf:aBlock startingAt:1.
  3017     (index ~~ 0) ifTrue:[
  3030     (index ~~ 0) ifTrue:[
  3018         timeoutArray at:index put:nil.
  3031 	timeoutArray at:index put:nil.
  3019         timeoutActionArray at:index put:nil.
  3032 	timeoutActionArray at:index put:nil.
  3020         timeoutSemaphoreArray at:index put:nil.
  3033 	timeoutSemaphoreArray at:index put:nil.
  3021         timeoutProcessArray at:index put:nil.
  3034 	timeoutProcessArray at:index put:nil.
  3022     ].
  3035     ].
  3023     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  3036     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  3024 !
  3037 !
  3025 
  3038 
  3026 removeTimeoutWithID:anID
  3039 removeTimeoutWithID:anID
  3030     |index "{ Class: SmallInteger }"
  3043     |index "{ Class: SmallInteger }"
  3031      wasBlocked|
  3044      wasBlocked|
  3032 
  3045 
  3033     index := anID.
  3046     index := anID.
  3034     (index > 0) ifTrue:[
  3047     (index > 0) ifTrue:[
  3035         wasBlocked := OperatingSystem blockInterrupts.
  3048 	wasBlocked := OperatingSystem blockInterrupts.
  3036 
  3049 
  3037         timeoutArray at:index put:nil.
  3050 	timeoutArray at:index put:nil.
  3038         timeoutActionArray at:index put:nil.
  3051 	timeoutActionArray at:index put:nil.
  3039         timeoutSemaphoreArray at:index put:nil.
  3052 	timeoutSemaphoreArray at:index put:nil.
  3040         timeoutProcessArray at:index put:nil.
  3053 	timeoutProcessArray at:index put:nil.
  3041 
  3054 
  3042         wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  3055 	wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  3043     ]
  3056     ]
  3044 
  3057 
  3045     "Created: 23.9.1996 / 14:32:33 / cg"
  3058     "Created: 23.9.1996 / 14:32:33 / cg"
  3046     "Modified: 23.9.1996 / 14:35:09 / cg"
  3059     "Modified: 23.9.1996 / 14:35:09 / cg"
  3047 !
  3060 !
  3048 
  3061 
  3049 timeoutHandlerProcess
  3062 timeoutHandlerProcess
  3050     (timeoutHandlerProcess isNil or:[timeoutHandlerProcess isDead]) ifTrue:[
  3063     (timeoutHandlerProcess isNil or:[timeoutHandlerProcess isDead]) ifTrue:[
  3051         timeoutHandlerProcess :=
  3064 	timeoutHandlerProcess :=
  3052                 [
  3065 		[
  3053                     [
  3066 		    [
  3054                         self timeoutHandlerProcessLoop.
  3067 			self timeoutHandlerProcessLoop.
  3055                     ] ensure:[
  3068 		    ] ensure:[
  3056                         timeoutHandlerProcess := nil
  3069 			timeoutHandlerProcess := nil
  3057                     ].
  3070 		    ].
  3058                 ] newProcess.
  3071 		] newProcess.
  3059 
  3072 
  3060         timeoutHandlerProcess
  3073 	timeoutHandlerProcess
  3061             priority:TimingPriority;
  3074 	    priority:TimingPriority;
  3062             name:'timeout handler';
  3075 	    name:'timeout handler';
  3063             beSystemProcess;
  3076 	    beSystemProcess;
  3064             resume.
  3077 	    resume.
  3065     ].
  3078     ].
  3066     ^ timeoutHandlerProcess.
  3079     ^ timeoutHandlerProcess.
  3067 
  3080 
  3068     "Modified: / 20-07-2006 / 09:52:27 / cg"
  3081     "Modified: / 20-07-2006 / 09:52:27 / cg"
  3069 !
  3082 !
  3071 timeoutHandlerProcessLoop
  3084 timeoutHandlerProcessLoop
  3072     "The timeoutHandlerProcess does nothing but wait.
  3085     "The timeoutHandlerProcess does nothing but wait.
  3073      It exists only, so that timeout blocks may be executed in its context."
  3086      It exists only, so that timeout blocks may be executed in its context."
  3074 
  3087 
  3075     [
  3088     [
  3076         [
  3089 	[
  3077             (Semaphore new name:'timeoutHandler') wait.
  3090 	    (Semaphore new name:'timeoutHandler') wait.
  3078         ] on:Exception do:[:ex|
  3091 	] on:Exception do:[:ex|
  3079             "ignore errors, but tell the user"
  3092 	    "ignore errors, but tell the user"
  3080             InfoPrinting == true ifTrue:[
  3093 	    InfoPrinting == true ifTrue:[
  3081                 ('ProcessorScheduler [warning]: error while handling timeouts in TimeoutHandlerProcess: ''' , ex description , '''') infoPrintCR.
  3094 		('ProcessorScheduler [warning]: error while handling timeouts in TimeoutHandlerProcess: ''' , ex description , '''') infoPrintCR.
  3082                 thisContext fullPrintAll.
  3095 		thisContext fullPrintAll.
  3083             ].
  3096 	    ].
  3084         ].
  3097 	].
  3085     ] loop.
  3098     ] loop.
  3086 ! !
  3099 ! !
  3087 
  3100 
  3088 !ProcessorScheduler methodsFor:'wait hooks'!
  3101 !ProcessorScheduler methodsFor:'wait hooks'!
  3089 
  3102 
  3096 
  3109 
  3097     |wasBlocked|
  3110     |wasBlocked|
  3098 
  3111 
  3099     wasBlocked := OperatingSystem blockInterrupts.
  3112     wasBlocked := OperatingSystem blockInterrupts.
  3100     preWaitActions isNil ifTrue:[
  3113     preWaitActions isNil ifTrue:[
  3101         preWaitActions := OrderedCollection new
  3114 	preWaitActions := OrderedCollection new
  3102     ].
  3115     ].
  3103     preWaitActions add:aBlock.
  3116     preWaitActions add:aBlock.
  3104     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  3117     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  3105 !
  3118 !
  3106 
  3119 
  3131 
  3144 
  3132     wasBlocked := OperatingSystem unblockInterrupts.
  3145     wasBlocked := OperatingSystem unblockInterrupts.
  3133 
  3146 
  3134     newProcessMaybeReady := false.
  3147     newProcessMaybeReady := false.
  3135     readableResultFdArray size < readFdArray size ifTrue:[
  3148     readableResultFdArray size < readFdArray size ifTrue:[
  3136         readableResultFdArray := Array new:(40 max:readFdArray size).
  3149 	readableResultFdArray := Array new:(40 max:readFdArray size).
  3137     ].
  3150     ].
  3138     writableResultFdArray size < writeFdArray size ifTrue:[
  3151     writableResultFdArray size < writeFdArray size ifTrue:[
  3139         writableResultFdArray := Array new:(40 max:writeFdArray size).
  3152 	writableResultFdArray := Array new:(40 max:writeFdArray size).
  3140     ].
  3153     ].
  3141 
  3154 
  3142     OperatingSystem isMSWINDOWSlike ifTrue:[
  3155     OperatingSystem isMSWINDOWSlike ifTrue:[
  3143         "/
  3156 	"/
  3144         "/ win32 does a WaitForMultipleObjects in select...
  3157 	"/ win32 does a WaitForMultipleObjects in select...
  3145         "/ unix waits for SIGCHLD
  3158 	"/ unix waits for SIGCHLD
  3146         "/
  3159 	"/
  3147         osChildExitActions keysDo:[:eachPid|
  3160 	osChildExitActions keysDo:[:eachPid|
  3148             eachPid address = 0 ifTrue:[
  3161 	    eachPid address = 0 ifTrue:[
  3149                 'Processor: remove 0 handle pid: ' infoPrint. eachPid infoPrintCR.
  3162 		'Processor: remove 0 handle pid: ' infoPrint. eachPid infoPrintCR.
  3150                 osChildExitActions safeRemoveKey:eachPid.
  3163 		osChildExitActions safeRemoveKey:eachPid.
  3151             ] ifFalse:[
  3164 	    ] ifFalse:[
  3152                 pidsFinished isNil ifTrue:[
  3165 		pidsFinished isNil ifTrue:[
  3153                     exceptArray := osChildExitActions keyArray.
  3166 		    exceptArray := osChildExitActions keyArray.
  3154                     pidsFinished := Array new:osChildExitActions size.
  3167 		    pidsFinished := Array new:osChildExitActions size.
  3155                 ].
  3168 		].
  3156             ].
  3169 	    ].
  3157         ].
  3170 	].
  3158     ].
  3171     ].
  3159 
  3172 
  3160     nReady := OperatingSystem
  3173     nReady := OperatingSystem
  3161                 selectOnAnyReadable:readFdArray
  3174 		selectOnAnyReadable:readFdArray
  3162                 writable:writeFdArray
  3175 		writable:writeFdArray
  3163                 exception:exceptArray
  3176 		exception:exceptArray
  3164                 readableInto:readableResultFdArray
  3177 		readableInto:readableResultFdArray
  3165                 writableInto:writableResultFdArray
  3178 		writableInto:writableResultFdArray
  3166                 exceptionInto:pidsFinished
  3179 		exceptionInto:pidsFinished
  3167                 withTimeOut:millis.
  3180 		withTimeOut:millis.
  3168 
  3181 
  3169     wasBlocked ifTrue:[
  3182     wasBlocked ifTrue:[
  3170         OperatingSystem blockInterrupts.
  3183 	OperatingSystem blockInterrupts.
  3171     ].
  3184     ].
  3172 
  3185 
  3173     nReady <= 0 ifTrue:[
  3186     nReady <= 0 ifTrue:[
  3174         "/ either still nothing to do,
  3187 	"/ either still nothing to do,
  3175         "/ or error (which should not happen)
  3188 	"/ or error (which should not happen)
  3176 
  3189 
  3177         (nReady < 0 and:[(err := OperatingSystem lastErrorSymbol) notNil]) ifTrue:[
  3190 	(nReady < 0 and:[(err := OperatingSystem lastErrorSymbol) notNil]) ifTrue:[
  3178             err == #EBADF ifTrue:[
  3191 	    err == #EBADF ifTrue:[
  3179                 "/ mhmh - one of the fd's given to me is corrupt.
  3192 		"/ mhmh - one of the fd's given to me is corrupt.
  3180                 "/ find out which one .... and remove it
  3193 		"/ find out which one .... and remove it
  3181                 self removeCorruptedFds
  3194 		self removeCorruptedFds
  3182             ] ifFalse:[
  3195 	    ] ifFalse:[
  3183                 err == #ENOENT ifTrue:[
  3196 		err == #ENOENT ifTrue:[
  3184                     'Processor [warning]: ENOENT in select; rd=' infoPrint.
  3197 		    'Processor [warning]: ENOENT in select; rd=' infoPrint.
  3185                     readFdArray infoPrint.
  3198 		    readFdArray infoPrint.
  3186                     ' wr=' infoPrint.
  3199 		    ' wr=' infoPrint.
  3187                     writeFdArray infoPrintCR.
  3200 		    writeFdArray infoPrintCR.
  3188                 ] ifFalse:[
  3201 		] ifFalse:[
  3189                     'Processor [warning]: error in select: ' infoPrint. err infoPrintCR.
  3202 		    'Processor [warning]: error in select: ' infoPrint. err infoPrintCR.
  3190                 ]
  3203 		]
  3191             ].
  3204 	    ].
  3192         ]
  3205 	]
  3193     ] ifFalse:[
  3206     ] ifFalse:[
  3194         readyIndex := 1.
  3207 	readyIndex := 1.
  3195         [nReady > 0
  3208 	[nReady > 0
  3196              and:[ readyIndex <= readableResultFdArray size
  3209 	     and:[ readyIndex <= readableResultFdArray size
  3197              and:[ (fd := readableResultFdArray at:readyIndex) notNil ]]]
  3210 	     and:[ (fd := readableResultFdArray at:readyIndex) notNil ]]]
  3198         whileTrue:[
  3211 	whileTrue:[
  3199             index := readFdArray identityIndexOf:fd.
  3212 	    index := readFdArray identityIndexOf:fd.
  3200             index ~~ 0 ifTrue:[
  3213 	    index ~~ 0 ifTrue:[
  3201                 action := readCheckArray at:index.
  3214 		action := readCheckArray at:index.
  3202                 sema := readSemaphoreArray at:index.
  3215 		sema := readSemaphoreArray at:index.
  3203                 sema notNil ifTrue:[
  3216 		sema notNil ifTrue:[
  3204                     sema signalOnce.
  3217 		    sema signalOnce.
  3205                     newProcessMaybeReady := true.
  3218 		    newProcessMaybeReady := true.
  3206                     action isNil ifTrue:[
  3219 		    action isNil ifTrue:[
  3207                         "before May 2014 we disabled the sema in the caller after wakeup.
  3220 			"before May 2014 we disabled the sema in the caller after wakeup.
  3208                          This caused ST/X to consume 100% cpu, when the caller didn't read
  3221 			 This caused ST/X to consume 100% cpu, when the caller didn't read
  3209                          the data (e.g. because his process was stopped)."
  3222 			 the data (e.g. because his process was stopped)."
  3210                         useIOInterrupts ifTrue:[
  3223 			useIOInterrupts ifTrue:[
  3211                             OperatingSystem disableIOInterruptsOn:fd
  3224 			    OperatingSystem disableIOInterruptsOn:fd
  3212                         ].
  3225 			].
  3213                         readFdArray at:index put:nil.
  3226 			readFdArray at:index put:nil.
  3214                         readSemaphoreArray at:index put:nil.    
  3227 			readSemaphoreArray at:index put:nil.
  3215                         "disable possible write side and timeouts as well"
  3228 			"disable possible write side and timeouts as well"
  3216                         self disableSemaphore:sema.
  3229 			self disableSemaphore:sema.
  3217                     ].
  3230 		    ].
  3218                 ].
  3231 		].
  3219                 action notNil ifTrue:[
  3232 		action notNil ifTrue:[
  3220                     action value.
  3233 		    action value.
  3221                     newProcessMaybeReady := true
  3234 		    newProcessMaybeReady := true
  3222                 ].
  3235 		].
  3223             ].
  3236 	    ].
  3224             nReady := nReady - 1.
  3237 	    nReady := nReady - 1.
  3225             readyIndex := readyIndex + 1.
  3238 	    readyIndex := readyIndex + 1.
  3226         ].
  3239 	].
  3227 
  3240 
  3228         readyIndex := 1.
  3241 	readyIndex := 1.
  3229         [nReady > 0
  3242 	[nReady > 0
  3230              and:[ readyIndex <= writableResultFdArray size
  3243 	     and:[ readyIndex <= writableResultFdArray size
  3231              and:[ (fd := writableResultFdArray at:readyIndex) notNil ]]]
  3244 	     and:[ (fd := writableResultFdArray at:readyIndex) notNil ]]]
  3232         whileTrue:[
  3245 	whileTrue:[
  3233             index := writeFdArray identityIndexOf:fd.
  3246 	    index := writeFdArray identityIndexOf:fd.
  3234             index ~~ 0 ifTrue:[
  3247 	    index ~~ 0 ifTrue:[
  3235                 action := writeCheckArray at:index.
  3248 		action := writeCheckArray at:index.
  3236                 sema := writeSemaphoreArray at:index.
  3249 		sema := writeSemaphoreArray at:index.
  3237                 sema notNil ifTrue:[
  3250 		sema notNil ifTrue:[
  3238                     sema signalOnce.
  3251 		    sema signalOnce.
  3239                     newProcessMaybeReady := true.
  3252 		    newProcessMaybeReady := true.
  3240                     action isNil ifTrue:[
  3253 		    action isNil ifTrue:[
  3241                         "now this is a one shot operation - see the input above"
  3254 			"now this is a one shot operation - see the input above"
  3242                         useIOInterrupts ifTrue:[
  3255 			useIOInterrupts ifTrue:[
  3243                             OperatingSystem disableIOInterruptsOn:fd
  3256 			    OperatingSystem disableIOInterruptsOn:fd
  3244                         ].
  3257 			].
  3245                         writeFdArray at:index put:nil.
  3258 			writeFdArray at:index put:nil.
  3246                         writeSemaphoreArray at:index put:nil.
  3259 			writeSemaphoreArray at:index put:nil.
  3247                         "disable possible read side and timeouts as well"
  3260 			"disable possible read side and timeouts as well"
  3248                         self disableSemaphore:sema.
  3261 			self disableSemaphore:sema.
  3249                     ].
  3262 		    ].
  3250                 ].
  3263 		].
  3251                 action notNil ifTrue:[
  3264 		action notNil ifTrue:[
  3252                     action value.
  3265 		    action value.
  3253                     newProcessMaybeReady := true
  3266 		    newProcessMaybeReady := true
  3254                 ]
  3267 		]
  3255             ].
  3268 	    ].
  3256             nReady := nReady - 1.
  3269 	    nReady := nReady - 1.
  3257             readyIndex := readyIndex + 1.
  3270 	    readyIndex := readyIndex + 1.
  3258         ].
  3271 	].
  3259 
  3272 
  3260         exceptArray notNil ifTrue:[
  3273 	exceptArray notNil ifTrue:[
  3261             "/ only for win32
  3274 	    "/ only for win32
  3262             readyIndex := 1.
  3275 	    readyIndex := 1.
  3263             [nReady > 0
  3276 	    [nReady > 0
  3264                  and:[ readyIndex <= pidsFinished size
  3277 		 and:[ readyIndex <= pidsFinished size
  3265                  and:[ (pid := pidsFinished at:readyIndex) notNil ]]]
  3278 		 and:[ (pid := pidsFinished at:readyIndex) notNil ]]]
  3266             whileTrue:[
  3279 	    whileTrue:[
  3267                 |osProcessStatus actionBlock|
  3280 		|osProcessStatus actionBlock|
  3268 "/'pid signaled: ' infoPrint. pid infoPrintCR.
  3281 "/'pid signaled: ' infoPrint. pid infoPrintCR.
  3269                 actionBlock := osChildExitActions removeKey:pid ifAbsent:nil.
  3282 		actionBlock := osChildExitActions removeKey:pid ifAbsent:nil.
  3270                 osProcessStatus := OperatingSystem childProcessWait:false pid:pid.
  3283 		osProcessStatus := OperatingSystem childProcessWait:false pid:pid.
  3271                 osProcessStatus notNil ifTrue:[
  3284 		osProcessStatus notNil ifTrue:[
  3272                     (osProcessStatus pid = pid) ifTrue:[
  3285 		    (osProcessStatus pid = pid) ifTrue:[
  3273                         actionBlock notNil ifTrue:[
  3286 			actionBlock notNil ifTrue:[
  3274                             actionBlock value:osProcessStatus.
  3287 			    actionBlock value:osProcessStatus.
  3275                             newProcessMaybeReady := true
  3288 			    newProcessMaybeReady := true
  3276                         ].
  3289 			].
  3277                     ].
  3290 		    ].
  3278                 ].
  3291 		].
  3279                 nReady := nReady - 1.
  3292 		nReady := nReady - 1.
  3280                 readyIndex := readyIndex + 1.
  3293 		readyIndex := readyIndex + 1.
  3281             ].
  3294 	    ].
  3282         ].
  3295 	].
  3283     ].
  3296     ].
  3284     ^ newProcessMaybeReady
  3297     ^ newProcessMaybeReady
  3285 
  3298 
  3286     "Modified: / 12-04-1996 / 09:31:22 / stefan"
  3299     "Modified: / 12-04-1996 / 09:31:22 / stefan"
  3287     "Modified: / 07-12-2006 / 19:48:17 / cg"
  3300     "Modified: / 07-12-2006 / 19:48:17 / cg"
  3296      Notice, that at the time of the message, we are still in the context
  3309      Notice, that at the time of the message, we are still in the context
  3297      of whichever process is currently running."
  3310      of whichever process is currently running."
  3298 
  3311 
  3299     gotIOInterrupt := true.
  3312     gotIOInterrupt := true.
  3300     activeProcess ~~ scheduler ifTrue:[
  3313     activeProcess ~~ scheduler ifTrue:[
  3301         interruptedProcess := activeProcess.
  3314 	interruptedProcess := activeProcess.
  3302         self threadSwitch:scheduler
  3315 	self threadSwitch:scheduler
  3303     ]
  3316     ]
  3304 
  3317 
  3305     "Modified: 21.12.1995 / 16:17:40 / stefan"
  3318     "Modified: 21.12.1995 / 16:17:40 / stefan"
  3306     "Modified: 4.8.1997 / 14:23:08 / cg"
  3319     "Modified: 4.8.1997 / 14:23:08 / cg"
  3307 !
  3320 !
  3315      an #EBADF error, leading to high-frequency polling and a locked up system.
  3328      an #EBADF error, leading to high-frequency polling and a locked up system.
  3316      (you could still fix things by interrupting on the console and fixing the
  3329      (you could still fix things by interrupting on the console and fixing the
  3317       readFdArray/writeFdArray in the debugger)"
  3330       readFdArray/writeFdArray in the debugger)"
  3318 
  3331 
  3319     readFdArray keysAndValuesDo:[:idx :fd |
  3332     readFdArray keysAndValuesDo:[:idx :fd |
  3320         |result sema|
  3333 	|result sema|
  3321 
  3334 
  3322         fd notNil ifTrue:[
  3335 	fd notNil ifTrue:[
  3323             result := OperatingSystem 
  3336 	    result := OperatingSystem
  3324                         selectOnAnyReadable:(Array with:fd) writable:nil exception:nil
  3337 			selectOnAnyReadable:(Array with:fd) writable:nil exception:nil
  3325                            readableInto:nil writableInto:nil exceptionInto:nil
  3338 			   readableInto:nil writableInto:nil exceptionInto:nil
  3326                            withTimeOut:0.
  3339 			   withTimeOut:0.
  3327 
  3340 
  3328             result < 0 ifTrue:[
  3341 	    result < 0 ifTrue:[
  3329                 ('Processor [info]: removing invalid read-select fileDescriptor: ' , fd printString) infoPrintCR.
  3342 		('Processor [info]: removing invalid read-select fileDescriptor: ' , fd printString) infoPrintCR.
  3330                 readFdArray at:idx put:nil.
  3343 		readFdArray at:idx put:nil.
  3331                 readCheckArray at:idx put:nil.
  3344 		readCheckArray at:idx put:nil.
  3332                 (sema := readSemaphoreArray at:idx) notNil ifTrue:[
  3345 		(sema := readSemaphoreArray at:idx) notNil ifTrue:[
  3333                     readSemaphoreArray at:idx put:nil.
  3346 		    readSemaphoreArray at:idx put:nil.
  3334                     sema signalOnce.
  3347 		    sema signalOnce.
  3335                 ].
  3348 		].
  3336             ]
  3349 	    ]
  3337         ].
  3350 	].
  3338     ].
  3351     ].
  3339 
  3352 
  3340     writeFdArray keysAndValuesDo:[:idx :fd |
  3353     writeFdArray keysAndValuesDo:[:idx :fd |
  3341         |result sema|
  3354 	|result sema|
  3342 
  3355 
  3343         fd notNil ifTrue:[
  3356 	fd notNil ifTrue:[
  3344             result := OperatingSystem 
  3357 	    result := OperatingSystem
  3345                         selectOnAnyReadable:(Array with:fd) writable:nil exception:nil
  3358 			selectOnAnyReadable:(Array with:fd) writable:nil exception:nil
  3346                            readableInto:nil writableInto:nil exceptionInto:nil
  3359 			   readableInto:nil writableInto:nil exceptionInto:nil
  3347                            withTimeOut:0.
  3360 			   withTimeOut:0.
  3348 
  3361 
  3349             result < 0 ifTrue:[
  3362 	    result < 0 ifTrue:[
  3350                 ('Processor [info]: removing invalid write-select fileDescriptor: ' , fd printString) infoPrintCR.
  3363 		('Processor [info]: removing invalid write-select fileDescriptor: ' , fd printString) infoPrintCR.
  3351                 writeFdArray at:idx put:nil.
  3364 		writeFdArray at:idx put:nil.
  3352                 writeCheckArray at:idx put:nil.
  3365 		writeCheckArray at:idx put:nil.
  3353                 (sema := writeSemaphoreArray at:idx) notNil ifTrue:[
  3366 		(sema := writeSemaphoreArray at:idx) notNil ifTrue:[
  3354                     writeSemaphoreArray at:idx put:nil.
  3367 		    writeSemaphoreArray at:idx put:nil.
  3355                     sema signalOnce.
  3368 		    sema signalOnce.
  3356                 ].
  3369 		].
  3357             ]
  3370 	    ]
  3358         ]
  3371 	]
  3359     ].
  3372     ].
  3360 
  3373 
  3361     OperatingSystem isMSWINDOWSlike ifTrue:[
  3374     OperatingSystem isMSWINDOWSlike ifTrue:[
  3362         "/
  3375 	"/
  3363         "/ win32 does a WaitForMultipleObjects in select...
  3376 	"/ win32 does a WaitForMultipleObjects in select...
  3364         "/ unix waits for SIGCHLD
  3377 	"/ unix waits for SIGCHLD
  3365         "/
  3378 	"/
  3366         osChildExitActions keysDo:[:eachPid |
  3379 	osChildExitActions keysDo:[:eachPid |
  3367             |result sema|
  3380 	    |result sema|
  3368 
  3381 
  3369             eachPid notNil ifTrue:[
  3382 	    eachPid notNil ifTrue:[
  3370                 result := OperatingSystem 
  3383 		result := OperatingSystem
  3371                             selectOnAnyReadable:nil writable:nil exception:(Array with:eachPid)
  3384 			    selectOnAnyReadable:nil writable:nil exception:(Array with:eachPid)
  3372                                readableInto:nil writableInto:nil exceptionInto:nil
  3385 			       readableInto:nil writableInto:nil exceptionInto:nil
  3373                                withTimeOut:0.
  3386 			       withTimeOut:0.
  3374 
  3387 
  3375                 result < 0 ifTrue:[
  3388 		result < 0 ifTrue:[
  3376                     ('Processor [info]: removing invalid except-select pid: ' , eachPid printString) infoPrintCR.
  3389 		    ('Processor [info]: removing invalid except-select pid: ' , eachPid printString) infoPrintCR.
  3377                     osChildExitActions safeRemoveKey:eachPid.
  3390 		    osChildExitActions safeRemoveKey:eachPid.
  3378                 ]
  3391 		]
  3379             ]
  3392 	    ]
  3380         ].
  3393 	].
  3381     ].
  3394     ].
  3382 
  3395 
  3383     "Modified: 12.4.1996 / 09:32:58 / stefan"
  3396     "Modified: 12.4.1996 / 09:32:58 / stefan"
  3384     "Modified: 27.1.1997 / 20:09:27 / cg"
  3397     "Modified: 27.1.1997 / 20:09:27 / cg"
  3385 !
  3398 !
  3387 schedulerInterrupt
  3400 schedulerInterrupt
  3388     "forced reschedule - switch to scheduler process which will decide
  3401     "forced reschedule - switch to scheduler process which will decide
  3389      what to do now."
  3402      what to do now."
  3390 
  3403 
  3391     activeProcess ~~ scheduler ifTrue:[
  3404     activeProcess ~~ scheduler ifTrue:[
  3392         interruptedProcess := activeProcess.
  3405 	interruptedProcess := activeProcess.
  3393         self threadSwitch:scheduler
  3406 	self threadSwitch:scheduler
  3394     ]
  3407     ]
  3395 !
  3408 !
  3396 
  3409 
  3397 timeToNextTimeout
  3410 timeToNextTimeout
  3398     "return the delta-T (in millis) to next timeout, or nil if
  3411     "return the delta-T (in millis) to next timeout, or nil if
  3404      If there were many, the list should be kept sorted ... keeping deltas
  3417      If there were many, the list should be kept sorted ... keeping deltas
  3405      to next (as in Unix kernel)"
  3418      to next (as in Unix kernel)"
  3406 
  3419 
  3407     n := timeoutArray size.
  3420     n := timeoutArray size.
  3408     1 to:n do:[:index |
  3421     1 to:n do:[:index |
  3409         aTime := timeoutArray at:index.
  3422 	aTime := timeoutArray at:index.
  3410         aTime notNil ifTrue:[
  3423 	aTime notNil ifTrue:[
  3411             now isNil ifTrue:[
  3424 	    now isNil ifTrue:[
  3412                 now := OperatingSystem getMillisecondTime.
  3425 		now := OperatingSystem getMillisecondTime.
  3413             ].
  3426 	    ].
  3414             delta := OperatingSystem millisecondTimeDeltaBetween:aTime and:now.
  3427 	    delta := OperatingSystem millisecondTimeDeltaBetween:aTime and:now.
  3415             delta <= 0 ifTrue:[
  3428 	    delta <= 0 ifTrue:[
  3416                 ^ 0.
  3429 		^ 0.
  3417             ].
  3430 	    ].
  3418             minDelta isNil ifTrue:[
  3431 	    minDelta isNil ifTrue:[
  3419                 minDelta := delta
  3432 		minDelta := delta
  3420             ] ifFalse:[
  3433 	    ] ifFalse:[
  3421                 minDelta := minDelta min:delta
  3434 		minDelta := minDelta min:delta
  3422             ]
  3435 	    ]
  3423         ]
  3436 	]
  3424     ].
  3437     ].
  3425     minDelta isNil ifTrue:[
  3438     minDelta isNil ifTrue:[
  3426         "this is safe, since always called with interruptsBlocked"
  3439 	"this is safe, since always called with interruptsBlocked"
  3427         anyTimeouts := false.
  3440 	anyTimeouts := false.
  3428     ].
  3441     ].
  3429 
  3442 
  3430     ^ minDelta
  3443     ^ minDelta
  3431 !
  3444 !
  3432 
  3445 
  3438      This method is called by the VM' interrupt handling mechanism.
  3451      This method is called by the VM' interrupt handling mechanism.
  3439      Notice, that at the time of the message, we are still in the context
  3452      Notice, that at the time of the message, we are still in the context
  3440      of whichever process is currently running."
  3453      of whichever process is currently running."
  3441 
  3454 
  3442     activeProcess ~~ scheduler ifTrue:[
  3455     activeProcess ~~ scheduler ifTrue:[
  3443         interruptedProcess := activeProcess.
  3456 	interruptedProcess := activeProcess.
  3444         self threadSwitch:scheduler
  3457 	self threadSwitch:scheduler
  3445     ]
  3458     ]
  3446 
  3459 
  3447     "Modified: 18.10.1996 / 20:35:54 / cg"
  3460     "Modified: 18.10.1996 / 20:35:54 / cg"
  3448 !
  3461 !
  3449 
  3462 
  3456 
  3469 
  3457     |millis doingGC anySema dT|
  3470     |millis doingGC anySema dT|
  3458 
  3471 
  3459     doingGC := true.
  3472     doingGC := true.
  3460     [doingGC] whileTrue:[
  3473     [doingGC] whileTrue:[
  3461         anyTimeouts ifTrue:[
  3474 	anyTimeouts ifTrue:[
  3462             millis := self timeToNextTimeout.
  3475 	    millis := self timeToNextTimeout.
  3463             (millis notNil and:[millis <= 0]) ifTrue:[
  3476 	    (millis notNil and:[millis <= 0]) ifTrue:[
  3464                 ^ self    "oops - hurry up checking"
  3477 		^ self    "oops - hurry up checking"
  3465             ].
  3478 	    ].
  3466         ].
  3479 	].
  3467 
  3480 
  3468         "
  3481 	"
  3469          if its worth doing, collect a bit of garbage;
  3482 	 if its worth doing, collect a bit of garbage;
  3470          but not, if a backgroundCollector is active
  3483 	 but not, if a backgroundCollector is active
  3471         "
  3484 	"
  3472         ObjectMemory backgroundCollectorRunning ifTrue:[
  3485 	ObjectMemory backgroundCollectorRunning ifTrue:[
  3473             doingGC := false
  3486 	    doingGC := false
  3474         ] ifFalse:[
  3487 	] ifFalse:[
  3475             doingGC := ObjectMemory gcStepIfUseful.
  3488 	    doingGC := ObjectMemory gcStepIfUseful.
  3476         ].
  3489 	].
  3477 
  3490 
  3478         "then do idle actions"
  3491 	"then do idle actions"
  3479         (idleActions notNil and:[idleActions size ~~ 0]) ifTrue:[
  3492 	(idleActions notNil and:[idleActions size ~~ 0]) ifTrue:[
  3480             idleActions do:[:aBlock |
  3493 	    idleActions do:[:aBlock |
  3481                 aBlock value.
  3494 		aBlock value.
  3482             ].
  3495 	    ].
  3483             ^ self   "go back checking"
  3496 	    ^ self   "go back checking"
  3484         ].
  3497 	].
  3485 
  3498 
  3486         doingGC ifTrue:[
  3499 	doingGC ifTrue:[
  3487             (self checkForIOWithTimeout:0) ifTrue:[
  3500 	    (self checkForIOWithTimeout:0) ifTrue:[
  3488                 ^ self  "go back checking"
  3501 		^ self  "go back checking"
  3489             ]
  3502 	    ]
  3490         ]
  3503 	]
  3491     ].
  3504     ].
  3492 
  3505 
  3493     exitWhenNoMoreUserProcesses ifTrue:[
  3506     exitWhenNoMoreUserProcesses ifTrue:[
  3494         "/ check if there are any processes at all
  3507 	"/ check if there are any processes at all
  3495         "/ stop dispatching if there is none
  3508 	"/ stop dispatching if there is none
  3496         "/ (and anyTimeouts is false, which means that no timeout blocks are present)
  3509 	"/ (and anyTimeouts is false, which means that no timeout blocks are present)
  3497         "/ and no readSemaphores are present (which means that noone is waiting for input)
  3510 	"/ and no readSemaphores are present (which means that noone is waiting for input)
  3498         "/ and no writeSemaphores are present
  3511 	"/ and no writeSemaphores are present
  3499 
  3512 
  3500         anyTimeouts ifFalse:[
  3513 	anyTimeouts ifFalse:[
  3501             anySema := (readSemaphoreArray findFirst:[:sema | sema notNil]) ~~ 0.
  3514 	    anySema := (readSemaphoreArray findFirst:[:sema | sema notNil]) ~~ 0.
  3502             anySema ifFalse:[
  3515 	    anySema ifFalse:[
  3503                 anySema := (writeSemaphoreArray findFirst:[:sema | sema notNil]) ~~ 0.
  3516 		anySema := (writeSemaphoreArray findFirst:[:sema | sema notNil]) ~~ 0.
  3504                 anySema ifFalse:[
  3517 		anySema ifFalse:[
  3505                     self anyUserProcessAtAll ifFalse:[
  3518 		    self anyUserProcessAtAll ifFalse:[
  3506                         dispatching := false.
  3519 			dispatching := false.
  3507                         ^ self
  3520 			^ self
  3508                     ]
  3521 		    ]
  3509                 ].
  3522 		].
  3510             ].
  3523 	    ].
  3511         ].
  3524 	].
  3512     ].
  3525     ].
  3513 
  3526 
  3514     preWaitActions notNil ifTrue:[
  3527     preWaitActions notNil ifTrue:[
  3515         preWaitActions do:[:action | action value].
  3528 	preWaitActions do:[:action | action value].
  3516     ].
  3529     ].
  3517 
  3530 
  3518     "/
  3531     "/
  3519     "/ absolutely nothing to do - simply wait
  3532     "/ absolutely nothing to do - simply wait
  3520     "/
  3533     "/
  3521     OperatingSystem supportsSelect ifFalse:[
  3534     OperatingSystem supportsSelect ifFalse:[
  3522         "SCO instant ShitStation has a bug here,
  3535 	"SCO instant ShitStation has a bug here,
  3523          waiting always 1 sec in the select - therefore we delay a bit and
  3536 	 waiting always 1 sec in the select - therefore we delay a bit and
  3524          return - effectively polling in 50ms cycles
  3537 	 return - effectively polling in 50ms cycles
  3525         "
  3538 	"
  3526         (self checkForIOWithTimeout:0) ifTrue:[
  3539 	(self checkForIOWithTimeout:0) ifTrue:[
  3527             ^ self  "go back checking"
  3540 	    ^ self  "go back checking"
  3528         ].
  3541 	].
  3529         OperatingSystem millisecondDelay:EventPollingInterval.
  3542 	OperatingSystem millisecondDelay:EventPollingInterval.
  3530         ^ self
  3543 	^ self
  3531     ].
  3544     ].
  3532 
  3545 
  3533     useIOInterrupts ifTrue:[
  3546     useIOInterrupts ifTrue:[
  3534         dT := 999999
  3547 	dT := 999999
  3535     ] ifFalse:[
  3548     ] ifFalse:[
  3536         dT := EventPollingInterval
  3549 	dT := EventPollingInterval
  3537     ].
  3550     ].
  3538 
  3551 
  3539     millis isNil ifTrue:[
  3552     millis isNil ifTrue:[
  3540         millis := dT.
  3553 	millis := dT.
  3541     ] ifFalse:[
  3554     ] ifFalse:[
  3542         millis := millis rounded min:dT.
  3555 	millis := millis rounded min:dT.
  3543     ].
  3556     ].
  3544 
  3557 
  3545     self checkForIOWithTimeout:millis
  3558     self checkForIOWithTimeout:millis
  3546 
  3559 
  3547     "Modified: 14.12.1995 / 13:37:46 / stefan"
  3560     "Modified: 14.12.1995 / 13:37:46 / stefan"
  3549 ! !
  3562 ! !
  3550 
  3563 
  3551 !ProcessorScheduler class methodsFor:'documentation'!
  3564 !ProcessorScheduler class methodsFor:'documentation'!
  3552 
  3565 
  3553 version
  3566 version
  3554     ^ '$Header: /cvs/stx/stx/libbasic/ProcessorScheduler.st,v 1.302 2015-02-04 20:08:53 stefan Exp $'
  3567     ^ '$Header: /cvs/stx/stx/libbasic/ProcessorScheduler.st,v 1.303 2015-04-27 17:04:46 cg Exp $'
  3555 !
  3568 !
  3556 
  3569 
  3557 version_CVS
  3570 version_CVS
  3558     ^ '$Header: /cvs/stx/stx/libbasic/ProcessorScheduler.st,v 1.302 2015-02-04 20:08:53 stefan Exp $'
  3571     ^ '$Header: /cvs/stx/stx/libbasic/ProcessorScheduler.st,v 1.303 2015-04-27 17:04:46 cg Exp $'
  3559 ! !
  3572 ! !
  3560 
  3573 
  3561 
  3574 
  3562 ProcessorScheduler initialize!
  3575 ProcessorScheduler initialize!