[PLUG] Spot the race condition!
Heath Morrison
heath at doublemarked.com
Tue Oct 6 06:09:52 UTC 2009
It appears that you are using a single qs_arg variable and passing a
pointer to it into each thread that you create. The next cycle of the
loop then clobbers everything in this variable's contents, even if the
thread you spawned is still working on it. Don't share your qs_arg
memory between threads. Make sure you don't make this a variable
scoped locally to your partition_index loop though, either. I'd
suggest pre-allocating an array of number_partitions variables for
your qs_args, or something similarly transparent.
-Heath
On Mon, Oct 5, 2009 at 8:53 PM, Jameson Williams
<jameson at jamesonwilliams.com> wrote:
> Hello all,
>
> I've been trying to implement the parallel sort algorithm described at
> http://www.cs.caltech.edu/~cs284/lectures/29oct97/sld001.htm. I'm currently
> working on quicksorting some sublists. However, only sometimes does my
> parallel quicksort routine produce sorted sublists, as expected. Sometimes
> it fails to sort. I believe this is likely do to a race condition involving
> my qs_arg object, but I'm not all together sure; my attempts to mutex it did
> no further good. Can someone with a keen eye spot the race condition and
> propose a solution?
>
> Thank you!
> Jameson Williams
>
>
>
> #include <errno.h>
> #include <error.h>
> #include <pthread.h>
> #include <stdlib.h>
> #include <stdio.h>
> #include <string.h>
>
> /*
> This is a cpu bound activity. NUMBER_THREADS should probably be however
> many cores your machine has.
> */
> #define NUMBER_THREADS 2
>
> typedef struct {
> void *base;
> size_t nmemb;
> size_t size;
> int(*compar)( const void *, const void * );
> } quicksort_arg_t;
>
> int intcmp( const void *a, const void *b ) {
> return *((int *)a) - *((int *)b);
> }
>
> void *quicksort_thread( void *arg ) {
> qsort( ((quicksort_arg_t *)arg)->base,
> ((quicksort_arg_t *)arg)->nmemb,
> ((quicksort_arg_t *)arg)->size,
> ((quicksort_arg_t *)arg)->compar );
> return ((quicksort_arg_t *)arg)->base;
> }
>
> void *quicksort( void *base, size_t nmemb, size_t size,
> int(*compar)( const void *, const void * ) ) {
> pthread_t *tids = NULL;
> int partition_index = 0;
> int number_partitions = NUMBER_THREADS;
> quicksort_arg_t qs_arg;
>
> /*
> Set the initial arguments for the first sub list partition sort.
> */
> qs_arg.base = base;
> qs_arg.nmemb = nmemb / number_partitions;
> qs_arg.size = size;
> qs_arg.compar = compar;
>
> if( (tids = malloc( sizeof( pthread_t ) * number_partitions )) ==
> NULL )
> error( EXIT_FAILURE, errno, "%s", strerror( errno ) );
>
> for( partition_index = 0;
> partition_index < number_partitions;
> partition_index++ ) {
>
> qs_arg.base = base + (qs_arg.nmemb * partition_index *
> qs_arg.size);
>
> if( partition_index == (number_partitions - 1) )
> qs_arg.nmemb = nmemb - (partition_index * qs_arg.nmemb);
>
> if( pthread_create( &tids[partition_index], NULL,
> quicksort_thread, &qs_arg ) != 0 ) {
> free( tids );
> error( EXIT_FAILURE, errno, "%s", strerror( errno ) );
> }
> }
>
> for( partition_index = 0;
> partition_index < number_partitions;
> partition_index++ ) {
>
> if( pthread_join( tids[partition_index], NULL ) != 0 ) {
> free( tids );
> error( EXIT_FAILURE, errno, "%s", strerror( errno ) );
> }
> }
>
>
> return NULL;
> }
>
> void test( void ) {
> int array[100];
> int i;
>
> for( i = 0; i < 100; i++ ) {
> array[i] = rand() % 10;
> }
>
> quicksort( array, 100, sizeof( int ), intcmp );
>
> for( i = 0; i < 100; i++ ) {
> if( i % 8 == 0 ) {
> printf( "\n" );
> }
> printf( "%2d", array[i] );
> }
>
> }
>
> int main( void ) {
> test();
>
> return 0;
> }
> _______________________________________________
> PLUG mailing list
> PLUG at lists.pdxlinux.org
> http://lists.pdxlinux.org/mailman/listinfo/plug
>
More information about the PLUG
mailing list