Commit 3a41480a authored by Joachim Jenke's avatar Joachim Jenke
Browse files

[OpenMP][Archer][TSan] Use TSan fibers to implement task-centric analysis for OpenMP tasks

Current thread-level analysis can hide a lot of data races in OpenMP tasking codes,
when tasks are randomly scheduled to the same thread, but even worse when unrelated
task dependencies introduce random synchronization between different threads.

This patch introduces a new analysis mode for Archer activated at runtime by
exporting ARCHER_OPTION=tasking=1, where OpenMP tasks are explicitly mapped to
TSan fibers.

Under review as #74646
parent 672d544b
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -339,12 +339,16 @@ void FiberSwitchImpl(ThreadState *from, ThreadState *to) {

ThreadState *FiberCreate(ThreadState *thr, uptr pc, unsigned flags) {
  void *mem = Alloc(sizeof(ThreadState));
  if ((flags & FiberSwitchFlagNoSync))
    thr->ignore_sync++;
  ThreadState *fiber = static_cast<ThreadState *>(mem);
  internal_memset(fiber, 0, sizeof(*fiber));
  Tid tid = ThreadCreate(thr, pc, 0, true);
  FiberSwitchImpl(thr, fiber);
  ThreadStart(fiber, tid, 0, ThreadType::Fiber);
  FiberSwitchImpl(fiber, thr);
  if ((flags & FiberSwitchFlagNoSync))
    thr->ignore_sync--;
  return fiber;
}

@@ -357,6 +361,8 @@ void FiberDestroy(ThreadState *thr, uptr pc, ThreadState *fiber) {

void FiberSwitch(ThreadState *thr, uptr pc,
                 ThreadState *fiber, unsigned flags) {
  if (thr == fiber)
    return;
  if (!(flags & FiberSwitchFlagNoSync))
    Release(thr, pc, (uptr)fiber);
  FiberSwitchImpl(thr, fiber);
+21 −13
Original line number Diff line number Diff line
@@ -463,6 +463,7 @@ int __ompt_get_task_info_internal(int ancestor_level, int *type,
}

int __ompt_get_task_memory_internal(void **addr, size_t *size, int blocknum) {
  *size = 0;
  if (blocknum != 0)
    return 0; // support only a single block

@@ -476,7 +477,14 @@ int __ompt_get_task_memory_internal(void **addr, size_t *size, int blocknum) {
  if (taskdata->td_flags.tasktype != TASK_EXPLICIT)
    return 0; // support only explicit task

  void *ret_addr;
  if (taskdata->td_size_alloc < 0)
    return 0;

  *addr = taskdata;
  *size = taskdata->td_size_alloc;
  return 0;

  /*  void *ret_addr;
    int64_t ret_size = taskdata->td_size_alloc - sizeof(kmp_taskdata_t);

    // kmp_task_t->data1 is an optional member
@@ -491,7 +499,7 @@ int __ompt_get_task_memory_internal(void **addr, size_t *size, int blocknum) {

    *addr = ret_addr;
    *size = (size_t)ret_size;
  return 1;
    return 1;*/
}

//----------------------------------------------------------
+254 −94

File changed.

Preview size limit exceeded, changes collapsed.

+45 −0
Original line number Diff line number Diff line
/*
 * DRB027b-taskdependmissing-orig-yes.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 && env ARCHER_OPTIONS=tasking=1 %libarcher-run-race | FileCheck %s
// RUN: %libarcher-compile && env ARCHER_OPTIONS=tasking=1:ignore_serial=1 %libarcher-run-race | FileCheck %s
// REQUIRES: tsan
#include "ompt/ompt-signal.h"
#include <assert.h>
#include <stdio.h>

int main() {
  int i = 0, sem = 0;
#pragma omp parallel shared(sem) num_threads(2)
  {
#pragma omp masked
    {
#pragma omp task
      {
        OMPT_SIGNAL(sem);
        i = 1;
      }
#pragma omp task
      {
        OMPT_SIGNAL(sem);
        i = 2;
      }
#pragma omp taskwait {}
    }
    OMPT_WAIT(sem, 2);
  }
  printf("i=%d\n", i);
  return 0;
}

// CHECK: WARNING: ThreadSanitizer: data race
// CHECK: ThreadSanitizer: reported {{[0-9]+}} warnings
+58 −0

File added.

Preview size limit exceeded, changes collapsed.

Loading