]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.nativemem/src/org/simantics/nativemem/NativeMem.java
Rudimentary Linux and MacOSX support for org.simantics.nativemem
[simantics/platform.git] / bundles / org.simantics.nativemem / src / org / simantics / nativemem / NativeMem.java
1 /*******************************************************************************
2  * Copyright (c) 2016, 2017 Association for Decentralized Information Management
3  * in Industry THTH ry.
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v1.0
6  * which accompanies this distribution, and is available at
7  * http://www.eclipse.org/legal/epl-v10.html
8  *
9  * Contributors:
10  *     Semantum Oy - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.nativemem;
13
14 import java.lang.reflect.InvocationTargetException;
15
16 import org.simantics.nativemem.internal.Arch;
17 import org.simantics.nativemem.internal.DummyProcessMemoryInfo;
18 import org.simantics.nativemem.internal.CMemoryInfo;
19 import org.simantics.nativemem.internal.OS;
20 import org.simantics.nativemem.internal.Resource;
21 import org.simantics.nativemem.internal.Resource32;
22 import org.simantics.nativemem.internal.Resource64;
23 import org.simantics.nativemem.internal.linux.Stat;
24 import org.simantics.nativemem.internal.win.ProcessMemoryCounters;
25 import org.simantics.nativemem.internal.win.Psapi32;
26 import org.simantics.nativemem.internal.win.Psapi64;
27
28 import com.sun.jna.platform.win32.Kernel32;
29 import com.sun.jna.platform.win32.WinNT.HANDLE;
30
31
32 public class NativeMem {
33
34     /**
35      * @param out
36      *            the structure to write the result into or <code>null</code> to
37      *            create a new structure
38      * @return the result structure
39      */
40     public static ProcessMemoryInfo getMemoryInfo(ProcessMemoryInfo out) {
41         switch (OS.calculate()) {
42         case WINDOWS:
43             return getProcessMemoryCounters(out);
44
45         case APPLE:
46             return getCMemoryInfo(out);
47
48         case LINUX: {
49             CMemoryInfo info = getCMemoryInfo(out);
50             info.peakRSS *= 1024L;
51             getCurrentRSS(info);
52             return info;
53         }
54
55         default:
56             return DummyProcessMemoryInfo.INSTANCE;
57         }
58     }
59
60     private static ProcessMemoryCounters getProcessMemoryCounters(ProcessMemoryInfo out) {
61         ProcessMemoryCounters counters = castOrCreate(out, ProcessMemoryCounters.class);
62         HANDLE proc = Kernel32.INSTANCE.GetCurrentProcess();
63         switch (Arch.calculate()) {
64         case X86: {
65             Psapi32.PROCESS_MEMORY_COUNTERS_EX pmem = new Psapi32.PROCESS_MEMORY_COUNTERS_EX();
66             boolean ok = Psapi32.INSTANCE.GetProcessMemoryInfo(proc, pmem, pmem.size());
67             if (ok)
68                 pmem.writeTo(counters);
69             return counters;
70         }
71
72         case X86_64: {
73             Psapi64.PROCESS_MEMORY_COUNTERS_EX pmem = new Psapi64.PROCESS_MEMORY_COUNTERS_EX();
74             boolean ok = Psapi64.INSTANCE.GetProcessMemoryInfo(proc, pmem, pmem.size());
75             if (ok)
76                 pmem.writeTo(counters);
77             return counters;
78         }
79
80         default:
81             return counters;
82         }
83     }
84
85     private static CMemoryInfo getCMemoryInfo(ProcessMemoryInfo out) {
86         CMemoryInfo info = castOrCreate(out, CMemoryInfo.class);
87
88         switch (Arch.calculate()) {
89         case X86: {
90             Resource32.Rusage rusage = new Resource32.Rusage();
91             int ok = Resource32.INSTANCE.getrusage(Resource.RUSAGE_SELF, rusage);
92             if (ok == 0)
93                 rusage.writeTo(info);
94             return info;
95         }
96
97         case X86_64: {
98             Resource64.Rusage rusage = new Resource64.Rusage();
99             int ok = Resource64.INSTANCE.getrusage(Resource.RUSAGE_SELF, rusage);
100             if (ok == 0)
101                 rusage.writeTo(info);
102             return info;
103         }
104
105         default:
106             return info;
107         }
108     }
109
110     private static CMemoryInfo getCurrentRSS(ProcessMemoryInfo out) {
111         CMemoryInfo info = castOrCreate(out, CMemoryInfo.class);
112
113         switch (Arch.calculate()) {
114         case X86: {
115             long rss = Stat.getCurrentRSS(Resource32.INSTANCE);
116             if (rss >= 0)
117                 info.currentRSS = rss;
118             return info;
119         }
120
121         case X86_64: {
122             long rss = Stat.getCurrentRSS(Resource64.INSTANCE);
123             if (rss >= 0)
124                 info.currentRSS = rss;
125             return info;
126         }
127
128         default:
129             return info;
130         }
131     }
132
133     private static <T> T castOrCreate(Object o, Class<T> clazz) {
134         if (clazz.isInstance(o))
135             return clazz.cast(o);
136         try {
137             return clazz.getConstructor().newInstance();
138         } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException
139                 | NoSuchMethodException | SecurityException e) {
140             throw new Error("Class " + clazz + " does not have a public parameterless constructor", e);
141         }
142     }
143
144 }