brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.0 KiB · 9ae751a Raw
150 lines · cpp
1//===-- lib/runtime/work-queue.cpp ------------------------------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "flang-rt/runtime/work-queue.h"10#include "flang-rt/runtime/environment.h"11#include "flang-rt/runtime/memory.h"12#include "flang-rt/runtime/type-info.h"13#include "flang/Common/visit.h"14 15namespace Fortran::runtime {16 17#if !defined(RT_DEVICE_COMPILATION) && !defined(OMP_OFFLOAD_BUILD)18// FLANG_RT_DEBUG code is disabled when false.19static constexpr bool enableDebugOutput{false};20#endif21 22RT_OFFLOAD_API_GROUP_BEGIN23 24RT_API_ATTRS int Ticket::Continue(WorkQueue &workQueue) {25  if (!begun) {26    begun = true;27    return common::visit(28        [&workQueue](29            auto &specificTicket) { return specificTicket.Begin(workQueue); },30        u);31  } else {32    return common::visit(33        [&workQueue](auto &specificTicket) {34          return specificTicket.Continue(workQueue);35        },36        u);37  }38}39 40RT_API_ATTRS WorkQueue::~WorkQueue() {41  if (anyDynamicAllocation_) {42    if (last_) {43      if ((last_->next = firstFree_)) {44        last_->next->previous = last_;45      }46      firstFree_ = first_;47      first_ = last_ = nullptr;48    }49    while (firstFree_) {50      TicketList *next{firstFree_->next};51      if (!firstFree_->isStatic) {52        FreeMemory(firstFree_);53      }54      firstFree_ = next;55    }56  }57}58 59RT_API_ATTRS Ticket &WorkQueue::StartTicket() {60  if (!firstFree_) {61    void *p{AllocateMemoryOrCrash(terminator_, sizeof(TicketList))};62    firstFree_ = new (p) TicketList;63    firstFree_->isStatic = false;64    anyDynamicAllocation_ = true;65  }66  TicketList *newTicket{firstFree_};67  if ((firstFree_ = newTicket->next)) {68    firstFree_->previous = nullptr;69  }70  TicketList *after{insertAfter_ ? insertAfter_->next : nullptr};71  if ((newTicket->previous = insertAfter_ ? insertAfter_ : last_)) {72    newTicket->previous->next = newTicket;73  } else {74    first_ = newTicket;75  }76  if ((newTicket->next = after)) {77    after->previous = newTicket;78  } else {79    last_ = newTicket;80  }81  newTicket->ticket.begun = false;82#if !defined(RT_DEVICE_COMPILATION) && !defined(OMP_OFFLOAD_BUILD)83  if (enableDebugOutput &&84      (executionEnvironment.internalDebugging &85          ExecutionEnvironment::WorkQueue)) {86    std::fprintf(stderr, "WQ: new ticket\n");87  }88#endif89  return newTicket->ticket;90}91 92RT_API_ATTRS int WorkQueue::Run() {93  while (last_) {94    TicketList *at{last_};95    insertAfter_ = last_;96#if !defined(RT_DEVICE_COMPILATION) && !defined(OMP_OFFLOAD_BUILD)97    if (enableDebugOutput &&98        (executionEnvironment.internalDebugging &99            ExecutionEnvironment::WorkQueue)) {100      std::fprintf(stderr, "WQ: %zd %s\n", at->ticket.u.index(),101          at->ticket.begun ? "Continue" : "Begin");102    }103#endif104    int stat{at->ticket.Continue(*this)};105#if !defined(RT_DEVICE_COMPILATION) && !defined(OMP_OFFLOAD_BUILD)106    if (enableDebugOutput &&107        (executionEnvironment.internalDebugging &108            ExecutionEnvironment::WorkQueue)) {109      std::fprintf(stderr, "WQ: ... stat %d\n", stat);110    }111#endif112    insertAfter_ = nullptr;113    if (stat == StatOk) {114      if (at->previous) {115        at->previous->next = at->next;116      } else {117        first_ = at->next;118      }119      if (at->next) {120        at->next->previous = at->previous;121      } else {122        last_ = at->previous;123      }124      if ((at->next = firstFree_)) {125        at->next->previous = at;126      }127      at->previous = nullptr;128      firstFree_ = at;129    } else if (stat != StatContinue) {130      Stop();131      return stat;132    }133  }134  return StatOk;135}136 137RT_API_ATTRS void WorkQueue::Stop() {138  if (last_) {139    if ((last_->next = firstFree_)) {140      last_->next->previous = last_;141    }142    firstFree_ = first_;143    first_ = last_ = nullptr;144  }145}146 147RT_OFFLOAD_API_GROUP_END148 149} // namespace Fortran::runtime150