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

     1  package kernel
     2  
     3  import (
     4  	"syscall"
     5  	"unsafe"
     6  
     7  	"github.com/icexin/eggos/kernel/isyscall"
     8  )
     9  
    10  // Timer depends on epoll and pipe.
    11  // When timer is frequently used, it will be more efficient
    12  // to implement it in the kernel
    13  
    14  const (
    15  	pipeReadFd  = epollFd + 1
    16  	pipeWriteFd = epollFd + 2
    17  )
    18  
    19  var (
    20  	// FIXME:
    21  	// avoid dup create pipe
    22  	epollPipeCreated bool
    23  	// the bytes number in pipe
    24  	pipeBufferBytes int
    25  )
    26  
    27  //go:nosplit
    28  func sysPipe2(req *isyscall.Request) {
    29  	if epollPipeCreated {
    30  		req.SetErrorNO(syscall.EINVAL)
    31  		return
    32  	}
    33  	epollPipeCreated = true
    34  	fds := (*[2]int32)(unsafe.Pointer(req.Arg(0)))
    35  	fds[0] = pipeReadFd
    36  	fds[1] = pipeWriteFd
    37  	req.SetRet(0)
    38  }
    39  
    40  //go:nosplit
    41  func sysPipeRead(req *isyscall.Request) {
    42  	fd := req.Arg(0)
    43  	buffer := req.Arg(1)
    44  	len := req.Arg(2)
    45  	_ = fd
    46  	_ = buffer
    47  
    48  	var n int
    49  	if int(len) < pipeBufferBytes {
    50  		n = int(len)
    51  	} else {
    52  		n = pipeBufferBytes
    53  	}
    54  
    55  	pipeBufferBytes -= n
    56  	epollNotify(pipeWriteFd, syscall.EPOLLOUT)
    57  	req.SetRet(uintptr(n))
    58  }
    59  
    60  //go:nosplit
    61  func sysPipeWrite(req *isyscall.Request) {
    62  	fd := req.Arg(0)
    63  	buffer := req.Arg(1)
    64  	len := req.Arg(2)
    65  	_ = fd
    66  	_ = buffer
    67  
    68  	pipeBufferBytes += int(len)
    69  	epollNotify(pipeReadFd, syscall.EPOLLIN)
    70  	req.SetRet(len)
    71  }