Arcane  v4.1.3.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
arcane/src/arcane/utils/PlatformUtils.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2026 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
4// See the top-level COPYRIGHT file for details.
5// SPDX-License-Identifier: Apache-2.0
6//-----------------------------------------------------------------------------
7/*---------------------------------------------------------------------------*/
8/* PlatformUtils.cc (C) 2000-2026 */
9/* */
10/* Fonctions utilitaires dépendant de la plateforme. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/utils/PlatformUtils.h"
15#include "arcane/utils/String.h"
16#include "arcane/utils/StdHeader.h"
17#include "arcane/utils/StackTrace.h"
18#include "arcane/utils/IStackTraceService.h"
19#include "arcane/utils/IOnlineDebuggerService.h"
20#include "arcane/utils/Iostream.h"
21#include "arcane/utils/StringBuilder.h"
22#include "arcane/utils/NotSupportedException.h"
23#include "arcane/utils/NotImplementedException.h"
24#include "arcane/utils/FatalErrorException.h"
25#include "arcane/utils/Array.h"
26#include "arcane/utils/StringList.h"
28#include "arcane/utils/CheckedConvert.h"
29#include "arccore/common/internal/MemoryUtilsInternal.h"
30
32
33#include <chrono>
34
35#ifndef ARCANE_OS_WIN32
36#define ARCANE_OS_UNIX
37#endif
38
39#ifdef ARCANE_OS_WIN32
40#include <sys/types.h>
41#include <sys/timeb.h>
42#include <sys/stat.h>
43#include <direct.h>
44#include <process.h>
45#include <windows.h>
46#include <shlobj.h>
47#endif
48
49#ifdef ARCANE_OS_UNIX
50#include <unistd.h>
51#include <sys/resource.h>
52#include <time.h>
53#include <sys/types.h>
54#include <sys/stat.h>
55#include <sys/time.h>
56#include <fcntl.h>
57#endif
58
59#ifdef ARCANE_OS_MACOS
60#include <cstdlib>
61#include <mach-o/dyld.h>
62#include <crt_externs.h>
63#else
64#include <malloc.h>
65#endif
66
67
68#if !defined(ARCANE_OS_CYGWIN) && !defined(ARCANE_OS_WIN32)
69#if defined(__i386__)
70#define ARCANE_HAS_I386_FPU_CONTROL_H
71#include <fpu_control.h>
72#endif
73#endif
74
75#ifndef ARCANE_OS_WIN32
76#include <pwd.h>
77#include <sys/types.h>
78#include <unistd.h>
79#endif
80
81// Support pour gérer les exceptions flottantes:
82// - sous Linux avec la GlibC, cela se fait via les méthodes
83// feenableexcept(), fedisableexcept() et fegetexcept()
84// - sous Win32, cela se fait via la méthode _controlfp() mais pour
85// l'instant ce n'est pas utilisé dans Arcane.
86#if defined(ARCANE_OS_LINUX) && defined(__USE_GNU)
87# include <fenv.h>
88# define ARCANE_GLIBC_FENV
89#endif
90
91/*---------------------------------------------------------------------------*/
92/*---------------------------------------------------------------------------*/
93
94namespace Arcane
95{
96
97/*---------------------------------------------------------------------------*/
98/*---------------------------------------------------------------------------*/
99
100namespace platform
101{
102 IOnlineDebuggerService* global_online_debugger_service = nullptr;
103 IProfilingService* global_profiling_service = nullptr;
104 IProcessorAffinityService* global_processor_affinity_service = nullptr;
105 IPerformanceCounterService* global_performance_counter_service = nullptr;
106 bool global_has_color_console = false;
107}
108
109/*---------------------------------------------------------------------------*/
110/*---------------------------------------------------------------------------*/
111
112extern "C++" ARCANE_UTILS_EXPORT IOnlineDebuggerService* platform::
114{
115 return global_online_debugger_service;
116}
117
118/*---------------------------------------------------------------------------*/
119/*---------------------------------------------------------------------------*/
120
121extern "C++" ARCANE_UTILS_EXPORT IOnlineDebuggerService* platform::
123{
124 IOnlineDebuggerService* old_service = global_online_debugger_service;
125 global_online_debugger_service = service;
126 return old_service;
127}
128
129/*---------------------------------------------------------------------------*/
130/*---------------------------------------------------------------------------*/
131
132extern "C++" ARCANE_UTILS_EXPORT IProfilingService* platform::
134{
135 return global_profiling_service;
136}
137
138/*---------------------------------------------------------------------------*/
139/*---------------------------------------------------------------------------*/
140
141extern "C++" ARCANE_UTILS_EXPORT IProfilingService* platform::
143{
144 IProfilingService* old_service = global_profiling_service;
145 global_profiling_service = service;
146 return old_service;
147}
148
149/*---------------------------------------------------------------------------*/
150/*---------------------------------------------------------------------------*/
151
152extern "C++" ARCANE_UTILS_EXPORT IProcessorAffinityService* platform::
154{
155 return global_processor_affinity_service;
156}
157
158/*---------------------------------------------------------------------------*/
159/*---------------------------------------------------------------------------*/
160
161extern "C++" ARCANE_UTILS_EXPORT IProcessorAffinityService* platform::
163{
164 IProcessorAffinityService* old_service = global_processor_affinity_service;
165 global_processor_affinity_service = service;
166 return old_service;
167}
168
169/*---------------------------------------------------------------------------*/
170/*---------------------------------------------------------------------------*/
171
172extern "C++" ARCANE_UTILS_EXPORT IPerformanceCounterService* platform::
174{
175 return global_performance_counter_service;
176}
177
178/*---------------------------------------------------------------------------*/
179/*---------------------------------------------------------------------------*/
180
181extern "C++" ARCANE_UTILS_EXPORT IPerformanceCounterService* platform::
183{
184 auto* old_service = global_performance_counter_service;
185 global_performance_counter_service = service;
186 return old_service;
187}
188
189/*---------------------------------------------------------------------------*/
190/*---------------------------------------------------------------------------*/
191
197
198/*---------------------------------------------------------------------------*/
199/*---------------------------------------------------------------------------*/
200
206
207/*---------------------------------------------------------------------------*/
208/*---------------------------------------------------------------------------*/
209
215
216/*---------------------------------------------------------------------------*/
217/*---------------------------------------------------------------------------*/
218
219extern "C++" ARCANE_UTILS_EXPORT IMemoryRessourceMng* platform::
220setDataMemoryRessourceMng(IMemoryRessourceMng* mng)
221{
223}
224
225/*---------------------------------------------------------------------------*/
226/*---------------------------------------------------------------------------*/
227
228IMemoryRessourceMng* platform::
230{
232}
233
234/*---------------------------------------------------------------------------*/
235/*---------------------------------------------------------------------------*/
236
237extern "C++" ARCANE_UTILS_EXPORT IThreadImplementation* platform::
239{
240 return Arccore::Concurrency::getThreadImplementation();
241}
242
243/*---------------------------------------------------------------------------*/
244/*---------------------------------------------------------------------------*/
245
246extern "C++" ARCANE_UTILS_EXPORT IThreadImplementation* platform::
248{
249 return Arccore::Concurrency::setThreadImplementation(service);
250}
251
252/*---------------------------------------------------------------------------*/
253/*---------------------------------------------------------------------------*/
254
255extern "C++" ARCANE_UTILS_EXPORT void platform::
256resetAlarmTimer(Integer nb_second)
257{
258#ifdef ARCANE_OS_UNIX
259 struct itimerval time_val;
260 struct itimerval otime_val;
261 time_val.it_value.tv_sec = nb_second;
262 time_val.it_value.tv_usec = 0;
263 time_val.it_interval.tv_sec = 0;
264 time_val.it_interval.tv_usec = 0;
265 // Utilise le temps virtuel et pas le temps réel.
266 // Cela permet de suspendre temporairement un job (par exemple
267 // pour régler des problèmes systèmes) sans déclencher l'alarme.
268 int r = setitimer(ITIMER_VIRTUAL,&time_val,&otime_val);
269 if (r!=0)
270 cout << "** ERROR in setitimer r=" << r << '\n';
271#endif
272}
273
274/*---------------------------------------------------------------------------*/
275/*---------------------------------------------------------------------------*/
276
277extern "C++" ARCANE_UTILS_EXPORT void platform::
279{
281}
282
283/*---------------------------------------------------------------------------*/
284/*---------------------------------------------------------------------------*/
285
286extern "C++" ARCANE_UTILS_EXPORT void platform::
288{
290}
291
292/*---------------------------------------------------------------------------*/
293/*---------------------------------------------------------------------------*/
294
295namespace
296{
297template<typename ByteType> bool
298_readAllFile(StringView filename, bool is_binary, Array<ByteType>& out_bytes)
299{
300 using namespace std;
301 long unsigned int file_length = platform::getFileLength(filename);
302 if (file_length == 0) {
303 //cerr << "** FAIL LENGTH\n";
304 return true;
305 }
306 ifstream ifile;
307 ios::openmode mode = ios::in;
308 if (is_binary)
309 mode |= ios::binary;
310 ifile.open(filename.toStdStringView().data());
311 if (ifile.fail()) {
312 //cerr << "** FAIL OPEN\n";
313 return true;
314 }
315 out_bytes.resize(file_length);
316 ifile.read((char*)(out_bytes.data()), file_length);
317 if (ifile.bad()) {
318 // cerr << "** BAD READ\n";
319 return true;
320 }
321 // Il est possible que le nombre d'octets lus soit inférieur
322 // à la longueur du fichier, notamment sous Windows avec les fichiers
323 // texte et la conversion des retour-chariots. Il faut donc redimensionner
324 // \a bytes à la bonne longueur.
325 size_t nb_read = ifile.gcount();
326 out_bytes.resize(nb_read);
327 //cerr << "** READ " << file_length << " bytes " << (const char*)(bytes.begin()) << "\n";
328 return false;
329}
330}
331
332/*---------------------------------------------------------------------------*/
333/*---------------------------------------------------------------------------*/
334
336readAllFile(StringView filename, bool is_binary, ByteArray& out_bytes)
337{
338 return _readAllFile(filename,is_binary,out_bytes);
339}
340
341/*---------------------------------------------------------------------------*/
342/*---------------------------------------------------------------------------*/
343
345readAllFile(StringView filename, bool is_binary, Array<std::byte>& out_bytes)
346{
347 return _readAllFile(filename,is_binary,out_bytes);
348}
349
350/*---------------------------------------------------------------------------*/
351/*---------------------------------------------------------------------------*/
352
353static bool global_has_dotnet_runtime = false;
354extern "C++" bool platform::
356{
357 return global_has_dotnet_runtime;
358}
359
360extern "C++" void platform::
362{
363 global_has_dotnet_runtime = v;
364}
365
366/*---------------------------------------------------------------------------*/
367/*---------------------------------------------------------------------------*/
368
369extern "C++" String platform::
371{
372 String full_path;
373#if defined(ARCANE_OS_LINUX)
374 char* buf = ::realpath("/proc/self/exe",nullptr);
375 if (buf){
376 full_path = StringView(buf);
377 ::free(buf);
378 }
379#elif defined(ARCANE_OS_WIN32)
380 char buf[2048];
381 int r = GetModuleFileNameA(NULL,buf,2000);
382 if (r>0){
383 full_path = StringView(buf);
384 }
385#elif defined(ARCANE_OS_MACOS)
386 char buf[2048];
387 uint32_t bufSize = 2000;
388 int r = _NSGetExecutablePath(buf, &bufSize);
389 if (r==0) { // success returns 0
390 full_path = StringView(buf);
391 }
392#else
393#error "platform::getExeFullPath() not implemented for this platform"
394#endif
395 return full_path;
396}
397
398/*---------------------------------------------------------------------------*/
399/*---------------------------------------------------------------------------*/
400
401extern "C++" void platform::
403{
404 arg_list.clear();
405#if defined(ARCANE_OS_LINUX)
406
407 const int BUFSIZE = 1024;
408 char buffer[BUFSIZE + 1];
409
410 UniqueArray<char> bytes;
411 bytes.reserve(1024);
412
413 {
414 const char* filename = "/proc/self/cmdline";
415 int fd = open(filename, O_RDONLY);
416 if (fd<0)
417 return;
418 ssize_t nb_read = 0;
419 // TODO: traiter les interruptions
420 while ((nb_read = read(fd, buffer, BUFSIZE)) > 0) {
421 buffer[BUFSIZE] = '\0';
422 bytes.addRange(Span<const char>(buffer, nb_read));
423 }
424 close(fd);
425 }
426
427 int size = bytes.size();
428 const char* ptr = bytes.data();
429 const char* end = ptr + size;
430 while (ptr < end) {
431 arg_list.add(StringView(ptr));
432 while (*ptr++ && ptr < end)
433 ;
434 }
435#elif defined(ARCANE_OS_WIN32)
436 LPWSTR* w_arg_list = nullptr;
437 int nb_arg = 0;
438
439 w_arg_list = ::CommandLineToArgvW(GetCommandLineW(), &nb_arg);
440 if (!w_arg_list)
441 ARCANE_FATAL("Can not get arguments from command line");
442
443 for (int i = 0; i < nb_arg; i++) {
444 std::wstring_view wstr_view(w_arg_list[i]);
446 arg_list.add(str);
447 }
448
449 ::LocalFree(w_arg_list);
450#elif defined(ARCANE_OS_MACOS)
451 int argc = *_NSGetArgc();
452 char** argv = *_NSGetArgv();
453 for (int i = 0; i < argc; i++) {
454 arg_list.add(StringView(argv[i]));
455 }
456#else
457 ARCANE_THROW(NotImplementedException, "not implemented for this platform");
458#endif
459}
460
461/*---------------------------------------------------------------------------*/
462/*---------------------------------------------------------------------------*/
463
464namespace
465{
466 String _getDebuggerStack(const char* command)
467 {
468 char filename[4096];
469 long pid = (long)getpid();
470 sprintf(filename, "errlog.%ld", pid);
471 int ret_value = system(command);
472 if (ret_value != 0) {
473 UniqueArray<Byte> bytes;
474 if (!platform::readAllFile(filename, false, bytes))
475 return String(bytes);
476 }
477 return {};
478 }
479} // namespace
480
481extern "C++" ARCANE_UTILS_EXPORT String platform::
483{
484 String result;
485#if defined(ARCANE_OS_LINUX)
486 const size_t cmd_size = 4096;
487 char cmd[cmd_size + 1];
488 //sprintf (cmd, "gdb --ex 'attach %ld' --ex 'info threads' --ex 'thread apply all bt'", (long)getpid ());
489 //sprintf (cmd, "gdb --ex 'attach %ld' --ex 'info threads' --ex 'thread apply all bt' --batch", (long)getpid ());
490 long pid = (long)getpid();
491 snprintf(cmd, cmd_size, "gdb --ex 'set debuginfod enabled off' --ex 'attach %ld' --ex 'info threads' --ex 'thread apply all bt full' --batch", pid);
492 result = _getDebuggerStack(cmd);
493#endif
494 return result;
495}
496
497/*---------------------------------------------------------------------------*/
498/*---------------------------------------------------------------------------*/
499
500extern "C++" ARCANE_UTILS_EXPORT String platform::
502{
503 String result;
504#if defined(ARCANE_OS_LINUX)
505 const size_t cmd_size = 4096;
506 char cmd[cmd_size + 1];
507 long pid = (long)getpid();
508 // Les commandes 'clrthreads', 'clrstack' et 'dumpstack' nécessitent
509 // d'avoir installé 'dotnet-sos'.
510 snprintf(cmd, cmd_size, "lldb -p %ld -o 'bt' -o 'bt all' -o 'clrthreads' -o 'clrstack' -o 'dumpstack' --batch", pid);
511 result = _getDebuggerStack(cmd);
512#endif
513 return result;
514}
515
516/*---------------------------------------------------------------------------*/
517/*---------------------------------------------------------------------------*/
518
519namespace
520{
521void (*global_garbage_collector_delegate)() = nullptr;
522}
523
524extern "C" ARCANE_UTILS_EXPORT void
525_ArcaneSetCallGarbageCollectorDelegate(void(*f)())
526{
527 global_garbage_collector_delegate = f;
528}
529
530extern "C++" void platform::
532{
533 if (global_garbage_collector_delegate)
534 (*global_garbage_collector_delegate)();
535}
536
537/*---------------------------------------------------------------------------*/
538/*---------------------------------------------------------------------------*/
539
540} // End namespace Arcane
541
542/*---------------------------------------------------------------------------*/
543/*---------------------------------------------------------------------------*/
#define ARCANE_THROW(exception_class,...)
Macro pour envoyer une exception avec formattage.
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
Fonctions utilitaires sur les chaînes de caractères.
ARCCORE_BASE_EXPORT String convertToArcaneString(const std::wstring_view &wstr)
Convertie wstr en une String.
Definition String.cc:1305
Fonctions de gestion mémoire et des allocateurs.
Integer size() const
Nombre d'éléments du vecteur.
Tableau d'items de types quelconques.
void resize(Int64 s)
Change le nombre d'éléments du tableau à s.
void reserve(Int64 new_capacity)
Réserve le mémoire pour new_capacity éléments.
const T * data() const
Accès à la racine du tableau hors toute protection.
void addRange(ConstReferenceType val, Int64 n)
Ajoute n élément de valeur val à la fin du tableau.
void clear()
Supprime tous les éléments de la collection.
Interface d'un allocateur pour la mémoire.
Interface d'un service de debugger hybrid.
Interface d'un service d'accès aux compteurs de performance.
Interface d'un service de gestion de l'affinité des coeurs CPU.
Interface d'un service de profiling.
Interface d'un service implémentant le support des threads.
Exception lorsqu'une fonction n'est pas implémentée.
Vue d'un tableau d'éléments de type T.
Definition Span.h:633
Vue sur une chaîne de caractères UTF-8.
Definition StringView.h:47
std::string_view toStdStringView() const ARCCORE_NOEXCEPT
Retourne une vue de la STL de la vue actuelle.
Definition StringView.h:112
Chaîne de caractères unicode.
Vecteur 1D de données avec sémantique par valeur (style STL).
ARCCORE_COMMON_EXPORT IMemoryRessourceMng * setDataMemoryResourceMng(IMemoryRessourceMng *mng)
Positionne le gestionnaire de ressource mémoire pour les données.
ARCCORE_COMMON_EXPORT IMemoryRessourceMng * getDataMemoryResourceMng()
Gestionnaire de ressource mémoire pour les données.
ARCCORE_COMMON_EXPORT IMemoryAllocator * setAcceleratorHostMemoryAllocator(IMemoryAllocator *a)
Positionne l'allocateur spécifique pour les accélérateurs.
ARCCORE_COMMON_EXPORT IMemoryAllocator * getDefaultDataAllocator()
Allocateur par défaut pour les données.
ARCCORE_COMMON_EXPORT IMemoryAllocator * getAcceleratorHostMemoryAllocator()
Allocateur spécifique pour les accélérateurs.
ARCCORE_BASE_EXPORT void platformTerminate()
Routines de fin de programme spécifiques à une platforme.
ARCCORE_BASE_EXPORT void platformInitialize()
Initialisations spécifiques à une platforme.
Espace de nom pour les fonctions dépendant de la plateforme.
IPerformanceCounterService * setPerformanceCounterService(IPerformanceCounterService *service)
Positionne le service utilisé pour gérer les compteurs interne du processeur.
void callDotNETGarbageCollector()
Appelle le Garbage Collector de '.Net' s'il est disponible.
String getLLDBStack()
Récupère la pile d'appel via lldb.
void fillCommandLineArguments(StringList &arg_list)
Remplit arg_list avec les arguments de la ligne de commande.
IMemoryRessourceMng * setDataMemoryRessourceMng(IMemoryRessourceMng *mng)
Positionne le gestionnaire de ressource mémoire pour les données.
void platformInitialize()
Initialisations spécifiques à une platforme.
IOnlineDebuggerService * setOnlineDebuggerService(IOnlineDebuggerService *service)
Positionne le service a utiliser pour l'architecture en ligne de debug.
IProfilingService * getProfilingService()
Service utilisé pour obtenir pour obtenir des informations de profiling.
IMemoryRessourceMng * getDataMemoryRessourceMng()
Gestionnaire de ressource mémoire pour les données.
void resetAlarmTimer(Integer nb_second)
Remet à timer d'alarme à nb_second.
void platformTerminate()
Routines de fin de programme spécifiques à une platforme.
ARCCORE_BASE_EXPORT long unsigned int getFileLength(const String &filename)
Longueur du fichier filename. Si le fichier n'est pas lisible ou n'existe pas, retourne 0.
IProfilingService * setProfilingService(IProfilingService *service)
Positionne le service utilisé pour obtenir des informations de profiling.
IMemoryAllocator * getAcceleratorHostMemoryAllocator()
Allocateur spécifique pour les accélérateurs.
IMemoryAllocator * getDefaultDataAllocator()
Allocateur par défaut pour les données.
String getExeFullPath()
Retourne le nom complet avec le chemin de l'exécutable.
bool readAllFile(StringView filename, bool is_binary, ByteArray &out_bytes)
Lit le contenu d'un fichier et le conserve dans out_bytes.
IProcessorAffinityService * setProcessorAffinityService(IProcessorAffinityService *service)
Positionne le service utilisé pour la gestion de l'affinité des processeurs.
void setHasDotNETRuntime(bool v)
Positionne si le code s'exécute avec le runtime .NET.
IProcessorAffinityService * getProcessorAffinityService()
Service utilisé pour la gestion de l'affinité des processeurs.
IMemoryAllocator * setAcceleratorHostMemoryAllocator(IMemoryAllocator *a)
Positionne l'allocateur spécifique pour les accélérateurs.
IThreadImplementation * getThreadImplementationService()
Service utilisé pour gérer les threads.
IPerformanceCounterService * getPerformanceCounterService()
Service utilisé pour obtenir pour obtenir les compteurs interne du processeur.
bool hasDotNETRuntime()
Vrai si le code s'exécute avec le runtime .NET.
String getGDBStack()
Récupère la pile d'appel via gdb.
IThreadImplementation * setThreadImplementationService(IThreadImplementation *service)
Positionne le service utilisé pour gérer les threads.
IOnlineDebuggerService * getOnlineDebuggerService()
Service utilisé pour obtenir la mise en place d'une architecture en ligne de debug.
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
Int32 Integer
Type représentant un entier.
Array< Byte > ByteArray
Tableau dynamique à une dimension de caractères.
Definition UtilsTypes.h:121
List< String > StringList
Tableau de chaînes de caractères unicode.
Definition UtilsTypes.h:509