JavaScript is required to for searching.
Skip Navigation Links
Exit Print View
Oracle Solaris Studio 12.3: Thread Analyzer User's Guide     Oracle Solaris Studio 12.3 Information Library
search filter icon
search icon

Document Information

Preface

1.  What is the Thread Analyzer and What Does It Do?

2.  The Data Race Tutorial

2.1 Data Race Tutorial Source Files

2.1.1 Getting the Data Race Tutorial Source Files

2.1.2 Source Code for prime_omp.c

2.1.3 Source Code for prime_pthr.c

2.1.3.1 Effect of Data Races in prime_omp.c and prime_pthr.c

2.2 How to Use the Thread Analyzer to Find Data Races

2.2.1 Instrument the Code

2.2.1.1 To Instrument Source Code

2.2.1.2 To Instrument Binary Code

2.2.2 Create a Data Race Detection Experiment

2.2.3 Examine the Data Race Detection Experiment

2.2.3.1 Using Thread Analyzer to View the Data Race Experiment

2.2.3.2 Using er_print to View the Data Race Experiment

2.3 Understanding the Experiment Results

2.3.1 Data Races in prime_omp.c

2.3.2 Data Races in prime_pthr.c

2.3.3 Call Stack Traces of Data Races

2.4 Diagnosing the Cause of a Data Race

2.4.1 Check Whether or Not the Data Race is a False Positive

2.4.2 Check Whether or Not the Data Race is Benign

2.4.3 Fix the Bug, Not the Data Race

2.4.3.1 Fixing Bugs in prime_omp.c

2.4.3.2 Fixing Bugs in prime_pthr.c

2.5 False Positives

2.5.1 User-Defined Synchronizations

2.5.2 Memory That is Recycled by Different Threads

2.6 Benign Data Races

2.6.1 A Program for Finding Primes

2.6.2 A Program that Verifies Array-Value Types

2.6.3 A Program Using Double-Checked Locking

3.  The Deadlock Tutorial

A.  APIs Recognized by the Thread Analyzer

B.  Useful Tips

2.1 Data Race Tutorial Source Files

This tutorial relies on two programs, both of which contain data races:

2.1.1 Getting the Data Race Tutorial Source Files

You can download the source files used in this tutorial from the samples download area of the Oracle Solaris Studio developer portal.

After you download and unpack the sample files, you can find the samples in the SolarisStudioSampleApplications/ThreadAnalyzer directory. The samples are located in the prime_omp and prime_pthr subdirectories. Each sample directory includes a Makefile and a DEMO file of instructions, but this tutorial does not follow those instructions or use the Makefile. Instead, you are instructed to execute commands individually.

To follow the tutorial, you can copy the prime_omp.c and prime_pthr.c files from the samples directories to a different directory, or you can create your own files and copy the code from the following code listings.

2.1.2 Source Code for prime_omp.c

The source code for prime_omp.c is shown below:

  1  /*
  2   * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All Rights Reserved.
  3   * @(#)prime_omp.c 1.3 (Oracle) 10/03/26
  4   */
  5
  6  #include <stdio.h>
  7  #include <math.h>
  8  #include <omp.h>
  9
 10  #define THREADS 4
 11  #define N 10000
 12
 13  int primes[N];
 14  int pflag[N];
 15
 16  int is_prime(int v)
 17  {
 18   int i;
 19   int bound = floor(sqrt(v)) + 1;
 20
 21   for (i = 2; i < bound; i++) {
 22          /* no need to check against known composites */
 23          if (!pflag[i])
 24              continue;
 25          if (v % i == 0) {
 26              pflag[v] = 0;
 27              return 0;
 28          }
 29      }
 30      return (v > 1);
 31  }
 32
 33  int main(int argn, char **argv)
 34  {
 35      int i;
 36      int total = 0;
 37
 38  #ifdef _OPENMP
 39      omp_set_dynamic(0);
 40      omp_set_num_threads(THREADS);
 41  #endif
 42
 43      for (i = 0; i < N; i++) {
 44          pflag[i] = 1;
 45      }
 46
 47      #pragma omp parallel for
 48      for (i = 2; i < N; i++) {
 49          if ( is_prime(i) ) {
 50              primes[total] = i;
 51              total++;
 52          }
 53      }
 54
 55      printf("Number of prime numbers between 2 and %d: %d\n",
 56             N, total);
 57
 58      return 0;
 59  }

2.1.3 Source Code for prime_pthr.c

The source code for prime_pthr.c is shown below:

  1  /*
  2   * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All Rights Reserved.
  3   * @(#)prime_pthr.c 1.4 (Oracle) 10/03/26
  4   */
  5
  6  #include <stdio.h>
  7  #include <math.h>
  8  #include <pthread.h>
  9
 10  #define THREADS 4
 11  #define N 10000
 12
 13  int primes[N];
 14  int pflag[N];
 15  int total = 0;
 16
 17  int is_prime(int v)
 18  {
 19      int i;
 20      int bound = floor(sqrt(v)) + 1;
 21
 22      for (i = 2; i < bound; i++) {
 23          /* no need to check against known composites */
 24          if (!pflag[i])
 25              continue;
 26          if (v % i == 0) {
 27              pflag[v] = 0;
 28              return 0;
 29          }
 30      }
 31      return (v > 1);
 32  }
 33
 34  void *work(void *arg)
 35  {
 36      int start;
 37      int end;
 38      int i;
 39
 40      start = (N/THREADS) * (*(int *)arg);
 41      end = start + N/THREADS;
 42      for (i = start; i < end; i++) {
 43          if ( is_prime(i) ) {
 44              primes[total] = i;
 45              total++;
 46          }
 47      }
 48      return NULL;
 49  }
 50
 51  int main(int argn, char **argv)
 52  {
 53      int i;
 54      pthread_t tids[THREADS-1];
 55
 56      for (i = 0; i < N; i++) {
 57          pflag[i] = 1;
 58      }
 59
 60      for (i = 0; i < THREADS-1; i++) {
 61          pthread_create(&tids[i], NULL, work, (void *)&i);
 62      }
 63
 64      i = THREADS-1;
 65      work((void *)&i);
 66
 67      for (i = 0; i < THREADS-1; i++) {
 68          pthread_join(tids[i], NULL);
 69      }
 70
 71      printf("Number of prime numbers between 2 and %d: %d\n",
 72             N, total);
 73
 74      return 0;
 75  }

2.1.3.1 Effect of Data Races in prime_omp.c and prime_pthr.c

The order of memory accesses is non-deterministic when code contains a race condition and the computation gives different results from run to run. The correct answer in the prime_omp and prime_pthr programs is 1229.

You can compile and run the examples so you can see that each execution of prime_omp or prime_pthr produces incorrect and inconsistent results because of the data races in the code.

In the following example, type the commands in bold to compile and run the prime_omp program:

% cc -xopenmp=noopt -o prime_omp prime_omp.c -lm
%
% ./prime_omp
Number of prime numbers between 2 and 10000: 1229
% ./prime_omp
Number of prime numbers between 2 and 10000: 1228
% ./prime_omp
Number of prime numbers between 2 and 10000: 1180

In the following example, type the commands in bold to compile and run the prime_pthr program:

% cc -mt -o prime_pthr prime_pthr.c -lm
%
% ./prime_pthr
Number of prime numbers between 2 and 10000: 1140
% ./prime_pthr
Number of prime numbers between 2 and 10000: 1122
% ./prime_pthr
Number of prime numbers between 2 and 10000: 1141

Notice the inconsistency of the results of the three runs of each program. You may need to run the programs more than three times to see inconsistent results.

Next you instrument the code and create experiments so you can find where the data races are occurring.