1 ------------------------------------------------------------------------------
3 -- GNAT RUN-TIME COMPONENTS --
5 -- S Y S T E M . M M A P . O S _ I N T E R F A C E --
9 -- Copyright (C) 2007-2016, AdaCore --
11 -- This library is free software; you can redistribute it and/or modify it --
12 -- under terms of the GNU General Public License as published by the Free --
13 -- Software Foundation; either version 3, or (at your option) any later --
14 -- version. This library is distributed in the hope that it will be useful, --
15 -- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- --
16 -- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. --
18 -- As a special exception under Section 7 of GPL version 3, you are granted --
19 -- additional permissions described in the GCC Runtime Library Exception, --
20 -- version 3.1, as published by the Free Software Foundation. --
22 -- You should have received a copy of the GNU General Public License and --
23 -- a copy of the GCC Runtime Library Exception along with this program; --
24 -- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
25 -- <http://www.gnu.org/licenses/>. --
27 -- GNAT was originally developed by the GNAT team at New York University. --
28 -- Extensive contributions were provided by Ada Core Technologies Inc. --
30 ------------------------------------------------------------------------------
32 with Ada
.IO_Exceptions
;
33 with System
; use System
;
35 with System
.OS_Lib
; use System
.OS_Lib
;
36 with System
.Mmap
.Unix
; use System
.Mmap
.Unix
;
38 package body System
.Mmap
.OS_Interface
is
41 (Addr
: File_Size
) return File_Size
;
42 -- Align some offset/length to the lowest page boundary
44 function Is_Mapping_Available
return Boolean renames
45 System
.Mmap
.Unix
.Is_Mapping_Available
;
46 -- Wheter memory mapping is actually available on this system. It is an
47 -- error to use Create_Mapping and Dispose_Mapping if this is False.
55 Use_Mmap_If_Available
: Boolean := True) return System_File
is
56 Fd
: constant File_Descriptor
:=
57 Open_Read
(Filename
, Binary
);
59 if Fd
= Invalid_FD
then
60 return Invalid_System_File
;
64 Mapped
=> Use_Mmap_If_Available
and then Is_Mapping_Available
,
66 Length
=> File_Size
(File_Length
(Fd
)));
75 Use_Mmap_If_Available
: Boolean := True) return System_File
is
76 Fd
: constant File_Descriptor
:=
77 Open_Read_Write
(Filename
, Binary
);
79 if Fd
= Invalid_FD
then
80 return Invalid_System_File
;
84 Mapped
=> Use_Mmap_If_Available
and then Is_Mapping_Available
,
86 Length
=> File_Size
(File_Length
(Fd
)));
93 procedure Close
(File
: in out System_File
) is
96 File
.Fd
:= Invalid_FD
;
103 function Read_From_Disk
105 Offset
, Length
: File_Size
) return System
.Strings
.String_Access
107 Buffer
: String_Access
:= new String (1 .. Integer (Length
));
109 -- ??? Lseek offset should be a size_t instead of a Long_Integer
111 Lseek
(File
.Fd
, Long_Integer (Offset
), Seek_Set
);
112 if System
.OS_Lib
.Read
(File
.Fd
, Buffer
.all'Address, Integer (Length
))
115 System
.Strings
.Free
(Buffer
);
116 raise Ada
.IO_Exceptions
.Device_Error
;
125 procedure Write_To_Disk
127 Offset
, Length
: File_Size
;
128 Buffer
: System
.Strings
.String_Access
) is
130 pragma Assert
(File
.Write
);
131 Lseek
(File
.Fd
, Long_Integer (Offset
), Seek_Set
);
132 if System
.OS_Lib
.Write
(File
.Fd
, Buffer
.all'Address, Integer (Length
))
135 raise Ada
.IO_Exceptions
.Device_Error
;
143 procedure Create_Mapping
145 Offset
, Length
: in out File_Size
;
147 Mapping
: out System_Mapping
)
153 Prot
:= PROT_READ
+ PROT_WRITE
;
158 Prot
:= Prot
+ PROT_WRITE
;
160 Flags
:= MAP_PRIVATE
;
163 -- Adjust offset and mapping length to account for the required
164 -- alignment of offset on page boundary.
167 Queried_Offset
: constant File_Size
:= Offset
;
169 Offset
:= Align
(Offset
);
171 -- First extend the length to compensate the offset shift, then align
172 -- it on the upper page boundary, so that the whole queried area is
175 Length
:= Length
+ Queried_Offset
- Offset
;
176 Length
:= Align
(Length
+ Get_Page_Size
- 1);
179 if Length
> File_Size
(Integer'Last) then
180 raise Ada
.IO_Exceptions
.Device_Error
;
183 (Address
=> System
.Mmap
.Unix
.Mmap
184 (Offset
=> off_t
(Offset
),
185 Length
=> Interfaces
.C
.size_t
(Length
),
193 ---------------------
194 -- Dispose_Mapping --
195 ---------------------
197 procedure Dispose_Mapping
198 (Mapping
: in out System_Mapping
)
201 pragma Unreferenced
(Ignored
);
204 (Mapping
.Address
, Interfaces
.C
.size_t
(Mapping
.Length
));
205 Mapping
:= Invalid_System_Mapping
;
212 function Get_Page_Size
return File_Size
is
213 function Internal
return Integer;
214 pragma Import
(C
, Internal
, "getpagesize");
216 return File_Size
(Internal
);
224 (Addr
: File_Size
) return File_Size
is
226 return Addr
- Addr
mod Get_Page_Size
;
229 end System
.Mmap
.OS_Interface
;