Main Content

MISRA C:2012 Dir 5.3

There shall be no dynamic thread creation

Since R2025b

Description

This checker is deactivated in a default Polyspace® as You Code analysis. See Checkers Deactivated in Polyspace as You Code Analysis (Polyspace Access).

Rule Definition

There shall be no dynamic thread creation.1

Rationale

Dynamic thread creation results in uncertainty about the number of threads running at a specific point in your code. This uncertainty makes the code error-prone and makes the code more difficult to maintain and debug. Instead of creating threads dynamically, use static thread pools instead.

Polyspace Implementation

Polyspace reports violations of this rule if any of these conditions are true:

  • Thread creation functions such as thrd_create() or pthread_create() are called outside main() or a designated startup function.

  • Thread creation functions are called in a loop that is not bounded by a constant.

This Datalog code specifies foo() as the startup function that creates the threads in your code:

.include "pql/checkers/thrd_create_unsafe.dl"
ThrdCreateUnsafe.is_unique_function_thrd_create("foo").
If your code contains more than one designated startup function or if your code creates threads in both main() and the startup function, Polyspace reports a violation.

For more information about using Datalog to modify Bug Finder checkers, see Datalog Format.

Troubleshooting

If you expect a rule violation but Polyspace does not report it, see Diagnose Why Coding Standard Violations Do Not Appear as Expected.

Examples

expand all

This code creates threads depending on the number of cores in the system. The call to pthread_create() is in a loop that is bounded by a variable. Polyspace reports a violation.

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>

#define ARRAY_SIZE 16

typedef struct {
    int *array;
    int start;
    int end;
    int sum;
} ThreadData;

void* sum_array(void* arg) {
    ThreadData* data = (ThreadData*)arg;
    data->sum = 0;
    for (int i = data->start; i < data->end; i++) {
        data->sum += data->array[i];
    }
    return NULL;
}

int main() {
    int array[ARRAY_SIZE];
    for (int i = 0; i < ARRAY_SIZE; i++) {
        array[i] = i + 1;
    }

    // Determine the number of threads based on the number of CPU cores
    int num_threads = sysconf(_SC_NPROCESSORS_ONLN);
    if (num_threads <= 0) {
        fprintf(stderr, "Error determining the number of CPU cores.\n");
        return 1;
    }

    pthread_t *threads = malloc(num_threads * sizeof(pthread_t));
    ThreadData *thread_data = malloc(num_threads * sizeof(ThreadData));
    int segment_size = ARRAY_SIZE / num_threads;

    for (int i = 0; i < num_threads; i++) {
        thread_data[i].array = array;
        thread_data[i].start = i * segment_size;
        thread_data[i].end = (i == num_threads - 1) ? ARRAY_SIZE : (i + 1) * segment_size;
        pthread_create(&threads[i], NULL, sum_array, &thread_data[i]);  //Noncompliant
    }

    int total_sum = 0;
    for (int i = 0; i < num_threads; i++) {
        pthread_join(threads[i], NULL);
        total_sum += thread_data[i].sum;
    }

    printf("Total sum: %d\n", total_sum);

    free(threads);
    free(thread_data);
    return 0;
}

Correction

To fix this issue, use a constant bound for the loop where the thread creation function is called.

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

// Defined constant bound for thread creation loop
#define NUM_THREADS 4
#define ARRAY_SIZE 16

typedef struct {
    int *array;
    int start;
    int end;
    int sum;
} ThreadData;

void* sum_array(void* arg) {
    ThreadData* data = (ThreadData*)arg;
    data->sum = 0;
    for (int i = data->start; i < data->end; i++) {
        data->sum += data->array[i];
    }
    return NULL;
}

int main() {
    int array[ARRAY_SIZE];
    for (int i = 0; i < ARRAY_SIZE; i++) {
        array[i] = i + 1;
    }

    pthread_t threads[NUM_THREADS];
    ThreadData thread_data[NUM_THREADS];
    int segment_size = ARRAY_SIZE / NUM_THREADS;

    for (int i = 0; i < NUM_THREADS; i++) {
        thread_data[i].array = array;
        thread_data[i].start = i * segment_size;
        thread_data[i].end = (i + 1) * segment_size;
        pthread_create(&threads[i], NULL, sum_array, &thread_data[i]); //Compliant
    }

    int total_sum = 0;
    for (int i = 0; i < NUM_THREADS; i++) {
        pthread_join(threads[i], NULL);
        total_sum += thread_data[i].sum;
    }

    printf("Total sum: %d\n", total_sum);
    return 0;
}

Check Information

Group: Concurrency considerations
Category: Required
AGC Category: Required

Version History

Introduced in R2025b


1 All MISRA coding rules and directives are © Copyright The MISRA Consortium Limited 2021.

The MISRA coding standards referenced in the Polyspace Bug Finder™ documentation are from the following MISRA standards:

  • MISRA C:2004

  • MISRA C:2012

  • MISRA C:2023

  • MISRA C++:2008

  • MISRA C++:2023

MISRA and MISRA C are registered trademarks of The MISRA Consortium Limited 2021.