69 lines
		
	
	
	
		
			2.5 KiB
		
	
	
	
		
			Scheme
		
	
	
	
	
	
		
		
			
		
	
	
			69 lines
		
	
	
	
		
			2.5 KiB
		
	
	
	
		
			Scheme
		
	
	
	
	
	
| 
								 | 
							
								;;; event.ss
							 | 
						||
| 
								 | 
							
								;;; Copyright 1984-2017 Cisco Systems, Inc.
							 | 
						||
| 
								 | 
							
								;;; 
							 | 
						||
| 
								 | 
							
								;;; Licensed under the Apache License, Version 2.0 (the "License");
							 | 
						||
| 
								 | 
							
								;;; you may not use this file except in compliance with the License.
							 | 
						||
| 
								 | 
							
								;;; You may obtain a copy of the License at
							 | 
						||
| 
								 | 
							
								;;; 
							 | 
						||
| 
								 | 
							
								;;; http://www.apache.org/licenses/LICENSE-2.0
							 | 
						||
| 
								 | 
							
								;;; 
							 | 
						||
| 
								 | 
							
								;;; Unless required by applicable law or agreed to in writing, software
							 | 
						||
| 
								 | 
							
								;;; distributed under the License is distributed on an "AS IS" BASIS,
							 | 
						||
| 
								 | 
							
								;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
							 | 
						||
| 
								 | 
							
								;;; See the License for the specific language governing permissions and
							 | 
						||
| 
								 | 
							
								;;; limitations under the License.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(let ()
							 | 
						||
| 
								 | 
							
								(define stop-event-timer
							 | 
						||
| 
								 | 
							
								   (lambda ()
							 | 
						||
| 
								 | 
							
								      ($set-timer (most-positive-fixnum))))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define start-event-timer
							 | 
						||
| 
								 | 
							
								  (lambda ()
							 | 
						||
| 
								 | 
							
								   ; set timer by way of $event, so recurrent calls to "set-timer" or
							 | 
						||
| 
								 | 
							
								   ; "{dis,en}able-interrupts" can't prevent interrupts
							 | 
						||
| 
								 | 
							
								    ($event)))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(set! set-timer
							 | 
						||
| 
								 | 
							
								  (lambda (ticks)
							 | 
						||
| 
								 | 
							
								    (unless (and (fixnum? ticks) (fx>= ticks 0))
							 | 
						||
| 
								 | 
							
								       ($oops 'set-timer "~s is not a nonnegative fixnum" ticks))
							 | 
						||
| 
								 | 
							
								    (let ([ticks-left (stop-event-timer)])
							 | 
						||
| 
								 | 
							
								      (let ([t ($tc-field 'timer-ticks ($tc))])
							 | 
						||
| 
								 | 
							
								        (if (fx> ticks 0)
							 | 
						||
| 
								 | 
							
								            (begin
							 | 
						||
| 
								 | 
							
								              ($tc-field 'something-pending ($tc) #t)
							 | 
						||
| 
								 | 
							
								              ($tc-field 'timer-ticks ($tc) ticks))
							 | 
						||
| 
								 | 
							
								            ($tc-field 'timer-ticks ($tc) #f))
							 | 
						||
| 
								 | 
							
								        (if (fx= ($tc-field 'disable-count ($tc)) 0)
							 | 
						||
| 
								 | 
							
								            (let ([old (if t (fx+ t ticks-left) 0)])
							 | 
						||
| 
								 | 
							
								              (start-event-timer)
							 | 
						||
| 
								 | 
							
								              old)
							 | 
						||
| 
								 | 
							
								            (or t 0))))))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(set! disable-interrupts
							 | 
						||
| 
								 | 
							
								  (lambda ()
							 | 
						||
| 
								 | 
							
								    (let ([ticks (stop-event-timer)])
							 | 
						||
| 
								 | 
							
								      (let ([disable-count ($tc-field 'disable-count ($tc))])
							 | 
						||
| 
								 | 
							
								        (when (and (fx= disable-count 0) ($tc-field 'timer-ticks ($tc)))
							 | 
						||
| 
								 | 
							
								          ($tc-field 'timer-ticks ($tc) (fx+ ($tc-field 'timer-ticks ($tc)) ticks)))
							 | 
						||
| 
								 | 
							
								        (when (fx= disable-count (most-positive-fixnum))
							 | 
						||
| 
								 | 
							
								          ($oops 'disable-interrupts
							 | 
						||
| 
								 | 
							
								                 "too many consecutive calls to disable-interrupts"))
							 | 
						||
| 
								 | 
							
								        (let ([disable-count (fx+ disable-count 1)])
							 | 
						||
| 
								 | 
							
								          ($tc-field 'disable-count ($tc) disable-count)
							 | 
						||
| 
								 | 
							
								          disable-count)))))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(set! enable-interrupts
							 | 
						||
| 
								 | 
							
								  (lambda ()
							 | 
						||
| 
								 | 
							
								    (let ([ticks (stop-event-timer)])
							 | 
						||
| 
								 | 
							
								      (let ([disable-count (fx- ($tc-field 'disable-count ($tc)) 1)])
							 | 
						||
| 
								 | 
							
								        (case disable-count
							 | 
						||
| 
								 | 
							
								          [(-1) ($set-timer ticks) 0]
							 | 
						||
| 
								 | 
							
								          [(0) ($tc-field 'disable-count ($tc) 0)
							 | 
						||
| 
								 | 
							
								               (start-event-timer)
							 | 
						||
| 
								 | 
							
								               0]
							 | 
						||
| 
								 | 
							
								          [else ($tc-field 'disable-count ($tc) disable-count)
							 | 
						||
| 
								 | 
							
								                disable-count])))))
							 | 
						||
| 
								 | 
							
								)
							 |