Go Runtime Implementations: Map

Code Path: src/runtime/map.go makemap Each hmap has a hash0 as seed hash. When the compiler generates the typing information for a map, the hasher function will be calculated with genhash function (code path: src/cmd/compile/internal/reflectdata/alg.go). If the map is not escaped, the hmap will be allocated by the compiler on the stack. Then makemap will allocate an array of bucket, the type of bucket is generated at compiling stage by MapBucketType (code path: src/cmd/compile/internal/reflectdata/reflect.go). ...

November 23, 2022

Go Runtime Implementations: Timer Scheduling

Code Path: src/runtime/time.go time.startTimer (implemented as addtimer) Each p has a timers list. When a user is adding a new timer, it will first try to clean up the timers list, then adds the new timer. Each timers list is a heap sorted by timer.when, and will be updated during add/delete timers. cleantimers cleantimers only checks the head of the timers list. Check if it’s timerDeleted, delete it from the timers list, and update p’s timer0When. Check if it’s timerModifiedEarlier or timerModifiedLater, delete it from the timers list and add it back to put it at the right position in the list. doaddtimer doaddtimer link the time to the p’s timers list, and sift up the heap to put it in the right position. ...

November 7, 2022

Go Runtime Implementations: Network Polling

Code Path: src/runtime/netpoll.go Network polling is platform-dependent, the following is of BSD family operating systems (based on kqueue). netpollinit Initialize a kqueue descriptor, and set CLOSEXEC flag on it. Initialize a non-blocking pipe, and use the reader/writer for netpollBreak. netpollBreak will try to write to the pipe and interrupt the kevent. netpoll netpoll is used to check the connections and return a list of g ready to run. It can block for delay ns at most. The delay parameter will be passed to kevent syscall. ...

November 5, 2022

Go Runtime Implementations: Select

Code Path: src/runtime/select.go IR stage IR will walk a select statement and generate the code accordingly: If there’s no case, replace the select statement with runtime.block, the current goroutine will be blocked forever. If there’s only one case, extract the send or receive operation from the case statement. Otherwise, convert case values to addresses. If there’s only one case with one default, replace it with non-block calls selectnbsend or selectnbrecv. Generate a select statement with the list of send and recv cases, and run selectgo on it. Run the case or default based on the returned index of selectgo. selectgo selectgo takes two major arguments: a list of scase and a list of the orders of recv/send. It returns the pos of case to execute. ...

November 4, 2022

Go Runtime Implementations: Slices

Code Path: src/runtime/slice.go makeslicecopy makeslicecopy is used for IR patterns like m = OMAKESLICE([]T, x); OCOPY(m, s), IR will rewrite this specific order of code path and replace it with OMAKESLICECOPY. If the elements has no pointer, SSA will generate code to do a mallocgc and memmove. Otherwise, the code will be expanded to makeslicecopy: Check the length of the slice to copy to. Do mallocgc Do memmove makeslice and `makeslice641 makeslice is used for make(slice, len, cap) statements, if cap is missing, by default it will be the same as len. ...

November 4, 2022

Go Runtime Implementations: Interfaces

Static Definition and Initialization Code Path: src/runtime/iface.go In proc.go, itabsinit will init the itabTable with the current activeModules information. The itabsinit function will read the itablinks from each module and add them to the global hash table. During the runtime, the getitab function will also build more items dynamically and fill the hash table accordingly. itablinks was produced for each module during the linking stage, and contains an array of itab. itab is generated by writeITab function (code path: cmd/compile/internal/reflectdata/reflect.go), used to store the type link between a concrete type (_type field) implementing an interface (inter field). If _type doesn’t implement inter, fun will be empty; else it will save the methods of _type implementing inter (not all methods of _type). ...

October 27, 2022

Go Runtime Implementations: Typing System

Compiling Code Path: src/cmd/compile/internal/ir/expr.go During the IR stage, each expression will get type info, it’s defined as miniExpr and can be assigned a types.Type value. Static Typing: types2 Code Path: src/cmd/compile/internal/types2 types and `types2 Conversion Code Path: src/cmd/compile/internal/noder/types.go Currently, both packages are in use, but much logic is being migrated to types2 package. types2 package was introduced as part of go generic features and has a better code structure than the old types package. ...

October 25, 2022

Go Runtime Implementations: Garbage Collection

Ref Garbage Collector Code Path: src/runtime/mgc.go gcinit gcinit runs after almost everything set up in schedinit. Set sweepDrainedMask Initialize gcController with GOGC (for GC percentage control) and GOMEMLIMIT (for memory limits). Initialize work semaphores. gcenable gcenable happens in the main goroutine, right after runtime_inittask. Start bgsweep Start bgscavenge GC GC runs a full garbage collection. Each run will finish the current GC cycle: sweep termination, mark, mark termination, and sweep. Then it will start a new GC cycle. Note that GC cycles can move forward to more than N+1. ...

October 18, 2022

Go Runtime Implementations: Stack and Memory Management

Stack Management Code Path: src/runtime/stack.go Stack pools are initialized before mheap_, because we don’t allocate any memory during this stage. Right after the stack pools initialized, the mheap_ will be initialized so later stack allocation is possible. stackpool stackpool is managed by the “order” (based on the ratio of stack size and _FixedStack) of the stack, each order of stack has its own stack pool. In stackinit, the stack pool will be initialized right after moduledataverify. ...

October 16, 2022

Go Runtime Implementations: Scheduling

Code Path: src/runtime/proc.go Start-Up Process of a Go program. Take src/runtime/asm_arm.s as an example: Take the address of g0 and m0. Set up m.g0 and g.m. Create istack. Do runtime check. Save argc and argv. Call runtime.osinit. Call runtime.schedinit. Call runtime.newproc for the main function. call runtime.mstart to start the M. runtime.osinit Take src/runtime/os_linux.go as an example: Get the number of processors. This is done by making a syscall SYS_sched_getaffinity. Get the huge page size. Run osArchInit. <- Seems not used. runtime.schedinit Initialize all the locks. Set up the g.racectx. Stop the world. moduledataverify. Defined in src/runtime/symtab.go, it will check moduledata’s binary info. stackinit. Defined in src/runtime/stack.go, it will setup the global stack pool, all stacks will be allocated by it. mallocinit. Defined in src/runtime/malloc.go, it will initialize the memory allocator used by Go. cpuinit. Set up the internal/cpu information. alginit. Defined in src/runtime/alg.go, set up the CPU instructions that will be used by some internal algorithms, depending on cpuinit. fastrandinit. Initialize the g0.m with mcommoninit. modulesinit. Defined in src/runtime/symtab.go, initialize the dynamic loaded modules. typelinksinit. Defined in src/runtime/type.go, initialized the dynamic-loaded module type informations. itabsinit. Defined in src/runtime/iface.go, update itabTable with the dynamic-loaded modules. stkobjinit. Defined in src/runtime/stkframe.go, this will set up methodValueCallFrameObjs, used by later GC module. Save the signal mask as initSigMask. Parse argv. Defined in src/runtime/runtime1.go. Parse environment variables. parsedebugvars. Defined in src/runtime/runtime1.go. gcinit. Set up the number of processors, and trim it accordingly with procresize: Grow allp as necessary. Initialize all the p’s of allp. Release old p’s. Track the idle and runnable p, and return the runnable p’s. There should be zero runnable p, since this is only a bootstrap process. Start the world. runtime.mstart mstart0 set up the stack info, then calls runtime.mstart1 to allocate the m: ...

October 14, 2022