Skip to content
This repository

Ensure 16-byte alignment for amd64 coroutine stack #230

Merged
merged 1 commit into from almost 2 years ago

3 participants

Jeremy Evans Jeremy Tregunna Steve Dekorte
Jeremy Evans

The AMD64 ABI requires that stacks be 16-byte aligned.  stackend is
going to be 16-byte aligned, 128 is a multiple of 16, and
sizeof(uintptr_t) is going to 8 on amd64, so this results in a stack
that is not 16-byte aligned on amd64 (at least for platforms where
this code branch is used, such as OpenBSD).  This results in bus errors
when floating point numbers are converted to strings, since snprintf
calls movaps with a non 16-byte aligned memory location.

With this patch, the iovm correctness tests pass on OpenBSD/amd64.

Jeremy Evans jeremyevans Ensure 16-byte alignment for amd64 coroutine stack
The AMD64 ABI requires that stacks be 16-byte aligned.  stackend is
going to be 16-byte aligned, 128 is a multiple of 16, and
sizeof(uintptr_t) is going to 8 on amd64, so this results in a stack
that is not 16-byte aligned on amd64 (at least for platforms where
this code branch is used, such as OpenBSD).  This results in bus errors
when floating point numbers are converted to strings, since snprintf
calls movaps with a non 16-byte aligned memory location.

With this patch, the iovm correctness tests pass on OpenBSD/amd64.
84c9e4f
Steve Dekorte stevedekorte merged commit 91c356f into from
Jeremy Tregunna

The proper way to do alignment is like this:

static inline size_t aligned_size(size_t size, size_t alignment)
{
    assert(alignment <= 0x8000);
    size_t r = size + --alignment + 2;
    return (r + 2 + alignment) & ~alignment;
}

Calling this function assumes that "alignment" is power of 2, and "size" would be the original stackend - sizeof(uintptr_t) - 128.

That's certainly looks like a more portable solution, compared to the quick hack I used. I'll be happy as long as the problem get's fixed. Not being familiar with the amd64 ABI or Io's internals, it took me many hours to diagnose the underlying problem causing the bus error, and figure out where the fix should be applied.

I'll accept whichever working version you guys recommend. Thanks for helping with this.

If you plan on having Io run on many platforms with different alignment requirements, then Jeremy Tregunna's code is probably best. If you only care about fixing amd64, then this pull request gets the job done with the least number of changes (2 characters).

I'll test out my code in place, and see if there are any regressions. Should all look ok, then I will send another pull.

Alright tested, and seems to work just fine. It's in #232.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Showing 1 unique commit by 1 author.

Oct 12, 2012
Jeremy Evans jeremyevans Ensure 16-byte alignment for amd64 coroutine stack
The AMD64 ABI requires that stacks be 16-byte aligned.  stackend is
going to be 16-byte aligned, 128 is a multiple of 16, and
sizeof(uintptr_t) is going to 8 on amd64, so this results in a stack
that is not 16-byte aligned on amd64 (at least for platforms where
this code branch is used, such as OpenBSD).  This results in bus errors
when floating point numbers are converted to strings, since snprintf
calls movaps with a non 16-byte aligned memory location.

With this patch, the iovm correctness tests pass on OpenBSD/amd64.
84c9e4f
This page is out of date. Refresh to see the latest.

Showing 1 changed file with 1 addition and 1 deletion. Show diff stats Hide diff stats

  1. +1 1  libs/coroutine/source/Coro.c
2  libs/coroutine/source/Coro.c
@@ -599,7 +599,7 @@ void Coro_setup(Coro *self, void *arg)
599 599 if (64 > (- sav[i] + (uintptr_t)&i))
600 600 break;
601 601 assert(i < sz);
602   - sav[i] = stackend - sizeof(uintptr_t) - 128;
  602 + sav[i] = stackend - sizeof(uintptr_t)*2 - 128;
603 603 }
604 604 }
605 605

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.