- Path:
src/runtime/chan.go
Compilation
When you make a chan with make function, the compiler will expand the expression to the makechan implementation. The actual expansion happens
at cmd/compile/internal/walk/expr.go. The runtime will determine whether to use makechan or makechan64.
Type Definitions
type _type
_type is used as the internal representation of a go type. The same structure is defined multiple times across the go runtime.
_type stores the following fields:
type chantype
makechan only uses chantype.elem, the other fields are used by the type system.
type waitq
waitq is a queue of waiting goroutines. There’s a special flag to check whether goroutine has grabbed the channel locks but not removed itself from waitq.
If the flag is true, dequeue will continue and try to find the next valid goroutine.
type hchan
hchan used a circular queue to save the buffered channel data.
Runtime Implementation
makechan
- Check the element’s size and alignment, and the expected
chan’s size. - Allocate the memory for
hchan. The memory allocation is very dense and the runtime will try to utilize the memory at its best effort.
chansend
- Check whether the channel is unresponsive and return.
- Lock the channel
- Check whether the channel is closed.
- Get a receiver from
waitq, and send the data directly to that goroutine, then return true. - If the channel buffer is not full yet,
memmovethe data to the circular queue, then return true. - If it’s not a blocking operation, return false.
- Block the current goroutine, and put it on the
sendq.
send
send will send the data to the target goroutine. It happens when the target goroutine is waiting and the data arrived on the channel.
The send operation will copy the data directly to the target goroutine’s stack, and make the target goroutine as ready state.
chanrecv
- Check whether the channel is unresponsive and return.
- Lock the channel
- If the queue is closed and the circular queue is empty, return.
- If there’s a waiting goroutine on
sendq,recvimmediately and return. - Move the data from the circular queue to the target memory address.
- If it’s not a blocking operation, return false.
- Block the current goroutine, and put it on the
waitq.
recv
recv happens under a similar condition to send.
- If the channel is unbuffered,
recvDirectfrom the sending goroutine to receiving goroutine. - Read the data from the circular queue first, and move the data to the target memory address.
- Mark the sending goroutine as ready to run. Note that the receiving goroutine is already running.
What’s Next
- Go’s typing system
- Go’s routines implementation.