I am working with a program (which I did not write) which has a pointer to a derived type in a module;
integer x, y, z
end type mytype
type (mytype), pointer :: p_mt
end module X [/fortran]
This module is accessed in a subroutine;
p_mt => GoGetOne()
p_mt % x = 7.0
So far, so good. However, subroutine Loop is accessed from with a parallel loop in another subroutine;
!$OMP parallel do
do i = 1 to 10000
It is my understanding that p_mt is global in scope, and therefore should not be accessed from within a parallel loop. If I declare Loop as pure;
[fortran]pure subroutine Loop()[/fortran]
the compiler flags the assignment of a value to p_mt as an error.
Am I missing something? Or is this a potential bug?
>>It is my understanding that p_mt is global in scope, and therefore should not be accessed from within a parallel loop. If I declare Loop as pure;
It should not be modified without the cooperation of the other threads (e.g. with barrier or such).
Trying to interpret your sketch, the corrective measure would be to place a pointer inside your subroutine
type (mytype), pointer :: p_mt_local
p_mt_local => GoGetOne()
p_mt_local % x = 7.0
Your understanding agrees with mine, as does your proposed solution. My problem is that I must first convince the owners of the code that it is broken, before they will agree to a fix. For various reasons, it will not do to fix it unilaterally myself.
The obvious solution is to put in some code to catch a race condition, where one thread modifies the pointer while another is using it. I have tried very hard to do that, without success, which leads me to wonder whether I am overlooking something. For example, perhaps OpenMP is making a private copy of the pointer, as it would do for a parallelized loop variable. It sounds like you are not aware of any such feature.
Are you aware of any document that deals with this case specifically? If not, what documents lead to your conclusion that the pointer is global in scope?
The problem is not technically a race condition.
Rather it is a case of using code that is suitable for single threaded use, yet unsuitable for multi-threaded use. The fact that the code works fine in single threaded mode does not assure the same code is multi-threaded safe. In this case it is not multi-thread safe.
To the owners of the code: Either affect changes to make the code multi-thread safe, or keep to a single thread model.
By the way, the "GoGetOne()" has to be thread safe as well.
>>perhaps OpenMP is making a private copy of the pointer
Not possible in your original sketch code. You call a subroutine that USEs the module p_mt.
You could make the pointer threadprivate, however, this will not fix GoGetOne, nor will it fix other potential issues. An example is the subroutine Loop is a search and you wish to terminate the search with p_mp => the first found item.
This should have been posted in open forum so others can learn from the discussion.