Home | History | Annotate | Download | only in ken
      1 // run
      2 
      3 // Copyright 2009 The Go Authors. All rights reserved.
      4 // Use of this source code is governed by a BSD-style
      5 // license that can be found in the LICENSE file.
      6 
      7 // Test communication operations including select.
      8 
      9 package main
     10 
     11 import "os"
     12 import "runtime"
     13 import "sync"
     14 
     15 var randx int
     16 
     17 func nrand(n int) int {
     18 	randx += 10007
     19 	if randx >= 1000000 {
     20 		randx -= 1000000
     21 	}
     22 	return randx % n
     23 }
     24 
     25 type Chan struct {
     26 	sc, rc chan int // send and recv chan
     27 	sv, rv int      // send and recv seq
     28 }
     29 
     30 var (
     31 	nproc      int
     32 	nprocLock  sync.Mutex
     33 	cval       int
     34 	end        int = 10000
     35 	totr, tots int
     36 	totLock    sync.Mutex
     37 	nc         *Chan
     38 )
     39 
     40 func init() {
     41 	nc = new(Chan)
     42 }
     43 
     44 func changeNproc(adjust int) int {
     45 	nprocLock.Lock()
     46 	nproc += adjust
     47 	ret := nproc
     48 	nprocLock.Unlock()
     49 	return ret
     50 }
     51 
     52 func mkchan(c, n int) []*Chan {
     53 	ca := make([]*Chan, n)
     54 	for i := 0; i < n; i++ {
     55 		cval = cval + 100
     56 		ch := new(Chan)
     57 		ch.sc = make(chan int, c)
     58 		ch.rc = ch.sc
     59 		ch.sv = cval
     60 		ch.rv = cval
     61 		ca[i] = ch
     62 	}
     63 	return ca
     64 }
     65 
     66 func expect(v, v0 int) (newv int) {
     67 	if v == v0 {
     68 		if v%100 == 75 {
     69 			return end
     70 		}
     71 		return v + 1
     72 	}
     73 	print("got ", v, " expected ", v0+1, "\n")
     74 	panic("fail")
     75 }
     76 
     77 func (c *Chan) send() bool {
     78 	//	print("send ", c.sv, "\n");
     79 	totLock.Lock()
     80 	tots++
     81 	totLock.Unlock()
     82 	c.sv = expect(c.sv, c.sv)
     83 	if c.sv == end {
     84 		c.sc = nil
     85 		return true
     86 	}
     87 	return false
     88 }
     89 
     90 func send(c *Chan) {
     91 	for {
     92 		for r := nrand(10); r >= 0; r-- {
     93 			runtime.Gosched()
     94 		}
     95 		c.sc <- c.sv
     96 		if c.send() {
     97 			break
     98 		}
     99 	}
    100 	changeNproc(-1)
    101 }
    102 
    103 func (c *Chan) recv(v int) bool {
    104 	//	print("recv ", v, "\n");
    105 	totLock.Lock()
    106 	totr++
    107 	totLock.Unlock()
    108 	c.rv = expect(c.rv, v)
    109 	if c.rv == end {
    110 		c.rc = nil
    111 		return true
    112 	}
    113 	return false
    114 }
    115 
    116 func recv(c *Chan) {
    117 	var v int
    118 
    119 	for {
    120 		for r := nrand(10); r >= 0; r-- {
    121 			runtime.Gosched()
    122 		}
    123 		v = <-c.rc
    124 		if c.recv(v) {
    125 			break
    126 		}
    127 	}
    128 	changeNproc(-1)
    129 }
    130 
    131 func sel(r0, r1, r2, r3, s0, s1, s2, s3 *Chan) {
    132 	var v int
    133 
    134 	a := 0 // local chans running
    135 
    136 	if r0.rc != nil {
    137 		a++
    138 	}
    139 	if r1.rc != nil {
    140 		a++
    141 	}
    142 	if r2.rc != nil {
    143 		a++
    144 	}
    145 	if r3.rc != nil {
    146 		a++
    147 	}
    148 	if s0.sc != nil {
    149 		a++
    150 	}
    151 	if s1.sc != nil {
    152 		a++
    153 	}
    154 	if s2.sc != nil {
    155 		a++
    156 	}
    157 	if s3.sc != nil {
    158 		a++
    159 	}
    160 
    161 	for {
    162 		for r := nrand(5); r >= 0; r-- {
    163 			runtime.Gosched()
    164 		}
    165 
    166 		select {
    167 		case v = <-r0.rc:
    168 			if r0.recv(v) {
    169 				a--
    170 			}
    171 		case v = <-r1.rc:
    172 			if r1.recv(v) {
    173 				a--
    174 			}
    175 		case v = <-r2.rc:
    176 			if r2.recv(v) {
    177 				a--
    178 			}
    179 		case v = <-r3.rc:
    180 			if r3.recv(v) {
    181 				a--
    182 			}
    183 		case s0.sc <- s0.sv:
    184 			if s0.send() {
    185 				a--
    186 			}
    187 		case s1.sc <- s1.sv:
    188 			if s1.send() {
    189 				a--
    190 			}
    191 		case s2.sc <- s2.sv:
    192 			if s2.send() {
    193 				a--
    194 			}
    195 		case s3.sc <- s3.sv:
    196 			if s3.send() {
    197 				a--
    198 			}
    199 		}
    200 		if a == 0 {
    201 			break
    202 		}
    203 	}
    204 	changeNproc(-1)
    205 }
    206 
    207 // direct send to direct recv
    208 func test1(c *Chan) {
    209 	changeNproc(2)
    210 	go send(c)
    211 	go recv(c)
    212 }
    213 
    214 // direct send to select recv
    215 func test2(c int) {
    216 	ca := mkchan(c, 4)
    217 
    218 	changeNproc(4)
    219 	go send(ca[0])
    220 	go send(ca[1])
    221 	go send(ca[2])
    222 	go send(ca[3])
    223 
    224 	changeNproc(1)
    225 	go sel(ca[0], ca[1], ca[2], ca[3], nc, nc, nc, nc)
    226 }
    227 
    228 // select send to direct recv
    229 func test3(c int) {
    230 	ca := mkchan(c, 4)
    231 
    232 	changeNproc(4)
    233 	go recv(ca[0])
    234 	go recv(ca[1])
    235 	go recv(ca[2])
    236 	go recv(ca[3])
    237 
    238 	changeNproc(1)
    239 	go sel(nc, nc, nc, nc, ca[0], ca[1], ca[2], ca[3])
    240 }
    241 
    242 // select send to select recv
    243 func test4(c int) {
    244 	ca := mkchan(c, 4)
    245 
    246 	changeNproc(2)
    247 	go sel(nc, nc, nc, nc, ca[0], ca[1], ca[2], ca[3])
    248 	go sel(ca[0], ca[1], ca[2], ca[3], nc, nc, nc, nc)
    249 }
    250 
    251 func test5(c int) {
    252 	ca := mkchan(c, 8)
    253 
    254 	changeNproc(2)
    255 	go sel(ca[4], ca[5], ca[6], ca[7], ca[0], ca[1], ca[2], ca[3])
    256 	go sel(ca[0], ca[1], ca[2], ca[3], ca[4], ca[5], ca[6], ca[7])
    257 }
    258 
    259 func test6(c int) {
    260 	ca := mkchan(c, 12)
    261 
    262 	changeNproc(4)
    263 	go send(ca[4])
    264 	go send(ca[5])
    265 	go send(ca[6])
    266 	go send(ca[7])
    267 
    268 	changeNproc(4)
    269 	go recv(ca[8])
    270 	go recv(ca[9])
    271 	go recv(ca[10])
    272 	go recv(ca[11])
    273 
    274 	changeNproc(2)
    275 	go sel(ca[4], ca[5], ca[6], ca[7], ca[0], ca[1], ca[2], ca[3])
    276 	go sel(ca[0], ca[1], ca[2], ca[3], ca[8], ca[9], ca[10], ca[11])
    277 }
    278 
    279 // wait for outstanding tests to finish
    280 func wait() {
    281 	runtime.Gosched()
    282 	for changeNproc(0) != 0 {
    283 		runtime.Gosched()
    284 	}
    285 }
    286 
    287 // run all tests with specified buffer size
    288 func tests(c int) {
    289 	ca := mkchan(c, 4)
    290 	test1(ca[0])
    291 	test1(ca[1])
    292 	test1(ca[2])
    293 	test1(ca[3])
    294 	wait()
    295 
    296 	test2(c)
    297 	wait()
    298 
    299 	test3(c)
    300 	wait()
    301 
    302 	test4(c)
    303 	wait()
    304 
    305 	test5(c)
    306 	wait()
    307 
    308 	test6(c)
    309 	wait()
    310 }
    311 
    312 // run all test with 4 buffser sizes
    313 func main() {
    314 
    315 	tests(0)
    316 	tests(1)
    317 	tests(10)
    318 	tests(100)
    319 
    320 	t := 4 * // buffer sizes
    321 		(4*4 + // tests 1,2,3,4 channels
    322 			8 + // test 5 channels
    323 			12) * // test 6 channels
    324 		76 // sends/recvs on a channel
    325 
    326 	if tots != t || totr != t {
    327 		print("tots=", tots, " totr=", totr, " sb=", t, "\n")
    328 		os.Exit(1)
    329 	}
    330 	os.Exit(0)
    331 }
    332