Project

General

Profile

Feature #2126

ruby_init_stack() - add ability to specify or query max_stack_size

Added by sunaku (Suraj Kurapati) about 11 years ago. Updated over 9 years ago.

Status:
Closed
Priority:
Normal
Assignee:
-
Target version:
-
[ruby-core:25668]

Description

=begin
Hello,

== Background ==

I am embedding Ruby 1.9 inside a callback function of a C program (a Verilog
simulator, to be precise):

  1. The first time when the callback function is called, I will initialize Ruby
    and create a Fiber (to run some Ruby code).

  2. For all subsequent times when the callback function is called, I will resume
    the Fiber. The Fiber will then run some Ruby code and return control back to
    the callback function, using Fiber.yield().

  3. This process repeats until the callback function is no longer called by the C
    program.

== Problem ==

Each time when the callback function is called, the C program's current stack
pointer is different: sometimes it descends below Ruby's stack start
addresss!

For this reason, it is not safe to use the default RUBY_INIT_STACK macro (which
assumes that the C program's current stack pointer never descends below Ruby's
stack start addresss).

== Request for Solution ==

To solve the problem, I need one of the following features:

  1. Add a max_stack_size parameter to ruby_init_stack():

    void ruby_init_stack(VALUE* stack_start, size_t max_stack_size);

    And also add a function to return Ruby's preferred stack size:

    size_t ruby_preferred_stack_size();

    This way, I can provide a custom stack to Ruby:

    size_t stack_size = ruby_preferred_stack_size();
    VALUE* stack_end = malloc(sizeof(VALUE) * stack_size);
    VALUE* stack_start = stack_end + stack_size;

    ruby_init_stack(stack_start, stack_size);

  2. Make ruby_init_stack() return the maximum stack size it has chosen:

    size_t ruby_init_stack(VALUE* stack_start);

    This way, I can grow my custom stack to fit Ruby's needs:

    VALUE* stack_end = malloc(sizeof(VALUE));
    size_t stack_size = ruby_init_stack(stack_end);
    VALUE* new_stack_end = realloc(stack_end, stack_size);

  3. Add a RUBY_AUTO_STACK macro which makes Ruby allocate its own stack on the
    heap using malloc(). I would call this macro instead of RUBY_INIT_STACK.

Thanks for your consideration.
=end


Related issues

Has duplicate Ruby master - Feature #2294: [PATCH] ruby_bind_stack() to embed Ruby in coroutineAssignedko1 (Koichi Sasada)Actions
#1

Updated by sunaku (Suraj Kurapati) about 11 years ago

=begin
Whoops, I assumed that the native machine's stack direction grows from
high to low. That is not protable, so here is my corrected request:

Add a max_stack_size parameter to ruby_init_stack():

  void ruby_init_stack(
    VALUE* stack_start,
    size_t max_stack_size,
    bool stack_descends         /* stack grows from high to low? */
  );

Add a function to return Ruby's preferred stack size:

  size_t ruby_stack_size_preference();

Add a function to return Ruby's preferred stack direction:

  bool ruby_stack_descends_p(); /* stack grows from high to low? */

This way, I can provide a custom stack to Ruby:

  size_t stack_size = ruby_stack_size_preference();
  bool stack_descends = ruby_stack_descends_p();

  VALUE* stack_start = malloc(stack_size);

  if (stack_descends) {
    stack_start += stack_size;
  }

  ruby_init_stack(stack_start, stack_size);

If you wish to minimize the number of new functions added to the Ruby
C API, then perhaps you could add a RUBY_INIT_STACK_ON_HEAP macro
which makes Ruby do (internally) everything in the code shown above.

Thanks for your consideration.
=end

#2

Updated by sunaku (Suraj Kurapati) about 11 years ago

=begin
Sigh, yet another mistake. Below is my corrected request. Sorry for
the trouble.

Add a max_stack_size parameter to ruby_init_stack():

  void ruby_init_stack(VALUE* stack_start, size_t max_stack_size);

Add a function to return Ruby's preferred stack size:

  size_t ruby_stack_size_preference();

Add a function to return Ruby's preferred stack direction:

  bool ruby_stack_descends_p(); /* stack grows from high to low? */

This way, I can provide a custom stack to Ruby:

  size_t stack_size = ruby_stack_size_preference();
  bool stack_descends = ruby_stack_descends_p();

  VALUE* stack_start = malloc(stack_size);

  if (stack_descends) {
    stack_start += stack_size;
  }

  ruby_init_stack(stack_start, stack_size);

If you wish to minimize the number of new functions added to the Ruby
C API, then perhaps you could add a RUBY_INIT_STACK_ON_HEAP macro
which makes Ruby do (internally) everything in the code shown above.

Thanks for your consideration.
=end

#3

Updated by matz (Yukihiro Matsumoto) about 11 years ago

=begin
Hi,

In message "Re: [ruby-core:25674] [Feature #2126] ruby_init_stack() - add ability to specify or query max_stack_size"
on Mon, 21 Sep 2009 02:42:14 +0900, Suraj Kurapati redmine@ruby-lang.org writes:

| This way, I can provide a custom stack to Ruby:
|
| size_t stack_size = ruby_stack_size_preference();
| bool stack_descends = ruby_stack_descends_p();
|
| VALUE* stack_start = malloc(stack_size);
|
| if (stack_descends) {
| stack_start += stack_size;
| }
|
| ruby_init_stack(stack_start, stack_size);

As far as I know, there's no portable way to switch machine stack to
pre-allocated heap region. I'm happy to be proven wrong.

                        matz.

=end

#4

Updated by sunaku (Suraj Kurapati) almost 11 years ago

=begin
Hi Matz,

Please take a look at issue #2258 (from note 16 onwards) which
provides a practical example of the need for a stack-informing
function in the Ruby C API.

That example uses UNIX System V contexts to switch the
machine stack to a pre-allocated heap region. Other1, more
cross-platform libraries, such as libpcl (portable coroutine
library), are also capable of doing this.

For your convenience, I will create a variation of that
example which uses libpcl and other libraries to demonstrate
the feasibility of this request.

Thanks for your consideration.

=end

#5

Updated by sunaku (Suraj Kurapati) almost 11 years ago

=begin
Hi Matz,

I added examples that use libpcl1 to issue #2258 (note 18).

Please consider the "ruby_bind_stack.patch" file attached to
that issue as my proposed solution for this feature request.

Thanks for your consideration.

=end

#6

Updated by sunaku (Suraj Kurapati) almost 11 years ago

=begin
Hi,

I created a new issue #2294 to summarize
this feature request and the results of
my experiments for solving issue #2126.

Please close this feature request and
refer to the new #2294 issue instead.

Thanks.
=end

#7

Updated by nobu (Nobuyoshi Nakada) almost 11 years ago

  • Status changed from Open to Closed

=begin
This issue was solved with changeset r25842.
Suraj, thank you for reporting this issue.
Your contribution to Ruby is greatly appreciated.
May Ruby be with you.

=end

Also available in: Atom PDF