=========The right >
/lib64/libpthread-2.5.so: 0x319720d6d5 ## __lll_unlock_wake
/lib64/libpthread-2.5.so: 0x319720a157 ## _L_unlock_766
/lib64/libpthread-2.5.so: 0x319720a0be ## pthread_mutex_unlock
/bianque/benchmark/lock/mutex: 0x400ae7 ## counter_func_1
/bianque/benchmark/lock/mutex: 0x400b4b ## counter_func_2
/bianque/benchmark/lock/mutex: 0x400b6b ## counter_func_3
/bianque/benchmark/lock/mutex: 0x400b8b ## counter_thread
/lib64/libpthread-2.5.so: 0x319720677d ## start_thread
/lib64/libc-2.5.so: 0x3196ad49ad ## __clone
=========The wrong >
/lib64/libpthread-2.5.so: 0x319720d6d5 ## __lll_unlock_wake
/bianque/benchmark/lock/mutex: 0x400b4b ## counter_func_2
/bianque/benchmark/lock/mutex: 0x400b6b ## counter_func_3
/bianque/benchmark/lock/mutex: 0x400b8b ## counter_thread
/lib64/libpthread-2.5.so: 0x319720677d ## start_thread
/lib64/libc-2.5.so: 0x3196ad49ad ## __clone
The wrong result skip 3 frames (_L_unlock_766, pthread_mutex_unlock, counter_func_1).
I suspect that the value of the CFA is miscalculated while through __lll_unlock_wake.
In the other complex example, we cannot get any frame above __lll_unlock_wake.
The test program I used:
-------------------------------------------
#include <stdio.h>
#include <pthread.h>
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
#define SPIN 10000000
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
long counter;
time_t end_time;
void* counter_func_1(void* arg)
{
int status;
int spin;
while(1) {
status = pthread_mutex_lock(&mutex);
if(status != 0)
fprintf(stderr, "Lock mutex\n");
for(spin = 0; spin < SPIN; spin++)
counter++;
status = pthread_mutex_unlock(&mutex);
if(status != 0)
fprintf(stderr, "Unlock mutex\n");
}
printf("Coutner is %#lx\n", counter);
return NULL;
}
void* counter_func_2(void* arg)
{
counter_func_1(NULL);
return NULL;
}
void* counter_func_3(void* arg)
{
counter_func_2(NULL);
return NULL;
}
void* counter_thread(void* arg)
{
counter_func_3(NULL);
return NULL;
}
void* monitor_thread(void* arg)
{
int status;
int misses = 0;
while(time(NULL) < end_time)
{
status = pthread_mutex_trylock(&mutex);
if(status != EBUSY)
{
if(status != 0)
fprintf(stderr, "Trylock mutex");
printf("Counter is %ld/n", counter/SPIN);
status = pthread_mutex_unlock(&mutex);
if(status != 0)
fprintf(stderr, "Unlock mutex");
}else
misses++;
}
printf("Monitro thread missed update %d times./n", misses);
return NULL;
}
#define THREAD_ARRAY_NUM 200
int main()
{
int status;
pthread_t pid_counter;
pthread_t pid_monitor;
pthread_t pid_array[THREAD_ARRAY_NUM];
end_time = time(NULL) + 600000000;
status = pthread_create(&pid_counter, NULL, counter_thread, NULL);
if(status != 0)
fprintf(stderr, "fail to create thread counter");
status = pthread_create(&pid_monitor, NULL, monitor_thread, NULL);
if(status != 0)
fprintf(stderr, "fail to create monitor thread");
for (int i = 0; i < THREAD_ARRAY_NUM; i++) {
status = pthread_create(&pid_array[i], NULL, counter_thread, NULL);
if (status != 0)
fprintf(stderr, "fail to create array thread: %d\n", i);
}
status = pthread_join(pid_counter, NULL);
if(status != 0)
fprintf(stderr, "fail to join counter thread");
status = pthread_join(pid_monitor, NULL);
if(status != 0)
fprintf(stderr, "fail to join monitor thread");
for (int i = 0; i < THREAD_ARRAY_NUM; i++) {
pthread_join(pid_array[i], NULL);
}
return 0;
}
Compiler command is :
g++ -O3 -fno-inline -o mutex mutex.cc -lpthread
Regards
Chenggang