Arcane  v3.14.10.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-2024 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-2024 */
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/Array.h"
24#include "arcane/utils/StringList.h"
25#include "arcane/utils/internal/MemoryRessourceMng.h"
26
27#include <chrono>
28
29#ifndef ARCANE_OS_WIN32
30#define ARCANE_OS_UNIX
31#endif
32
33#ifdef ARCANE_OS_WIN32
34#include <sys/types.h>
35#include <sys/timeb.h>
36#include <sys/stat.h>
37#include <direct.h>
38#include <process.h>
39#include <windows.h>
40#include <shlobj.h>
41#endif
42
43#ifdef ARCANE_OS_UNIX
44#include <unistd.h>
45#include <sys/resource.h>
46#include <time.h>
47#include <sys/types.h>
48#include <sys/stat.h>
49#include <sys/time.h>
50#include <fcntl.h>
51#endif
52
53#include <malloc.h>
54
55#if !defined(ARCANE_OS_CYGWIN) && !defined(ARCANE_OS_WIN32)
56#if defined(__i386__)
57#define ARCANE_HAS_I386_FPU_CONTROL_H
58#include <fpu_control.h>
59#endif
60#endif
61
62#ifndef ARCANE_OS_WIN32
63#include <pwd.h>
64#include <sys/types.h>
65#include <unistd.h>
66#endif
67
68// Support pour gérer les exceptions flottantes:
69// - sous Linux avec la GlibC, cela se fait via les méthodes
70// feenableexcept(), fedisableexcept() et fegetexcept()
71// - sous Win32, cela se fait via la méthode _controlfp() mais pour
72// l'instant ce n'est pas utilisé dans Arcane.
73#if defined(ARCANE_OS_LINUX) && defined(__USE_GNU)
74# include <fenv.h>
75# define ARCANE_GLIBC_FENV
76#endif
77
78/*---------------------------------------------------------------------------*/
79/*---------------------------------------------------------------------------*/
80
81namespace Arcane
82{
83
84/*---------------------------------------------------------------------------*/
85/*---------------------------------------------------------------------------*/
86
87namespace platform
88{
89 IOnlineDebuggerService* global_online_debugger_service = nullptr;
90 ISymbolizerService* global_symbolizer_service = nullptr;
91 IProfilingService* global_profiling_service = nullptr;
92 IProcessorAffinityService* global_processor_affinity_service = nullptr;
93 IMemoryAllocator* global_accelerator_host_memory_allocator = nullptr;
94 IDynamicLibraryLoader* global_dynamic_library_loader = nullptr;
95 MemoryRessourceMng global_default_data_memory_ressource_mng;
96 IMemoryRessourceMng* global_data_memory_ressource_mng = nullptr;
97 IPerformanceCounterService* global_performance_counter_service = nullptr;
98 bool global_has_color_console = false;
99}
100
101/*---------------------------------------------------------------------------*/
102/*---------------------------------------------------------------------------*/
103
104extern "C++" ARCANE_UTILS_EXPORT ISymbolizerService* platform::
106{
107 return global_symbolizer_service;
108}
109
110/*---------------------------------------------------------------------------*/
111/*---------------------------------------------------------------------------*/
112
113extern "C++" ARCANE_UTILS_EXPORT ISymbolizerService* platform::
115{
116 ISymbolizerService* old_service = global_symbolizer_service;
117 global_symbolizer_service = service;
118 return old_service;
119}
120
121/*---------------------------------------------------------------------------*/
122/*---------------------------------------------------------------------------*/
123
124extern "C++" ARCANE_UTILS_EXPORT IOnlineDebuggerService* platform::
126{
127 return global_online_debugger_service;
128}
129
130/*---------------------------------------------------------------------------*/
131/*---------------------------------------------------------------------------*/
132
133extern "C++" ARCANE_UTILS_EXPORT IOnlineDebuggerService* platform::
135{
136 IOnlineDebuggerService* old_service = global_online_debugger_service;
137 global_online_debugger_service = service;
138 return old_service;
139}
140
141/*---------------------------------------------------------------------------*/
142/*---------------------------------------------------------------------------*/
143
144extern "C++" ARCANE_UTILS_EXPORT IProfilingService* platform::
146{
147 return global_profiling_service;
148}
149
150/*---------------------------------------------------------------------------*/
151/*---------------------------------------------------------------------------*/
152
153extern "C++" ARCANE_UTILS_EXPORT IProfilingService* platform::
155{
156 IProfilingService* old_service = global_profiling_service;
157 global_profiling_service = service;
158 return old_service;
159}
160
161/*---------------------------------------------------------------------------*/
162/*---------------------------------------------------------------------------*/
163
164extern "C++" ARCANE_UTILS_EXPORT IDynamicLibraryLoader* platform::
166{
167 return global_dynamic_library_loader;
168}
169
170/*---------------------------------------------------------------------------*/
171/*---------------------------------------------------------------------------*/
172
173extern "C++" ARCANE_UTILS_EXPORT IDynamicLibraryLoader* platform::
175{
176 IDynamicLibraryLoader* old_service = global_dynamic_library_loader;
177 global_dynamic_library_loader = idll;
178 return old_service;
179}
180
181/*---------------------------------------------------------------------------*/
182/*---------------------------------------------------------------------------*/
183
184extern "C++" ARCANE_UTILS_EXPORT IProcessorAffinityService* platform::
186{
187 return global_processor_affinity_service;
188}
189
190/*---------------------------------------------------------------------------*/
191/*---------------------------------------------------------------------------*/
192
193extern "C++" ARCANE_UTILS_EXPORT IProcessorAffinityService* platform::
195{
196 IProcessorAffinityService* old_service = global_processor_affinity_service;
197 global_processor_affinity_service = service;
198 return old_service;
199}
200
201/*---------------------------------------------------------------------------*/
202/*---------------------------------------------------------------------------*/
203
204extern "C++" ARCANE_UTILS_EXPORT IPerformanceCounterService* platform::
206{
207 return global_performance_counter_service;
208}
209
210/*---------------------------------------------------------------------------*/
211/*---------------------------------------------------------------------------*/
212
213extern "C++" ARCANE_UTILS_EXPORT IPerformanceCounterService* platform::
215{
216 auto* old_service = global_performance_counter_service;
217 global_performance_counter_service = service;
218 return old_service;
219}
220
221/*---------------------------------------------------------------------------*/
222/*---------------------------------------------------------------------------*/
223
224extern "C++" ARCANE_UTILS_EXPORT IMemoryAllocator* platform::
226{
227 return global_accelerator_host_memory_allocator;
228}
229
230/*---------------------------------------------------------------------------*/
231/*---------------------------------------------------------------------------*/
232
233extern "C++" ARCANE_UTILS_EXPORT IMemoryAllocator* platform::
235{
236 IMemoryAllocator* old = global_accelerator_host_memory_allocator;
237 global_accelerator_host_memory_allocator = a;
238 return old;
239}
240
241/*---------------------------------------------------------------------------*/
242/*---------------------------------------------------------------------------*/
243
249
250/*---------------------------------------------------------------------------*/
251/*---------------------------------------------------------------------------*/
252
253extern "C++" ARCANE_UTILS_EXPORT IMemoryRessourceMng* platform::
255{
257 IMemoryRessourceMng* old = global_data_memory_ressource_mng;
258 global_data_memory_ressource_mng = mng;
259 return old;
260}
261
262/*---------------------------------------------------------------------------*/
263/*---------------------------------------------------------------------------*/
264
265extern "C++" ARCANE_UTILS_EXPORT IMemoryRessourceMng* platform::
267{
268 IMemoryRessourceMng* a = global_data_memory_ressource_mng;
269 if (!a)
270 return &global_default_data_memory_ressource_mng;
271 return a;
272}
273
274/*---------------------------------------------------------------------------*/
275/*---------------------------------------------------------------------------*/
276
277extern "C++" ARCANE_UTILS_EXPORT IThreadImplementation* platform::
279{
280 return Arccore::Concurrency::getThreadImplementation();
281}
282
283/*---------------------------------------------------------------------------*/
284/*---------------------------------------------------------------------------*/
285
286extern "C++" ARCANE_UTILS_EXPORT IThreadImplementation* platform::
288{
289 return Arccore::Concurrency::setThreadImplementation(service);
290}
291
292/*---------------------------------------------------------------------------*/
293/*---------------------------------------------------------------------------*/
294
295extern "C++" ARCANE_UTILS_EXPORT void platform::
297{
298#ifdef ARCANE_OS_UNIX
299 struct itimerval time_val;
300 struct itimerval otime_val;
301 time_val.it_value.tv_sec = nb_second;
302 time_val.it_value.tv_usec = 0;
303 time_val.it_interval.tv_sec = 0;
304 time_val.it_interval.tv_usec = 0;
305 // Utilise le temps virtuel et pas le temps réel.
306 // Cela permet de suspendre temporairement un job (par exemple
307 // pour régler des problèmes systèmes) sans déclencher l'alarme.
309 if (r!=0)
310 cout << "** ERROR in setitimer r=" << r << '\n';
311#endif
312}
313
314/*---------------------------------------------------------------------------*/
315/*---------------------------------------------------------------------------*/
316
317extern "C++" ARCANE_UTILS_EXPORT void platform::
319{
321}
322
323/*---------------------------------------------------------------------------*/
324/*---------------------------------------------------------------------------*/
325
326extern "C++" ARCANE_UTILS_EXPORT void platform::
328{
330}
331
332/*---------------------------------------------------------------------------*/
333/*---------------------------------------------------------------------------*/
334
335namespace
336{
337template<typename ByteType> bool
339{
340 using namespace std;
341 long unsigned int file_length = platform::getFileLength(filename);
342 if (file_length == 0) {
343 //cerr << "** FAIL LENGTH\n";
344 return true;
345 }
346 ifstream ifile;
347 ios::openmode mode = ios::in;
348 if (is_binary)
349 mode |= ios::binary;
350 ifile.open(filename.toStdStringView().data());
351 if (ifile.fail()) {
352 //cerr << "** FAIL OPEN\n";
353 return true;
354 }
355 out_bytes.resize(file_length);
356 ifile.read((char*)(out_bytes.data()), file_length);
357 if (ifile.bad()) {
358 // cerr << "** BAD READ\n";
359 return true;
360 }
361 // Il est possible que le nombre d'octets lus soit inférieur
362 // à la longueur du fichier, notamment sous Windows avec les fichiers
363 // texte et la conversion des retour-chariots. Il faut donc redimensionner
364 // \a bytes à la bonne longueur.
365 size_t nb_read = ifile.gcount();
366 out_bytes.resize(nb_read);
367 //cerr << "** READ " << file_length << " bytes " << (const char*)(bytes.begin()) << "\n";
368 return false;
369}
370}
371
372/*---------------------------------------------------------------------------*/
373/*---------------------------------------------------------------------------*/
374
377{
378 return _readAllFile(filename,is_binary,out_bytes);
379}
380
381/*---------------------------------------------------------------------------*/
382/*---------------------------------------------------------------------------*/
383
386{
387 return _readAllFile(filename,is_binary,out_bytes);
388}
389
390/*---------------------------------------------------------------------------*/
391/*---------------------------------------------------------------------------*/
392
393static bool global_has_dotnet_runtime = false;
394extern "C++" bool platform::
396{
397 return global_has_dotnet_runtime;
398}
399
400extern "C++" void platform::
402{
403 global_has_dotnet_runtime = v;
404}
405
406/*---------------------------------------------------------------------------*/
407/*---------------------------------------------------------------------------*/
408
409extern "C++" String platform::
411{
413#if defined(ARCANE_OS_LINUX)
414 char* buf = ::realpath("/proc/self/exe",nullptr);
415 if (buf){
416 full_path = StringView(buf);
417 ::free(buf);
418 }
419#elif defined(ARCANE_OS_WIN32)
420 char buf[2048];
421 int r = GetModuleFileNameA(NULL,buf,2000);
422 if (r>0){
423 full_path = StringView(buf);
424 }
425#else
426#error "platform::getExeFullPath() not implemented for this platform"
427#endif
428 return full_path;
429}
430
431/*---------------------------------------------------------------------------*/
432/*---------------------------------------------------------------------------*/
433
434extern "C++" String platform::
436{
438 if (dll_name.null())
439 return full_path;
440#if defined(ARCANE_OS_LINUX)
441 {
442 std::ifstream ifile("/proc/self/maps");
443 String v;
444 String true_name = "lib" + dll_name + ".so";
445 while (ifile.good()){
446 ifile >> v;
447 Span<const Byte> vb = v.bytes();
448 if (vb.size()>0 && vb[0]=='/'){
449 if (v.endsWith(true_name)){
450 full_path = v;
451 //std::cout << "V='" << v << "'\n";
452 break;
453 }
454 }
455 }
456 }
457#elif defined(ARCANE_OS_WIN32)
459 if (!hModule)
460 return full_path;
464#else
465 throw NotSupportedException(A_FUNCINFO);
466//#error "platform::getSymbolFullPath() not implemented for this platform"
467#endif
468 return full_path;
469}
470
471/*---------------------------------------------------------------------------*/
472/*---------------------------------------------------------------------------*/
473
474extern "C++" void platform::
476{
477 arg_list.clear();
478#if defined(ARCANE_OS_LINUX)
479
480 const int BUFSIZE = 1024;
481 char buffer[BUFSIZE + 1];
482
483 UniqueArray<char> bytes;
484 bytes.reserve(1024);
485
486 {
487 const char* filename = "/proc/self/cmdline";
488 int fd = open(filename, O_RDONLY);
489 if (fd<0)
490 return;
491 ssize_t nb_read = 0;
492 // TODO: traiter les interruptions
493 while ((nb_read = read(fd, buffer, BUFSIZE)) > 0) {
494 buffer[BUFSIZE] = '\0';
495 bytes.addRange(Span<const char>(buffer, nb_read));
496 }
497 close(fd);
498 }
499
500 int size = bytes.size();
501 const char* ptr = bytes.data();
502 const char* end = ptr + size;
503 while (ptr < end) {
504 arg_list.add(StringView(ptr));
505 while (*ptr++ && ptr < end)
506 ;
507 }
508#endif
509}
510
511/*---------------------------------------------------------------------------*/
512/*---------------------------------------------------------------------------*/
513// TODO: mettre ensuite dans 'Arccore'
514
515extern "C++" ARCANE_UTILS_EXPORT Int64 platform::
517{
518 auto x = std::chrono::high_resolution_clock::now();
519 // Converti la valeur en nanosecondes.
520 auto y = std::chrono::time_point_cast<std::chrono::nanoseconds>(x);
521 // Retourne le temps en nano-secondes.
522 return static_cast<Int64>(y.time_since_epoch().count());
523}
524
525/*---------------------------------------------------------------------------*/
526/*---------------------------------------------------------------------------*/
527
528extern "C++" ARCANE_UTILS_EXPORT Int64 platform::
530{
531#if defined(ARCCORE_OS_WIN32)
534 return si.dwPageSize;
535#elif defined(ARCANE_OS_LINUX)
536 return ::sysconf(_SC_PAGESIZE);
537#else
538#warning "getPageSize() not implemented for your platform. Default is 4096"
539 Int64 page_size = 4096;
540 return page_size;
541#endif
542}
543
544/*---------------------------------------------------------------------------*/
545/*---------------------------------------------------------------------------*/
546
547namespace
548{
549 String _getDebuggerStack(const char* command)
550 {
551 char filename[4096];
552 long pid = (long)getpid();
553 sprintf(filename, "errlog.%ld", pid);
554 int ret_value = system(command);
555 if (ret_value != 0) {
556 UniqueArray<Byte> bytes;
557 if (!platform::readAllFile(filename, false, bytes))
558 return String(bytes);
559 }
560 return {};
561 }
562} // namespace
563
564extern "C++" ARCANE_UTILS_EXPORT String platform::
566{
567 String result;
568#if defined(ARCANE_OS_LINUX)
569 const size_t cmd_size = 4096;
570 char cmd[cmd_size + 1];
571 //sprintf (cmd, "gdb --ex 'attach %ld' --ex 'info threads' --ex 'thread apply all bt'", (long)getpid ());
572 //sprintf (cmd, "gdb --ex 'attach %ld' --ex 'info threads' --ex 'thread apply all bt' --batch", (long)getpid ());
573 long pid = (long)getpid();
574 snprintf(cmd, cmd_size, "gdb --ex 'set debuginfod enabled off' --ex 'attach %ld' --ex 'info threads' --ex 'thread apply all bt full' --batch", pid);
575 result = _getDebuggerStack(cmd);
576#endif
577 return result;
578}
579
580/*---------------------------------------------------------------------------*/
581/*---------------------------------------------------------------------------*/
582
583extern "C++" ARCANE_UTILS_EXPORT String platform::
585{
586 String result;
587#if defined(ARCANE_OS_LINUX)
588 const size_t cmd_size = 4096;
589 char cmd[cmd_size + 1];
590 long pid = (long)getpid();
591 // Les commandes 'clrthreads', 'clrstack' et 'dumpstack' nécessitent
592 // d'avoir installé 'dotnet-sos'.
593 snprintf(cmd, cmd_size, "lldb -p %ld -o 'bt' -o 'bt all' -o 'clrthreads' -o 'clrstack' -o 'dumpstack' --batch", pid);
594 result = _getDebuggerStack(cmd);
595#endif
596 return result;
597}
598
599/*---------------------------------------------------------------------------*/
600/*---------------------------------------------------------------------------*/
601
602namespace
603{
605}
606
607extern "C" ARCANE_UTILS_EXPORT void
608_ArcaneSetCallGarbageCollectorDelegate(void(*f)())
609{
610 global_garbage_collector_delegate = f;
611}
612
613extern "C++" void platform::
615{
617 (*global_garbage_collector_delegate)();
618}
619
620/*---------------------------------------------------------------------------*/
621/*---------------------------------------------------------------------------*/
622
623} // End namespace Arcane
624
625/*---------------------------------------------------------------------------*/
626/*---------------------------------------------------------------------------*/
#define ARCANE_CHECK_POINTER(ptr)
Macro retournant le pointeur ptr s'il est non nul ou lancant une exception s'il est nul.
Tableau d'items de types quelconques.
Interface d'une chargeur dynamique de bibliothèque.
Gestion des ressources mémoire pour les CPU et accélérateurs.
virtual IMemoryAllocator * getAllocator(eMemoryRessource r)=0
Allocateur mémoire pour la ressource r.
Interface d'un service de debugger hybrid.
Interface d'un service d'accès aux compteurs de performance.
Interface d'un service de de trace des appels de fonctions.
Interface d'un service de profiling.
Interface d'un service de récupération des symboles du code source.
Lecteur des fichiers de maillage via la bibliothèque LIMA.
Definition Lima.cc:120
Gestion des ressources mémoire pour les CPU et accélérateurs.
Interface d'un service implémentant le support des threads.
Exception lorsqu'une opération n'est pas supportée.
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.
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.
String getLoadedSharedLibraryFullPath(const String &dll_name)
Retourne le chemin complet d'une bibliothèque dynamique chargée.
ISymbolizerService * setSymbolizerService(ISymbolizerService *service)
Positionne le service pour obtenir des informations sur les symboles du code source.
IDynamicLibraryLoader * getDynamicLibraryLoader()
Service utilisé pour charger dynamiquement des bibliothèques.
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.
ISymbolizerService * getSymbolizerService()
Service utilisé pour obtenir des informations sur les symboles du code source.
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.
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.
Int64 getPageSize()
Taille des pages du système hôte en octets.
String getExeFullPath()
Retourne le nom complet avec le chemin de l'exécutable.
Int64 getRealTimeNS()
Temps horloge en nano-secondes.
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.
IDynamicLibraryLoader * setDynamicLibraryLoader(IDynamicLibraryLoader *idll)
Positionne le service utilisé pour charger dynamiquement des bibliothèques.
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 -*-
@ UnifiedMemory
Alloue en utilisant la mémoire unifiée.
ARCCORE_BASE_EXPORT void platformInitialize()
Initialisations spécifiques à une platforme.
ARCCORE_BASE_EXPORT void platformTerminate()
Routines de fin de programme spécifiques à une platforme.