Main Content

Shared variable

Global variables shared between multiple tasks and protected from concurrent access by the tasks

Description

A shared protected global variable has the following properties:

  • The variable is used in more than one task.

  • All operations on the variable are protected from interruption through critical sections or temporal exclusion. The calls to functions beginning and ending a critical section must be reachable.

In code that is not intended for multitasking, all global variables are non-shared.

In your verification results, these variables are colored green on the Source, Results List and Variable Access panes. On the Source pane, the coloring is applied to the variable only during declaration.

Examples

expand all

#include <limits.h>
int shared_var;

void inc() {
    shared_var+=2;
}

void reset() {
    shared_var = 0;
}

void task() {
    volatile int randomValue = 0;
    while(randomValue) {
        reset();
        inc();
        inc();
    }
}

void interrupt() {
    shared_var = INT_MAX;
}

void interrupt_handler() {
    volatile int randomValue = 0;
    while(randomValue) {
        interrupt();
    }
}

void main() {
}

In this example, shared_var is a protected shared variable if you specify the following multitasking options:

OptionValue
Configure multitasking manually
Tasks

task

interrupt_handler

Temporally exclusive taskstask interrupt_handler

On the command-line, you can use the following:

 polyspace-code-prover
   -entry-points task,interrupt_handler
   -temporal-exclusions-file "C:\exclusions_file.txt"
where the file C:\exclusions_file.txt has the following line:
task interrupt_handler

The variable is shared between task and interrupt_handler. However, because task and interrupt_handler are temporally exclusive, operations on the variable cannot interrupt each other.

#include <limits.h>
int shared_var;

void inc() {
    shared_var+=2;
}

void reset() {
    shared_var = 0;
}

void take_semaphore(void);
void give_semaphore(void);

void task() {
    volatile int randomValue = 0;
    while(randomValue) {
        take_semaphore();
        reset();
        inc();
        inc();
        give_semaphore();
    }
}

void interrupt() {
    shared_var = INT_MAX;
}

void interrupt_handler() {
    volatile int randomValue = 0;
    while(randomValue) {
        take_semaphore();
        interrupt();
        give_semaphore();
    }
}

void main() {
}

In this example, shared_var is a protected shared variable if you specify the following:

OptionValue
Configure multitasking manually
Tasks

task

interrupt_handler

Critical section detailsStarting routineEnding routine
take_semaphoregive_semaphore

On the command-line, you can use the following:

 polyspace-code-prover 
   -entry-points task,interrupt_handler
   -critical-section-begin take_semaphore:cs1
   -critical-section-end give_semaphore:cs1

The variable is shared between task and interrupt_handler. However, because operations on the variable are between calls to the starting and ending procedure of the same critical section, they cannot interrupt each other.

struct S {
    unsigned int var_1;
    unsigned int var_2;
};

volatile int randomVal;

struct S sharedStruct;

void task1(void) {
    while(randomVal)
    	operation1();
}

void task2(void) {
    while(randomVal)
	    operation2();
}

void operation1(void) {
        sharedStruct.var_1++;
}

void operation2(void) {
        sharedStruct.var_2++;
}

int main(void) {
    return 0;
}

In this example, sharedStruct is a protected shared variable if you specify the following:

On the command-line, you can use the following:

 polyspace-code-prover 
    -entry-points task1,task2

The software determines that sharedStruct is protected because:

  • task1 operates only on sharedStruct.var_1.

  • task2 operates only on sharedStruct.var_2.

If you select the result, the Result Details pane indicates that the access pattern protects all operations on the variable. On the Variable Access pane, the row for variable sharedStruct lists Access pattern as the protection type.

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

pthread_mutex_t lock;
pthread_t id1, id2; 

int var; 

void * t1(void* b) { 
    pthread_mutex_lock(&lock); 
    var++; 
    pthread_mutex_unlock(&lock); 
} 

void * t2(void* a) { 
    pthread_mutex_lock(&lock); 
    var = 1; 
    pthread_mutex_unlock(&lock); 
} 

int main(void) { 
    pthread_create(&id1, NULL, t1, NULL); 
    pthread_create(&id2, NULL, t2, NULL); 

    return 0; 
}

var is a shared, protected variable if you specify the following options:

On the command-line, you can use the following:

 polyspace-code-prover
    -enable-concurrency-detection

In this example, if you specify the concurrency detection option, Polyspace® Code Prover™ detects that your program uses multitasking. Two task, lock and var, share two variables. lock is a pthread mutex variable, which pthread_mutex_lock and pthread_mutex_unlock use to lock and unlock their mutexes. The inherent pthread design patterns protect lock. The Results Details pane and Variable Access pane list Design Pattern as the protection type.

The mutex locking and unlocking mechanisms protect var, the other shared variable. The Results Details pane and Variable Access pane list Mutex as the protection type.

Code Prover does not detect shared memory regions that do not have a name. Unnamed memory regions can be created by assigning absolute addresses to pointers or dynamically allocating memory. There is no named variable that represents these regions.

For instance, in this example, ptr points to dynamically allocated memory.

#include <stdlib.h>

int* ptr;

void flip() {
   *ptr = 0;
}

void flop() {
   if (*ptr == 0) {
      *ptr = 1;
  }
}
void main() {
   ptr = (int*) malloc(sizeof(int));
}
Even if you specify that the functions flip() and flop() act as entry points to your application, Code Prover does not show that the memory region pointed to by ptr (or *ptr) can be concurrently accessed.

Check Information

Language: C | C++