Maybe a bug in modifying a global from a function?

11 views
Skip to first unread message

Jeff R. Allen

unread,
Oct 19, 2010, 7:59:34 AM10/19/10
to golan...@googlegroups.com
I wrote the following program while I was experimenting with Go's concurrency:

package main
import "runtime"
var i int
func f(inc int) {
for {
i += inc
}
}
func main() {
runtime.GOMAXPROCS(3)
go f(1)
go f(-1)
runtime.Gosched()

for j := 0; ; j++ {
if (j % 1e9) == 0 {
print(i, "\n")
}
}
}

What I wanted to do was see how things work in the absence of any
events that cause a yield to the scheduler.

Using "ps -elm" I was able to clearly see my three threads spinning
away. Nifty. But the print in main only ever prints 0. It seems
unlikely I'm so unlucky as to never see a -1, or a 1, so I looked a
little closer. What I found in the assembly for f() seems like a bug:

400800 (7) TEXT main.f+0(SB),$34359738368
400800 64488b0c25f0ffffff (7) MOVQ -16(FS),CX
400809 483b21 (7) CMPQ SP,(CX)
40080c 7705 (7) JHI ,400813
40080e e802480000 (7) CALL ,405015+runtime.morestack8
400813 8b4c2408 (7) MOVL main.inc+8(SP),CX
400817 8b042538324100 (7) MOVL main.i+0(SB),AX
40081e 01c8 (9) ADDL CX,AX
400820 ebfc (9) JMP ,40081e

The bug is that main.i is loaded into register CX and incremented
there, instead of being incremented in RAM so that main.main() can see
it get updated. (This is with release.2010-10-13.1.)

The only thing I could find in the spec is that "The scope of an
identifier denoting a constant, type, variable, or function declared
at top level (outside any function) is the package block." So it seems
to me that f(1), f(-1) and main() all should be seeing the *same* i,
and not their own copies of it stored in a register.

What do the Go masters think?

-jeff

roger peppe

unread,
Oct 19, 2010, 8:03:29 AM10/19/10
to Jeff R. Allen, golan...@googlegroups.com
you need to read this: http://golang.org/doc/go_mem.html

Jeff R. Allen

unread,
Nov 1, 2010, 3:35:06 AM11/1/10
to golang-nuts
Based on this thread, I wrote a blog entry explaining how "happens
before" can affect 8g's decision on register assignment, take a look
if you are interested in understanding the low-level effects of The Go
Memory Model web page Roger mentioned:

http://blog.nella.org/?p=769

Go team, thanks for a fun language to play with and write about!

-jeff

Skip Tavakkolian

unread,
Nov 1, 2010, 3:02:22 PM11/1/10
to Jeff R. Allen, golang-nuts
about the question on your blog re: the behavior with GOMAXPROCS=1, i
don't think the scheduler is guaranteed to be precise. also, in that
example one goroutine seems to have an advantage because of the time
println provides before the next channel read.

but even with more tweaking (see attached), over the long run one
function will be stalled more than the other.

-Skip

hb4.go
Reply all
Reply to author
Forward
0 new messages