Index: openmp/tools/archer/ompt-tsan.cpp =================================================================== --- openmp/tools/archer/ompt-tsan.cpp +++ openmp/tools/archer/ompt-tsan.cpp @@ -192,6 +192,8 @@ /// Required OMPT inquiry functions. static ompt_get_parallel_info_t ompt_get_parallel_info; static ompt_get_thread_data_t ompt_get_thread_data; +typedef int (*ompt_get_task_memory_t)(void **addr, size_t *size, int blocknum); +static ompt_get_task_memory_t ompt_get_task_memory; typedef char ompt_tsan_clockid; @@ -201,11 +203,11 @@ return ret; } +namespace { static int pagesize{0}; // Data structure to provide a threadsafe pool of reusable objects. // DataPool -namespace { template struct DataPool final { static __thread DataPool *ThreadDataPool; std::mutex DPMutex{}; @@ -471,7 +473,7 @@ /// Whether this task is an included task. int TaskType{0}; - /// count execution phase + /// Count execution phase int execution{0}; /// Count how often this structure has been put into child tasks + 1. @@ -480,6 +482,10 @@ /// Reference to the parent that created this task. TaskData *Parent{nullptr}; + /// Store private data from start to end + size_t PrivateDataSize{0}; + void *PrivateDataAddr{nullptr}; + /// Reference to the team of this task. ParallelData *Team{nullptr}; @@ -567,6 +573,8 @@ free(Dependencies); Dependencies = nullptr; DependencyCount = 0; + PrivateDataSize = 0; + PrivateDataAddr = nullptr; #ifdef DEBUG freed = 0; #endif @@ -960,6 +968,8 @@ static void endTask(TaskData *FromTask) { if (!FromTask) return; + if (FromTask->PrivateDataSize > 0) + TsanNewMemory(FromTask->PrivateDataAddr, FromTask->PrivateDataSize); } static void startTask(TaskData *ToTask) { @@ -968,6 +978,20 @@ // Handle dependencies on first execution of the task if (ToTask->execution == 0) { ToTask->execution++; + if (ompt_get_task_memory) { + void *addr; + size_t size; + int ret_task_memory = 0, block = 0; + do { + size = 0; + ret_task_memory = ompt_get_task_memory(&addr, &size, block++); + if (size > 0) { + TsanNewMemory(addr, size); + ToTask->PrivateDataAddr = addr; + ToTask->PrivateDataSize = size; + } + } while (ret_task_memory); + } acquireDependencies(ToTask); } // 1. Task will begin execution after it has been created. @@ -1162,6 +1186,7 @@ ompt_get_parallel_info = (ompt_get_parallel_info_t)lookup("ompt_get_parallel_info"); ompt_get_thread_data = (ompt_get_thread_data_t)lookup("ompt_get_thread_data"); + ompt_get_task_memory = (ompt_get_task_memory_t)lookup("ompt_get_task_memory"); if (ompt_get_parallel_info == NULL) { fprintf(stderr, "Could not get inquiry function 'ompt_get_parallel_info', " Index: openmp/tools/archer/tests/task/reuse-task-storage.c =================================================================== --- /dev/null +++ openmp/tools/archer/tests/task/reuse-task-storage.c @@ -0,0 +1,51 @@ +/* + * reuse-task-storage.c -- Archer testcase + */ + +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// +// See tools/archer/LICENSE.txt for details. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + + +// RUN: %libarcher-compile-and-run | FileCheck %s +// REQUIRES: tsan +#include +#include +#include +#include "ompt/ompt-signal.h" + +int main(int argc, char *argv[]) { + int var = 0, a = 0; + +#pragma omp parallel num_threads(8) shared(var, a) + { +#pragma omp master + for(int i=0; i<10; i++) + { + for(int j=0; j<100; j++) +#pragma omp task shared(var) + { + OMPT_SIGNAL(a); + #pragma omp atomic update + var++; + } + + // Give other threads time to steal the task. + OMPT_WAIT(a, (i*100)); + } + + } + + fprintf(stderr, "DONE\n"); + int error = (var != 1000); + return error; +} + +// CHECK-NOT: ThreadSanitizer: data race +// CHECK-NOT: ThreadSanitizer: reported +// CHECK: DONE