FAQ
I've been searching as best I can but most search attempts ended up with
results about: stack data structures, stack overflow (the website) or
stacks as they relate to groups of objects in video games. Not very helpful.

I did come across this article from Ian Lance Taylor on the gcc wiki which
talks about an implementation: http://gcc.gnu.org/wiki/SplitStacks but it
didn't really answer much for me.

I also came across this article by Dave Cheney but it raised as many
questions as it answered:
http://dave.cheney.net/2013/06/02/why-is-a-goroutines-stack-infinite

When a Go program starts, it's my understanding that the OS allocates an
amount of stack space (between 1-8mb, typically, depending on the
OS/architecture). In a single thread if a program requests more stack space
but the frame pointer would exceed the stack segment then the result would
be a stack overflow. However, in Go a new stack would be created on the
heap to prevent this from happening. If you continually straddle this
boundary between the heap allocated stack and the "true" system allocated
stack, it would be called stack splitting?

I have read http://golang.org/doc/faq#goroutines but it's not clear
specifically what is meant by a segmented stack. Is a segmented stack
having one or more heap allocated stacks on top of the system allocated
stack or is it how goroutines have their own mini-stack segments?

I'm very (emphasis on VERY) new to assembly but my understanding is that
the stack pointer is an internal CPU register. When a stack overflow would
occur and the program responds by requesting more stack space from the
heap, must the stack pointer now be maintained by the Go program rather
than a CPU register? This would be an assembly based stack data structure
(linked list)? Or I am I way off base now?

--
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+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Search Discussions

  • Ian Lance Taylor at Feb 20, 2014 at 10:36 pm

    On Thu, Feb 20, 2014 at 1:51 PM, Rob Thornton wrote:
    When a Go program starts, it's my understanding that the OS allocates an
    amount of stack space (between 1-8mb, typically, depending on the
    OS/architecture). In a single thread if a program requests more stack space
    but the frame pointer would exceed the stack segment then the result would
    be a stack overflow. However, in Go a new stack would be created on the heap
    to prevent this from happening. If you continually straddle this boundary
    between the heap allocated stack and the "true" system allocated stack, it
    would be called stack splitting?
    The "stack splitting" is the allocation of the stack on the heap.
    When that happens, the stack has been split. This does not happen in
    a conventional C program.

    Note that Go normally does not run on the system allocated thread
    stack, but always runs on its own heap allocated stacks. Note also
    that for 1.3 we are likely to switch to growable stacks, in which the
    stack is grown as needed but not normally split except perhaps in some
    special cases.

    I have read http://golang.org/doc/faq#goroutines but it's not clear
    specifically what is meant by a segmented stack. Is a segmented stack having
    one or more heap allocated stacks on top of the system allocated stack or is
    it how goroutines have their own mini-stack segments?
    Goroutines always use heap allocated stacks.

    I'm very (emphasis on VERY) new to assembly but my understanding is that the
    stack pointer is an internal CPU register. When a stack overflow would occur
    and the program responds by requesting more stack space from the heap, must
    the stack pointer now be maintained by the Go program rather than a CPU
    register? This would be an assembly based stack data structure (linked
    list)? Or I am I way off base now?
    The stack pointer is a register. When a goroutine splits the stack,
    it updates the stack pointer. So, yes, the stack pointer is
    maintained by the Go program, and, yes, the stack pointer is a CPU
    register. The two statements are not incompatible.

    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Rob Thornton at Feb 20, 2014 at 11:38 pm
    Thank you, Ian this clears up most of my confusion on the subject. I do
    have a couple more points I hope you can clear up for me.
    On Thursday, 20 February 2014 14:36:40 UTC-8, Ian Lance Taylor wrote:
    On Thu, Feb 20, 2014 at 1:51 PM, Rob Thornton wrote:

    When a Go program starts, it's my understanding that the OS allocates an
    amount of stack space (between 1-8mb, typically, depending on the
    OS/architecture). In a single thread if a program requests more stack space
    but the frame pointer would exceed the stack segment then the result would
    be a stack overflow. However, in Go a new stack would be created on the heap
    to prevent this from happening. If you continually straddle this boundary
    between the heap allocated stack and the "true" system allocated stack, it
    would be called stack splitting?
    The "stack splitting" is the allocation of the stack on the heap.
    When that happens, the stack has been split. This does not happen in
    a conventional C program.

    Note that Go normally does not run on the system allocated thread
    stack, but always runs on its own heap allocated stacks. Note also
    that for 1.3 we are likely to switch to growable stacks, in which the
    stack is grown as needed but not normally split except perhaps in some
    special cases.
    Regarding Go normally only using the heap allocated stack, do you mind my
    asking why you wouldn't utilize any of the thread based stack? I am
    assuming you're making a trade off between wasting said memory and
    complexity?

    I have read http://golang.org/doc/faq#goroutines but it's not clear
    specifically what is meant by a segmented stack. Is a segmented stack having
    one or more heap allocated stacks on top of the system allocated stack or is
    it how goroutines have their own mini-stack segments?
    Goroutines always use heap allocated stacks.

    I'm very (emphasis on VERY) new to assembly but my understanding is that the
    stack pointer is an internal CPU register. When a stack overflow would occur
    and the program responds by requesting more stack space from the heap, must
    the stack pointer now be maintained by the Go program rather than a CPU
    register? This would be an assembly based stack data structure (linked
    list)? Or I am I way off base now?
    The stack pointer is a register. When a goroutine splits the stack,
    it updates the stack pointer. So, yes, the stack pointer is
    maintained by the Go program, and, yes, the stack pointer is a CPU
    register. The two statements are not incompatible.
    After reading your answer I felt quite foolish because the answer should
    have been clear.

    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Aram Hăvărneanu at Feb 21, 2014 at 12:44 am

    Regarding Go normally only using the heap allocated stack, do you
    mind my asking why you wouldn't utilize any of the thread based
    stack?
    There is no other stack. The runtime creates threads passing them
    a pointer to an already allocated block of memory to use for their
    stacks. That block of memory comes from the heap (an exception is
    obviously made for the initial thread of a program, which's stack
    is controlled by the operating system). This stack is used for g0,
    the scheduler stack. It's also used on Windows and Solaris for
    making system calls (in reality just calls into a C library).
    After reading your answer I felt quite foolish because the answer
    should have been clear.
    Just a note, Go programs manipulate the stack pointer, but every C
    program does as well.

    --
    Aram Hăvărneanu

    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Dave Cheney at Feb 21, 2014 at 1:07 am

    On Friday, 21 February 2014 10:38:10 UTC+11, Rob Thornton wrote:
    Thank you, Ian this clears up most of my confusion on the subject. I do
    have a couple more points I hope you can clear up for me.
    On Thursday, 20 February 2014 14:36:40 UTC-8, Ian Lance Taylor wrote:

    On Thu, Feb 20, 2014 at 1:51 PM, Rob Thornton <rthorn...@gmail.com>
    wrote:
    When a Go program starts, it's my understanding that the OS allocates an
    amount of stack space (between 1-8mb, typically, depending on the
    OS/architecture). In a single thread if a program requests more stack space
    but the frame pointer would exceed the stack segment then the result would
    be a stack overflow. However, in Go a new stack would be created on the heap
    to prevent this from happening. If you continually straddle this boundary
    between the heap allocated stack and the "true" system allocated stack, it
    would be called stack splitting?
    The "stack splitting" is the allocation of the stack on the heap.
    When that happens, the stack has been split. This does not happen in
    a conventional C program.

    Note that Go normally does not run on the system allocated thread
    stack, but always runs on its own heap allocated stacks. Note also
    that for 1.3 we are likely to switch to growable stacks, in which the
    stack is grown as needed but not normally split except perhaps in some
    special cases.
    Regarding Go normally only using the heap allocated stack, do you mind my
    asking why you wouldn't utilize any of the thread based stack? I am
    assuming you're making a trade off between wasting said memory and
    complexity?
    In addition to what Aram has said it is important to emphasise that memory
    is not wasted if it is not used.

    Ie, in C if I malloc 8mb of memory from the heap essentially nothing
    happens. You get a pointer, but the operating system generally defers
    actually satisfying that request until you start to read or write to that
    memory range. The larger the requested allocation, the more the operating
    system will delay fulfilling the promise until absolutely necessary.

    I have read http://golang.org/doc/faq#goroutines but it's not clear
    specifically what is meant by a segmented stack. Is a segmented stack having
    one or more heap allocated stacks on top of the system allocated stack or is
    it how goroutines have their own mini-stack segments?
    Goroutines always use heap allocated stacks.

    I'm very (emphasis on VERY) new to assembly but my understanding is that the
    stack pointer is an internal CPU register. When a stack overflow would occur
    and the program responds by requesting more stack space from the heap, must
    the stack pointer now be maintained by the Go program rather than a CPU
    register? This would be an assembly based stack data structure (linked
    list)? Or I am I way off base now?
    The stack pointer is a register. When a goroutine splits the stack,
    it updates the stack pointer. So, yes, the stack pointer is
    maintained by the Go program, and, yes, the stack pointer is a CPU
    register. The two statements are not incompatible.
    After reading your answer I felt quite foolish because the answer should
    have been clear.

    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Rob Thornton at Feb 21, 2014 at 3:36 pm
    Thanks Aram and Dave. I think answers all my original questions!

    One last curiousity:

    Dave, in your article you stated that a goroutine has a 4096 byte stack. Is
    this because it is the typical page size for most operating systems? In the
    case of SPARC, where I believe the page size is doubled to 8192 bytes,
    would the stack size be increased to match?
    On Thursday, 20 February 2014 17:06:56 UTC-8, Dave Cheney wrote:


    On Friday, 21 February 2014 10:38:10 UTC+11, Rob Thornton wrote:

    Thank you, Ian this clears up most of my confusion on the subject. I do
    have a couple more points I hope you can clear up for me.
    On Thursday, 20 February 2014 14:36:40 UTC-8, Ian Lance Taylor wrote:

    On Thu, Feb 20, 2014 at 1:51 PM, Rob Thornton <rthorn...@gmail.com>
    wrote:
    When a Go program starts, it's my understanding that the OS allocates an
    amount of stack space (between 1-8mb, typically, depending on the
    OS/architecture). In a single thread if a program requests more stack space
    but the frame pointer would exceed the stack segment then the result would
    be a stack overflow. However, in Go a new stack would be created on the heap
    to prevent this from happening. If you continually straddle this boundary
    between the heap allocated stack and the "true" system allocated stack, it
    would be called stack splitting?
    The "stack splitting" is the allocation of the stack on the heap.
    When that happens, the stack has been split. This does not happen in
    a conventional C program.

    Note that Go normally does not run on the system allocated thread
    stack, but always runs on its own heap allocated stacks. Note also
    that for 1.3 we are likely to switch to growable stacks, in which the
    stack is grown as needed but not normally split except perhaps in some
    special cases.
    Regarding Go normally only using the heap allocated stack, do you mind my
    asking why you wouldn't utilize any of the thread based stack? I am
    assuming you're making a trade off between wasting said memory and
    complexity?
    In addition to what Aram has said it is important to emphasise that memory
    is not wasted if it is not used.

    Ie, in C if I malloc 8mb of memory from the heap essentially nothing
    happens. You get a pointer, but the operating system generally defers
    actually satisfying that request until you start to read or write to that
    memory range. The larger the requested allocation, the more the operating
    system will delay fulfilling the promise until absolutely necessary.

    I have read http://golang.org/doc/faq#goroutines but it's not clear
    specifically what is meant by a segmented stack. Is a segmented stack having
    one or more heap allocated stacks on top of the system allocated stack or is
    it how goroutines have their own mini-stack segments?
    Goroutines always use heap allocated stacks.

    I'm very (emphasis on VERY) new to assembly but my understanding is that the
    stack pointer is an internal CPU register. When a stack overflow would occur
    and the program responds by requesting more stack space from the heap, must
    the stack pointer now be maintained by the Go program rather than a CPU
    register? This would be an assembly based stack data structure (linked
    list)? Or I am I way off base now?
    The stack pointer is a register. When a goroutine splits the stack,
    it updates the stack pointer. So, yes, the stack pointer is
    maintained by the Go program, and, yes, the stack pointer is a CPU
    register. The two statements are not incompatible.
    After reading your answer I felt quite foolish because the answer should
    have been clear.

    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Aram Hăvărneanu at Feb 21, 2014 at 5:34 pm
    The goroutine stack size is 8kB now, not 4kB as before. This means
    that each stack uses 8kB of address space. Most goroutines still
    only use 4kB of physical memory though. The operating system will
    only map the second page when it faults as the user (code) tries
    to access it the first time.

    On a potential SPARC, goroutines would probably start with 8kB
    stacks which would use 8k of physical memory, as the page size is
    8kB. There's no requirement that stack size be a multiple of page
    size, however, it can be smaller. The operating system will map
    memory in page-size increments, but the Go memory allocator can
    allocate space for stacks of any size.

    It's no different than amd64 2MB pages. A single 2MB page can back
    many stack segments; stack segments can be very small.

    --
    Aram Hăvărneanu

    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Rob Thornton at Feb 21, 2014 at 6:38 pm
    Excellent, thank you very much Aram!

    Rob
    On Friday, 21 February 2014 09:34:04 UTC-8, Aram Hăvărneanu wrote:

    The goroutine stack size is 8kB now, not 4kB as before. This means
    that each stack uses 8kB of address space. Most goroutines still
    only use 4kB of physical memory though. The operating system will
    only map the second page when it faults as the user (code) tries
    to access it the first time.

    On a potential SPARC, goroutines would probably start with 8kB
    stacks which would use 8k of physical memory, as the page size is
    8kB. There's no requirement that stack size be a multiple of page
    size, however, it can be smaller. The operating system will map
    memory in page-size increments, but the Go memory allocator can
    allocate space for stacks of any size.

    It's no different than amd64 2MB pages. A single 2MB page can back
    many stack segments; stack segments can be very small.

    --
    Aram Hăvărneanu
    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupgolang-nuts @
categoriesgo
postedFeb 20, '14 at 9:51p
activeFeb 21, '14 at 6:38p
posts8
users4
websitegolang.org

People

Translate

site design / logo © 2021 Grokbase