All
I have a question about pthread_cond_wait(). In short, I create two POSIX thread in a process, If I execute the following code, why is cpu utilization full?
I take experiments on it, if I remove comment mark before bool isNodeConnect3, the program seems to be no probelm, CPU utilization is almost 0%, in other words, theads will go to sleep and don't spend CPU resource, that's what I want.
Is it a data algnment probelm? maybe, but I don't think so, because I bracket my struct by "#pragma pack(push,1) ... #pragma (pop)" Could you give me suggestion??
Environment
Host OS is win7/intel 64 bit, guest OS is ubuntu 10.04LTS
Give "number of processor cores:4" to guest OS
The following is my test code, you can build and run it by
gcc -o program1 program1.c -pthread && ./program1
Get CPU utilization is 25%. Result depends on your setting.
Thanks a lot.
Code
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <string.h>
#include <pthread.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <errno.h>
#include <stdbool.h>
#pragma pack(push,1)
struct BUFF_TX{
pthread_mutex_t mutex_lock;
pthread_cond_t more;
};
struct AtreeNode{
struct BUFF_TX buff_tx;
bool isNodeConnect;
bool isNodeConnect1;
bool isNodeConnect2;
// bool isNodeConnect3; // important
pthread_t thrd_tx;
};
struct AtreeNode treeNode[2];
int tmp[2];
#pragma (pop)
void Thread_TX(int *nodeIdx)
{
int idx = *nodeIdx;
while(1)
{
printf("Thread %d enter mutex lock...\n", idx);
pthread_mutex_lock(&treeNode[idx].buff_tx.mutex_lock);
while(1)
{
if(idx==0)
{
printf("idx==0 wait...\n");
pthread_cond_wait(&(treeNode[0].buff_tx.more), &treeNode[idx].buff_tx.mutex_lock);
}
else if(idx==1)
{
printf("idx==1 wait...\n");
pthread_cond_wait(&(treeNode[1].buff_tx.more), &treeNode[idx].buff_tx.mutex_lock);
}
else
printf("err\n");
}
pthread_mutex_unlock(&treeNode[idx].buff_tx.mutex_lock);
printf("Thread %d leave mutex lock...\n", idx);
}
}
int main(int argc, char *argv[])
{
int i;
int ret;
tmp[0] = 0;
tmp[1] = 1;
for(i=0; i<2; i++)
{
if(pthread_cond_init(&treeNode[i].buff_tx.more, NULL) != 0)
{
printf("cond %d init fail.\n", i);
exit(EXIT_FAILURE);
}
if(pthread_mutex_init(&treeNode[i].buff_tx.mutex_lock, NULL) != 0)
{
printf("mutex lock %d init fail.\n", i);
exit(EXIT_FAILURE);
}
}
for(i=0; i<2; i++)
{
ret = pthread_create(&treeNode[i].thrd_tx, NULL, (void *)Thread_TX, (void *)(&tmp[i]));
if(ret)
{
printf("pthread_create thrd_tx %d err\n", i);
return false;
}
}
pthread_join(treeNode[0].thrd_tx, NULL);
pthread_join(treeNode[1].thrd_tx, NULL);
exit(EXIT_SUCCESS);
}
Remove #pragma pack(1) and forget you ever heard of it. Your problem is that you are passing an invalid pointer to pthread_cond_wait. pthread_cond_t has a particular alignment requirement and you are creating objects which are not necessarily aligned to that requirement, and thus their addresses are not valid to pass to pthread_cond_wait. See also https://sourceware.org/bugzilla/show_bug.cgi?id=16549 which was RESOLVED by being MOVED to a bug report against GCC for not catching the invalid pointer usage.
You should be able to confirm whether this is the actual cause of your issue by running your program under strace -f and seeing that the futex syscalls are failing with EINVAL or similar.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With