On Tue, 23 Dec 2025 19:07:13 +0900
Takashi Yano wrote:
> On Mon, 22 Dec 2025 16:46:53 +0100
> Corinna Vinschen wrote:
> > On Dec 22 23:37, Takashi Yano via Cygwin wrote:
> > > Alignment issue?
> > >
> > > This might be the right thing.
> > >
> > > diff --git a/winsup/cygwin/thread.cc b/winsup/cygwin/thread.cc
> > > index 86a00e76e..ec1e3c98c 100644
> > > --- a/winsup/cygwin/thread.cc
> > > +++ b/winsup/cygwin/thread.cc
> > > @@ -630,6 +630,8 @@ pthread::cancel ()
> > > threadlist_t *tl_entry = cygheap->find_tls (cygtls);
> > > if (!cygtls->inside_kernel (&context))
> > > {
> > > + if ((context._CX_stackPtr & 8) == 0)
> > > + context._CX_stackPtr -= 8;
> >
> > Does that really help? Checking for 8 byte alignment is usually done
> > with (X & 7) != 0, because this won't catch 16 byte aligned stacks.
>
> This code does not aim for 8 byte alignment, but 16n + 8. I assume
> context._CX_stackPtr & 7 is always 0. I wonder if this assumption
> is true. What if user code pushes 16 bit register such as AX?
> It might be necessary to mask least 3 bits in advance.
>
> diff --git a/winsup/cygwin/thread.cc b/winsup/cygwin/thread.cc
> index 86a00e76e..628aef16f 100644
> --- a/winsup/cygwin/thread.cc
> +++ b/winsup/cygwin/thread.cc
> @@ -630,6 +630,9 @@ pthread::cancel ()
> threadlist_t *tl_entry = cygheap->find_tls (cygtls);
> if (!cygtls->inside_kernel (&context))
> {
> + context._CX_stackPtr &= 0xfffffffffffffff8UL;
> + if ((context._CX_stackPtr & 8) == 0)
> + context._CX_stackPtr -= 8;
> context._CX_instPtr = (ULONG_PTR) pthread::static_cancel_self;
> SetThreadContext (win32_obj_id, &context);
> }
I confirmed that the attached reproducer (repro.c) works fine with
this patch.
--
Takashi Yano <[email protected]>
#include <pthread.h>
#include <unistd.h>
#include <stdio.h>
#define USE_ASYNC 1
static int thread_started;
void *mythread(void *)
{
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
#if USE_ASYNC
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
#else
pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
#endif
thread_started = 1;
for (;;)
{
__asm__ ("push %ax");
for (volatile int i=0; i<1000; i++) ;
__asm__ ("pop %ax");
for (volatile int i=0; i<1000; i++) ;
#if !USE_ASYNC
pthread_testcancel();
#endif
}
return NULL;
}
int main()
{
int i;
pthread_t t;
void *result = 0;
thread_started = 0;
pthread_create(&t, NULL, mythread, NULL);
while (thread_started == 0)
usleep(1000);
usleep(10000);
pthread_cancel(t);
pthread_join(t, &result);
if (result != PTHREAD_CANCELED)
printf("Thread started %d: result %d\n", thread_started, result);
else
printf("Thread canceled.\n");
return 0;
}
--
Problem reports: https://cygwin.com/problems.html
FAQ: https://cygwin.com/faq/
Documentation: https://cygwin.com/docs.html
Unsubscribe info: https://cygwin.com/ml/#unsubscribe-simple