github.com/aclements/go-misc@v0.0.0-20240129233631-2f6ede80790c/go-weave/models/cl20858.go (about)

     1  // Copyright 2016 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // +build ignore
     6  
     7  // cl20858 is a model for checking the proposed scheduler change in CL
     8  // 20858.
     9  package main
    10  
    11  import (
    12  	"github.com/aclements/go-misc/go-weave/amb"
    13  	"github.com/aclements/go-misc/go-weave/weave"
    14  )
    15  
    16  var sched = weave.Scheduler{Strategy: &amb.StrategyDFS{}}
    17  
    18  func mainOld() {
    19  	sched.Run(func() {
    20  		runnext, runqhead, runqtail = 0, 0, 0
    21  
    22  		runqput(1)
    23  		sched.Go(func() {
    24  			runqput(2)
    25  			runqget()
    26  		})
    27  		if runqempty() {
    28  			panic("runqempty")
    29  		}
    30  	})
    31  }
    32  
    33  func main() {
    34  	states := 0
    35  	sched.Run(func() {
    36  		states++
    37  		runnext, runqhead, runqtail = 0, 0, 0
    38  
    39  		sched.Go(func() {
    40  			for i := 0; i < 5; i++ {
    41  				if sched.Amb(2) == 0 {
    42  					runqget()
    43  				} else {
    44  					runqput(1)
    45  				}
    46  			}
    47  		})
    48  		var empty, nonempty, checks int
    49  		v := runqempty()
    50  		if empty == 0 && v == true {
    51  			panic("spurious runqempty()")
    52  		}
    53  		if nonempty == checks && v == false {
    54  			panic("spurious !runqempty()")
    55  		}
    56  	})
    57  	println(states, "states")
    58  }
    59  
    60  var runnext int
    61  var runqhead, runqtail int
    62  var runq [256]int
    63  
    64  func runqput(g int) {
    65  	old := runnext
    66  	runnext = g
    67  	sched.Sched()
    68  	if old == 0 {
    69  		return
    70  	}
    71  
    72  	h := runqhead
    73  	sched.Sched()
    74  	t := runqtail
    75  	sched.Sched()
    76  	if t-h < len(runq) {
    77  		runq[t%len(runq)] = g
    78  		sched.Sched()
    79  		runqtail = t + 1
    80  		sched.Sched()
    81  		return
    82  	}
    83  	panic("runq full")
    84  }
    85  
    86  func runqget() int {
    87  	next := runnext
    88  	if next != 0 {
    89  		runnext = 0
    90  		sched.Sched()
    91  		return next
    92  	}
    93  
    94  	for {
    95  		h := runqhead
    96  		sched.Sched()
    97  		t := runqtail
    98  		sched.Sched()
    99  		if t == h {
   100  			return 0
   101  		}
   102  		g := runq[h%len(runq)]
   103  		sched.Sched()
   104  		if runqhead == h {
   105  			runqhead = h + 1
   106  			sched.Sched()
   107  			return g
   108  		}
   109  	}
   110  }
   111  
   112  func runqemptyOld() bool {
   113  	h := runqhead
   114  	sched.Sched()
   115  	t := runqtail
   116  	sched.Sched()
   117  	n := runnext
   118  	sched.Sched()
   119  	return h == t && n == 0
   120  }
   121  
   122  func runqempty() bool {
   123  	for {
   124  		h := runqhead
   125  		sched.Sched()
   126  		t := runqtail
   127  		sched.Sched()
   128  		n := runnext
   129  		sched.Sched()
   130  		t2 := runqtail
   131  		sched.Sched()
   132  		if t == t2 {
   133  			return h == t && n == 0
   134  		}
   135  	}
   136  }
   137  
   138  func runqemptyTest() bool {
   139  	for {
   140  		h := runqhead
   141  		sched.Sched()
   142  		n := runnext
   143  		sched.Sched()
   144  		t := runqtail
   145  		sched.Sched()
   146  		return h == t && n == 0
   147  	}
   148  }