Varargs issues

Peter Wemm peter at wemm.org
Mon Dec 1 20:07:02 PST 2003


Peter Wemm wrote:
> James Van Artsdalen wrote:
> > I looked at the example I was suspicious of and realized that I had
> > overlooked that the caller implicitly allocates 8 bytes in the stack
> > due to the CALL opcode.  It's perfectly reasonable for a function to
> > start with something like:
> > 
> > doo:
> > 	push	(64 bit) val
> > 	call	z
> > 
> > since the return address + the push makes an even 16 bytes.
> > 
> > There are two different pthread_create () functions.  The one in
> > /usr/src/lib/libc_r/uthread/uthread_create.c does this to ensure that
> > the stack starts off right:
> > 
> >                         SET_STACK_JB(new_thread->ctx.jb,
> >                             (long)new_thread->stack + pattr->stacksize_attr
> >                             - sizeof(double));
> > 
> > sizeof (double) isn't really portable - sizeof (&_pthread_create) would
> > be better - but it clearly leaves the stack with a value that gcc expects,
> > i.e., an "odd" value in 8-byte units (0xfff8 instead of 0xfff0).
> 
> This stuff is all pretty broken for amd64.  I'm amazed that it even remotely
> works.  The situation right now is that if a pthread_create()ed thread
> tries to do floating point, it'll blow up sooner or later.  If its not
> in varargs, it'll be in the function prologue/epilogue when it saves and
> restores the xmm registers.

This patch seems to fix it for me so far.  Now to find the same problems in
the libkse code...

http://people.freebsd.org/~peter/libc_r.diff

Index: libc_r/uthread/uthread_create.c
===================================================================
RCS file: /home/ncvs/src/lib/libc_r/uthread/uthread_create.c,v
retrieving revision 1.37
diff -u -r1.37 uthread_create.c
--- libc_r/uthread/uthread_create.c     6 Jan 2003 00:56:23 -0000       1.37
+++ libc_r/uthread/uthread_create.c     2 Dec 2003 04:00:20 -0000
@@ -73,6 +73,9 @@
        pthread_t       new_thread;
        pthread_attr_t  pattr;
        void           *stack;
+#if !defined(__ia64__)
+       u_long          stackp;
+#endif

        if (thread == NULL)
                return(EINVAL);
@@ -145,10 +148,12 @@
                        SET_RETURN_ADDR_JB(new_thread->ctx.jb, _thread_start);

 #if !defined(__ia64__)
+                       stackp = (long)new_thread->stack + pattr->stacksize_attr - sizeof(double);
+#if defined(__amd64__)
+                       stackp &= ~0xFUL;
+#endif
                        /* The stack starts high and builds down: */
-                       SET_STACK_JB(new_thread->ctx.jb,
-                           (long)new_thread->stack + pattr->stacksize_attr
-                           - sizeof(double));
+                       SET_STACK_JB(new_thread->ctx.jb, stackp);
 #else
                        SET_STACK_JB(new_thread->ctx.jb,
                            (long)new_thread->stack, pattr->stacksize_attr);
Index: libc_r/uthread/uthread_init.c
===================================================================
RCS file: /home/ncvs/src/lib/libc_r/uthread/uthread_init.c,v
retrieving revision 1.45
diff -u -r1.45 uthread_init.c
--- libc_r/uthread/uthread_init.c       11 Jan 2003 00:43:20 -0000      1.45
+++ libc_r/uthread/uthread_init.c       2 Dec 2003 04:00:20 -0000
@@ -208,6 +208,9 @@
        size_t          len;
        int             mib[2];
        int             sched_stack_size;       /* Size of scheduler stack. */
+#if !defined(__ia64__)
+       u_long          stackp;
+#endif

        struct clockinfo clockinfo;
        struct sigaction act;
@@ -374,8 +377,11 @@
                /* Setup the context for the scheduler: */
                _setjmp(_thread_kern_sched_jb);
 #if !defined(__ia64__)
-               SET_STACK_JB(_thread_kern_sched_jb, _thread_kern_sched_stack +
-                   sched_stack_size - sizeof(double));
+               stackp = (long)_thread_kern_sched_stack + sched_stack_size - sizeof(double);
+#if defined(__amd64__)
+               stackp &= ~0xFUL;
+#endif
+               SET_STACK_JB(_thread_kern_sched_jb, stackp);
 #else
                SET_STACK_JB(_thread_kern_sched_jb, _thread_kern_sched_stack,
                    sched_stack_size);
Index: libc_r/uthread/uthread_sig.c
===================================================================
RCS file: /home/ncvs/src/lib/libc_r/uthread/uthread_sig.c,v
retrieving revision 1.45
diff -u -r1.45 uthread_sig.c
--- libc_r/uthread/uthread_sig.c        5 Mar 2003 04:28:08 -0000       1.45
+++ libc_r/uthread/uthread_sig.c        2 Dec 2003 04:00:20 -0000
@@ -1048,13 +1048,20 @@
         * Leave a little space on the stack and round down to the
         * nearest aligned word:
         */
+#if defined(__amd64__)
+       stackp -= 128;          /* Skip over 128 byte red-zone */
+#endif
        stackp -= sizeof(double);
+#if defined(__amd64__)
+       stackp &= ~0xFUL;
+#else
        stackp &= ~0x3UL;
 #endif
+#endif

        /* Allocate room on top of the stack for a new signal frame: */
        stackp -= sizeof(struct pthread_signal_frame);
-#if defined(__ia64__)
+#if defined(__ia64__) || defined(__amd64__)
        stackp &= ~0xFUL;
 #endif

@@ -1087,6 +1094,9 @@
         */
 #if !defined(__ia64__)
        stackp -= sizeof(double);
+#if defined(__amd64__)
+       stackp &= ~0xFUL;
+#endif
 #endif
        _setjmp(thread->ctx.jb);
 #if !defined(__ia64__)

Cheers,
-Peter
--
Peter Wemm - peter at wemm.org; peter at FreeBSD.org; peter at yahoo-inc.com
"All of this is for nothing if we don't go to the stars" - JMS/B5



More information about the freebsd-amd64 mailing list