github.com/icexin/eggos@v0.4.2-0.20220216025428-78b167e4f349/kernel/trap_thread.go (about)

     1  package kernel
     2  
     3  import (
     4  	"fmt"
     5  	"runtime"
     6  	"syscall"
     7  	"unsafe"
     8  
     9  	"github.com/icexin/eggos/drivers/pic"
    10  	"github.com/icexin/eggos/kernel/trap"
    11  	"github.com/icexin/eggos/log"
    12  )
    13  
    14  var (
    15  	// 因为中断处理是异步的,在获取一次中断期间可能发生了多次中断,
    16  	// irqset按位保存发生的中断,对应的中断号为IRQ_BASE+1<<bit
    17  	irqset uintptr
    18  
    19  	traptask threadptr
    20  )
    21  
    22  func runTrapThread() {
    23  	runtime.LockOSThread()
    24  	var trapset uintptr
    25  	var err syscall.Errno
    26  	const setsize = unsafe.Sizeof(irqset) * 8
    27  
    28  	my := Mythread()
    29  	traptask = (threadptr)(unsafe.Pointer(my))
    30  	log.Infof("[trap] tid:%d", my.id)
    31  
    32  	for {
    33  		trapset, _, err = syscall.Syscall(SYS_WAIT_IRQ, 0, 0, 0)
    34  		if err != 0 {
    35  			throw("bad SYS_WAIT_IRQ return")
    36  		}
    37  		for i := uintptr(0); i < setsize; i++ {
    38  			if trapset&(1<<i) == 0 {
    39  				continue
    40  			}
    41  			trapno := uintptr(pic.IRQ_BASE + i)
    42  
    43  			handler := trap.Handler(int(trapno))
    44  			if handler == nil {
    45  				fmt.Printf("trap handler for %d not found\n", trapno)
    46  				pic.EOI(trapno)
    47  				continue
    48  			}
    49  			handler()
    50  		}
    51  	}
    52  }
    53  
    54  //go:nosplit
    55  func wakeIRQ(no uintptr) {
    56  	irqset |= 1 << (no - pic.IRQ_BASE)
    57  	wakeup(&irqset, 1)
    58  	Yield()
    59  }
    60  
    61  //go:nosplit
    62  func waitIRQ() uintptr {
    63  	if irqset != 0 {
    64  		ret := irqset
    65  		irqset = 0
    66  		return ret
    67  	}
    68  	sleepon(&irqset)
    69  	ret := irqset
    70  	irqset = 0
    71  	return ret
    72  }