Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

runtime: support linux/arm 64kB page size #12480

Closed
prodigy7 opened this issue Sep 3, 2015 · 8 comments
Closed

runtime: support linux/arm 64kB page size #12480

prodigy7 opened this issue Sep 3, 2015 · 8 comments
Milestone

Comments

@prodigy7
Copy link

prodigy7 commented Sep 3, 2015

Hi,

I bought last week a Zyxel NAS540 which uses a kernel with 64k pages. Now, after some days of investigating how I can run own software on the NAS (the NAS itself is open for access from outside), I found out that

  • it was really a bad idea setting kernel size from 4k to 64k because it breaks the compatibility with many many many ready build software packages
  • it wasn't a manufacture / device specific problem. There are some other manufactures (maybe they all using a kernel provided by the board manufacture), WD for example, having the same issue with newer firmware versions.

It would nice, if Go would be supplemented with a build for ARM/64k. Another discussion related to that topic in context with the software syncthing could also found here: syncthing/syncthing#928

I compiled syncthing like here https://forum.syncthing.net/t/request-for-64k-binaries/5555/9 described but when I start syncthing, I got errors like that and I think its a 64k problem:

[VUFJZ] 19:21:35 INFO: syncthing unknown-dev "Beryllium Bedbug" (go1.5 linux-arm default) unknown@unknown 1970-01-01 00:00:00 UTC
[VUFJZ] 19:21:35 INFO: My ID: VUFJZWO-S5JJRJO-TFQVE5M-5HDXDDV-NIBS3L2-KNTU2G3-HRV77Q2-LR3XXXX
[VUFJZ] 19:21:35 INFO: Database block cache capacity 8192 KiB
...
Panic at 2015-09-03T19:21:35Z
fatal error: runtime: cannot map pages in arena address space

runtime stack:
runtime.throw(0x6591c0, 0x30)
        /usr/lib64/go/src/runtime/panic.go:527 +0x78
runtime.sysMap(0xb01000, 0x1000, 0x11200001, 0x9be1a8)
        /usr/lib64/go/src/runtime/mem_linux.go:157 +0x180
runtime.mHeap_MapSpans(0x9abf08, 0x11600000)
        /usr/lib64/go/src/runtime/mheap.go:314 +0xc8
runtime.mHeap_SysAlloc(0x9abf08, 0x400000, 0x10d15f20)
        /usr/lib64/go/src/runtime/malloc.go:425 +0x198
runtime.mHeap_Grow(0x9abf08, 0x200, 0x0)
        /usr/lib64/go/src/runtime/mheap.go:628 +0x68
runtime.mHeap_AllocSpanLocked(0x9abf08, 0x200, 0x0)
        /usr/lib64/go/src/runtime/mheap.go:532 +0x6c8
runtime.mHeap_Alloc_m(0x9abf08, 0x200, 0x0, 0xa7801, 0x67924)
        /usr/lib64/go/src/runtime/mheap.go:425 +0x23c
runtime.mHeap_Alloc.func1()
        /usr/lib64/go/src/runtime/mheap.go:484 +0x40
runtime.systemstack(0x10d15f70)
        /usr/lib64/go/src/runtime/asm_arm.s:256 +0xa8
runtime.mHeap_Alloc(0x9abf08, 0x200, 0x0, 0x10c10101, 0x10ba07ff)
        /usr/lib64/go/src/runtime/mheap.go:485 +0x58
runtime.largeAlloc(0x400000, 0x1, 0x10c0b5a0)
        /usr/lib64/go/src/runtime/malloc.go:745 +0xb4
runtime.mallocgc.func3()
        /usr/lib64/go/src/runtime/malloc.go:634 +0x34
runtime.systemstack(0x10c19400)
        /usr/lib64/go/src/runtime/asm_arm.s:242 +0x80
runtime.mstart()
        /usr/lib64/go/src/runtime/proc1.go:674

goroutine 1 [running]:
runtime.systemstack_switch()
        /usr/lib64/go/src/runtime/asm_arm.s:187 +0x4 fp=0x10d2a594 sp=0x10d2a590
runtime.mallocgc(0x400000, 0x4ccc60, 0x1, 0x1)
        /usr/lib64/go/src/runtime/malloc.go:635 +0x9e8 fp=0x10d2a600 sp=0x10d2a594
runtime.newarray(0x4ccc60, 0x400000, 0x10c0b5a4)
        /usr/lib64/go/src/runtime/malloc.go:777 +0xe4 fp=0x10d2a620 sp=0x10d2a600
runtime.makeslice(0x4c3198, 0x0, 0x0, 0x400000, 0x0, 0x0, 0x0, 0x0)
        /usr/lib64/go/src/runtime/slice.go:32 +0x1d8 fp=0x10d2a648 sp=0x10d2a620
github.com/syndtr/goleveldb/leveldb/memdb.New(0x31e24c48, 0x10c0b010, 0x400000, 0x10d2a700)
        /usr/lib64/go/contrib/src/github.com/syndtr/goleveldb/leveldb/memdb/memdb.go:466 +0xa8 fp=0x10d2a698 sp=0x10d2a648
github.com/syndtr/goleveldb/leveldb.(*DB).newMem(0x10da2620, 0x0, 0x0, 0x0, 0x0)
        /usr/lib64/go/contrib/src/github.com/syndtr/goleveldb/leveldb/db_state.go:125 +0x528 fp=0x10d2a710 sp=0x10d2a698
github.com/syndtr/goleveldb/leveldb.(*DB).recoverJournal(0x10da2620, 0x0, 0x0)
        /usr/lib64/go/contrib/src/github.com/syndtr/goleveldb/leveldb/db.go:609 +0x1130 fp=0x10d2a978 sp=0x10d2a710
github.com/syndtr/goleveldb/leveldb.openDB(0x10d65420, 0x0, 0x0, 0x0)
        /usr/lib64/go/contrib/src/github.com/syndtr/goleveldb/leveldb/db.go:122 +0x914 fp=0x10d2aa64 sp=0x10d2a978
github.com/syndtr/goleveldb/leveldb.Open(0x31e249e0, 0x10d9ec80, 0x10d4a8f0, 0x0, 0x0, 0x0)
        /usr/lib64/go/contrib/src/github.com/syndtr/goleveldb/leveldb/db.go:194 +0x16c fp=0x10d2aa8c sp=0x10d2aa64
github.com/syndtr/goleveldb/leveldb.OpenFile(0x10c16dc0, 0x31, 0x10d4a8f0, 0x0, 0x0, 0x0)
        /usr/lib64/go/contrib/src/github.com/syndtr/goleveldb/leveldb/db.go:216 +0x80 fp=0x10d2aab8 sp=0x10d2aa8c
main.syncthingMain()
        /public/src/github.com/syncthing/syncthing/cmd/syncthing/main.go:599 +0x1624 fp=0x10d2b850 sp=0x10d2aab8
main.main()
        /public/src/github.com/syncthing/syncthing/cmd/syncthing/main.go:388 +0x2394 fp=0x10d2bf94 sp=0x10d2b850
runtime.main()
        /usr/lib64/go/src/runtime/proc.go:111 +0x2b4 fp=0x10d2bfbc sp=0x10d2bf94
runtime.goexit()
        /usr/lib64/go/src/runtime/asm_arm.s:1036 +0x4 fp=0x10d2bfbc sp=0x10d2bfbc

goroutine 6 [syscall]:
os/signal.loop()
        /usr/lib64/go/src/os/signal/signal_unix.go:22 +0x14
created by os/signal.init.1
        /usr/lib64/go/src/os/signal/signal_unix.go:28 +0x30

goroutine 7 [chan receive]:
main.trackCPUUsage()
        /public/src/github.com/syncthing/syncthing/cmd/syncthing/gui_unix.go:24 +0x108
created by main.init.3
        /public/src/github.com/syncthing/syncthing/cmd/syncthing/gui_unix.go:17 +0x24

goroutine 8 [select]:
github.com/thejerf/suture.(*Supervisor).Serve(0x10c7c080)
        /usr/lib64/go/contrib/src/github.com/thejerf/suture/suture.go:432 +0xcec
created by github.com/thejerf/suture.(*Supervisor).ServeBackground
        /usr/lib64/go/contrib/src/github.com/thejerf/suture/suture.go:394 +0x2c

goroutine 9 [select]:
github.com/syncthing/syncthing/lib/events.(*Subscription).Poll(0x10c13550, 0xf8475800, 0xd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ...)
        /usr/lib64/go/contrib/src/github.com/syncthing/syncthing/lib/events/events.go:201 +0x3d4
github.com/syncthing/syncthing/lib/events.(*BufferedSubscription).pollingLoop(0x10c0e990)
        /usr/lib64/go/contrib/src/github.com/syncthing/syncthing/lib/events/events.go:239 +0x38
created by github.com/syncthing/syncthing/lib/events.NewBufferedSubscription
    /usr/lib64/go/contrib/src/github.com/syncthing/syncthing/lib/events/events.go:233 +0x268

goroutine 10 [select]:
    github.com/syndtr/goleveldb/leveldb/util.(*BufferPool).drain(0x10d4aa50)
        /usr/lib64/go/contrib/src/github.com/syndtr/goleveldb/leveldb/util/buffer_pool.go:206 +0x260
created by github.com/syndtr/goleveldb/leveldb/util.NewBufferPool
        /usr/lib64/go/contrib/src/github.com/syndtr/goleveldb/leveldb/util/buffer_pool.go:237 +0x258
@bradfitz
Copy link
Contributor

bradfitz commented Sep 3, 2015

What is the concrete bug here?

This reads to me like syncthing has a bug.

Or, what is Go doing wrong?

/cc @davecheney @minux @ianlancetaylor

@minux
Copy link
Member

minux commented Sep 3, 2015

see also #10180 for the linker enhancement and more discussion
of this issue (this one could probably be merged into that one.)

Basically runtime assumes 4KB pages in its memory allocator,
that can be changed but will probably slow things down (the
_PhysPageSize will no longer be a constant.)

@rsc rsc changed the title Support for ARM/Linux with 64k page size runtime: support linux/arm 64kB page size Oct 19, 2015
@rsc rsc added this to the Go1.6 milestone Oct 23, 2015
@rsc rsc modified the milestones: Unplanned, Go1.6 Nov 24, 2015
@thoscut
Copy link

thoscut commented Feb 3, 2016

Some newer Synology NAS like the DS715+ are affected as well as the kernel is using 64k pages.

@rmoriz
Copy link

rmoriz commented Jul 12, 2016

Other ARM-based NAS like ("Western Digital My Cloud Mirror")[http://www.wdc.com/de/products/products.aspx?id=1640] have a PAGESIZE of 32768. Popular golang projects like syncthing and rclone wont work there.

@davecheney
Copy link
Contributor

Austin and Rick are here at GopherCon, i'll ask them what the consequences
of making the page size a variable set at startup rather than a constant. I
think the concern is that constant is used in a complicated expression in
hot loop of the gc.

On Tue, Jul 12, 2016 at 8:12 AM, Roland Moriz notifications@github.com
wrote:

Other ARM-based NAS like "Western Digital My Cloud" have a PAGESIZE of
32768.


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
#12480 (comment), or mute
the thread
https://github.com/notifications/unsubscribe/AAAcA0rYQQDMFYWd24OKd4jx4SiFSx-gks5qU6DJgaJpZM4F3g3x
.

@davecheney
Copy link
Contributor

/cc @aclements @RLH this is the issue we spoke about at GopherCon.

@gopherbot
Copy link
Contributor

CL https://golang.org/cl/25021 mentions this issue.

@ianlancetaylor ianlancetaylor modified the milestones: Go1.8, Unplanned Jul 19, 2016
@aclements
Copy link
Member

@prodigy7, @tseel, @rmoriz, you should be able to cherry-pick https://go-review.googlesource.com/c/25021 on to Go 1.7 to get larger pages on your NASes. You'll have to rebuild the toolchain, but it should work. The next release should work without any additional effort, since it will detect whatever the OS page size is and use that directly.

There may still be linker issues with Go on large page machines, as documented in #10180. Since this has been reduced to solving the remaining problems in #10180, I'm going to go ahead and close this as a dup.

gopherbot pushed a commit that referenced this issue Sep 6, 2016
Currently we assume the physical page size on ARM is 4kB. While this
is usually true, the architecture also supports 16kB and 64kB physical
pages, and Linux (and possibly other OSes) can be configured to use
these larger page sizes.

With Go 1.6, such a configuration could potentially run, but generally
resulted in memory corruption or random panics. With current master,
this configuration will cause the runtime to panic during init on
Linux when it checks the true physical page size (and will still cause
corruption or panics on other OSes).

However, the assumed physical page size only has to be a multiple of
the true physical page size, the scavenger can now deal with large
physical page sizes, and the rest of the runtime can deal with a
larger assumed physical page size than the true size. Hence, there's
little disadvantage to conservatively setting the assumed physical
page size to 64kB on ARM.

This may result in some extra memory use, since we can only return
memory at multiples of the assumed physical page size. However, it is
a simple change that should make Go run on systems configured for
larger page sizes. The following commits will make the runtime query
the actual physical page size from the OS, but this is a simple step
there.

Updates #12480.

Change-Id: I851829595bc9e0c76235c847a7b5f62ad82b5302
Reviewed-on: https://go-review.googlesource.com/25021
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Minux Ma <minux@golang.org>
gopherbot pushed a commit that referenced this issue Sep 6, 2016
Currently the physical page size assumed by the runtime is hard-coded.
On Linux the runtime at least fetches the OS page size during init and
sanity checks against the hard-coded value, but they may still differ.
On other OSes we wouldn't even notice.

Add support on all OSes to fetch the actual OS physical page size
during runtime init and lift the sanity check of PhysPageSize from the
Linux init code to general malloc init. Currently this is the only use
of the retrieved page size, but we'll add more shortly.

Updates #12480 and #10180.

Change-Id: I065f2834bc97c71d3208edc17fd990ec9058b6da
Reviewed-on: https://go-review.googlesource.com/25050
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rick Hudson <rlh@golang.org>
gopherbot pushed a commit that referenced this issue Sep 6, 2016
Now that the runtime fetches the true physical page size from the OS,
make the physical page size used by heap growth a variable instead of
a constant. This isn't used in any performance-critical paths, so it
shouldn't be an issue.

sys.PhysPageSize is also renamed to sys.DefaultPhysPageSize to make it
clear that it's not necessarily the true page size. There are no uses
of this constant any more, but we'll keep it around for now.

Updates #12480 and #10180.

Change-Id: I6c23b9df860db309c38c8287a703c53817754f03
Reviewed-on: https://go-review.googlesource.com/25022
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rick Hudson <rlh@golang.org>
tmm1 pushed a commit to fancybits/go that referenced this issue Nov 9, 2016
Currently we assume the physical page size on ARM is 4kB. While this
is usually true, the architecture also supports 16kB and 64kB physical
pages, and Linux (and possibly other OSes) can be configured to use
these larger page sizes.

With Go 1.6, such a configuration could potentially run, but generally
resulted in memory corruption or random panics. With current master,
this configuration will cause the runtime to panic during init on
Linux when it checks the true physical page size (and will still cause
corruption or panics on other OSes).

However, the assumed physical page size only has to be a multiple of
the true physical page size, the scavenger can now deal with large
physical page sizes, and the rest of the runtime can deal with a
larger assumed physical page size than the true size. Hence, there's
little disadvantage to conservatively setting the assumed physical
page size to 64kB on ARM.

This may result in some extra memory use, since we can only return
memory at multiples of the assumed physical page size. However, it is
a simple change that should make Go run on systems configured for
larger page sizes. The following commits will make the runtime query
the actual physical page size from the OS, but this is a simple step
there.

Updates golang#12480.

Change-Id: I851829595bc9e0c76235c847a7b5f62ad82b5302
Reviewed-on: https://go-review.googlesource.com/25021
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Minux Ma <minux@golang.org>
tmm1 pushed a commit to fancybits/go that referenced this issue Nov 9, 2016
Currently the physical page size assumed by the runtime is hard-coded.
On Linux the runtime at least fetches the OS page size during init and
sanity checks against the hard-coded value, but they may still differ.
On other OSes we wouldn't even notice.

Add support on all OSes to fetch the actual OS physical page size
during runtime init and lift the sanity check of PhysPageSize from the
Linux init code to general malloc init. Currently this is the only use
of the retrieved page size, but we'll add more shortly.

Updates golang#12480 and golang#10180.

Change-Id: I065f2834bc97c71d3208edc17fd990ec9058b6da
Reviewed-on: https://go-review.googlesource.com/25050
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rick Hudson <rlh@golang.org>
tmm1 pushed a commit to fancybits/go that referenced this issue Nov 9, 2016
Now that the runtime fetches the true physical page size from the OS,
make the physical page size used by heap growth a variable instead of
a constant. This isn't used in any performance-critical paths, so it
shouldn't be an issue.

sys.PhysPageSize is also renamed to sys.DefaultPhysPageSize to make it
clear that it's not necessarily the true page size. There are no uses
of this constant any more, but we'll keep it around for now.

Updates golang#12480 and golang#10180.

Change-Id: I6c23b9df860db309c38c8287a703c53817754f03
Reviewed-on: https://go-review.googlesource.com/25022
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rick Hudson <rlh@golang.org>
@golang golang locked and limited conversation to collaborators Aug 19, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

10 participants