LinuxQuestions.org
Download your favorite Linux distribution at LQ ISO.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 03-14-2012, 08:51 AM   #1
adixon
Member
 
Registered: Oct 2010
Posts: 34

Rep: Reputation: 3
thread unequal distribution in symmetric context


Hey all,
Relearning some c coding and testing out threading for the first time - wrote what should be a simple program, however it does not do what i expected. I want it to run freddi thread, then main thread symmetrically however my output is inconsistent at best.

here's the test code:
Code:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

#define _memory    -5
#define _badthread -6
#define _badyield  -7
#define _badlock   -8
#define _badunlock -9

#define throw(R,E) if(R)return E
#define require(R,E) do{if(R){print_error(E);exit(0);}}while(0)

void print_error(long err)
{
	switch(err)
	{
		case _memory:
			fprintf(stdout,"error allocation failed\n");
		break;
		case _badthread:
			fprintf(stdout,"error bad thread\n");
		break;
		case _badyield:
			fprintf(stdout,"error bad yield\n");
		break;
		case _badlock:
			fprintf(stdout,"error bad lock\n");
		break;
		case _badunlock:
			fprintf(stdout,"error bad unlock\n");
		break;
	}
}

void *freddi()
{
	while(1)
	{
		fprintf(stdout,"@");
	}
	return 0;
}

int main(int argc, char *argv[])
{
#define log_error(T,E) fprintf(stdout,"thread %d: ",T);print_error(E)
	pthread_t freddy; void **ret;
	require(!(ret = malloc(sizeof(void *))),_memory);
	require(pthread_create(&freddy,0,&freddi,0),_badthread);
	while(1)
	{
		fprintf(stdout,"*");
	}
	pthread_join(freddy,ret);
	fprintf(stdout,"\n");
	if(ret)print_error((long)(*ret));
	free(ret);
	return 0;
}
This is some sample output I'm getting (its very inconsistent)

Code:
@@@@*@*@@@@*@*@*****@*@@@@*@***@*@*@*****@*@*@*@@*@*@*@*@*@*@*@@@@*@****@*@*@*@****@*@*@**@*@*@*****@*@*@*@*@*@***@*@*@@@*@*****@*@*@*@*@*@*@*@*@*@*@*@*@*@*@@@*@***@*@*@****@*@*@*@*@@@*@***@*@****@*@*@*@*@@@@@*@*@*@@@@@*@*@*@***@*@@@@*@*@*****@*@*@*@@@@***************************************************************@*@*@*@***@*@*@****@*@*@****@@*@*@@@@*@@*@*@*@*@@*@*@*@*@*@@@*@*@*@*@*@*@*@*@@*@****@@@*@*@*@*@*@*@*@*@@@*@*@*@*@*@**@*@*@****@*@*@*@*@@*@*@@@*@*@*@*@*@*@*@*@*@*@*@*@*@*@*@@@@*@*@*@*@*@*@*@*@*@*@*@*@*@*@*@@@@*@****@*@*@*@**@*@*@@@@*@@@*@*@*@*@@@@*@*@*@*@*@*@*@*@*@*@*@*@*@*@****@*@***@*@*@*@*@*@*@*@*@@@*@@**@*@***@*@*@@@*@*@*@*@@@@*@*@*@*@*@*@*@***@*@*@*@*@*@*@****@*@*@*@*@****@*@***@*@*@*@*@@@*@*@*@*@****@*@*@@@@*@****@*@@@*@@@*@****@*@@*@*@@*@**@*@*@*@*****@*@****@*@@@*@*@*@@@@*@*@*@*@*@*@@@@@*@*@@*@*@*@*@*@@*@*****@*@*@****@
Can anyone explain why these threads are not being run symmetrically?
If so how could you modify to make it symmetric?
 
Old 03-15-2012, 05:29 AM   #2
kalleanka
Member
 
Registered: Aug 2003
Location: Mallorca, Spain
Distribution: xubuntu
Posts: 551

Rep: Reputation: 38
Threads can run when(in any order) they want. You have to checkout how threads should wait for each other. Search for thread, wait, join, synchronization, timeout etc
 
Old 03-16-2012, 03:36 AM   #3
adixon
Member
 
Registered: Oct 2010
Posts: 34

Original Poster
Rep: Reputation: 3
Thanks kalleanka,
so ive changed the code to act symmetrically;

Code:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

#define _memory    -5
#define _badthread -6
#define _badyield  -7
#define _badlock   -8
#define _badunlock -9

#define throw(R,E) if(R)return E
#define require(R,E) do{if(R){print_error(E);exit(0);}}while(0)

int freddy = 0,jason = 0;
pthread_mutex_t fred_lock = PTHREAD_MUTEX_INITIALIZER,jason_lock = PTHREAD_MUTEX_INITIALIZER;

void print_error(long err)
{
	switch(err)
	{
		case _memory:
			fprintf(stdout,"error allocation failed\n");
		break;
		case _badthread:
			fprintf(stdout,"error bad thread\n");
		break;
		case _badyield:
			fprintf(stdout,"error bad yield\n");
		break;
		case _badlock:
			fprintf(stdout,"error bad lock\n");
		break;
		case _badunlock:
			fprintf(stdout,"error bad unlock\n");
		break;
	}
}

void *freddi()
{
	while(1)
	{
		require(pthread_mutex_lock(&fred_lock),_badlock);
			while(freddy < 80)
			{
				fprintf(stdout,"@");
				++freddy;
			}
		require(pthread_mutex_unlock(&fred_lock),_badunlock);
		require(pthread_mutex_lock(&jason_lock),_badlock);
			jason = 0;
		require(pthread_mutex_unlock(&jason_lock),_badunlock);
	}
	return 0;
}

int main(int argc, char *argv[])
{
#define log_error(T,E) fprintf(stdout,"thread %d: ",T);print_error(E)
	pthread_t freddy; void **ret;
	require(!(ret = malloc(sizeof(void *))),_memory);
	require(pthread_create(&freddy,0,&freddi,0),_badthread);
	while(1)
	{
		require(pthread_mutex_lock(&jason_lock),_badlock);
			while(jason < 80)
			{
				fprintf(stdout,"*");
				++jason;
			}
		require(pthread_mutex_unlock(&jason_lock),_badunlock);
		require(pthread_mutex_lock(&fred_lock),_badlock);
			freddy = 0;
		require(pthread_mutex_unlock(&fred_lock),_badunlock);
	}
	pthread_join(freddy,ret);
	fprintf(stdout,"\n");
	if(ret)print_error((long)(*ret));
	free(ret);
	return 0;
}
only it seems like freddy dies after its first run as I get this output

Quote:
********************************************************************************
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
********************************************************************************
********************************************************************************
********************************************************************************
********************************************************************************
********************************************************************************
********************************************************************************
********************************************************************************
********************************************************************************
********************************************************************************
********************************************************************************
********************************************************************************
********************************************************************************
********************************************************************************
not sure why jason takes over, any ideas?
 
Old 03-18-2012, 09:34 PM   #4
ta0kira
Senior Member
 
Registered: Sep 2004
Distribution: FreeBSD 9.1, Kubuntu 12.10
Posts: 3,078

Rep: Reputation: Disabled
Quote:
Originally Posted by adixon View Post
not sure why jason takes over, any ideas?
This:
Quote:
Originally Posted by adixon View Post
Code:
pthread_t freddy;
A more practical solution in this situation might be a pthread barrier, which will block all threads that pthread_barrier_wait until the Nth "waiter". You also shouldn't count on buffered output working well between threads.
Kevin Barry

Last edited by ta0kira; 03-18-2012 at 09:36 PM.
 
1 members found this post helpful.
Old 03-30-2012, 03:03 AM   #5
adixon
Member
 
Registered: Oct 2010
Posts: 34

Original Poster
Rep: Reputation: 3
thanks ta0kira,
ill have to look into the pthread barrier (is this like a mutex?).
Could you recommend any reading on the buffered output - I don't quite understand the importance in the threaded context
 
Old 03-30-2012, 10:23 PM   #6
ta0kira
Senior Member
 
Registered: Sep 2004
Distribution: FreeBSD 9.1, Kubuntu 12.10
Posts: 3,078

Rep: Reputation: Disabled
I generally have the following analogy in mind wrt pthread barriers. You set its "size" N when you initialize it, which means that it takes the effort of N threads to "break it down". Sort of like a wall that prevents passing until N people arrive to push it over. Or you could say that it releases every time k%N==0 with k being the cumulative number of pthread_barrier_wait calls.

write is atomic in many cases (dependent on the underlying device); however, fprintf isn't (as far as I know.) That means if two threads are writing to the output stream at once the output might end up interleaved. In general this should not happen with write for "reasonable" output sizes (<4096 is probably a safe guess.) I don't know if there are any good references regarding how buffered output works, but basically when you print to a FILE* the data is appended to a buffer within the process and when certain conditions are met (e.g. '\n' is printed) it will write some/all of the buffered data.
Kevin Barry
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
changing thread user context in linux neel_learning_linux Linux - Newbie 3 07-31-2009 02:34 AM
Counting thread's context switches bluehive Programming 2 06-15-2008 06:35 PM
Counting thread's context switches bluehive Linux - Newbie 0 06-10-2008 09:00 AM
Handling of Interrupts in thread context asurya Linux - Newbie 1 04-05-2006 09:15 AM
Kernel Thread Execution Context and PID ratwings Linux - Newbie 0 02-11-2005 04:06 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 07:09 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration