github.com/icexin/eggos@v0.4.2-0.20220216025428-78b167e4f349/kernel/syscall_thread.go (about) 1 package kernel 2 3 import ( 4 "runtime" 5 "syscall" 6 "unsafe" 7 8 "github.com/icexin/eggos/kernel/isyscall" 9 "github.com/icexin/eggos/kernel/sys" 10 "github.com/icexin/eggos/log" 11 ) 12 13 var ( 14 syscalltask threadptr 15 16 // pendingCall is the address of pending forward syscall 17 pendingCall uintptr 18 ) 19 20 //go:nosplit 21 func forwardCall(call *isyscall.Request) { 22 // wait syscall task fetch pendingCall 23 for pendingCall != 0 { 24 sleepon(&pendingCall) 25 } 26 pendingCall = uintptr(unsafe.Pointer(call)) 27 // tell syscall task pendingCall is avaiable 28 // we can't only wakeup only one thread here 29 wakeup(&pendingCall, -1) 30 31 // wait on syscall task handle request 32 sleepon(&call.Lock) 33 34 // for debug purpose 35 if -call.Ret() == uintptr(isyscall.EPANIC) { 36 preparePanic(Mythread().tf) 37 } 38 } 39 40 //go:nosplit 41 func fetchPendingCall() uintptr { 42 // waiting someone call forward syscall 43 for pendingCall == 0 { 44 sleepon(&pendingCall) 45 } 46 ret := pendingCall 47 pendingCall = 0 48 // wakeup one thread, pendingCall is avaiable 49 wakeup(&pendingCall, 1) 50 return ret 51 } 52 53 // runSyscallThread run in normal go code space 54 func runSyscallThread() { 55 runtime.LockOSThread() 56 my := Mythread() 57 syscalltask = (threadptr)(unsafe.Pointer(my)) 58 log.Infof("[syscall] tid:%d", my.id) 59 for { 60 callptr, _, err := syscall.Syscall(SYS_WAIT_SYSCALL, 0, 0, 0) 61 if err != 0 { 62 throw("bad SYS_WAIT_SYSCALL return") 63 } 64 call := (*isyscall.Request)(unsafe.Pointer(callptr)) 65 66 no := call.NO() 67 handler := isyscall.GetHandler(no) 68 if handler == nil { 69 log.Errorf("[syscall] unhandled %s(%d)(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x)", 70 syscallName(int(no)), no, 71 call.Arg(0), call.Arg(1), call.Arg(2), call.Arg(3), 72 call.Arg(4), call.Arg(5)) 73 call.SetErrorNO(syscall.ENOSYS) 74 call.Done() 75 continue 76 } 77 go func() { 78 handler(call) 79 var iret interface{} 80 ret := call.Ret() 81 if hasErrno(ret) { 82 iret = syscall.Errno(-ret) 83 } else { 84 iret = ret 85 } 86 log.Debugf("[syscall] %s(%d)(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x) = %v", 87 syscallName(int(no)), no, 88 call.Arg(0), call.Arg(1), call.Arg(2), call.Arg(3), 89 call.Arg(4), call.Arg(5), iret, 90 ) 91 call.Done() 92 }() 93 } 94 } 95 96 func hasErrno(n uintptr) bool { 97 return 1<<(sys.PtrSize*8-1)&n != 0 98 }