]> Cypherpunks.ru repositories - gostls13.git/blobdiff - src/runtime/runtime2.go
runtime: make it harder to introduce deadlocks with forEachP
[gostls13.git] / src / runtime / runtime2.go
index 9e702aa033396e057d3f2ce84686fffa59b3e687..e7a3d4ed1ba2e4857bcc43fca70e3b33f9e01582 100644 (file)
@@ -342,7 +342,7 @@ type gobuf struct {
        bp   uintptr // for framepointer-enabled architectures
 }
 
-// sudog represents a g in a wait list, such as for sending/receiving
+// sudog (pseudo-g) represents a g in a wait list, such as for sending/receiving
 // on a channel.
 //
 // sudog is necessary because the g ↔ synchronization object relation
@@ -382,6 +382,13 @@ type sudog struct {
        // because c was closed.
        success bool
 
+       // waiters is a count of semaRoot waiting list other than head of list,
+       // clamped to a uint16 to fit in unused space.
+       // Only meaningful at the head of the list.
+       // (If we wanted to be overly clever, we could store a high 16 bits
+       // in the second entry in the list.)
+       waiters uint16
+
        parent   *sudog // semaRoot binary tree
        waitlink *sudog // g.waiting list or semaRoot
        waittail *sudog // semaRoot
@@ -416,7 +423,7 @@ type g struct {
        // stack describes the actual stack memory: [stack.lo, stack.hi).
        // stackguard0 is the stack pointer compared in the Go stack growth prologue.
        // It is stack.lo+StackGuard normally, but can be StackPreempt to trigger a preemption.
-       // stackguard1 is the stack pointer compared in the C stack growth prologue.
+       // stackguard1 is the stack pointer compared in the //go:systemstack stack growth prologue.
        // It is stack.lo+StackGuard on g0 and gsignal stacks.
        // It is ~0 on other goroutine stacks, to trigger a call to morestackc (and crash).
        stack       stack   // offset known to runtime/cgo
@@ -433,7 +440,7 @@ type g struct {
        // param is a generic pointer parameter field used to pass
        // values in particular contexts where other storage for the
        // parameter would be difficult to find. It is currently used
-       // in three ways:
+       // in four ways:
        // 1. When a channel operation wakes up a blocked goroutine, it sets param to
        //    point to the sudog of the completed blocking operation.
        // 2. By gcAssistAlloc1 to signal back to its caller that the goroutine completed
@@ -441,6 +448,8 @@ type g struct {
        //    stack may have moved in the meantime.
        // 3. By debugCallWrap to pass parameters to a new goroutine because allocating a
        //    closure in the runtime is forbidden.
+       // 4. When a panic is recovered and control returns to the respective frame,
+       //    param may point to a savedOpenDeferState.
        param        unsafe.Pointer
        atomicstatus atomic.Uint32
        stackLock    uint32 // sigprof/scang lock; TODO: fold in to atomicstatus
@@ -472,6 +481,7 @@ type g struct {
        parkingOnChan atomic.Bool
 
        raceignore    int8  // ignore race detection events
+       nocgocallback bool  // whether disable callback from C
        tracking      bool  // whether we're tracking this G for sched latency statistics
        trackingSeq   uint8 // used to decide whether to track this G
        trackingStamp int64 // timestamp of when the G last started being tracked
@@ -561,6 +571,7 @@ type m struct {
        printlock     int8
        incgo         bool          // m is executing a cgo call
        isextra       bool          // m is an extra m
+       isExtraInC    bool          // m is an extra m that is not executing Go code
        freeWait      atomic.Uint32 // Whether it is safe to free g0 and delete m (one of freeMRef, freeMStack, freeMWait)
        fastrand      uint64
        needextram    bool
@@ -573,17 +584,21 @@ type m struct {
        alllink       *m // on allm
        schedlink     muintptr
        lockedg       guintptr
-       createstack   [32]uintptr // stack that created this thread.
+       createstack   [32]uintptr // stack that created this thread, it's used for StackRecord.Stack0, so it must align with it.
        lockedExt     uint32      // tracking for external LockOSThread
        lockedInt     uint32      // tracking for internal lockOSThread
        nextwaitm     muintptr    // next m waiting for lock
-       waitunlockf   func(*g, unsafe.Pointer) bool
-       waitlock      unsafe.Pointer
-       waittraceev   byte
-       waittraceskip int
-       startingtrace bool
-       syscalltick   uint32
-       freelink      *m // on sched.freem
+
+       // wait* are used to carry arguments from gopark into park_m, because
+       // there's no stack to put them on. That is their sole purpose.
+       waitunlockf          func(*g, unsafe.Pointer) bool
+       waitlock             unsafe.Pointer
+       waitTraceBlockReason traceBlockReason
+       waitTraceSkip        int
+
+       syscalltick uint32
+       freelink    *m // on sched.freem
+       trace       mTraceState
 
        // these are here because they are too large to be on the stack
        // of low-level NOSPLIT functions.
@@ -604,6 +619,9 @@ type m struct {
        // Whether this is a pending preemption signal on this M.
        signalPending atomic.Uint32
 
+       // pcvalue lookup cache
+       pcvalueCache pcvalueCache
+
        dlogPerM
 
        mOS
@@ -670,15 +688,11 @@ type p struct {
                buf [128]*mspan
        }
 
-       tracebuf traceBufPtr
+       // Cache of a single pinner object to reduce allocations from repeated
+       // pinner creation.
+       pinnerCache *pinner
 
-       // traceSweep indicates the sweep events should be traced.
-       // This is used to defer the sweep start event until a span
-       // has actually been swept.
-       traceSweep bool
-       // traceSwept and traceReclaimed track the number of bytes
-       // swept and reclaimed by sweeping in the current sweep loop.
-       traceSwept, traceReclaimed uintptr
+       trace pTraceState
 
        palloc persistentAlloc // per-P to avoid mutex
 
@@ -946,7 +960,7 @@ type funcinl struct {
 // layout of Itab known to compilers
 // allocated in non-garbage-collected memory
 // Needs to be in sync with
-// ../cmd/compile/internal/reflectdata/reflect.go:/^func.WriteTabs.
+// ../cmd/compile/internal/reflectdata/reflect.go:/^func.WritePluginTable.
 type itab struct {
        inter *interfacetype
        _type *_type
@@ -998,29 +1012,16 @@ func extendRandom(r []byte, n int) {
 // initialize them are not required. All defers must be manually scanned,
 // and for heap defers, marked.
 type _defer struct {
-       started bool
-       heap    bool
-       // openDefer indicates that this _defer is for a frame with open-coded
-       // defers. We have only one defer record for the entire frame (which may
-       // currently have 0, 1, or more defers active).
-       openDefer bool
+       heap      bool
+       rangefunc bool    // true for rangefunc list
        sp        uintptr // sp at time of defer
        pc        uintptr // pc at time of defer
        fn        func()  // can be nil for open-coded defers
-       _panic    *_panic // panic that is running defer
        link      *_defer // next defer on G; can point to either heap or stack!
 
-       // If openDefer is true, the fields below record values about the stack
-       // frame and associated function that has the open-coded defer(s). sp
-       // above will be the sp for the frame, and pc will be address of the
-       // deferreturn call in the function.
-       fd   unsafe.Pointer // funcdata for the function associated with the frame
-       varp uintptr        // value of varp for the stack frame
-       // framepc is the current pc associated with the stack frame. Together,
-       // with sp above (which is the sp associated with the stack frame),
-       // framepc/sp can be used as pc/sp pair to continue a stack trace via
-       // gentraceback().
-       framepc uintptr
+       // If rangefunc is true, *head is the head of the atomic linked list
+       // during a range-over-func execution.
+       head *atomic.Pointer[_defer]
 }
 
 // A _panic holds information about an active panic.
@@ -1032,14 +1033,39 @@ type _defer struct {
 // _panic values only live on the stack, regular stack pointer
 // adjustment takes care of them.
 type _panic struct {
-       argp      unsafe.Pointer // pointer to arguments of deferred call run during panic; cannot move - known to liblink
-       arg       any            // argument to panic
-       link      *_panic        // link to earlier panic
-       pc        uintptr        // where to return to in runtime if this panic is bypassed
-       sp        unsafe.Pointer // where to return to in runtime if this panic is bypassed
-       recovered bool           // whether this panic is over
-       aborted   bool           // the panic was aborted
-       goexit    bool
+       argp unsafe.Pointer // pointer to arguments of deferred call run during panic; cannot move - known to liblink
+       arg  any            // argument to panic
+       link *_panic        // link to earlier panic
+
+       // startPC and startSP track where _panic.start was called.
+       startPC uintptr
+       startSP unsafe.Pointer
+
+       // The current stack frame that we're running deferred calls for.
+       sp unsafe.Pointer
+       lr uintptr
+       fp unsafe.Pointer
+
+       // retpc stores the PC where the panic should jump back to, if the
+       // function last returned by _panic.next() recovers the panic.
+       retpc uintptr
+
+       // Extra state for handling open-coded defers.
+       deferBitsPtr *uint8
+       slotsPtr     unsafe.Pointer
+
+       recovered   bool // whether this panic has been recovered
+       goexit      bool
+       deferreturn bool
+}
+
+// savedOpenDeferState tracks the extra state from _panic that's
+// necessary for deferreturn to pick up where gopanic left off,
+// without needing to unwind the stack.
+type savedOpenDeferState struct {
+       retpc           uintptr
+       deferBitsOffset uintptr
+       slotsOffset     uintptr
 }
 
 // ancestorInfo records details of where a goroutine was started.
@@ -1086,6 +1112,7 @@ const (
        waitReasonDebugCall                               // "debug call"
        waitReasonGCMarkTermination                       // "GC mark termination"
        waitReasonStoppingTheWorld                        // "stopping the world"
+       waitReasonFlushProcCaches                         // "flushing proc caches"
 )
 
 var waitReasonStrings = [...]string{
@@ -1121,6 +1148,7 @@ var waitReasonStrings = [...]string{
        waitReasonDebugCall:             "debug call",
        waitReasonGCMarkTermination:     "GC mark termination",
        waitReasonStoppingTheWorld:      "stopping the world",
+       waitReasonFlushProcCaches:       "flushing proc caches",
 }
 
 func (w waitReason) String() string {