public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* Statement expression with function-call variable lifetime
@ 2005-06-29 17:34 Shaun Jackman
  2005-06-29 17:39 ` Daniel Jacobowitz
  2005-06-30  2:21 ` Russell Shaw
  0 siblings, 2 replies; 5+ messages in thread
From: Shaun Jackman @ 2005-06-29 17:34 UTC (permalink / raw)
  To: gcc

Hello,

I'm implementing a tiny vfork/exit implementation using setjmp and
longjmp. Since the function calling setjmp can't return (if you still
want to longjmp to its jmp_buf) I implemented vfork using a statement
expression macro. Here's my implementation of vfork.

jmp_buf *vfork_jmp_buf;
#define vfork() ({ \
	int setjmp_ret; \
	jmp_buf *prev_jmp_buf = vfork_jmp_buf, new_jmp_buf; \
	vfork_jmp_buf = &new_jmp_buf; \
	if( (setjmp_ret = setjmp(*vfork_jmp_buf)) != 0 ) \
		vfork_jmp_buf = prev_jmp_buf; \
	setjmp_ret; \
})

Unfortunately, after tracing a nasty bug I found that the same problem
applies to leaving a statement expression as does returning from a
function. The storage allocated for prev_jmp_buf and new_jmp_buf is
unallocated as soon as we leave the scope of the statement expression.
gcc quickly reuses that stack space later in the same function,
overwriting the saved jmp_buf. Does anyone have a suggestion how I can
allocate some storage space here for prev_jmp_buf and new_jmp_buf that
will last the lifetime of the function call instead of the lifetime of
the statement expression macro? My best idea was to use alloca, but it
wouldn't look pretty. Can someone confirm that memory allocated with
alloca would last the lifetime of the function call, and not the
lifetime of the statement expression?

Please cc me in your reply. Thanks,
Shaun

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Statement expression with function-call variable lifetime
  2005-06-29 17:34 Statement expression with function-call variable lifetime Shaun Jackman
@ 2005-06-29 17:39 ` Daniel Jacobowitz
  2005-06-29 21:49   ` Shaun Jackman
  2005-06-30  2:21 ` Russell Shaw
  1 sibling, 1 reply; 5+ messages in thread
From: Daniel Jacobowitz @ 2005-06-29 17:39 UTC (permalink / raw)
  To: Shaun Jackman; +Cc: gcc

On Wed, Jun 29, 2005 at 10:34:20AM -0700, Shaun Jackman wrote:
> the statement expression macro? My best idea was to use alloca, but it
> wouldn't look pretty. Can someone confirm that memory allocated with
> alloca would last the lifetime of the function call, and not the
> lifetime of the statement expression?

Yes, that's correct (and the only way to do this).

-- 
Daniel Jacobowitz
CodeSourcery, LLC

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Statement expression with function-call variable lifetime
  2005-06-29 17:39 ` Daniel Jacobowitz
@ 2005-06-29 21:49   ` Shaun Jackman
  0 siblings, 0 replies; 5+ messages in thread
From: Shaun Jackman @ 2005-06-29 21:49 UTC (permalink / raw)
  To: gcc

On 6/29/05, Daniel Jacobowitz <drow@false.org> wrote:
> On Wed, Jun 29, 2005 at 10:34:20AM -0700, Shaun Jackman wrote:
> > the statement expression macro? My best idea was to use alloca, but it
> > wouldn't look pretty. Can someone confirm that memory allocated with
> > alloca would last the lifetime of the function call, and not the
> > lifetime of the statement expression?
> 
> Yes, that's correct (and the only way to do this).

Great! I've rewritten the vfork macro to use alloca. Here's the big
catch, the pointer returned by alloca is stored on the stack, and it
gets trashed upon leaving the statement expression. Where can I store
the pointer returned by alloca? Please don't say allocate some memory
for the pointer using alloca. <evil grin> My best idea so far was to
make the pointer returned by alloca (struct context *c, see below)
static, so that each time the macro is invoked, a little static memory
is put aside for it. I think this would work, but it doesn't seem to
me to be the best solution.

Here's the revised vfork macro that uses alloca:

jmp_buf *vfork_jmp_buf;

struct context {
	jmp_buf *prev_jmp_buf;
	jmp_buf new_jmp_buf;
};

# define vfork() ({ \
	int setjmp_ret; \
	struct context *c = alloca(sizeof *c); \
	c->prev_jmp_buf = vfork_jmp_buf; \
	vfork_jmp_buf = &c->new_jmp_buf; \
	if( (setjmp_ret = setjmp(*vfork_jmp_buf)) != 0 ) \
		vfork_jmp_buf = c->prev_jmp_buf; \
	setjmp_ret; \
})

Cheers,
Shaun

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Statement expression with function-call variable lifetime
  2005-06-29 17:34 Statement expression with function-call variable lifetime Shaun Jackman
  2005-06-29 17:39 ` Daniel Jacobowitz
@ 2005-06-30  2:21 ` Russell Shaw
  2005-06-30  6:08   ` Shaun Jackman
  1 sibling, 1 reply; 5+ messages in thread
From: Russell Shaw @ 2005-06-30  2:21 UTC (permalink / raw)
  To: Shaun Jackman; +Cc: gcc

Shaun Jackman wrote:
> Hello,
> 
> I'm implementing a tiny vfork/exit implementation using setjmp and
> longjmp. Since the function calling setjmp can't return (if you still
> want to longjmp to its jmp_buf) I implemented vfork using a statement
> expression macro. Here's my implementation of vfork.
> 
> jmp_buf *vfork_jmp_buf;
> #define vfork() ({ \
> 	int setjmp_ret; \
> 	jmp_buf *prev_jmp_buf = vfork_jmp_buf, new_jmp_buf; \
> 	vfork_jmp_buf = &new_jmp_buf; \
> 	if( (setjmp_ret = setjmp(*vfork_jmp_buf)) != 0 ) \
> 		vfork_jmp_buf = prev_jmp_buf; \
> 	setjmp_ret; \
> })
> 
> Unfortunately, after tracing a nasty bug I found that the same problem
> applies to leaving a statement expression as does returning from a
> function. The storage allocated for prev_jmp_buf and new_jmp_buf is
> unallocated as soon as we leave the scope of the statement expression.
> gcc quickly reuses that stack space later in the same function,
> overwriting the saved jmp_buf. Does anyone have a suggestion how I can
> allocate some storage space here for prev_jmp_buf and new_jmp_buf that
> will last the lifetime of the function call instead of the lifetime of
> the statement expression macro? My best idea was to use alloca, but it
> wouldn't look pretty. Can someone confirm that memory allocated with
> alloca would last the lifetime of the function call, and not the
> lifetime of the statement expression?
> 
> Please cc me in your reply. Thanks,
> Shaun

Alloca is like creating a stack variable, except it just gives you some
generic bytes that don't mean anything. Exiting the local scope will
trash the local variables and anything done with alloca(). You'll need
to store some information in a global variable. This C exceptions method
stores things as a linked list in nested stack frames and keeps a pointer
to the list in a global variable. Well worth studying:

   http://ldeniau.home.cern.ch/ldeniau/html/exception/exception.html

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Statement expression with function-call variable lifetime
  2005-06-30  2:21 ` Russell Shaw
@ 2005-06-30  6:08   ` Shaun Jackman
  0 siblings, 0 replies; 5+ messages in thread
From: Shaun Jackman @ 2005-06-30  6:08 UTC (permalink / raw)
  To: Russell Shaw; +Cc: gcc

On 6/29/05, Russell Shaw <rjshaw@netspace.net.au> wrote:
> Alloca is like creating a stack variable, except it just gives you some
> generic bytes that don't mean anything. Exiting the local scope will
> trash the local variables and anything done with alloca(). You'll need
> to store some information in a global variable. This C exceptions method
> stores things as a linked list in nested stack frames and keeps a pointer
> to the list in a global variable. Well worth studying:
> 
>    http://ldeniau.home.cern.ch/ldeniau/html/exception/exception.html

Thanks! That linked was a very good reference. Here's the new and
improved vfork macro. It works nicely! If anyone's curious enough, I
can post the exit and waitpid macros that accompany it. I'm using
these macros to implement a Busybox system that does not need a fork
system call.

Thanks for all your help, Daniel and Russell! Cheers,
Shaun

struct vfork_context {
	struct vfork_context *prev;
	jmp_buf jmp;
} *vfork_context;

# define vfork() ({ \
	int setjmp_ret; \
	struct vfork_context *c = alloca(sizeof *c); \
	c->prev = vfork_context; \
	vfork_context = c; \
	if( (setjmp_ret = setjmp(c->jmp)) != 0 ) \
		vfork_context = vfork_context->prev; \
	setjmp_ret; \
})

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2005-06-30  6:08 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2005-06-29 17:34 Statement expression with function-call variable lifetime Shaun Jackman
2005-06-29 17:39 ` Daniel Jacobowitz
2005-06-29 21:49   ` Shaun Jackman
2005-06-30  2:21 ` Russell Shaw
2005-06-30  6:08   ` Shaun Jackman

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).