Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TMapFile.cxx
Go to the documentation of this file.
1// @(#)root/io:$Id$
2// Author: Fons Rademakers 08/07/97
3
4/*************************************************************************
5 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11#ifdef WIN32
12#pragma optimize("",off)
13#endif
14
15/**
16\class TMapFile
17\ingroup IO
18
19This class implements a shared memory region mapped to a file.
20Objects can be placed into this shared memory area using the Add()
21member function. To actually place a copy of the object is shared
22memory call Update() also whenever the mapped object(s) change(s)
23call Update() to put a fresh copy in the shared memory. This extra
24step is necessary since it is not possible to share objects with
25virtual pointers between processes (the vtbl ptr points to the
26originators unique address space and can not be used by the
27consumer process(es)). Consumer processes can map the memory region
28from this file and access the objects stored in it via the Get()
29method (which returns a copy of the object stored in the shared
30memory with correct vtbl ptr set). Only objects of classes with a
31Streamer() member function defined can be shared.
32
33I know the current implementation is not ideal (you need to copy to
34and from the shared memory file) but the main problem is with the
35class' virtual_table pointer. This pointer points to a table unique
36for every process. Therefore, different options are:
37 -# One could allocate an object directly in shared memory in the
38 producer, but the consumer still has to copy the object from
39 shared memory into a local object which has the correct vtbl
40 pointer for that process (copy ctor's can be used for creating
41 the local copy).
42 -# Another possibility is to only allow objects without virtual
43 functions in shared memory (like simple C structs), or to
44 forbid (how?) the consumer from calling any virtual functions
45 of the objects in shared memory.
46 -# A last option is to copy the object internals to shared memory
47 and copy them again from there. This is what is done in the
48 TMapFile (using the object Streamer() to make a deep copy).
49
50Option 1) saves one copy, but requires solid copy ctor's (along the
51full inheritance chain) to rebuild the object in the consumer. Most
52classes don't provide these copy ctor's, especially not when objects
53contain collections, etc. 2) is too limiting or dangerous (calling
54accidentally a virtual function will segv). So since we have a
55robust Streamer mechanism I opted for 3).
56**/
57
58
59#ifdef WIN32
60# include <windows.h>
61# include <process.h>
62# ifdef GetObject
63# undef GetObject
64# endif
65# define HAVE_SEMOP
66
67# ifdef CreateSemaphore
68# undef CreateSemaphore
69# endif
70
71# ifdef AcquireSemaphore
72# undef AcquireSemaphore;
73# endif
74
75# ifdef ReleaseSemaphore
76# undef ReleaseSemaphore
77# endif
78
79# ifdef DeleteSemaphore
80# undef DeleteSemaphore
81# endif
82
83#else
84# define INVALID_HANDLE_VALUE -1
85#endif
86
87#include <fcntl.h>
88#include <errno.h>
89
90#include "TMapFile.h"
91#include "TKeyMapFile.h"
92#include "TDirectoryFile.h"
93#include "TBrowser.h"
94#include "TStorage.h"
95#include "TString.h"
96#include "TSystem.h"
97#include "TClass.h"
98#include "TROOT.h"
99#include "TBufferFile.h"
100#include "TVirtualMutex.h"
101#include "mmprivate.h"
102
103#include <cmath>
104
105#if defined(R__UNIX) && !defined(R__MACOSX) && !defined(R__WINGCC)
106#define HAVE_SEMOP
107#include <sys/types.h>
108#include <sys/ipc.h>
109#include <sys/sem.h>
110#ifndef WIN32
111union semun {
112 int val; // value for SETVAL
113 struct semid_ds *buf; // buffer for IPC_STAT & IPC_SET
114 ushort *array; // array for GETALL & SETALL
115};
116#endif
117#if defined(R__LINUX) || defined(R__LYNXOS) || defined(R__HURD)
118# define SEM_A 0200 // alter permission
119# define SEM_R 0400 // read permission
120#endif
121#endif
122
123
126
127//void *ROOT::Internal::gMmallocDesc = 0; //is initialized in TStorage.cxx
128
129
130namespace {
131////////////////////////////////////////////////////////////////////////////////
132/// Delete memory and return true if memory belongs to a TMapFile.
133 static bool FreeIfTMapFile(void* ptr) {
134 if (TMapFile *mf = TMapFile::WhichMapFile(ptr)) {
135 if (mf->IsWritable())
136 ::mfree(mf->GetMmallocDesc(), ptr);
137 return true;
138 }
139 return false;
140 }
141}
142
143
144////////////////////////////////////////////////////////////////////////////////
145/// Set ROOT::Internal::gFreeIfTMapFile on library load.
146
149 ROOT::Internal::gFreeIfTMapFile = FreeIfTMapFile;
150 }
153 }
155
156
157////////////////////////////////////////////////////////////////////////////////
158//// Constructor.
159
160TMapRec::TMapRec(const char *name, const TObject *obj, Int_t size, void *buf)
161{
162 fName = StrDup(name);
163 fClassName = 0;
164 fObject = (TObject*)obj;
165 fBuffer = buf;
166 fBufSize = size;
167 fNext = 0;
168}
169
170////////////////////////////////////////////////////////////////////////////////
171/// Destructor.
172
174{
175 delete [] fName;
176 delete [] fClassName;
177}
178
179////////////////////////////////////////////////////////////////////////////////
180/// This method returns a pointer to the original object.
181
182/// NOTE: this pointer is only valid in the process that produces the shared
183/// memory file. In a consumer process this pointer is illegal! Be careful.
184
186{
187 return fObject;
188}
189
190
191
192
194
195////////////////////////////////////////////////////////////////////////////////
196/// Default ctor. Does not much except setting some basic values.
197
199{
200 fFd = -1;
201 fVersion = 0;
202 fName = nullptr;
203 fTitle = nullptr;
204 fOption = nullptr;
205 fMmallocDesc = nullptr;
206 fBaseAddr = 0;
207 fSize = 0;
208 fFirst = nullptr;
209 fLast = nullptr;
210 fOffset = 0;
211 fDirectory = nullptr;
212 fBrowseList = nullptr;
214 fSemaphore = -1;
215 fhSemaphore = 0;
216 fGetting = nullptr;
217 fWritten = 0;
218 fSumBuffer = 0;
219 fSum2Buffer = 0;
220}
221
222////////////////////////////////////////////////////////////////////////////////
223/// Create a memory mapped file.
224///
225/// This opens a file (to which the
226/// memory will be mapped) and attaches a memory region to it.
227/// Option can be either: "NEW", "CREATE", "RECREATE", "UPDATE" or
228/// "READ" (see TFile). The default open mode is "READ". The size
229/// argument specifies the maximum size of shared memory file in bytes.
230/// This protected ctor is called via the static Create() method.
231
232TMapFile::TMapFile(const char *name, const char *title, Option_t *option,
233 Int_t size, TMapFile *&newMapFile)
234{
235#ifndef WIN32
236 fFd = -1;
237 fSemaphore = -1;
238 fhSemaphore = 0;
239#else
242#endif
243 fMmallocDesc = nullptr;
244 fSize = size;
245 fFirst = 0;
246 fOffset = 0;
247 fVersion = gROOT->GetVersionInt();
248 fTitle = StrDup(title);
250 fDirectory = nullptr;
251 fBrowseList = nullptr;
252 fGetting = nullptr;
253 fWritten = 0;
254 fSumBuffer = 0;
255 fSum2Buffer = 0;
256
257 char *cleanup = nullptr;
258 Bool_t create = kFALSE;
259 Bool_t recreate, update, read;
260
261 {
262 TString opt = option;
263
264 if (!opt.CompareTo("NEW", TString::kIgnoreCase) ||
265 !opt.CompareTo("CREATE", TString::kIgnoreCase))
266 create = kTRUE;
267 recreate = opt.CompareTo("RECREATE", TString::kIgnoreCase)
268 ? kFALSE : kTRUE;
269 update = opt.CompareTo("UPDATE", TString::kIgnoreCase)
270 ? kFALSE : kTRUE;
271 read = opt.CompareTo("READ", TString::kIgnoreCase)
272 ? kFALSE : kTRUE;
273 if (!create && !recreate && !update && !read) {
274 read = kTRUE;
275 delete [] fOption;
276 fOption = StrDup("READ");
277 }
278 }
279
280 const char *fname;
281 if ((fName = gSystem->ExpandPathName(name))) {
282 fname = fName;
283 } else {
284 Error("TMapFile", "error expanding path %s", name);
285 goto zombie;
286 }
287
288 if (recreate) {
289 if (!gSystem->AccessPathName(fname, kFileExists))
290 gSystem->Unlink(fname);
291 recreate = kFALSE;
292 create = kTRUE;
293 delete [] fOption;
294 fOption = StrDup("CREATE");
295 }
296 if (create && !gSystem->AccessPathName(fname, kFileExists)) {
297 Error("TMapFile", "file %s already exists", fname);
298 goto zombie;
299 }
300 if (update) {
301 if (gSystem->AccessPathName(fname, kFileExists)) {
302 update = kFALSE;
303 create = kTRUE;
304 }
306 Error("TMapFile", "no write permission, could not open file %s", fname);
307 goto zombie;
308 }
309 }
310 if (read) {
311 if (gSystem->AccessPathName(fname, kFileExists)) {
312 Error("TMapFile", "file %s does not exist", fname);
313 goto zombie;
314 }
316 Error("TMapFile", "no read permission, could not open file %s", fname);
317 goto zombie;
318 }
319 }
320
321 // Open file to which memory will be mapped
322 if (create || update) {
323#ifndef WIN32
324 fFd = open(fname, O_RDWR | O_CREAT, 0644);
325#else
326 fFd = (Longptr_t) CreateFile(fname, // pointer to name of the file
327 GENERIC_WRITE | GENERIC_READ, // access (read-write) mode
328 FILE_SHARE_WRITE | FILE_SHARE_READ, // share mode
329 NULL, // pointer to security attributes
330 OPEN_ALWAYS, // how to create
331 FILE_ATTRIBUTE_TEMPORARY, // file attributes
332 (HANDLE) NULL); // handle to file with attributes to copy
333#endif
335 SysError("TMapFile", "file %s can not be opened", fname);
336 goto zombie;
337 }
339 } else {
340#ifndef WIN32
341 fFd = open(fname, O_RDONLY);
342#else
343 fFd = (Longptr_t) CreateFile(fname, // pointer to name of the file
344 GENERIC_READ, // access (read-write) mode
345 FILE_SHARE_WRITE | FILE_SHARE_READ, // share mode
346 NULL, // pointer to security attributes
347 OPEN_EXISTING, // how to create
348 FILE_ATTRIBUTE_TEMPORARY, // file attributes
349 (HANDLE) NULL); // handle to file with attributes to copy
350#endif
352 SysError("TMapFile", "file %s can not be opened for reading", fname);
353 goto zombie;
354 }
356 }
357
358 // Attach memory region to file.
359 void *mapto;
360 TMapFile *mapfil;
361
362 if (((mapto = MapToAddress()) == (void *)-1) ||
363#ifndef WIN32
364 ((fMmallocDesc = mmalloc_attach(fFd, mapto, fSize)) == 0)) {
365#else
366 ((fMmallocDesc = mmalloc_attach((HANDLE) fFd, mapto, fSize)) == 0)) {
367#endif
368
369 if (mapto == (void *)-1) {
370 Error("TMapFile", "no memory mapped file capability available\n"
371 "Use rootn.exe or link application against \"-lNew\"");
372 } else {
373 if (fMmallocDesc == 0 && fWritable)
374 Error("TMapFile", "mapped file not in mmalloc format or\n"
375 "already open in RW mode by another process");
376 if (fMmallocDesc == 0 && !fWritable)
377 Error("TMapFile", "mapped file not in mmalloc format");
378 }
379#ifndef WIN32
380 close(fFd);
381#else
382 CloseHandle((HANDLE) fFd);
383#endif
384 fFd = -1;
385 if (create)
386 gSystem->Unlink(fname);
387 goto zombie;
388
389 } else if ((mapfil = (TMapFile *) mmalloc_getkey(fMmallocDesc, 0)) != 0) {
390
391 // File contains mmalloc heap. If we are in write mode and mapped
392 // file already connected in write mode switch to read-only mode.
393 // Check if ROOT versions are compatible.
394 // If so update mapped version of TMapFile to reflect current
395 // situation (only if not opened in READ mode).
396 if (mapfil->fVersion != fVersion) {
397 Error("TMapFile", "map file %s (%d) incompatible with current ROOT version (%d)",
398 fname, mapfil->fVersion, fVersion);
399 mmalloc_detach(fMmallocDesc);
400#ifndef WIN32
401 close(fFd);
402#else
403 CloseHandle((HANDLE) fFd);
404#endif
405 fFd = -1;
406 fMmallocDesc = 0;
407 goto zombie;
408 }
409
410 if (mapfil->fWritable && fWritable) {
411 Warning("TMapFile", "map file already open in write mode, opening in read-only mode");
413 }
414
415 fBaseAddr = mapfil->fBaseAddr;
416 fSize = mapfil->fSize;
417
418 if (fWritable) {
419 // create new TMapFile object in mapped heap to get correct vtbl ptr
422 TMapFile *mf = new TMapFile(*mapfil);
423 mf->fFd = fFd;
424 mf->fWritable = kTRUE;
425 cleanup = mf->fOption;
426 mf->fOption = StrDup(fOption);
428#ifdef WIN32
430#endif
431 mmalloc_setkey(fMmallocDesc, 0, mf);
433 mapfil = mf;
434 } else {
435 ROOT::Internal::gMmallocDesc = 0; // make sure we are in sbrk heap
436 fOffset = ((struct mdesc *) fMmallocDesc)->offset;
437 TMapFile *mf = new TMapFile(*mapfil, fOffset);
438 delete [] mf->fOption;
439 mf->fFd = fFd;
440 mf->fOption = StrDup("READ");
442 mf->fWritable = kFALSE;
443 mapfil = mf;
444 }
445
446 // store shadow mapfile (it contains the real fFd in case map
447 // is not writable)
448 fVersion = -1; // make this the shadow map file
450 gROOT->GetListOfMappedFiles()->AddLast(this);
451
452 } else {
453
454 // New file. If the file is writable create a new copy of the
455 // TMapFile which will now be allocated on the memory mapped heap.
456 if (!fWritable) {
457 Error("TMapFile", "map file is not writable");
458 mmalloc_detach(fMmallocDesc);
459#ifndef WIN32
460 close(fFd);
461#else
462 CloseHandle((HANDLE) fFd);
463#endif
464 fFd = -1;
465 fMmallocDesc = 0;
466 goto zombie;
467 }
468
469 fBaseAddr = (ULongptr_t)((struct mdesc *) fMmallocDesc)->base;
470
472
474
475 mapfil = new TMapFile(*this);
476 mmalloc_setkey(fMmallocDesc, 0, mapfil);
477
479
480 // store shadow mapfile
481 fVersion = -1; // make this the shadow map file
483 gROOT->GetListOfMappedFiles()->AddLast(this);
484
485 }
486
487 mapfil->InitDirectory();
488 {
490 gROOT->GetListOfMappedFiles()->AddFirst(mapfil);
491 }
492
493 if (cleanup) delete [] cleanup;
494
495 newMapFile = mapfil;
496
497 return;
498
499zombie:
500 // error in file opening occured, make this object a zombie
501 MakeZombie();
502 newMapFile = this;
504}
505
506////////////////////////////////////////////////////////////////////////////////
507/// Private copy ctor.
508///
509/// Used by the ctor to create a new version
510/// of TMapFile in the memory mapped heap. It's main purpose is to
511/// correctly create the string data members.
512
514{
515 fFd = f.fFd;
516 fVersion = f.fVersion;
517 fName = StrDup((char *)((Longptr_t)f.fName + offset));
518 fTitle = StrDup((char *)((Longptr_t)f.fTitle + offset));
519 fOption = StrDup((char *)((Longptr_t)f.fOption + offset));
520 fMmallocDesc = f.fMmallocDesc;
521 fBaseAddr = f.fBaseAddr;
522 fSize = f.fSize;
523 fFirst = f.fFirst;
524 fLast = f.fLast;
525 fWritable = f.fWritable;
526 fSemaphore = f.fSemaphore;
527 fOffset = offset;
528 fDirectory = nullptr;
529 fBrowseList = nullptr;
530 fGetting = nullptr;
531 fWritten = f.fWritten;
532 fSumBuffer = f.fSumBuffer;
533 fSum2Buffer = f.fSum2Buffer;
534#ifdef WIN32
536#else
537 fhSemaphore = f.fhSemaphore;
538#endif
539}
540
541////////////////////////////////////////////////////////////////////////////////
542/// TMapFiles may not be deleted, since we want to keep the complete
543/// TMapFile object in the mapped file for later re-use. To enforce this
544/// the delete operator has been made private. Use Close() to properly
545/// terminate a TMapFile (also done via the TROOT dtor).
546
548{
550 delete fDirectory; fDirectory = nullptr;
551 if (fBrowseList) {
553 delete fBrowseList;
554 fBrowseList = nullptr;
555 }
556
557
558 // if shadow map file we are done here
559 if (fVersion == -1)
560 return;
561
562 // Writable mapfile is allocated in mapped memory. This object should
563 // not be deleted by ::operator delete(), because it is needed if we
564 // want to connect later to the file again.
565 if (fWritable)
567
568 Close("dtor");
569
571
572 delete [] fName; fName = nullptr;
573 delete [] fOption; fOption = nullptr;
574 delete [] fTitle; fTitle = nullptr;
575}
576
577////////////////////////////////////////////////////////////////////////////////
578/// Create the directory associated to this mapfile
579
581{
582 gDirectory = nullptr;
586 fDirectory->Build();
587 fDirectory->SetMother(this);
589}
590
591////////////////////////////////////////////////////////////////////////////////
592/// Add an object to the list of objects to be stored in shared memory.
593/// To place the object actually into shared memory call Update().
594
595void TMapFile::Add(const TObject *obj, const char *name)
596{
597 if (!fWritable || !fMmallocDesc) return;
598
599 Bool_t lock = fGetting != obj ? kTRUE : kFALSE;
600
601 if (lock)
603
605
606 const char *n;
607 if (name && *name)
608 n = name;
609 else
610 n = obj->GetName();
611
612 if (Remove(n, kFALSE)) {
613 //Warning("Add", "replaced object with same name %s", n);
614 }
615
616 TMapRec *mr = new TMapRec(n, obj, 0, 0);
617 if (!fFirst) {
618 fFirst = mr;
619 fLast = mr;
620 } else {
621 fLast->fNext = mr;
622 fLast = mr;
623 }
624
626
627 if (lock)
629}
630
631////////////////////////////////////////////////////////////////////////////////
632/// Update an object (or all objects, if obj == 0) in shared memory.
633
635{
636 if (!fWritable || !fMmallocDesc) return;
637
639
641
642 Bool_t all = (obj == 0) ? kTRUE : kFALSE;
643
644 TMapRec *mr = fFirst;
645 while (mr) {
646 if (all || mr->fObject == obj) {
647 TBufferFile *b;
648 if (!mr->fBufSize) {
650 mr->fClassName = StrDup(mr->fObject->ClassName());
651 } else
653 b->MapObject(mr->fObject); //register obj in map to handle self reference
654 mr->fObject->Streamer(*b);
655 mr->fBufSize = b->BufferSize();
656 mr->fBuffer = b->Buffer();
657 SumBuffer(b->Length());
658 b->DetachBuffer();
659 delete b;
660 }
661 mr = mr->fNext;
662 }
663
665
667}
668
669////////////////////////////////////////////////////////////////////////////////
670/// Remove object from shared memory.
671///
672/// Returns pointer to removed object if successful, 0 otherwise.
673
675{
676 if (!fWritable || !fMmallocDesc) return 0;
677
678 if (lock)
680
681 TObject *retObj = 0;
682 TMapRec *prev = 0, *mr = fFirst;
683 while (mr) {
684 if (mr->fObject == obj) {
685 if (mr == fFirst) {
686 fFirst = mr->fNext;
687 if (mr == fLast)
688 fLast = 0;
689 } else {
690 prev->fNext = mr->fNext;
691 if (mr == fLast)
692 fLast = prev;
693 }
694 retObj = obj;
695 delete mr;
696 break;
697 }
698 prev = mr;
699 mr = mr->fNext;
700 }
701
702 if (lock)
704
705 return retObj;
706}
707
708////////////////////////////////////////////////////////////////////////////////
709/// Remove object by name from shared memory.
710///
711/// Returns pointer to removed object if successful, 0 otherwise.
712
714{
715 if (!fWritable || !fMmallocDesc) return 0;
716
717 if (lock)
719
720 TObject *retObj = 0;
721 TMapRec *prev = 0, *mr = fFirst;
722 while (mr) {
723 if (!strcmp(mr->fName, name)) {
724 if (mr == fFirst) {
725 fFirst = mr->fNext;
726 if (mr == fLast)
727 fLast = 0;
728 } else {
729 prev->fNext = mr->fNext;
730 if (mr == fLast)
731 fLast = prev;
732 }
733 retObj = mr->fObject;
734 delete mr;
735 break;
736 }
737 prev = mr;
738 mr = mr->fNext;
739 }
740
741 if (lock)
743
744 return retObj;
745}
746
747////////////////////////////////////////////////////////////////////////////////
748/// Remove all objects from shared memory.
749
751{
752 if (!fWritable || !fMmallocDesc) return;
753
755
756 TMapRec *mr = fFirst;
757 while (mr) {
758 TMapRec *t = mr;
759 mr = mr->fNext;
760 delete t;
761 }
762 fFirst = fLast = 0;
763
765}
766
767////////////////////////////////////////////////////////////////////////////////
768/// Return pointer to object retrieved from shared memory.
769///
770/// The object must
771/// be deleted after use. If delObj is a pointer to a previously allocated
772/// object it will be deleted. Returns 0 in case object with the given
773/// name does not exist.
774
775TObject *TMapFile::Get(const char *name, TObject *delObj)
776{
777 if (!fMmallocDesc) return 0;
778
780
781 delete delObj;
782
783 TObject *obj = 0;
784 TMapRec *mr = GetFirst();
785 while (OrgAddress(mr)) {
786 if (!strcmp(mr->GetName(fOffset), name)) {
787 if (!mr->fBufSize) goto release;
789 if (!cl) {
790 Error("Get", "unknown class %s", mr->GetClassName(fOffset));
791 goto release;
792 }
793
794 obj = (TObject *)cl->New();
795 if (!obj) {
796 Error("Get", "cannot create new object of class %s", mr->GetClassName(fOffset));
797 goto release;
798 }
799
800 fGetting = obj;
802 b->MapObject(obj); //register obj in map to handle self reference
803 obj->Streamer(*b);
804 b->DetachBuffer();
805 delete b;
806 fGetting = 0;
807 goto release;
808 }
809 mr = mr->GetNext(fOffset);
810 }
811
812release:
814
815 return obj;
816}
817
818////////////////////////////////////////////////////////////////////////////////
819/// Create semaphore used for synchronizing access to shared memory.
820
821#ifndef WIN32
823#else
824void TMapFile::CreateSemaphore(int pid)
825#endif
826{
827#ifdef HAVE_SEMOP
828#ifndef WIN32
829 // create semaphore to synchronize access (should use read/write lock)
830 fSemaphore = semget(IPC_PRIVATE, 1, SEM_R|SEM_A|(SEM_R>>3)|(SEM_A>>3)|
831 (SEM_R>>6)|(SEM_A>>6));
832
833 // set semaphore to 1
834 if (fSemaphore != -1) {
835 union semun set;
836 set.val = 1;
837 semctl(fSemaphore, 0, SETVAL, set);
838 }
839#else
840 char buffer[] ="ROOT_Semaphore_xxxxxxxx";
841 int lbuf = strlen(buffer);
842 if (!pid) fSemaphore = getpid();
843 fhSemaphore = (ULongptr_t)CreateMutex(NULL,FALSE,itoa(fSemaphore,&buffer[lbuf-8],16));
844 if (fhSemaphore == 0) fSemaphore = (Longptr_t)INVALID_HANDLE_VALUE;
845#endif
846#endif
847}
848
849////////////////////////////////////////////////////////////////////////////////
850/// Delete the semaphore.
851
853{
854#ifdef HAVE_SEMOP
855 // remove semaphore
856#ifndef WIN32
857 if (fSemaphore != -1) {
858 int semid = fSemaphore;
859 fSemaphore = -1;
860 union semun set;
861 set.val = 0;
862 semctl(semid, 0, IPC_RMID, set);
863 }
864#else
866 CloseHandle((HANDLE)fhSemaphore);
867 fhSemaphore = 0;
869 }
870#endif
871#endif
872}
873
874////////////////////////////////////////////////////////////////////////////////
875/// Acquire semaphore. Returns 0 if OK, -1 on error.
876
878{
879#ifdef HAVE_SEMOP
880#ifndef WIN32
881 if (fSemaphore != -1) {
882 struct sembuf buf = { 0, -1, SEM_UNDO };
883 int intr = 0;
884again:
885 if (semop(fSemaphore, &buf, 1) == -1) {
886#if defined(R__FBSD) || defined(R__OBSD)
887 if (TSystem::GetErrno() == EINVAL)
888#else
889 if (TSystem::GetErrno() == EIDRM)
890#endif
891 fSemaphore = -1;
892#if !defined(R__FBSD)
893 if (TSystem::GetErrno() == EINTR) {
894 if (intr > 2)
895 return -1;
897 intr++;
898 goto again;
899 }
900#endif
901 }
902 }
903#else
904 // Enter Critical section to "write" lock
906 WaitForSingleObject((HANDLE)fhSemaphore,INFINITE);
907#endif
908#endif
909
910 // file might have grown, update mapping on reader to new size
911 if (!fWritable && fMmallocDesc) {
912 if (mmalloc_update_mapping(fMmallocDesc) == -1)
913 Error("AcquireSemaphore", "cannot update mapping");
914 }
915
916 return 0;
917}
918
919////////////////////////////////////////////////////////////////////////////////
920/// Release semaphore. Returns 0 if OK, -1 on error.
921
923{
924#ifdef HAVE_SEMOP
925#ifndef WIN32
926 if (fSemaphore != -1) {
927 struct sembuf buf = { 0, 1, SEM_UNDO };
928 if (semop(fSemaphore, &buf, 1) == -1) {
929#if defined(R__FBSD) || defined(R__OBSD)
930 if (TSystem::GetErrno() == EINVAL)
931#else
932 if (TSystem::GetErrno() == EIDRM)
933#endif
934 fSemaphore = -1;
935 }
936 }
937#else
939 ReleaseMutex((HANDLE)fhSemaphore);
940#endif
941#endif
942 return 0;
943}
944
945////////////////////////////////////////////////////////////////////////////////
946/// Close a mapped file.
947///
948/// First detach mapped memory then close file.
949/// No member functions of a TMapFile that was opened in write mode
950/// may be called after Close() (this includes, of course, "delete" which
951/// would call the dtors). The option="dtor" is only used when called
952/// via the ~TMapFile.
953
955{
956 if (!fMmallocDesc) return;
957
958 TMapFile *shadow = FindShadowMapFile();
959 if (!shadow) {
960 Error("Close", "shadow map == 0, should never happen!");
961 return;
962 }
963
964 {
966 gROOT->GetListOfMappedFiles()->Remove(shadow);
967 gROOT->GetListOfMappedFiles()->Remove(this);
968 }
969
970 if (shadow->fWritable) {
973 }
974
975 if (fMmallocDesc) {
976 if (strcmp(option, "dtor"))
977 mmalloc_detach(fMmallocDesc);
978
979 // If writable cannot access fMmallocDesc anymore since
980 // it points to the just unmapped memory region. Any further
981 // access to this TMapFile will cause a crash.
982 if (!shadow->fWritable)
983 fMmallocDesc = 0;
984 }
985
986 if (shadow->fFd != -1)
987#ifndef WIN32
988 close(shadow->fFd);
989#else
990 CloseHandle((HANDLE)shadow->fFd);
991#endif
992
993 delete shadow;
994}
995
996////////////////////////////////////////////////////////////////////////////////
997/// Returns shadow map file.
998
1000{
1002 TObjLink *lnk = ((TList *)gROOT->GetListOfMappedFiles())->LastLink();
1003 while (lnk) {
1004 TMapFile *mf = (TMapFile*)lnk->GetObject();
1005 if (mf->fVersion == -1 && fBaseAddr == mf->fBaseAddr && fSize == mf->fSize)
1006 return mf;
1007 lnk = lnk->Prev();
1008 }
1009 return 0;
1010}
1011
1012////////////////////////////////////////////////////////////////////////////////
1013/// Print some info about the mapped file.
1014
1016{
1017 Printf("Memory mapped file: %s", fName);
1018 Printf("Title: %s", fTitle);
1019 if (fMmallocDesc) {
1020 Printf("Option: %s", fOption);
1021 size_t size = (size_t)((struct mdesc *)fMmallocDesc)->top - fBaseAddr;
1022 Printf("Mapped Memory region: 0x%zx - 0x%zx (%.2f MB)", (size_t)fBaseAddr, (size_t)fBaseAddr + size,
1023 (float)size/1048576);
1024 Printf("Current breakval: 0x%zx", (size_t)GetBreakval());
1025 } else
1026 Printf("Option: file closed");
1027}
1028
1029////////////////////////////////////////////////////////////////////////////////
1030/// Returns kTRUE in case object is a folder (i.e. contains browsable lists).
1031
1033{
1034 if (fMmallocDesc && fVersion > 0) return kTRUE;
1035 return kFALSE;
1036}
1037
1038////////////////////////////////////////////////////////////////////////////////
1039/// Browse contents of TMapFile.
1040
1042{
1043 if (b && fMmallocDesc) {
1044
1046
1047 TMapRec *mr = GetFirst();
1048 TKeyMapFile *keymap;
1049 if (!fBrowseList) fBrowseList = new TList();
1050 while (OrgAddress(mr)) {
1052 if (!keymap) {
1053 keymap = new TKeyMapFile(mr->GetName(fOffset),mr->GetClassName(fOffset),this);
1054 fBrowseList->Add(keymap);
1055 }
1056 b->Add(keymap, keymap->GetName());
1057 mr = mr->GetNext(fOffset);
1058 }
1059
1061
1062 }
1063}
1064
1065////////////////////////////////////////////////////////////////////////////////
1066/// Cd to associated directory.
1067
1068Bool_t TMapFile::cd(const char *path)
1069{
1070 if (fDirectory)
1071 return fDirectory->cd(path);
1072 return kFALSE;
1073}
1074
1075////////////////////////////////////////////////////////////////////////////////
1076/// List contents of TMapFile.
1077
1079{
1080 if (fMmallocDesc) {
1081
1082 ((TMapFile*)this)->AcquireSemaphore();
1083
1084 Printf("%-20s %-20s %-10s", "Object", "Class", "Size");
1085 if (!fFirst)
1086 Printf("*** no objects stored in memory mapped file ***");
1087
1088 TMapRec *mr = GetFirst();
1089 while (OrgAddress(mr)) {
1090 Printf("%-20s %-20s %-10d", mr->GetName(fOffset),
1091 mr->GetClassName(fOffset), mr->fBufSize);
1092 mr = mr->GetNext(fOffset);
1093 }
1094
1095 ((TMapFile*)this)->ReleaseSemaphore();
1096
1097 }
1098}
1099
1100////////////////////////////////////////////////////////////////////////////////
1101/// Increment statistics for buffer sizes of objects in this file.
1102
1104{
1105 fWritten++;
1106 fSumBuffer += bufsize;
1107 fSum2Buffer += bufsize*bufsize;
1108}
1109
1110////////////////////////////////////////////////////////////////////////////////
1111/// Return the best buffer size for objects in this file.
1112///
1113/// The best buffer size is estimated based on the current mean value
1114/// and standard deviation of all objects written so far to this file.
1115/// Returns mean value + one standard deviation.
1116
1118{
1119 if (!fWritten) return TBuffer::kMinimalSize;
1121 Double_t rms2 = TMath::Abs(fSum2Buffer/fSumBuffer - mean*mean);
1122 return (Int_t)(mean + std::sqrt(rms2));
1123}
1124
1125////////////////////////////////////////////////////////////////////////////////
1126/// Return the current location in the memory region for this malloc heap which
1127/// represents the end of memory in use. Returns 0 if map file was closed.
1128
1130{
1131 if (!fMmallocDesc) return 0;
1132 return (void *)((struct mdesc *)fMmallocDesc)->breakval;
1133}
1134
1135////////////////////////////////////////////////////////////////////////////////
1136/// Create a memory mapped file.
1137///
1138/// This opens a file (to which the
1139/// memory will be mapped) and attaches a memory region to it.
1140/// Option can be either: "NEW", "CREATE", "RECREATE", "UPDATE"
1141/// or "READ" (see TFile). The default open mode is "READ". The size
1142/// argument specifies the maximum size of shared memory file in bytes.
1143/// TMapFile's can only be created via this method. Create() enforces that
1144/// a TMapFile is always on the memory mapped heap (when "NEW", "CREATE"
1145/// or "RECREATE" are used).
1146
1148 const char *title)
1149{
1150 TMapFile *newMapFile;
1151 new TMapFile(name, title, option, size, newMapFile);
1152
1153 return newMapFile;
1154}
1155
1156////////////////////////////////////////////////////////////////////////////////
1157/// Set preferred map address.
1158///
1159/// Find out preferred map address as follows:
1160/// -# Run consumer program to find the preferred map address. Remember begin of mapped region, i.e. 0x40b4c000
1161/// ~~~{.cpp}
1162/// $ root
1163/// root [0] m = TMapFile::Create("dummy.map", "recreate", 10000000);
1164/// root [1] m.Print()
1165/// Memory mapped file: dummy.map
1166/// Title:
1167/// Option: CREATE
1168/// Mapped Memory region: 0x40b4c000 - 0x40d95f00 (2.29 MB)
1169/// Current breakval: 0x40b53000
1170/// root [2] .q
1171/// $ rm dummy.map
1172/// ~~~
1173/// -# Add to producer program, just before creating the TMapFile:
1174/// TMapFile::SetMapAddress(0x40b4c000);
1175///
1176/// Repeat this if more than one map file is being used.
1177/// The above procedure allow programs using, e.g., different number of
1178/// shared libraries (that cause the default mapping address to be
1179/// different) to create shared memory regions in the same location
1180/// without overwriting a shared library. The above assumes the consumer
1181/// program is larger (i.e. has more shared memory occupied) than the
1182/// producer. If this is not true inverse the procedure.
1183
1185{
1186 fgMapAddress = addr;
1187}
1188
1189////////////////////////////////////////////////////////////////////////////////
1190/// Return the base address at which we would like the next TMapFile's
1191/// mapped data to start.
1192///
1193/// For now, we let the system decide (start address 0). There are
1194/// a lot of issues to deal with here to make this work reasonably,
1195/// including:
1196/// - Avoid memory collisions with existing mapped address spaces
1197/// - Reclaim address spaces when their mmalloc heaps are unmapped
1198/// - When mmalloc heaps are shared between processes they have to be
1199/// mapped at the same addresses in each
1200///
1201/// Once created, a mmalloc heap that is to be mapped back in must be
1202/// mapped at the original address. I.e. each TMapFile will expect
1203/// to be remapped at it's original address. This becomes a problem if
1204/// the desired address is already in use.
1205
1207{
1208#ifdef R__HAVE_MMAP
1210 return (void *)fgMapAddress;
1211 else
1212 return (void *)-1;
1213#else
1214 return (void *)-1;
1215#endif
1216}
1217
1218////////////////////////////////////////////////////////////////////////////////
1219/// Need special "operator delete" in which we close the shared memory.
1220/// This has to be done after the dtor chain has been finished.
1221
1222void TMapFile::operator delete(void *ptr)
1223{
1224 mmalloc_detach(fgMmallocDesc);
1225 fgMmallocDesc = 0;
1226
1227 TObject::operator delete(ptr);
1228}
1229
1230////////////////////////////////////////////////////////////////////////////////
1231
1233{
1234 // Don't use gROOT so that this routine does not trigger TROOT's initialization
1235 // This is essential since this routine is called via operator delete
1236 // which is used during RegisterModule (i.e. during library loading, including the initial
1237 // start up). Using gROOT leads to recursive call to RegisterModule and initialization of
1238 // the interpreter in the middle of the execution of RegisterModule (i.e. undefined behavior).
1239 if (!ROOT::Internal::gROOTLocal || !ROOT::Internal::gROOTLocal->GetListOfMappedFiles())
1240 return 0;
1241
1242 TObjLink *lnk = ((TList *)ROOT::Internal::gROOTLocal->GetListOfMappedFiles())->LastLink();
1243 while (lnk) {
1244 TMapFile *mf = (TMapFile*)lnk->GetObject();
1245 if (!mf) return 0;
1246 if ((ULongptr_t)addr >= mf->fBaseAddr + mf->fOffset &&
1247 (ULongptr_t)addr < (ULongptr_t)mf->GetBreakval() + mf->fOffset)
1248 return mf;
1249 lnk = lnk->Prev();
1250 }
1251 return 0;
1252}
1253
#define b(i)
Definition RSha256.hxx:100
#define f(i)
Definition RSha256.hxx:104
static void update(gsl_integration_workspace *workspace, double a1, double b1, double area1, double error1, double a2, double b2, double area2, double error2)
static void cleanup()
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
long Longptr_t
Definition RtypesCore.h:82
unsigned long ULongptr_t
Definition RtypesCore.h:83
constexpr Bool_t kFALSE
Definition RtypesCore.h:101
constexpr Bool_t kTRUE
Definition RtypesCore.h:100
const char Option_t
Definition RtypesCore.h:66
#define ClassImp(name)
Definition Rtypes.h:377
#define gDirectory
Definition TDirectory.h:386
Option_t Option_t option
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h offset
char name[80]
Definition TGX11.cxx:110
struct SetFreeIfTMapFile_t gSetFreeIfTMapFile
#define INVALID_HANDLE_VALUE
Definition TMapFile.cxx:84
R__EXTERN TVirtualMutex * gROOTMutex
Definition TROOT.h:63
#define gROOT
Definition TROOT.h:405
void Printf(const char *fmt,...)
Formats a string in a circular formatting buffer and prints the string.
Definition TString.cxx:2481
char * StrDup(const char *str)
Duplicate the string str.
Definition TString.cxx:2535
@ kFileExists
Definition TSystem.h:44
@ kReadPermission
Definition TSystem.h:47
@ kWritePermission
Definition TSystem.h:46
R__EXTERN TSystem * gSystem
Definition TSystem.h:560
#define R__LOCKGUARD(mutex)
Using a TBrowser one can browse all ROOT objects.
Definition TBrowser.h:37
The concrete implementation of TBuffer for writing/reading to/from a ROOT file or socket.
Definition TBufferFile.h:47
@ kWrite
Definition TBuffer.h:73
@ kRead
Definition TBuffer.h:73
@ kMinimalSize
Definition TBuffer.h:78
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition TClass.h:81
void * New(ENewType defConstructor=kClassNew, Bool_t quiet=kFALSE) const
Return a pointer to a newly allocated object of this class.
Definition TClass.cxx:4978
static TClass * GetClass(const char *name, Bool_t load=kTRUE, Bool_t silent=kFALSE)
Static method returning pointer to TClass of the specified class name.
Definition TClass.cxx:2968
A ROOT file is structured in Directories (like a file system).
virtual void Build(TFile *motherFile=nullptr, TDirectory *motherDir=nullptr)
Definition TDirectory.h:186
virtual Bool_t cd()
Change current directory to "this" directory.
void SetName(const char *newname) override
Set the name for directory If the directory name is changed after the directory was written once,...
virtual void SetMother(TObject *mother)
Definition TDirectory.h:258
Utility class for browsing TMapFile objects.
Definition TKeyMapFile.h:20
A doubly linked list.
Definition TList.h:38
TObject * FindObject(const char *name) const override
Find an object in this list using its name.
Definition TList.cxx:578
void Add(TObject *obj) override
Definition TList.h:81
void Delete(Option_t *option="") override
Remove all objects from the list AND delete all heap based objects.
Definition TList.cxx:470
This class implements a shared memory region mapped to a file.
Definition TMapFile.h:25
static TMapFile * WhichMapFile(void *addr)
void * GetBreakval() const
Return the current location in the memory region for this malloc heap which represents the end of mem...
Int_t fWritten
Number of objects written so far.
Definition TMapFile.h:47
static TMapFile * Create(const char *name, Option_t *option="READ", Int_t size=kDefaultMapSize, const char *title="")
Create a memory mapped file.
TMapRec * fLast
Last object in list of shared objects.
Definition TMapFile.h:39
Int_t fVersion
ROOT version (or -1 for shadow map file)
Definition TMapFile.h:31
Bool_t IsFolder() const override
Returns kTRUE in case object is a folder (i.e. contains browsable lists).
ULongptr_t fBaseAddr
Base address of mapped memory region.
Definition TMapFile.h:36
const char * GetName() const override
Returns name of object.
Definition TMapFile.h:93
void ls(Option_t *option="") const override
List contents of TMapFile.
void Close(Option_t *option="")
Close a mapped file.
Definition TMapFile.cxx:954
TDirectory * fDirectory
Pointer to directory associated to this mapfile.
Definition TMapFile.h:41
void SumBuffer(Int_t bufsize)
Increment statistics for buffer sizes of objects in this file.
const char * GetTitle() const override
Returns title of object.
Definition TMapFile.h:96
TObject * Get(const char *name, TObject *retObj=nullptr)
Return pointer to object retrieved from shared memory.
Definition TMapFile.cxx:775
void Print(Option_t *option="") const override
Print some info about the mapped file.
char * fTitle
Title of mapped file.
Definition TMapFile.h:33
void InitDirectory()
Create the directory associated to this mapfile.
Definition TMapFile.cxx:580
void RemoveAll()
Remove all objects from shared memory.
Definition TMapFile.cxx:750
Double_t fSum2Buffer
Sum of squares of buffer sizes of objects written so far.
Definition TMapFile.h:49
Bool_t fWritable
TRUE if mapped file opened in RDWR mode.
Definition TMapFile.h:43
Longptr_t fOffset
Offset in bytes for region mapped by reader.
Definition TMapFile.h:40
void * OrgAddress(void *addr) const
Definition TMapFile.h:101
Bool_t cd(const char *path=nullptr)
Cd to associated directory.
void DeleteSemaphore()
Delete the semaphore.
Definition TMapFile.cxx:852
Longptr_t fSemaphore
Modification semaphore (or getpid() for WIN32)
Definition TMapFile.h:44
TList * fBrowseList
List of KeyMapFile objects.
Definition TMapFile.h:42
TMapRec * fFirst
List of streamed objects is shared memory.
Definition TMapFile.h:38
ULongptr_t fhSemaphore
HANDLE of WIN32 Mutex object to implement semaphore.
Definition TMapFile.h:45
static void * MapToAddress()
Return the base address at which we would like the next TMapFile's mapped data to start.
void Update(TObject *obj=nullptr)
Update an object (or all objects, if obj == 0) in shared memory.
Definition TMapFile.cxx:634
TObject * fGetting
Don't deadlock in update mode, when from Get() Add() is called.
Definition TMapFile.h:46
TMapFile * FindShadowMapFile()
Returns shadow map file.
Definition TMapFile.cxx:999
void * fMmallocDesc
Pointer to mmalloc descriptor.
Definition TMapFile.h:35
Double_t fSumBuffer
Sum of buffer sizes of objects written so far.
Definition TMapFile.h:48
static void * fgMmallocDesc
Used in Close() and operator delete()
Definition TMapFile.h:52
void CreateSemaphore(Int_t pid=0)
Create semaphore used for synchronizing access to shared memory.
Definition TMapFile.cxx:822
Longptr_t fFd
Descriptor of mapped file.
Definition TMapFile.h:30
Int_t fSize
Original start size of memory mapped region.
Definition TMapFile.h:37
TObject * Remove(TObject *obj, Bool_t lock)
Remove object from shared memory.
Definition TMapFile.cxx:674
Int_t ReleaseSemaphore()
Release semaphore. Returns 0 if OK, -1 on error.
Definition TMapFile.cxx:922
static void SetMapAddress(Longptr_t addr)
Set preferred map address.
char * fName
Name of mapped file.
Definition TMapFile.h:32
TMapFile()
Default ctor. Does not much except setting some basic values.
Definition TMapFile.cxx:198
char * fOption
Directory creation options.
Definition TMapFile.h:34
friend class TMapRec
Definition TMapFile.h:27
Int_t AcquireSemaphore()
Acquire semaphore. Returns 0 if OK, -1 on error.
Definition TMapFile.cxx:877
void Browse(TBrowser *b) override
Browse contents of TMapFile.
void Add(const TObject *obj, const char *name="")
Add an object to the list of objects to be stored in shared memory.
Definition TMapFile.cxx:595
virtual ~TMapFile()
TMapFiles may not be deleted, since we want to keep the complete TMapFile object in the mapped file f...
Definition TMapFile.cxx:547
static Longptr_t fgMapAddress
Map to this address, set address via SetMapAddress()
Definition TMapFile.h:51
Int_t GetBestBuffer()
Return the best buffer size for objects in this file.
TMapRec * GetFirst() const
Definition TMapFile.h:97
Keep track of an object in the mapped file.
Definition TMapFile.h:132
TObject * fObject
Pointer to original object.
Definition TMapFile.h:139
Int_t fBufSize
Buffer size.
Definition TMapFile.h:141
TMapRec(const TMapRec &)=delete
char * fName
Object name.
Definition TMapFile.h:137
const char * GetClassName(Longptr_t offset=0) const
Definition TMapFile.h:151
TMapRec * fNext
Next MapRec in list.
Definition TMapFile.h:142
TObject * GetObject() const
This method returns a pointer to the original object.
Definition TMapFile.cxx:185
const char * GetName(Longptr_t offset=0) const
Definition TMapFile.h:150
TMapRec * GetNext(Longptr_t offset=0) const
Definition TMapFile.h:155
void * GetBuffer(Longptr_t offset=0) const
Definition TMapFile.h:152
char * fClassName
Class name.
Definition TMapFile.h:138
void * fBuffer
Buffer containing object of class name.
Definition TMapFile.h:140
~TMapRec()
Destructor.
Definition TMapFile.cxx:173
virtual void SetTitle(const char *title="")
Set the title of the TNamed.
Definition TNamed.cxx:164
const char * GetName() const override
Returns name of object.
Definition TNamed.h:47
Mother of all ROOT objects.
Definition TObject.h:41
virtual const char * GetName() const
Returns name of object.
Definition TObject.cxx:439
virtual void Streamer(TBuffer &)
Stream an object of class TObject.
Definition TObject.cxx:882
virtual void SysError(const char *method, const char *msgfmt,...) const
Issue system error message.
Definition TObject.cxx:984
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition TObject.cxx:207
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:956
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:970
static void SetDtorOnly(void *obj)
Set destructor only flag.
Definition TObject.cxx:1067
void MakeZombie()
Definition TObject.h:53
static Bool_t HasCustomNewDelete()
return the has custom delete flag
Definition TStorage.cxx:494
Basic string class.
Definition TString.h:139
int CompareTo(const char *cs, ECaseCompare cmp=kExact) const
Compare a string to char *cs2.
Definition TString.cxx:450
@ kIgnoreCase
Definition TString.h:279
static void ResetErrno()
Static function resetting system error number.
Definition TSystem.cxx:279
virtual Bool_t ExpandPathName(TString &path)
Expand a pathname getting rid of special shell characters like ~.
Definition TSystem.cxx:1277
static Int_t GetErrno()
Static function returning system error number.
Definition TSystem.cxx:263
virtual Bool_t AccessPathName(const char *path, EAccessMode mode=kFileExists)
Returns FALSE if one can access a file using the specified access mode.
Definition TSystem.cxx:1299
virtual int Unlink(const char *name)
Unlink, i.e.
Definition TSystem.cxx:1384
const Int_t n
Definition legend1.C:16
#define FALSE
Definition mesh.c:45
R__EXTERN TROOT * gROOTLocal
Definition TROOT.h:378
R__EXTERN FreeIfTMapFile_t * gFreeIfTMapFile
Definition TStorage.h:148
R__EXTERN void * gMmallocDesc
Definition TStorage.h:149
Short_t Abs(Short_t d)
Returns the absolute value of parameter Short_t d.
Definition TMathBase.h:123
Set ROOT::Internal::gFreeIfTMapFile on library load.
Definition TMapFile.cxx:147