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

Reply via email to