Peter Naulls wrote:
Peter Naulls wrote:
Lee Noar wrote:

Does it fail in pthread_yield_return by any chance?

Well, I certainly don't have enough information to rule out
the later crash there.  Anyway, thanks for looking as this;
people are not often interested in looking at such hard
problems :-|


Incidentally, I put a pthread_yield in a simple X program
using shared libraries, and it worked fine.

Perhaps it's a StrongARM thing. The reason I ask is that the following code failed to work when built dynamically, but worked perfectly when built statically:

--8<-- pthread-test-lib1.c --

#include <stdio.h>
#include <pthread.h>

static int x = 10;

static pthread_t lib_thread;

static void *
tf (void *arg)
{
  while (1)
  {
    printf("Library 1 thread before yield: %d\n", x);
    pthread_yield();
    printf("Library 1 thread after yield: %d\n", x);
  }
}

void pthread_lib1_create(void)
{
  if (pthread_create(&lib_thread, NULL, tf, NULL) != 0)
    printf("Failed to create thread in library 1\n");
}

--8<--

--8<-- pthread-test-lib2.c --

#include <stdio.h>
#include <pthread.h>

static int x = 20;

static pthread_t lib_thread;

static void *
tf (void *arg)
{
  while (1)
  {
    printf("Library 2 thread before yield: %d\n", x);
    pthread_yield();
    printf("Library 2 thread after yield: %d\n", x);
  }
}

void pthread_lib2_create(void)
{
  if (pthread_create(&lib_thread, NULL, tf, NULL) != 0)
    printf("Failed to create thread in library 2\n");
}

--8<--

--8<-- pthread-test-main.c --

#include <stdio.h>

extern void pthread_lib1_create(void);
extern void pthread_lib2_create(void);

static int x = 30;

int main(void)
{
  pthread_lib1_create();
  pthread_lib2_create();

  while (1)
  {
    printf("In main before yield: %d\n", x);
    pthread_yield();
    printf("In main after yield: %d\n", x);
  }

  return 0;
}

--8<--

Dynamic build:

arm-unknown-riscos-gcc pthread-test-lib1.c -O2 -o libpthread-test1.so -shared -fPIC

arm-unknown-riscos-gcc pthread-test-lib2.c -O2 -o libpthread-test2.so -shared -fPIC

arm-unknown-riscos-gcc pthread-test-main.c -O2 -o pthread-test-main,e1f -L. -lpthread-test1 -lpthread-test2

Static build:

arm-unknown-riscos-gcc pthread-test-main.c pthread-test-lib1.c pthread-test-lib2.c -O2 -o pthread-test-main-S,e1f -static

There are 3 threads including the main one. In the dynamic build, each thread is called once upto pthread_yield, but when switching from the last back to the first it crashes. Initially, I traced it to pthread_yield_return which conists of one instruction that restores registers from the stack based on fp. Although fp pointed into the stack, it was not to a stack frame.
Eventually, I traced this to the STMFD instruction in pthread_yield:

  STMDB a1, {r4-r14}^

I found that for the first thread, it failed to save r14 into __cbreg so all registers saved were one register out of step and on the reload, instead of restoring fp(r11) to fp(r11), it restored sl(r10) to fp(r11) hence the pointer into the stack. I confirmed that the base register was correct and not 4 bytes out and the other two threads were correctly saved. I've search ARM's documents for the StrongARM looking for a CPU bug, but I can't find anything and that wouldn't explain why the static build works.

I've found that using this sequence instead stops the crash:

 ADD    a1, a1, #13*4
 STMDB  a1, {r4-r12}
 STMIA  a1!,{r13,r14}^

Can anyone reproduce these results?

Thanks,
Lee.


_______________________________________________
GCCSDK mailing list [email protected]
Bugzilla: http://www.riscos.info/bugzilla/index.cgi
List Info: http://www.riscos.info/mailman/listinfo/gcc
Main Page: http://www.riscos.info/index.php/GCCSDK

Reply via email to