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.
Related
I'm trying to write multithread program to calculate usage of processor. The problem is that i don't know how to safely end threads. I have to end them by signal SIGTERM and I tried
while(flag), phread_exit(), exit(), return(void*)0 but non of them work. I need to end infinite loop and return to main function. I've got two results: Exiting the whole program or program stopped and do nothing.
How can I solve it?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <signal.h>
#include <ctype.h>
#include <unistd.h>
#include <sys/sysinfo.h>
#include <ctype.h>
#include <malloc.h>
#include <time.h>
#include <semaphore.h>
#include "cpudata.h"
#include"cpu_result.h"
#include "reader.h"
#include "analyzer.h"
#include "writer.h"
#define NUM_THREADS 3 //Number of threads
//Declaring variables as volatile
volatile struct cpu_data *datax1;
volatile struct cpu_data *datax2;
volatile struct cpu_result *result;
//Declaring semaphores
sem_t sem1;
sem_t sem2;
sem_t sem3;
volatile int flag=1;
volatile int val[NUM_THREADS]={0,0,0};
void handle_sigterm(int signum)
{
flag=0;
}
void *reader(void *ptr) //Thread to read
{ while(flag){
sem_post(&sem3);
sem_wait(&sem1);
sleep(1); //Make sure that semaphores changes value
load_data(datax1);
sleep(1); //Making sure that values datax1 and datax2 are different
load_data(datax2);
if(datax1==datax2) //checking if values are different
{
perror("Datas are the same \n");
}
}
pthread_exit(val[0]);
}
void *analyzer(void *ptr)//Thread to calculate data
{ while(flag){
sem_post(&sem1);
sem_wait(&sem2);
sleep(1);//Make sure that semaphores changes value
for(int i=0;i<NOPT+1;i++)
{
result[i]=calculate(datax1[i],datax2[i]);//calculating data
}
}
pthread_exit(val[1]);
}
void *writer(void *ptr)//thread to write data
{ while(flag){
sem_post(&sem2);
sem_wait(&sem3);
sleep(1);//Make sure that semaphores changes value
writeresult(result);
printf("\n\n\n\n\n\n");
}
pthread_exit(val[2]);
}
int main(int argc, char **argv)
{
struct sigaction action;
memset(&action,0,sizeof(struct sigaction));
action.sa_handler=handle_sigterm;
sigaction(SIGTERM,&action,NULL);
//Allocating memory for data
datax1=(struct cpu_data *)malloc((NOPT+1)*sizeof(struct cpu_data));
datax2=(struct cpu_data *)malloc((NOPT+1)*sizeof(struct cpu_data));
result=(struct cpu_result *)malloc((NOPT+1)*sizeof(struct cpu_result));
pthread_t thread[NUM_THREADS];//declaring threads
//Initializing semaphores
sem_init(&sem1,0,1);
sem_init(&sem2,0,1);
sem_init(&sem3,0,1);
//creating threads
pthread_create(&thread[0],NULL, &reader, NULL);
pthread_create(&thread[1],NULL, &analyzer, NULL);
pthread_create(&thread[2],NULL, &writer, NULL);
//make sure threads are working
for(int i=0;i<NUM_THREADS;i++){
pthread_join(thread[0],NULL);
pthread_join(thread[1],NULL);
pthread_join(thread[2],NULL);
}
//stopping threads
for(int i=0;i<NUM_THREADS;i++){
pthread_cancel(thread[0]);
pthread_cancel(thread[1]);
pthread_cancel(thread[2]);
}
//freeing memory
sem_destroy(&sem1);
sem_destroy(&sem2);
sem_destroy(&sem3);
free(datax1);
free(datax2);
free(result);
printf("SAFETY CLOSING");
return 0;
}
I would like to measure the CPU and User time passed between starting a process and sending SIGINT signal using C times function.
However, on print I just get 0. Can't see the problem..
#include <stdio.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/times.h>
#include <signal.h>
struct tms time_start;
struct tms time_end;
clock_t start;
clock_t end;
void handle() {
times(&time_end);
end = time_end.tms_stime;
}
int main(int argc, char *argv[]) {
signal(SIGINT, handle);
times(&time_start);
start = time_start.tms_utime;
pause();
printf("end: %ld, start: %ld\n", (long) end, (long) start);
return 0;
}
This is the output I get:
k#sc:dir$ ./my_time
^Cend: 0, start: 0
on print I just get 0. Can't see the problem..
The tms_stime is the CPU time spend in the kernel on behalf of the process. pause() is doing nothing, so it doesn't count for CPU time, signal and times are not computationally demanding functions - your program is doing nothing. Do some I/O operations, get that kernel to work to see some changes in times.
For example the following program reads 400000000 bytes from /dev/urandom:
#include <time.h>
#include <sys/times.h>
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
struct tms time_end;
void handle() {
times(&time_end);
}
int main(int argc, char *argv[]) {
signal(SIGINT, handle);
// read from urandom so that kernel has to generate randomness
FILE *f = fopen("/dev/urandom", "r");
for (int i = 0; i < 20000000; ++i) {
char buf[20];
fread(buf, sizeof(buf), 1, f);
}
fclose(f);
pause();
printf("tms_stime = %ld\n", (long)time_end.tms_stime);
return 0;
}
Saved as 1.c file and executed on my system in shell outputs:
$ sh -c 'gcc 1.c ; ./a.out & child=$!; sleep 2; kill -INT $child ; wait'
tms_stime = 127
On linux there is also CLOCK_PROCESS_CPUTIME_ID you might be interested in.
I am trying to understand the behavior of volatile and compiler optimization in C through an example.
For this, I referred:
Where to use volatile?
Why is volatile needed in C?
https://software.intel.com/en-us/blogs/2007/11/30/volatile-almost-useless-for-multi-threaded-programming
All of the above posts have at least one answer related to signal handler so for this, I have written a simple code to actually implement and observe the behavior in Linux just for understanding.
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <pthread.h>
int counter = 0;
void *thread0_func(void *arg)
{
printf("Thread 0\n");
while(1)
{
}
return NULL;
}
void *thread1_func(void *arg)
{
printf("Thread 1\n");
while(counter == 0)
{
printf("Counter: %d\n", counter);
usleep(90000);
}
return NULL;
}
void action_handler(int sig_no)
{
printf("SigINT Generated: %d\n",counter);
counter += 1;
}
int main(int argc, char **argv)
{
pthread_t thread_id[2];
struct sigaction sa;
sa.sa_handler = action_handler;
if(sigaction(SIGINT, &sa, NULL))
perror("Cannot Install Sig handler");
if(pthread_create(&thread_id[0], NULL, thread0_func, NULL))
{
perror("Error Creating Thread 0");
}
if(pthread_create(&thread_id[1], NULL, thread1_func, NULL))
{
perror("Error Creating Thread 0");
}
else
{
}
while(1)
{
if(counter >= 5)
{
printf("Value of Counter is more than five\n");
}
usleep(90000);
}
return (0);
}
This code is just for learning and understanding.
I tried compiling the code using:
gcc -O3 main.c -o main -pthread
But the compiler is not acting on global variable counter and is not optimizing it.
I was expecting *thread1_func to execute in a forever loop and the if (counter >= 5) to be never true.
What am I missing here?
GCC Version: gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.4)
Your if tests on the value of counter are interspersed with calls to usleep and printf. These are opaque library calls. The compiler cannot see through them and so it has to assume they may have access to the counter external variable, and so it has to reload the counter variable after those calls.
If you move these calls out, the code gets optimized as you expect:
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <pthread.h>
int counter = 0;
void *thread0_func(void *arg)
{
printf("Thread 0\n");
while(1)
{
}
return NULL;
}
void *thread1_func(void *arg)
{
printf("Thread 1\n");
unsigned i=0;
while(counter == 0)
{
i++;
}
printf("Thread 1: %d, i=%u\n", counter, i);
return NULL;
}
void action_handler(int sig_no)
{
printf("SigINT Generated: %d\n",counter);
counter += 1;
}
int main(int argc, char **argv)
{
pthread_t thread_id[2];
struct sigaction sa;
sa.sa_handler = action_handler;
if(sigaction(SIGINT, &sa, NULL))
perror("Cannot Install Sig handler");
if(pthread_create(&thread_id[0], NULL, thread0_func, NULL))
{
perror("Error Creating Thread 0");
}
if(pthread_create(&thread_id[1], NULL, thread1_func, NULL))
{
perror("Error Creating Thread 0");
}
else
{
}
while(1)
{
if(counter >= 5)
{
printf("Value of Counter is more than five\n");
}
usleep(90000);
}
return (0);
}
Even if you make the counter variable static, the compiler will still not optimize, because although an external library definitely won't see the counter variable, the external call may theoretically have a mutex lock, which would allow another thread to change the variable without a data race. Now neither usleep nor printf are wrappers around a mutex lock, but the compiler doesn't know, nor does it do inter-thread optimization, so it has to be conservative and reload the counter variable after the call and the reload is what prevents the optimization you expect.
Of course, a simple explanation would be that your program is undefined if the signal handler executes, because you should've made counter volatile sig_atomic_t and you should've have synced your inter-thread access to it with either _Atomic or a mutex -- and in an undefined program, anything is possible.
I've spent quite a few hours on trying to figure this one out and I'm completly stuck. The program is supposed to start 6 threads. Where some threads start where others end. Right now, I'm trying to get one single thread (thread 0) to execute. The caps lock commenting shows where I have added code and done my mistakes. My main struggle here is dealing with the pointers. Could anyone give me any pointers (ha..ha.. :c )?
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#define SHARED 1
sem_t sem[6];
struct threadargs
{
int id; /* thread number */
int sec; /* how many sec to sleep */
int signal[6]; /* which threads to signal when done */
};
void *tfunc(void *arg)
{
int i;
struct threadargs *targs=arg;
sem_wait(sem); //WAIT FOR OWN SEMAPHORE
printf("Thread %d is running\n", targs->id);
sleep(targs->sec);
printf("Thread %d is completed and may wake others..\n", targs->id);
for(i=0; i<6; i++) //ITERATE OVER signal_ARRAY &
{ //WAKE THREAD NUMBER i IF
if(targs->signal[i] == 1) //signal[i] IS 1
pthread_cond_signal(&sem[i]);
}
}
int main(void)
{
int i, j;
struct threadargs *targs[6];
pthread_t tid[6];
for(i=0; i<6; i++)
{
targs[i] = (struct threadargs*) malloc(sizeof(struct threadargs));
for(j=0; j<6; j++)
{ targs[i]->signal[j]=0; }
}
targs[0]->id=1;
targs[0]->sec=1;
targs[0]->signal[1]=1;
targs[0]->signal[4]=1;
sem[0] = 0; //INITIALIZE THREAD'S SEMAPHORE TO 0 or 1
pthread_create(targs[0], NULL, tfunc, NULL) // START THREAD
for(i=0; i<6; i++)
pthread_join(tid[i], NULL);
return 0;
}
Alright. First things first, I do recommend taking a second look at your coding style. It is of course highly subjective and I won't say yours is bad, but it took me a while to figure it out (if you really want to know, I recommend the Linux coding style for C/C++ code).
Lets get on with your problem. As far as I can see, the main issue seems that you're basically comparing pointers to apples with pointers to banana's (in other words, you're using the wrong pointer type in the wrong place).
To make sure that calls to functions and the like are correct, make sure to look up the API documentation for functions that are new to you (examples: pthread_create, sem_init, sem_wait, sem_post, pthread_cond_signal).
As you can see, pthread_cond_signal doesn't take a sem_t* as argument, and therefore you can't pass one to it and expect it to work. Below you'll find an example program showing how semaphores are used.
First, a new thread is created which will be put in waiting state instantly. As soon as the main tread finished counting from 0 to 150, it will post ('unlock') the semaphore and allowing the second thread to finish its execution.
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
static sem_t sem_thread_one;
static pthread_t thread_one_data;
static int x;
static void *tfunc(void *arg)
{
sem_wait(&sem_thread_one);
printf("Thread 1 is running. The value of x is %i\n", x);
return NULL;
}
int main(int argc, char **argv)
{
sem_init(&sem_thread_one, 0 /* don't share between processes */, 0);
if(pthread_create(&thread_one_data, NULL, &tfunc, NULL)) {
fprintf(stderr, "Could not create thread, exiting!\n");
return -EXIT_FAILURE;
}
while(x < 150) {
x++;
}
sem_post(&sem_thread_one);
if(pthread_join(thread_one_data, NULL)) {
fprintf(stderr, "Could not join threads, exiting!\n");
return -EXIT_FAILURE;
}
sem_destroy(&sem_thread_one);
printf("Program ran succesfully!\n");
return -EXIT_SUCCESS;
}
Save in a file sem.c and compile & link using:
gcc -Wall -Os -pthread -o sem_test sem.c
Now a second example, but now using pthread_cond_t. The functionality of the program is somewhat similar, it waits for a counter to reach a certain number.
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <pthread.h>
static pthread_t thread_one_data, thread_two_data;
static volatile int x, y, idx = 10;
static int count = 1;
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t condition = PTHREAD_COND_INITIALIZER;
static void *cond_test_wait(void *arg)
{
pthread_mutex_lock(&mutex);
while(count < 10) {
printf("Waiting for `count < 10' to become true\n");
pthread_cond_wait(&condition, &mutex);
}
pthread_mutex_unlock(&mutex);
printf("Test wait thread finished. Value of count: %i\n", count);
return NULL;
}
static void *cond_test_signal(void *arg)
{
while(count < 10) {
pthread_mutex_lock(&mutex);
pthread_cond_signal(&condition);
/* do more intelligent things here */
count++;
pthread_mutex_unlock(&mutex);
}
printf("Test signal thread finished\n");
return NULL;
}
int main(int argc, char **argv)
{
if(pthread_create(&thread_one_data, NULL, &cond_test_wait, NULL)) {
fprintf(stderr, "Could not create thread, exiting!\n");
return -EXIT_FAILURE;
}
if(pthread_create(&thread_two_data, NULL, &cond_test_signal, NULL)) {
fprintf(stderr, "Could not create thread, exiting!\n");
return -EXIT_FAILURE;
}
pthread_join(thread_one_data, NULL);
pthread_join(thread_two_data, NULL);
pthread_cond_destroy(&condition);
pthread_mutex_destroy(&mutex);
printf("Program ran succesfully!\n");
return -EXIT_SUCCESS;
}
Save in a file cond.c and compile & link using:
gcc -o cond -pthread -Os -Wall cond.c
Do note how neat condition work in this example. You can use them to wait until any expression (= condition) becomes true. After the condition becomes true normal execution continue's.
If you need any more help, don't hesitate to ask in the comments. Good luck combining the above examples to fix up your program.
I'm attempting to write a C program in OSX that will change another program's execution flow, exactly like a debugger would. But before I put all of the "pieces" together, I need to test that each of them work individually first.
I've successfully used mach_vm_read_overwrite() and mach_vm_write() to read and write to the stack.
I've successfully used thread_get_state() and thread_set_state() to read and write to registers.
All that's left is to use thread_create_running() to create a thread in the task to execute my arbitrary function. However, whenever I create a thread, OSX completely crashes and automatically reboots my computer, lol. Can someone explain what is going on in more detail?
Here's my remote program, test.c:
#include <unistd.h>
#include <stdio.h>
void function1() {
printf("lol 1\n");
}
void function2() {
printf("lol 2\n");
}
void function3() {
printf("lol 3\n");
}
int main(int argc, char **argv) {
while(1) {
function1();
sleep(1);
function2();
sleep(1);
function3();
sleep(1);
}
return 0;
}
And here's my tiny debugger-in-progress:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ptrace.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <stdint.h>
#include <mach/mach_traps.h>
#include <mach/mach_init.h>
#include <mach/mach_error.h>
#include <mach/mach.h>
#include <mach/mach_types.h>
#include <mach/i386/thread_status.h>
void error(char *msg) {
printf("error: %s\n", msg);
exit(1);
}
int main(int argc, char **argv) {
pid_t pid;
mach_port_t eq_task;
kern_return_t err;
thread_act_port_array_t thread_list;
mach_msg_type_number_t thread_count;
x86_thread_state_t x86_state;
mach_msg_type_number_t sc = x86_THREAD_STATE_COUNT;
thread_act_t remoteThread;
// Make sure we have an argument
if (argc != 2)
error("requires a PID");
else
pid = (pid_t)atoi(argv[1]);
// Make sure we're root
if (getuid() && geteuid())
error("requires root");
// Get the task port
err = task_for_pid(mach_task_self(), pid, &eq_task);
if ((err != KERN_SUCCESS) || !MACH_PORT_VALID(eq_task))
error("getting eq task");
// Suspend the process
if(task_suspend(eq_task))
error("suspending the task");
// Get a list of threads from the port
if (task_threads(eq_task, &thread_list, &thread_count))
error("cannot get list of tasks");
// Get the registers
if (thread_get_state(thread_list[0], x86_THREAD_STATE, (thread_state_t)&x86_state, &sc))
error("getting state from thread");
// Create a new thread
err = thread_create_running(eq_task, x86_THREAD_STATE, (thread_state_t)&x86_state, x86_THREAD_STATE_COUNT, &remoteThread);
// BLACK SCREEN AND CRASH
// Resume the process again
if(task_resume(eq_task))
error("resuming the task");
}
I would assume that your trying to execute this in an XD bit, unless your running rocking an AMD instead of an intel. Then it would be NX opposed to XD. This would cause the application or even the entire computer to crash.