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