1553 anyUserProcessAtAll |
1553 anyUserProcessAtAll |
1554 "return true, if there is any user process still running, |
1554 "return true, if there is any user process still running, |
1555 or waiting on a semaphore. |
1555 or waiting on a semaphore. |
1556 This is used to determine if we should stop scheduling |
1556 This is used to determine if we should stop scheduling |
1557 in standAlone applications. |
1557 in standAlone applications. |
1558 A user process has a non-zero processGroup." |
1558 A user process has a non-zero processGroup. |
1559 |
1559 Should be called with interrupts blocked." |
1560 |listArray l prio "{ Class: SmallInteger }" |
1560 |
1561 wasBlocked| |
1561 |listArray l prio "{ Class: SmallInteger }"| |
1562 |
1562 |
1563 prio := HighestPriority. |
1563 prio := HighestPriority. |
1564 wasBlocked := OperatingSystem blockInterrupts. |
|
1565 |
1564 |
1566 listArray := quiescentProcessLists. |
1565 listArray := quiescentProcessLists. |
1567 |
1566 |
1568 [prio >= 1] whileTrue:[ |
1567 [prio >= 1] whileTrue:[ |
1569 l := listArray at:prio. |
1568 l := listArray at:prio. |
1570 l notNil ifTrue:[ |
1569 l notNil ifTrue:[ |
1571 l linksDo:[:aProcess | |
1570 l linksDo:[:aProcess | |
1572 aProcess isUserProcess ifTrue:[ |
1571 aProcess isUserProcess ifTrue:[ |
1573 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
1572 ^ true. |
1574 ^ true. |
1573 ] |
1575 ] |
1574 ] |
1576 ] |
1575 ]. |
1577 ]. |
1576 prio := prio - 1 |
1578 prio := prio - 1 |
|
1579 ]. |
1577 ]. |
1580 |
1578 |
1581 "/ any user process waiting on a sema? |
1579 "/ any user process waiting on a sema? |
1582 (readSemaphoreArray contains:[:sema | |
1580 (readSemaphoreArray contains:[:sema | |
1583 sema notNil and:[sema waitingProcesses contains:[:p | p notNil and:[p isUserProcess] ]]] |
1581 sema notNil and:[sema waitingProcesses contains:[:p | p notNil and:[p isUserProcess] ]]] |
1584 ) ifTrue:[ |
1582 ) ifTrue:[ |
1585 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
1583 ^ true. |
1586 ^ true. |
|
1587 ]. |
1584 ]. |
1588 (writeSemaphoreArray contains:[:sema | |
1585 (writeSemaphoreArray contains:[:sema | |
1589 sema notNil and:[sema waitingProcesses contains:[:p | p notNil and:[p isUserProcess] ]]] |
1586 sema notNil and:[sema waitingProcesses contains:[:p | p notNil and:[p isUserProcess] ]]] |
1590 ) ifTrue:[ |
1587 ) ifTrue:[ |
1591 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
1588 ^ true. |
1592 ^ true. |
|
1593 ]. |
1589 ]. |
1594 (timeoutSemaphoreArray contains:[:sema | |
1590 (timeoutSemaphoreArray contains:[:sema | |
1595 sema notNil and:[sema waitingProcesses contains:[:p | p notNil and:[p isUserProcess] ]]] |
1591 sema notNil and:[sema waitingProcesses contains:[:p | p notNil and:[p isUserProcess] ]]] |
1596 ) ifTrue:[ |
1592 ) ifTrue:[ |
1597 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
1593 ^ true. |
1598 ^ true. |
|
1599 ]. |
1594 ]. |
1600 (timeoutProcessArray contains:[:p | p notNil and:[p isUserProcess] ] |
1595 (timeoutProcessArray contains:[:p | p notNil and:[p isUserProcess] ] |
1601 ) ifTrue:[ |
1596 ) ifTrue:[ |
1602 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
1597 ^ true. |
1603 ^ true. |
1598 ]. |
1604 ]. |
1599 |
1605 |
|
1606 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
|
1607 ^ false |
1600 ^ false |
1608 |
1601 |
1609 " |
1602 " |
1610 Processor anyUserProcessAtAll |
1603 Processor anyUserProcessAtAll |
1611 " |
1604 " |
2920 |
2910 |
2921 "Modified: 23.9.1996 / 14:34:18 / cg" |
2911 "Modified: 23.9.1996 / 14:34:18 / cg" |
2922 ! |
2912 ! |
2923 |
2913 |
2924 addTimedBlock:aBlock for:aProcess atMilliseconds:aMillisecondTime |
2914 addTimedBlock:aBlock for:aProcess atMilliseconds:aMillisecondTime |
2925 "add the argument, aBlock to the list of time-scheduled-blocks; to be |
2915 "add the argument, aBlock to the list of time-scheduled-blocks; |
2926 evaluated by aProcess when the millisecondClock value passes |
2916 to be evaluated by aProcess when the millisecondClock value passes |
2927 aMillisecondTime. |
2917 aMillisecondTime. |
2928 If that block is already in the timeout list, |
2918 If that block is already in the timeout list, its trigger-time is changed. |
2929 its trigger-time is changed. |
2919 The process specified by the argument, aProcess |
2930 The process specified by the argument, aProcess will be interrupted |
2920 will be interrupted for execution of the block. |
2931 for execution of the block. |
|
2932 If aProcess is nil, the block will be evaluated by the scheduler itself |
2921 If aProcess is nil, the block will be evaluated by the scheduler itself |
2933 (which is dangerous - the block should not raise any error conditions). |
2922 (which is dangerous: the block should not raise any error conditions). |
2934 If the process is active at trigger time, the interrupt will occur in |
2923 If the process is active at trigger time, the interrupt will occur in |
2935 whatever method it is executing; if suspended at trigger time, it will be |
2924 whatever method it is executing; |
2936 resumed. |
2925 if suspended at trigger time, it will be resumed. |
2937 The block will be removed from the timed-block list after evaluation |
2926 The block will be removed from the timed-block list after evaluation |
2938 (i.e. it will trigger only once). |
2927 (i.e. it will trigger only once). |
2939 Returns an ID, which can be used in #removeTimeoutWidthID:" |
2928 Returns an ID, which can be used in #removeTimeoutWidthID:" |
2940 |
2929 |
2941 |index "{ Class: SmallInteger }" |
2930 |index "{ Class: SmallInteger }" |
2942 wasBlocked| |
2931 wasBlocked| |
2943 |
2932 |
2944 wasBlocked := OperatingSystem blockInterrupts. |
2933 wasBlocked := OperatingSystem blockInterrupts. |
2945 index := timeoutActionArray identityIndexOf:aBlock startingAt:1. |
2934 index := timeoutActionArray identityIndexOf:aBlock startingAt:1. |
2946 index ~~ 0 ifTrue:[ |
2935 index ~~ 0 ifTrue:[ |
2947 timeoutArray at:index put:aMillisecondTime |
2936 timeoutArray at:index put:aMillisecondTime |
2948 ] ifFalse:[ |
2937 ] ifFalse:[ |
2949 index := timeoutArray indexOf:nil. |
2938 index := timeoutArray indexOf:nil. |
2950 index ~~ 0 ifTrue:[ |
2939 index ~~ 0 ifTrue:[ |
2951 timeoutArray at:index put:aMillisecondTime. |
2940 timeoutArray at:index put:aMillisecondTime. |
2952 timeoutActionArray at:index put:aBlock. |
2941 timeoutActionArray at:index put:aBlock. |
2953 timeoutSemaphoreArray at:index put:nil. |
2942 timeoutSemaphoreArray at:index put:nil. |
2954 timeoutProcessArray at:index put:aProcess |
2943 timeoutProcessArray at:index put:aProcess |
2955 ] ifFalse:[ |
2944 ] ifFalse:[ |
2956 timeoutArray := timeoutArray copyWith:aMillisecondTime. |
2945 timeoutArray := timeoutArray copyWith:aMillisecondTime. |
2957 timeoutActionArray := timeoutActionArray copyWith:aBlock. |
2946 timeoutActionArray := timeoutActionArray copyWith:aBlock. |
2958 timeoutSemaphoreArray := timeoutSemaphoreArray copyWith:nil. |
2947 timeoutSemaphoreArray := timeoutSemaphoreArray copyWith:nil. |
2959 timeoutProcessArray := timeoutProcessArray copyWith:aProcess. |
2948 timeoutProcessArray := timeoutProcessArray copyWith:aProcess. |
2960 index := timeoutArray size. |
2949 index := timeoutArray size. |
2961 ]. |
2950 ]. |
2962 ]. |
2951 ]. |
2963 |
2952 |
2964 anyTimeouts := true. |
2953 anyTimeouts := true. |
2965 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
2954 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
2966 ^ index |
2955 ^ index |
3045 "/ looks ugly, but as this is called very often, reduces idle allocation by a lot. |
3034 "/ looks ugly, but as this is called very often, reduces idle allocation by a lot. |
3046 |
3035 |
3047 now := OperatingSystem getMillisecondTime. |
3036 now := OperatingSystem getMillisecondTime. |
3048 n := timeoutArray size. |
3037 n := timeoutArray size. |
3049 1 to:n do:[:index | |
3038 1 to:n do:[:index | |
3050 aTime := timeoutArray at:index. |
3039 aTime := timeoutArray at:index. |
3051 aTime notNil ifTrue:[ |
3040 aTime notNil ifTrue:[ |
3052 (OperatingSystem millisecondTime:now isAfter:aTime) ifTrue:[ |
3041 (OperatingSystem millisecondTime:now isAfter:aTime) ifTrue:[ |
3053 "this one should be triggered" |
3042 "this one should be triggered" |
3054 |
3043 |
3055 sema := timeoutSemaphoreArray at:index. |
3044 sema := timeoutSemaphoreArray at:index. |
3056 sema notNil ifTrue:[ |
3045 sema notNil ifTrue:[ |
3057 timeoutSemaphoreArray at:index put:nil. |
3046 timeoutSemaphoreArray at:index put:nil. |
3058 timedActionCounter := (timedActionCounter + 1 bitAnd:SmallInteger maxVal). |
3047 timedActionCounter := (timedActionCounter + 1 bitAnd:SmallInteger maxVal). |
3059 sema signalOnce. |
3048 sema signalOnce. |
3060 ] ifFalse:[ |
3049 ] ifFalse:[ |
3061 "to support pure-events" |
3050 "to support pure-events" |
3062 block := timeoutActionArray at:index. |
3051 block := timeoutActionArray at:index. |
3063 block notNil ifTrue:[ |
3052 block notNil ifTrue:[ |
3064 "/ usually (>99%), there is only one single timeout action to call; |
3053 "/ usually (>99%), there is only one single timeout action to call; |
3065 "/ avoid creation of an OrderedCollection |
3054 "/ avoid creation of an OrderedCollection |
3066 firstBlockToEvaluate isNil ifTrue:[ |
3055 firstBlockToEvaluate isNil ifTrue:[ |
3067 firstBlockToEvaluate := block. |
3056 firstBlockToEvaluate := block. |
3068 firstProcess := timeoutProcessArray at:index. |
3057 firstProcess := timeoutProcessArray at:index. |
3069 ] ifFalse:[ |
3058 ] ifFalse:[ |
3070 blocksAndProcessesToEvaluate isNil ifTrue:[ |
3059 blocksAndProcessesToEvaluate isNil ifTrue:[ |
3071 blocksAndProcessesToEvaluate := OrderedCollection |
3060 blocksAndProcessesToEvaluate := OrderedCollection |
3072 with:firstBlockToEvaluate |
3061 with:firstBlockToEvaluate |
3073 with:firstProcess. |
3062 with:firstProcess. |
3074 ]. |
3063 ]. |
3075 blocksAndProcessesToEvaluate add:block. |
3064 blocksAndProcessesToEvaluate add:block. |
3076 blocksAndProcessesToEvaluate add:(timeoutProcessArray at:index). |
3065 blocksAndProcessesToEvaluate add:(timeoutProcessArray at:index). |
3077 ]. |
3066 ]. |
3078 timeoutActionArray at:index put:nil. |
3067 timeoutActionArray at:index put:nil. |
3079 timeoutProcessArray at:index put:nil. |
3068 timeoutProcessArray at:index put:nil. |
3080 ] |
3069 ] |
3081 ]. |
3070 ]. |
3082 timeoutArray at:index put:nil. |
3071 timeoutArray at:index put:nil. |
3083 ] ifFalse:[ |
3072 ] ifFalse:[ |
3084 "there are still pending timeouts" |
3073 "there are still pending timeouts" |
3085 anyTimeouts := true. |
3074 anyTimeouts := true. |
3086 indexOfLastTimeout := index. |
3075 indexOfLastTimeout := index. |
3087 ] |
3076 ] |
3088 ] |
3077 ] |
3089 ]. |
3078 ]. |
3090 |
3079 |
3091 "shrink the arrays, if they are 50% free" |
3080 "shrink the arrays, if they are 50% free" |
3092 n > 20 ifTrue:[ |
3081 n > 20 ifTrue:[ |
3093 halfSize := n // 2. |
3082 halfSize := n // 2. |
3094 (indexOfLastTimeout ~~ 0 and:[indexOfLastTimeout < halfSize]) ifTrue:[ |
3083 (indexOfLastTimeout ~~ 0 and:[indexOfLastTimeout < halfSize]) ifTrue:[ |
3095 wasBlocked := OperatingSystem blockInterrupts. |
3084 wasBlocked := OperatingSystem blockInterrupts. |
3096 (timeoutArray at:indexOfLastTimeout+1) isNil ifTrue:[ "/ no new timeouts arrived |
3085 (timeoutArray at:indexOfLastTimeout+1) isNil ifTrue:[ "/ no new timeouts arrived |
3097 timeoutArray := timeoutArray copyTo:halfSize. |
3086 timeoutArray := timeoutArray copyTo:halfSize. |
3098 timeoutSemaphoreArray := timeoutSemaphoreArray copyTo:halfSize. |
3087 timeoutSemaphoreArray := timeoutSemaphoreArray copyTo:halfSize. |
3099 timeoutActionArray := timeoutActionArray copyTo:halfSize. |
3088 timeoutActionArray := timeoutActionArray copyTo:halfSize. |
3100 timeoutProcessArray := timeoutProcessArray copyTo:halfSize. |
3089 timeoutProcessArray := timeoutProcessArray copyTo:halfSize. |
3101 ]. |
3090 ]. |
3102 wasBlocked ifFalse:[ OperatingSystem unblockInterrupts ]. |
3091 wasBlocked ifFalse:[ OperatingSystem unblockInterrupts ]. |
3103 ]. |
3092 ]. |
3104 ]. |
3093 ]. |
3105 |
3094 |
3106 "/ usually (>99%), there is only one single timeout action to call; |
3095 "/ usually (>99%), there is only one single timeout action to call; |
3107 "/ above code avoided the creation of an OrderedCollection |
3096 "/ above code avoided the creation of an OrderedCollection |
3108 blocksAndProcessesToEvaluate isNil ifTrue:[ |
3097 blocksAndProcessesToEvaluate isNil ifTrue:[ |
3109 firstBlockToEvaluate notNil ifTrue:[ |
3098 firstBlockToEvaluate notNil ifTrue:[ |
3110 timedActionCounter := (timedActionCounter + 1 bitAnd:SmallInteger maxVal). |
3099 timedActionCounter := (timedActionCounter + 1 bitAnd:SmallInteger maxVal). |
3111 (firstProcess isNil or:[firstProcess == scheduler or:[PureEventDriven]]) ifTrue:[ |
3100 (firstProcess isNil or:[firstProcess == scheduler or:[PureEventDriven]]) ifTrue:[ |
3112 firstBlockToEvaluate value |
3101 firstBlockToEvaluate value |
3113 ] ifFalse:[ |
3102 ] ifFalse:[ |
3114 firstProcess isDead ifTrue:[ |
3103 firstProcess isDead ifTrue:[ |
3115 "/ a timedBlock for a process which has already terminated |
3104 "/ a timedBlock for a process which has already terminated |
3116 "/ issue a warning and do not execute it. |
3105 "/ issue a warning and do not execute it. |
3117 "/ (exeuting here may be dangerous, since it would run at scheduler priority here, |
3106 "/ (executing here may be dangerous, since it would run at scheduler priority here, |
3118 "/ and thereby could block the whole smalltalk system. |
3107 "/ and thereby could block the whole smalltalk system. |
3119 "/ For this reason is it IGNORED here.) |
3108 "/ For this reason is it IGNORED here.) |
3120 "/ Could handle it in timeoutProcess, but we don't, |
3109 |
3121 "/ because otherwise timeouts might be reissued forever... |
3110 "/ Could handle it in timeoutProcess, but we don't, |
3122 "/ (timeoutHandlerProcess notNil and:[timeoutHandlerProcess isDead not]) ifTrue:[ |
3111 "/ because otherwise timeouts might be reissued forever... |
3123 "/ timeoutHandlerProcess interruptWith:block. |
3112 "/ (timeoutHandlerProcess notNil and:[timeoutHandlerProcess isDead not]) ifTrue:[ |
3124 "/ ] ifFalse:[ |
3113 "/ timeoutHandlerProcess interruptWith:block. |
3125 ('ProcessorScheduler [warning]: cannot evaluate timedBlock (', firstBlockToEvaluate displayString, ') for dead process: ''' , firstProcess name , '''') infoPrintCR. |
3114 "/ ] ifFalse:[ |
3126 "/ ]. |
3115 ('ProcessorScheduler [warning]: cannot evaluate timedBlock (', firstBlockToEvaluate displayString, ') for dead process: ''' , firstProcess name , '''') infoPrintCR. |
3127 ] ifFalse:[ |
3116 "/ ]. |
3128 firstProcess interruptWith:firstBlockToEvaluate |
3117 ] ifFalse:[ |
3129 ] |
3118 firstProcess interruptWith:firstBlockToEvaluate |
3130 ] |
3119 ] |
3131 ]. |
3120 ] |
|
3121 ]. |
3132 ] ifFalse:[ |
3122 ] ifFalse:[ |
3133 n := blocksAndProcessesToEvaluate size. |
3123 n := blocksAndProcessesToEvaluate size. |
3134 1 to:n by:2 do:[:index | |
3124 1 to:n by:2 do:[:index | |
3135 block := blocksAndProcessesToEvaluate at:index. |
3125 block := blocksAndProcessesToEvaluate at:index. |
3136 p := blocksAndProcessesToEvaluate at:index+1. |
3126 p := blocksAndProcessesToEvaluate at:index+1. |
3137 (p isNil or:[p == scheduler or:[PureEventDriven]]) ifTrue:[ |
3127 (p isNil or:[p == scheduler or:[PureEventDriven]]) ifTrue:[ |
3138 block value. |
3128 block value. |
3139 timedActionCounter := (timedActionCounter + 1 bitAnd:SmallInteger maxVal). |
3129 timedActionCounter := (timedActionCounter + 1 bitAnd:SmallInteger maxVal). |
3140 ] ifFalse:[ |
3130 ] ifFalse:[ |
3141 p isDead ifTrue:[ |
3131 p isDead ifTrue:[ |
3142 "/ a timedBlock for a process which has already terminated |
3132 "/ a timedBlock for a process which has already terminated |
3143 "/ issue a warning and do not execute it. |
3133 "/ issue a warning and do not execute it. |
3144 "/ (exeuting here may be dangerous, since it would run at scheduler priority here, |
3134 "/ (executing here may be dangerous, since it would run at scheduler priority here, |
3145 "/ and thereby could block the whole smalltalk system. |
3135 "/ and thereby could block the whole smalltalk system. |
3146 "/ For this reason is it IGNORED here.) |
3136 "/ For this reason is it IGNORED here.) |
3147 "/ Could handle it in timeoutProcess, but we don't, |
3137 |
3148 "/ because otherwise timeouts might be reissued forever... |
3138 "/ Could handle it in timeoutProcess, but we don't, |
3149 "/ (timeoutHandlerProcess notNil and:[timeoutHandlerProcess isDead not]) ifTrue:[ |
3139 "/ because otherwise timeouts might be reissued forever... |
3150 "/ timeoutHandlerProcess interruptWith:block. |
3140 "/ (timeoutHandlerProcess notNil and:[timeoutHandlerProcess isDead not]) ifTrue:[ |
3151 "/ ] ifFalse:[ |
3141 "/ timeoutHandlerProcess interruptWith:block. |
3152 ('ProcessorScheduler [warning]: cannot evaluate timedBlock (', block displayString, ') for dead process: ''' , p name , '''') infoPrintCR. |
3142 "/ ] ifFalse:[ |
3153 "/ ]. |
3143 ('ProcessorScheduler [warning]: cannot evaluate timedBlock (', block displayString, ') for dead process: ''' , p name , '''') infoPrintCR. |
3154 ] ifFalse:[ |
3144 "/ ]. |
3155 timedActionCounter := (timedActionCounter + 1 bitAnd:SmallInteger maxVal). |
3145 ] ifFalse:[ |
3156 p interruptWith:block |
3146 timedActionCounter := (timedActionCounter + 1 bitAnd:SmallInteger maxVal). |
3157 ] |
3147 p interruptWith:block |
3158 ] |
3148 ] |
3159 ] |
3149 ] |
|
3150 ] |
3160 ]. |
3151 ]. |
3161 |
3152 |
3162 "Modified: / 30-07-2013 / 19:33:24 / cg" |
3153 "Modified: / 30-07-2013 / 19:33:24 / cg" |
3163 ! |
3154 ! |
3164 |
3155 |