DPC++ Runtime
Runtime libraries for oneAPI DPC++
config.cpp
Go to the documentation of this file.
1 //==---------------- config.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-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include <detail/config.hpp>
10 #include <sycl/detail/common.hpp>
13 #include <sycl/detail/os_util.hpp>
14 
15 #include <cstring>
16 #include <fstream>
17 #include <limits>
18 
19 namespace sycl {
20 inline namespace _V1 {
21 namespace detail {
22 
23 #ifndef SYCL_CONFIG_FILE_NAME
24 #define SYCL_CONFIG_FILE_NAME "sycl.conf"
25 #endif // SYCL_CONFIG_FILE_NAME
26 
27 // Stringify an argument to pass it in _Pragma directive below.
28 #ifndef __SYCL_STRINGIFY
29 #define __SYCL_STRINGIFY(x) #x
30 #endif // __SYCL_STRINGIFY
31 
32 #define CONFIG(Name, MaxSize, CompileTimeDef) \
33  const char *SYCLConfigBase<Name>::MValueFromFile = nullptr; \
34  char SYCLConfigBase<Name>::MStorage[MaxSize + 1]; \
35  const char *const SYCLConfigBase<Name>::MCompileTimeDef = \
36  getStrOrNullptr(__SYCL_STRINGIFY(CompileTimeDef)); \
37  const char *const SYCLConfigBase<Name>::MConfigName = __SYCL_STRINGIFY(Name);
38 #include "detail/config.def"
39 #undef CONFIG
40 
41 static void initValue(const char *Key, const char *Value) {
42 #define CONFIG(Name, MaxSize, CompileTimeDef) \
43  if (0 == strncmp(Key, SYCLConfigBase<Name>::MConfigName, MAX_CONFIG_NAME)) { \
44  strncpy(SYCLConfigBase<Name>::MStorage, Value, MaxSize); \
45  SYCLConfigBase<Name>::MStorage[MaxSize] = '\0'; \
46  SYCLConfigBase<Name>::MValueFromFile = SYCLConfigBase<Name>::MStorage; \
47  return; \
48  }
49 #include "detail/config.def"
50 #undef CONFIG
51 }
52 
53 void readConfig(bool ForceInitialization) {
54  static bool Initialized = false;
55  if (!ForceInitialization && Initialized) {
56  return;
57  }
58 
59  std::fstream File;
60  if (const char *ConfigFile = getenv("SYCL_CONFIG_FILE_NAME"))
61  File.open(ConfigFile, std::ios::in);
62  else {
63  const std::string LibSYCLDir = sycl::detail::OSUtil::getCurrentDSODir();
64  File.open(LibSYCLDir + sycl::detail::OSUtil::DirSep + SYCL_CONFIG_FILE_NAME,
65  std::ios::in);
66  }
67 
68  if (File.is_open()) {
69  char Key[MAX_CONFIG_NAME] = {0}, Value[MAX_CONFIG_VALUE] = {0};
70  std::string BufString;
71  std::size_t Position = std::string::npos;
72  while (!File.eof()) {
73  // Expected format:
74  // ConfigName=Value\r
75  // ConfigName=Value #comment
76  // ConfigName=Value
77  // TODO: Skip spaces before and after '='
78  std::getline(File, BufString);
79  if (File.fail() && !File.eof()) {
80  // Fail to process the line.
81  File.clear(File.rdstate() & ~std::ios_base::failbit);
82  File.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
83  throw sycl::exception(
85  "An error occurred while attempting to read a line");
86  }
87  // Handle '\r'
88  if ((BufString.length() > 0) &&
89  (BufString[BufString.length() - 1] == '\r')) {
90  BufString.pop_back();
91  }
92  // Handle comments
93  if (BufString.find("#") != std::string::npos) {
94  BufString.erase(BufString.find("#"));
95  while ((BufString.length() > 0) &&
96  (BufString[BufString.length() - 1] == ' ')) {
97  BufString.pop_back();
98  }
99  }
100  // Skip lines with a length = 0 or which don't have "="
101  if ((BufString.length() == 0) ||
102  (BufString.find("=") == std::string::npos)) {
103  continue;
104  }
105  // Finding the position of '='
106  Position = BufString.find("=");
107  // Checking that the variable name is less than MAX_CONFIG_NAME and more
108  // than zero character
109  if ((Position <= MAX_CONFIG_NAME) && (Position > 0)) {
110  // Checking that the value is less than MAX_CONFIG_VALUE and
111  // more than zero character
112  if ((BufString.length() - (Position + 1) <= MAX_CONFIG_VALUE) &&
113  (BufString.length() != Position + 1)) {
114  // Checking for spaces at the beginning and end of the line,
115  // before and after '='
116  if ((BufString[0] == ' ') ||
117  (BufString[BufString.length() - 1] == ' ') ||
118  (BufString[Position - 1] == ' ') ||
119  (BufString[Position + 1] == ' ')) {
120  throw sycl::exception(
122  "SPACE found at the beginning/end of the line "
123  "or before/after '='");
124  }
125  // Creating pairs of (key, value)
126  BufString.copy(Key, Position, 0);
127  Key[Position] = '\0';
128  BufString.copy(Value, BufString.length() - (Position + 1),
129  Position + 1);
130  Value[BufString.length() - (Position + 1)] = '\0';
131  } else {
132  throw sycl::exception(
134  "The value contains more than " +
135  std::to_string(MAX_CONFIG_VALUE) +
136  " characters or does not contain them at all");
137  }
138  } else {
140  "Variable name is more than " +
141  std::to_string(MAX_CONFIG_NAME) +
142  " or less than one character");
143  }
144 
145  initValue(Key, Value);
146  }
147  File.close();
148  }
149  Initialized = true;
150 }
151 
152 // Prints configs name with their value
153 void dumpConfig() {
154 #define CONFIG(Name, MaxSize, CompileTimeDef) \
155  { \
156  const char *Val = SYCLConfigBase<Name>::getRawValue(); \
157  std::cerr << SYCLConfigBase<Name>::MConfigName << " : " \
158  << (Val ? Val : "unset") << std::endl; \
159  }
160 #include "detail/config.def"
161 #undef CONFIG
162 }
163 
164 // Array is used by SYCL_DEVICE_FILTER and SYCL_DEVICE_ALLOWLIST and
165 // ONEAPI_DEVICE_SELECTOR
166 // TODO: Remove esimd_emulator in the next ABI breaking window.
167 // TODO: host device type will be removed once sycl_ext_oneapi_filter_selector
168 // is removed.
169 const std::array<std::pair<std::string, backend>, 8> &getSyclBeMap() {
170  static const std::array<std::pair<std::string, backend>, 8> SyclBeMap = {
171  {{"host", backend::host},
172  {"opencl", backend::opencl},
173  {"level_zero", backend::ext_oneapi_level_zero},
174  {"cuda", backend::ext_oneapi_cuda},
175  {"hip", backend::ext_oneapi_hip},
176  {"esimd_emulator", backend::ext_intel_esimd_emulator},
177  {"native_cpu", backend::ext_oneapi_native_cpu},
178  {"*", backend::all}}};
179  return SyclBeMap;
180 }
181 
182 } // namespace detail
183 } // namespace _V1
184 } // namespace sycl
#define SYCL_CONFIG_FILE_NAME
Definition: config.cpp:24
void readConfig(bool ForceInitialization)
Definition: config.cpp:53
const std::array< std::pair< std::string, backend >, 8 > & getSyclBeMap()
Definition: config.cpp:169
constexpr int MAX_CONFIG_VALUE
Definition: config.hpp:49
void dumpConfig()
Definition: config.cpp:153
constexpr int MAX_CONFIG_NAME
Definition: config.hpp:48
static void initValue(const char *Key, const char *Value)
Definition: config.cpp:41
std::error_code make_error_code(sycl::errc E) noexcept
Constructs an error code using e and sycl_category()
Definition: exception.cpp:91
Definition: access.hpp:18