const maxAlign … const hchanSize … const debugChan … type hchan … type waitq … //go:linkname reflect_makechan reflect.makechan func reflect_makechan(t *chantype, size int) *hchan { … } func makechan64(t *chantype, size int64) *hchan { … } func makechan(t *chantype, size int) *hchan { … } // chanbuf(c, i) is pointer to the i'th slot in the buffer. // // chanbuf should be an internal detail, // but widely used packages access it using linkname. // Notable members of the hall of shame include: // - github.com/fjl/memsize // // Do not remove or change the type signature. // See go.dev/issue/67401. // //go:linkname chanbuf func chanbuf(c *hchan, i uint) unsafe.Pointer { … } // full reports whether a send on c would block (that is, the channel is full). // It uses a single word-sized read of mutable state, so although // the answer is instantaneously true, the correct answer may have changed // by the time the calling function receives the return value. func full(c *hchan) bool { … } // entry point for c <- x from compiled code. // //go:nosplit func chansend1(c *hchan, elem unsafe.Pointer) { … } /* * generic single channel send/recv * If block is not nil, * then the protocol will not * sleep but return if it could * not complete. * * sleep can wake up with g.param == nil * when a channel involved in the sleep has * been closed. it is easiest to loop and re-run * the operation; we'll see that it's now closed. */ func chansend(c *hchan, ep unsafe.Pointer, block bool, callerpc uintptr) bool { … } // send processes a send operation on an empty channel c. // The value ep sent by the sender is copied to the receiver sg. // The receiver is then woken up to go on its merry way. // Channel c must be empty and locked. send unlocks c with unlockf. // sg must already be dequeued from c. // ep must be non-nil and point to the heap or the caller's stack. func send(c *hchan, sg *sudog, ep unsafe.Pointer, unlockf func(), skip int) { … } // timerchandrain removes all elements in channel c's buffer. // It reports whether any elements were removed. // Because it is only intended for timers, it does not // handle waiting senders at all (all timer channels // use non-blocking sends to fill the buffer). func timerchandrain(c *hchan) bool { … } func sendDirect(t *_type, sg *sudog, src unsafe.Pointer) { … } func recvDirect(t *_type, sg *sudog, dst unsafe.Pointer) { … } func closechan(c *hchan) { … } // empty reports whether a read from c would block (that is, the channel is // empty). It is atomically correct and sequentially consistent at the moment // it returns, but since the channel is unlocked, the channel may become // non-empty immediately afterward. func empty(c *hchan) bool { … } // entry points for <- c from compiled code. // //go:nosplit func chanrecv1(c *hchan, elem unsafe.Pointer) { … } //go:nosplit func chanrecv2(c *hchan, elem unsafe.Pointer) (received bool) { … } // chanrecv receives on channel c and writes the received data to ep. // ep may be nil, in which case received data is ignored. // If block == false and no elements are available, returns (false, false). // Otherwise, if c is closed, zeros *ep and returns (true, false). // Otherwise, fills in *ep with an element and returns (true, true). // A non-nil ep must point to the heap or the caller's stack. func chanrecv(c *hchan, ep unsafe.Pointer, block bool) (selected, received bool) { … } // recv processes a receive operation on a full channel c. // There are 2 parts: // 1. The value sent by the sender sg is put into the channel // and the sender is woken up to go on its merry way. // 2. The value received by the receiver (the current G) is // written to ep. // // For synchronous channels, both values are the same. // For asynchronous channels, the receiver gets its data from // the channel buffer and the sender's data is put in the // channel buffer. // Channel c must be full and locked. recv unlocks c with unlockf. // sg must already be dequeued from c. // A non-nil ep must point to the heap or the caller's stack. func recv(c *hchan, sg *sudog, ep unsafe.Pointer, unlockf func(), skip int) { … } func chanparkcommit(gp *g, chanLock unsafe.Pointer) bool { … } // compiler implements // // select { // case c <- v: // ... foo // default: // ... bar // } // // as // // if selectnbsend(c, v) { // ... foo // } else { // ... bar // } func selectnbsend(c *hchan, elem unsafe.Pointer) (selected bool) { … } // compiler implements // // select { // case v, ok = <-c: // ... foo // default: // ... bar // } // // as // // if selected, ok = selectnbrecv(&v, c); selected { // ... foo // } else { // ... bar // } func selectnbrecv(elem unsafe.Pointer, c *hchan) (selected, received bool) { … } //go:linkname reflect_chansend reflect.chansend0 func reflect_chansend(c *hchan, elem unsafe.Pointer, nb bool) (selected bool) { … } //go:linkname reflect_chanrecv reflect.chanrecv func reflect_chanrecv(c *hchan, nb bool, elem unsafe.Pointer) (selected bool, received bool) { … } func chanlen(c *hchan) int { … } func chancap(c *hchan) int { … } //go:linkname reflect_chanlen reflect.chanlen func reflect_chanlen(c *hchan) int { … } //go:linkname reflectlite_chanlen internal/reflectlite.chanlen func reflectlite_chanlen(c *hchan) int { … } //go:linkname reflect_chancap reflect.chancap func reflect_chancap(c *hchan) int { … } //go:linkname reflect_chanclose reflect.chanclose func reflect_chanclose(c *hchan) { … } func (q *waitq) enqueue(sgp *sudog) { … } func (q *waitq) dequeue() *sudog { … } func (c *hchan) raceaddr() unsafe.Pointer { … } func racesync(c *hchan, sg *sudog) { … } // Notify the race detector of a send or receive involving buffer entry idx // and a channel c or its communicating partner sg. // This function handles the special case of c.elemsize==0. func racenotify(c *hchan, idx uint, sg *sudog) { … }