1 //
2 // Copyright (c) 2010-2018 Antmicro
3 // Copyright (c) 2011-2015 Realtime Embedded
4 //
5 // This file is licensed under the MIT License.
6 // Full license text is available in 'licenses/MIT.txt'.
7 //
8 using System;
9 using System.Runtime.InteropServices;
10 using System.Threading;
11 using Antmicro.Renode.Core;
12 using Antmicro.Migrant.Hooks;
13 using Antmicro.Migrant;
14 
15 namespace Antmicro.Renode.Core
16 {
17     public sealed class SerializableMappedSegment : IMappedSegment, IDisposable
18     {
SerializableMappedSegment(ulong size, ulong startingOffset)19         public SerializableMappedSegment(ulong size, ulong startingOffset)
20         {
21             Size = size;
22             StartingOffset = startingOffset;
23             MakeSegment();
24         }
25 
26         public IntPtr Pointer { get { return pointer; } }
27 
28         public ulong StartingOffset { get; private set; }
29 
30         public ulong Size { get; private set; }
31 
Touch()32         public void Touch()
33         {
34             if(pointer != IntPtr.Zero)
35             {
36                 return;
37             }
38             var sizeAsInt = checked((int)Size);
39             pointer = Marshal.AllocHGlobal(sizeAsInt);
40             var zeroBuf = new byte[sizeAsInt];
41             Marshal.Copy(zeroBuf, 0, pointer, sizeAsInt);
42         }
43 
Dispose()44         public void Dispose()
45         {
46             var oldPointer = Interlocked.Exchange(ref pointer, IntPtr.Zero);
47             if(oldPointer != IntPtr.Zero)
48             {
49                 Marshal.FreeHGlobal(oldPointer);
50             }
51         }
52 
53         [PreSerialization]
PrepareBuffer()54         private void PrepareBuffer()
55         {
56             if(pointer == IntPtr.Zero)
57             {
58                 return;
59             }
60             var sizeAsInt = checked((int)Size);
61             buffer = new byte[sizeAsInt];
62             Marshal.Copy(pointer, buffer, 0, sizeAsInt);
63         }
64 
65         [PostSerialization]
DisposeBuffer()66         private void DisposeBuffer()
67         {
68             buffer = null;
69         }
70 
71         [PostDeserialization]
MakeSegment()72         private void MakeSegment()
73         {
74             if(pointer != IntPtr.Zero)
75             {
76                 throw new InvalidOperationException("Unexpected non null pointer during initialization.");
77             }
78             if(buffer != null)
79             {
80                 Touch();
81                 Marshal.Copy(buffer, 0, pointer, checked((int)Size));
82                 buffer = null;
83             }
84         }
85 
86         [Transient]
87         private IntPtr pointer;
88         private byte[] buffer;
89     }
90 }
91 
92