141 lines
2.4 KiB
C
141 lines
2.4 KiB
C
|
/* BeginSourceFile more_steps.c
|
||
|
|
||
|
This file creates a lot of threads which then execute
|
||
|
in parallel, so that wdb can be tested on handling
|
||
|
simultaneous thread events.
|
||
|
|
||
|
To compile:
|
||
|
|
||
|
cc -Ae +DA1.0 -g -o more_steps -lpthread more_steps.c
|
||
|
|
||
|
To run:
|
||
|
|
||
|
more_threads
|
||
|
*/
|
||
|
|
||
|
#include <unistd.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <stdio.h>
|
||
|
#include <assert.h>
|
||
|
#include <pthread.h>
|
||
|
|
||
|
#define TRUE 1
|
||
|
#define FALSE 0
|
||
|
#define N_THREADS 3
|
||
|
#define PHASES 3
|
||
|
|
||
|
typedef enum {
|
||
|
ZERO,
|
||
|
ONE,
|
||
|
TWO,
|
||
|
THREE
|
||
|
} phase_t;
|
||
|
|
||
|
/* Uncomment to turn on debugging output */
|
||
|
/* #define DEBUG */
|
||
|
|
||
|
/* Locks.
|
||
|
*/
|
||
|
int lock_one; /* Main W, others R */
|
||
|
int lock_two; /* ditto */
|
||
|
int lock_end[ N_THREADS ]; /* Main R, others R[i] */
|
||
|
int phase[ N_THREADS ];
|
||
|
|
||
|
/* Routine for each thread to run.
|
||
|
*/
|
||
|
void *spin( vp )
|
||
|
void * vp;
|
||
|
{
|
||
|
int me = (int) vp;
|
||
|
int i;
|
||
|
|
||
|
lock_end[ me ] = TRUE;
|
||
|
|
||
|
phase[ me ] = ONE;
|
||
|
|
||
|
while( lock_one );
|
||
|
|
||
|
phase[ me ] = TWO;
|
||
|
|
||
|
while( lock_two );
|
||
|
|
||
|
phase[ me ] = THREE;
|
||
|
|
||
|
lock_end[ me ] = FALSE;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
do_pass()
|
||
|
{
|
||
|
int i;
|
||
|
pthread_t t[ N_THREADS ];
|
||
|
int err;
|
||
|
int done;
|
||
|
|
||
|
/* Start N_THREADS threads, then join them so
|
||
|
* that they are terminated.
|
||
|
*/
|
||
|
for( i = 0; i < N_THREADS; i++ ) {
|
||
|
err = pthread_create( &t[i], NULL, spin, (void *)i );
|
||
|
if( err != 0 ) {
|
||
|
printf( "== Start/stop, error in thread %d create\n", i );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Do phase 1.
|
||
|
*/
|
||
|
lock_one = FALSE;
|
||
|
|
||
|
/* Do phase 2.
|
||
|
*/
|
||
|
lock_two = FALSE;
|
||
|
|
||
|
/* Be done.
|
||
|
*/
|
||
|
done = 0;
|
||
|
while( !done ) {
|
||
|
|
||
|
/* Be optimistic.
|
||
|
*/
|
||
|
done = 1;
|
||
|
for( i = 0; i < N_THREADS; i++ ) {
|
||
|
if( lock_end[i] ) {
|
||
|
/* Thread "i" is not ready yet.
|
||
|
*/
|
||
|
done = 0;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Finish up
|
||
|
*/
|
||
|
for( i = 0; i < N_THREADS; i++ ) {
|
||
|
err = pthread_join(t[i], NULL ); /* Line 105 */
|
||
|
if( err != 0 ) { /* Line 106 */
|
||
|
printf( "== Start/stop, error in thread %d join\n", i );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
i = 10; /* Line 109. Null line for setting bpts on. */
|
||
|
}
|
||
|
|
||
|
main( argc, argv )
|
||
|
int argc;
|
||
|
char **argv;
|
||
|
{
|
||
|
int i;
|
||
|
|
||
|
/* Init
|
||
|
*/
|
||
|
lock_one = TRUE;
|
||
|
lock_two = TRUE;
|
||
|
for( i = 0; i < N_THREADS; i++ ) {
|
||
|
lock_end[i] = TRUE;
|
||
|
phase[i] = ZERO;
|
||
|
}
|
||
|
|
||
|
do_pass();
|
||
|
return(0);
|
||
|
}
|