Threads In C


buntz

Still Fresh
Joined
Jun 9, 2006
Messages
50
hello,

I'm having some problems getting threads to work properly on the GP2X. I create a thread with pthread_create(), and it seems to take over my gp2x.

Code:
pthread_attr_init(&tattr);

tattr.__schedpolicy=0;
tattr.__schedparam.sched_priority=2;

pthread_create(&tid, &tattr, Run, NULL);
		
drawText(screen, "a", 0, 100, 255, 255 ,255);
SDL_Flip(screen);		


while (!done)
{

	   //just hang out until someone hits "x"
	   key = waitForButton();

	if (key == 14)
	{
		done = 1;
	}
		
}


I see the "a" on the screen in the begining, until the procedures the thread calls clear the screen and start doing their thing. But after that happens, I can hit "x" all day and it will never end the program. I know it has to do with the thread because the program wokred fine before I put the thread code in. It waited for a button, and if x was pressed it exited to the menu, if not, it looped once more and then waited for another buttone to be pressed.

I thought it could have been a problem with the priority, so I changed it threads priority to 2, meaning that the main program (that while loop) would have a high priority, right? But obviously that didn't work. Do I have to do anything else special to get both branches of my program to execute along side each other?

Thanks in advance

so uh yeah

a sched_yield() fixxed the problem

sorry to bother everyone
 
Since you're using SDL, why not use a SDL_Thread?

It is as simple as creating a function taking a void* as argument, then declaring a thread with this funtion :) You have some simple tools, like waiting for a thread, or mutex
 
here is a simple thread example I put together that shows thread start up and syncronization:

Code:
/*

Examine Multiprocessor issues using
threads to simulate multiple CPU's

*/



//#include "../inc/local_mutex.h"
#include <pthread.h>
#include <fcntl.h>
#include <stdarg.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>

/*

#define DEBUG 1
#define TRACE 1

#include "../inc/types.h"
#include "../inc/debug.h"

*/

#define enter(a) 
#define rtnval(a) return(a)
#define rtn_noval(a) return
#define TRUE 1
#define FALSE 0
#define Log_debug(b) 


static char const ident[] =
  "$Id: lab4_1.c,v 1.1 2004/04/13 01:36:19 gmiller Exp $";

void *do_one_thing (int *);
void *do_another_thing (int *);
void do_wrap_up (int, int);

pthread_cond_t start_cv = PTHREAD_COND_INITIALIZER;
pthread_mutex_t start_mutex = PTHREAD_MUTEX_INITIALIZER;

pthread_cond_t done_cv = PTHREAD_COND_INITIALIZER;
pthread_mutex_t done_mutex = PTHREAD_MUTEX_INITIALIZER;

pthread_mutex_t print_mutex = PTHREAD_MUTEX_INITIALIZER;

int r1 = 0, r2 = 0, done = 0;


/*

  Funtion to implement a "pretty" version of the output
  code so that the main functions do get too UGLY.

*/


void
t_printf (char *fmt, ...)
{
  va_list ap;
  static char my_fn[] = "t_printf";

  //enter(my_fn);

  pthread_mutex_lock (&print_mutex);

  va_start (ap, fmt);
  vprintf (fmt, ap);
  va_end (ap);

  fflush (stdout);
  pthread_mutex_unlock (&print_mutex);

  //rtn_noval();

}


/*

Process 1 CPU work

*/

void *
do_one_thing (int *pnum_times)
{
  int i, j, x;
  static char my_fn[] = "do_one_thing";

  enter(my_fn);

/*

  Lock start_mutex so we can wait for
  a startup signal on the condition variable.

*/

  pthread_mutex_lock (&start_mutex);
  t_printf ("waiting do_one_thing\n");
  fflush (stdout);

/*

  pthread_cond_wait set's up wait on condition
  variable and unlocks the mutex and then waits
  for the condition variable to signal.  Then it
  will lock the mutex

*/


  pthread_cond_wait (&start_cv, &start_mutex);

/* 

  Ok ... we got control of the mutex so it is
  locked.  We don't need it locked so we unlock
  it to allow another thread to do it's thing.

*/

  pthread_mutex_unlock (&start_mutex);

/*

  Since our threads can do printf over each other
  I have chosen to control output with a mutex
  so none of the messages from each thread will
  over-write each other.

  ** Note **
  This should be done in a function or macro to
  keep from making the code so UGLY.


*/


  //sleep(1);

  t_printf ("Starting ... do_one_thing\n");
   Log_debug ("Starting ... do_one_thing");


  for (i = 0; i < 100; i++) {

	t_printf ("+");


	for (j = 0; j < 100000; j++)
	  x = x + i;
	(*pnum_times)++;
  }

  Log_debug ("Ready to lock done in do_one_thing");
  pthread_mutex_lock (&done_mutex);
  Log_debug ("Done locked in do_one_thing");
  t_printf ("@(");
  done++;
  Log_debug ("Send signal for done in do_one_thing");
  pthread_cond_signal (&done_cv);
  Log_debug ("Sent signal for done in do_one_thing");
  Log_debug ("Ready to unlock done in do_one_thing");
  pthread_mutex_unlock (&done_mutex);
  Log_debug ("Done unlocked in do_one_thing");
  t_printf ("!(");


//  sleep (10);
  pthread_exit ((void *) NULL);
  rtnval(NULL);

}

void *
do_another_thing (int *pnum_times)
{
  int i, j, x;
  static char my_fn[] = "do_another_thing";

  enter(my_fn);

  pthread_mutex_lock (&start_mutex);
  t_printf ("waiting do_another_thing\n");
  fflush (stdout);

  pthread_cond_wait (&start_cv, &start_mutex);
  pthread_mutex_unlock (&start_mutex);

  //sleep(1);

  t_printf ("Starting ... do_another_thing\n");
  Log_debug ("Starting ... do_another_thing");

  for (i = 0; i < 100; i++) {

	t_printf ("-");

	for (j = 0; j < 100000; j++)
	  x = x + i;
	(*pnum_times)++;
  }

  Log_debug ("Ready to lock done in do_another_thing");
  pthread_mutex_lock (&done_mutex);
  Log_debug ("Done locked in do_another_thing");
  t_printf ("@)");
  done++;
  Log_debug ("Send signal for done in do_another_thing");
  pthread_cond_signal (&done_cv);
  Log_debug ("Sent signal for done in do_another_thing");
  Log_debug ("Ready to unlock done in do_another_thing");
  pthread_mutex_unlock (&done_mutex);
  Log_debug ("Done unlocked in do_another_thing");
  t_printf ("!)");

//  sleep (10);
  pthread_exit ((void *) NULL);
  rtnval(NULL);

}

void
do_wrap_up (int one_times, int another_times)
{
  int total;
  static char my_fn[] = "do_wrap_up";

  enter(my_fn);

  t_printf ("\n");
  total = one_times + another_times;
  t_printf ("wrap up: doing another %d, another %d, total %d\n",
			one_times, another_times, total);

  fflush (stdout);

  rtn_noval();

}

int
main ()
{

  pthread_t thread1, thread2;
  int complete = FALSE;
  static char my_fn[] = "lab4_1";

  enter(my_fn);
  // set_debug ();

  pthread_create (&thread1, NULL, (void *) do_one_thing, (void *) &r1);

  pthread_create (&thread2, NULL, (void *) do_another_thing, (void *) &r2);


  sleep (5);
  t_printf ("Ready to start threads ..... \n");
  fflush (stdout);
  pthread_mutex_lock (&start_mutex);
  pthread_cond_broadcast (&start_cv);
  pthread_mutex_unlock (&start_mutex);


  while (complete == FALSE) {
	t_printf ("&");

	Log_debug ("Inside check loop");
	/*

	   Condition wait required the mutex to be locked before the call
	   so the conf=dition variable can be modified.  After the modification
	   the mutex is unlocked to initiate the wait.  When woken up the 
	   mutex is again locked to that we have freedom to checke the condition
	   variaible again.
	 */

	pthread_mutex_lock (&done_mutex);
	if (done >= 2) {
	  complete = TRUE;
	  pthread_mutex_unlock (&done_mutex);
	  continue;
	}
	Log_debug ("Now do cond_wait");
	pthread_cond_wait (&done_cv, &done_mutex);
	Log_debug ("cond_wait complete");
	t_printf ("%");
	if (done >= 2)
	  complete = TRUE;
	Log_debug ("1. Done needs unlocking");
	pthread_mutex_unlock (&done_mutex);
	Log_debug ("1. Done is unlocked");
	t_printf ("#");
  }

  //sleep(1);
  Log_debug ("Loop has exited");

  t_printf ("^");


  t_printf ("\nAll threads complete\n");
  fflush (stdout);

  pthread_join(thread1, NULL);
  pthread_join(thread2, NULL);

  do_wrap_up (r1, r2);
  fflush (stdout);

  rtnval(0);

}

code for local_mutex.h
Code:
/*

	Common Local Header File: local_mutex.h

*/

#ifndef LOCAL_MUTEX_H
#define LOCAL_MUTEX_H
#define _REENTRANT
#include	<pthread.h>
#include	<stdio.h>
#include	<stdlib.h>
#include	<unistd.h>
#include	<sys/types.h>
#include	<sys/time.h>
#include	<sys/wait.h>

#endif
 
I had no idea SLD had fucntions for threads. Next time I'll check the documentation first.

I did get it working with pthreads though, so right now I'm not going to change it, got bigger fish to fry.
 
Back
Top