On Monday, February 6, 2017 at 11:16:22 AM UTC, T L wrote: > > > > On Monday, February 6, 2017 at 6:43:04 PM UTC+8, T L wrote: >> >> >> >> On Monday, February 6, 2017 at 3:14:22 AM UTC+8, Ian Lance Taylor wrote: >>> >>> On Sun, Feb 5, 2017 at 10:52 AM, T L <tapi...@gmail.com> wrote: >>> > Ian, thanks for the answers. >>> > >>> > But I still not very confirm on many points. >>> > >>> > Up to now, there are two places mention the alignments in Go. >>> > >>> > The first is in the end of Go spec: >>> > >>> > >>> > Size and alignment guarantees >>> > >>> > For the numeric types, the following sizes are guaranteed: >>> > >>> > type size in bytes >>> > >>> > byte, uint8, int8 1 >>> > uint16, int16 2 >>> > uint32, int32, float32 4 >>> > uint64, int64, float64, complex64 8 >>> > complex128 16 >>> > >>> > The following minimal alignment properties are guaranteed: >>> > >>> > For a variable x of any type: unsafe.Alignof(x) is at least 1. >>> > For a variable x of struct type: unsafe.Alignof(x) is the largest of >>> all the >>> > values unsafe.Alignof(x.f) for each field f of x, but at least 1. >>> > For a variable x of array type: unsafe.Alignof(x) is the same as >>> > unsafe.Alignof(x[0]), but at least 1. >>> > >>> > A struct or array type has size zero if it contains no fields (or >>> elements, >>> > respectively) that have a size greater than zero. Two distinct >>> zero-size >>> > variables may have the same address in memory. >>> > >>> > >>> > The second is at the end of sync/atomic docs: >>> > >>> > >>> > On x86-32, the 64-bit functions use instructions unavailable before >>> the >>> > Pentium MMX. >>> > >>> > On non-Linux ARM, the 64-bit functions use instructions unavailable >>> before >>> > the ARMv6k core. >>> > >>> > On both ARM and x86-32, it is the caller's responsibility to arrange >>> for >>> > 64-bit alignment of 64-bit words accessed atomically. The first word >>> in a >>> > global variable or in an allocated struct or slice can be relied upon >>> to be >>> > 64-bit aligned. >>> > >>> > >>> > I feel the two are not enough to remove all my confusions. >>> > >>> > So could you help me remove the following confusions: >>> > >>> > >>> > 1. What does the "allocated struct or slice" mean? >>> > >>> > >>> > Currently, I think it means the structs or slices created by new, or >>> the >>> > structs or slices escape to heap. >>> > >>> > Is my understanding right? >>> >>> Those cases are "allocated struct or slice," yes. The phrase also >>> includes variables defined with a struct or slice type. >>> >>> >>> > 2. Are local 8-bytes variables 64bit aligned on 32bit OSes? >>> > >>> > >>> > I found there are many usages of the 64bit functions of atomic package >>> being >>> > used on local 8-bytes variables in go source. >>> > >>> > So I think the answer is yes. Right? >>> >>> Yes. >>> >>> >> I installed a 32bit VM and found that local int64 and [N]int64 variables >> are not guaranteed to be 64bit aligned. >> But the magic is, if the local int64 variables are passed to atomic 64bit >> functions, then they become 64bit aligned for sure. >> Quite magic. >> >> It looks when local int64 variables are escaped to heap if their >> addresses are passed to atomic 64bit functions. >> And it looks 64bit words allocated on heap are always 64bit aligned, even >> on 32bit OSes. >> >> >> > > The same is for local structs which first field is a 64bit word. Such > local structs are also not guaranteed to be 64bit aligned. > But if the addresses of the 64bit word fields are passed to atomic 64bit > functions, then the local structs will escape to heap, > so the local structs become 64bit aligned on heap. > > The same for local slices.
The full code: // go version go1.7.5 linux/386 package main import ( "sync/atomic" ) func fa() { println("========== fa") var b bool var arr [5]int64 println(&b, &arr) // 0x1843bf73 0x1843bf74 } func fa2() { println("========== fa2") var b bool var arr [5]int64 println(&b, &arr) // 0x1843bf57 0x184120f0 atomic.LoadInt64(&arr[0]) } func fb() { println("========== fb") var b bool var x = new(int64) println(&b, &x) // 0x1843bf73 0x1843bf74 } func fb2() { println("========== fb2") var b bool var x int64 println(&b, &x) // 0x1843bf57 0x184120f0 atomic.LoadInt64(&x) } func fc() { println("========== fc") var b bool var slc = make([]int64, 1) println(&b, &slc[0]) // 0x1843bf5b 0x1843bf5c } func fc2() { println("========== fc2") var b bool var slc = make([]int64, 1) println(&b, &slc[0]) // 0x1843bf37 0x1840e0e0 atomic.LoadInt64(&slc[0]) } func fd() { type T struct { x int64 } println("========== fd") var b bool var t T println(&b, &t.x) // 0x1843bf33 0x1843bf34 } func fd2() { type T struct { x int64 } println("========== fd2") var b bool var t T println(&b, &t.x) // 0x1843bf37 0x1840e0f0 atomic.LoadInt64(&t.x) } func fd3() { type T struct { x int64 } println("========== fd3") var b bool var t = new(T) println(&b, &t.x) // 0x1843bf33 0x1843bf34 } func main() { fa() fa2() fb() fb2() fc() fc2() fd() fd2() fd3() } > > >> >>> > 3. Are expvar.Int and expvar.Float safe to be embedded in other >>> structs on >>> > 32bit OSes? >>> > >>> > >>> > I think the answer is no. Is my opinion right? >>> >>> You could embed them as the first field of a struct (if you were then >>> careful to not embed that struct, (except as the first field)). >>> >>> It would not be portable to embed them as anything other than the first >>> field. >>> >>> I think this is problematic, and it would be nice to figure out a way to >>> fix it. >>> >>> Ian >>> >> -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.