主要内容

MISRA C:2012 Rule 22.20

Thread-specific storage pointers shall be created before being accessed

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

Thread-specific storage pointers shall be created before being accessed.1

Rationale

The C standard does not define order of thread execution. If your code defines thread-specific storage pointers within threads, then the states of the pointers are dependent on thread execution order. Determining the validity of the pointer state in such a case is difficult.

Create thread-specific storage by calling tss_create() before they are accessed in threads. This pattern allows checking the validity of the thread-specific storage pointers in a deterministic way.

Polyspace Implementation

Polyspace reports a violation of this rule if either of these conditions is true:

  • A tss_t object is used in the code but it is not explicitly created using tss_create().

  • Multiple functions call the function tss_create(). Polyspace expects either main() or another unique function to call tss_create().

  • The main() function calls tss_create() after the threads are created.

  • The unique thread-specific storage creation function is called by main() after the threads are created.

Extend Checker

By default, Polyspace looks for the unique functions that create the thread-specific storage and the threads. In a Datalog file, you can specify either or both:

  • The unique thread-specific storage creation function.

  • The unique thread-creation function.

For example, this Datalog code designates tss_create_caller() as the function that calls tss_create() and thrd_maker() as the function that creates the threads. Then, it instructs Polyspace to report a violation when the function thrd_maker() is called before the function tss_create(). The function names are specified without the trailing parentheses.

Concurrency.Basic.is_unique_function_using_tss_create("tss_create_caller").
Concurrency.Basic.is_unique_function_starting_threads("thrd_maker").
Concurrency.Basic.raise_if_thread_start_before_tss_create().
Save this code as a Datalog (.dl) file and use it as an input to the option -code-behavior-specifications. For more details about modifying checker behavior using Datalog, see Modify Bug Finder Checkers Through Code Behavior Specifications.

Troubleshooting

If you expect a rule violation but do not see it, refer to Diagnose Why Coding Standard Violations Do Not Appear as Expected.

Examples

expand all

In this code, the thread-specific storage object SecondKey is consumed in the function nonCompliantFunction(), but this object is not explicitly created by using tss_create(). Polyspace reports a violation. In the function tss_init(), the threads-specific storage object FirstKey is explicitly created before it is assigned to FirstThread. This pattern is compliant with the rule.

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

tss_t FirstKey;
tss_t SecondKey;  //Noncompliant

thrd_t FirstThread;
thrd_t SecondThread;

void nonCompliantFunction() {
    // Missing tss_create() call
    int *value = (int *)tss_get(SecondKey); 
}

void CompliantFunction() {

    int *value = (int *)tss_get(FirstKey);

    tss_delete(FirstKey);
}

int tss_init(){
    if (tss_create(&FirstKey, free) != thrd_success) { 
        return 1;
    }
    
    thrd_create(&FirstThread, CompliantFunction, NULL);
    return 0;
}

int main() {
    if (tss_init() != 0) {
        return 1;
    }

    nonCompliantFunction();
    CompliantFunction();

    return 0;
}

In this code, the function Func() creates the tss_t object. Because both main() and Func() call tss_create() to create a tss_t object, Polyspace reports a violation.

#include <stdio.h>
#include <stdlib.h>
#include <threads.h>
void Func(void);
void Func2(void);

tss_t FirstKey;
tss_t SecondKey;  

thrd_t FirstThread;
thrd_t SecondThread;

void Func() {
   if (tss_create(&SecondKey, free) != thrd_success) {  //Noncompliant 
        // handle error
    }
    
    thrd_create(&SecondThread, Func2, NULL);  
}

int main() {
    if (tss_create(&FirstKey, free) != thrd_success) { 
        // handle error
    }
    
    thrd_create(&FirstThread, Func, NULL);    

    return 0;
}

In this code, the thread creation function is called before calling the function that creates the tss_t objects.

Extend the checker by creating a Datalog file behavior.dl with the following code that specifies the function tssCreate() as the function that creates the thread-specific storage and createThreads() as the function that creates the threads:

.include "models/interfaces/concurrency.dl"
Concurrency.Basic.is_unique_function_using_tss_create("tssCreate").
Concurrency.Basic.is_unique_function_starting_threads("createThreads").
Concurrency.Basic.raise_if_thread_start_before_tss_create().
Specify the Datalog file as an input to the option -code-behavior-specifications as:
-code-behavior-specification behavior.dl
Polyspace reports a violation when the thread-specific storage creation function is invoked after the thread creation function in main().

#include <stdio.h>
#include <stdlib.h>
#include <threads.h>
    void Func(void);
void Func2(void);

tss_t FirstKey;
tss_t SecondKey;
int val1;
int val2;

thrd_t FirstThread;
thrd_t SecondThread;

void createThreads(void) {
	thrd_create(&FirstThread, Func, NULL);
	thrd_create(&SecondThread, Func, NULL);
}

void tssCreate(void) {
	if(tss_create(&FirstKey, free) != thrd_success) {
		// handle error
	}
	if(tss_create(&SecondKey, free) != thrd_success) {
		// handle error
	}
}

int main() {

	createThreads();
	tssCreate(); //Noncompliant
	return 0;
}

In this code, the function tssCreate() creates all thread-specific storage. The main() function invokes tssCreate() before the creation of any threads.

To designate tssCreate() as the function that creates all thread specific storage, copy this content in a Datalog file behavior.dl: and use it as an input to -code-behavior-specifications.

Specify the Datalog file as an input to the option -code-behavior-specifications as:

-code-behavior-specification behavior.dl
When the function bar() also calls tss_create(), Polyspace reports a violation.

#include <stdio.h>
#include <stdlib.h>
#include <threads.h>
void Func(void);
void Func2(void);


tss_t FirstKey;
tss_t SecondKey;
tss_t ThirdKey;
int val1;
int val2;

thrd_t     FirstThread;
thrd_t     SecondThread;

void createThreads(void) {
	thrd_create(&FirstThread, Func, NULL);
	thrd_create(&SecondThread, Func, NULL);
}

void tssCreate(void) {
	if(tss_create(&FirstKey, free) != thrd_success) { //Compliant
		// handle error
	}
	if(tss_create(&SecondKey, free) != thrd_success) { //Compliant
		// handle error
	}
}

void bar(void){
    if(tss_create(&ThirdKey, free) != thrd_success) { //Noncompliant
		// handle error
	}
    
}

int main() {
	tssCreate();
	createThreads();

	return 0;
}

Check Information

Group: Resources
Category: Mandatory
AGC Category: Mandatory

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.