[Tizen.System.Information][Non-ACR] Add API for internal (#2740)
authoryunmiha <49266695+yunmiha@users.noreply.github.com>
Tue, 16 Mar 2021 10:57:51 +0000 (19:57 +0900)
committerGitHub <noreply@github.com>
Tue, 16 Mar 2021 10:57:51 +0000 (19:57 +0900)
* [Tizen.System.Information] Add API

- GetGemRss
- GetGpu
- GetSwap

Signed-off-by: Yunmi Ha <yunmi.ha@samsung.com>
* [Tizen.System.Information] Add API

    - GetGemRss
    - GetGpu
    - GetSwap

Signed-off-by: Yunmi Ha <yunmi.ha@samsung.com>
* Fix build warning

Signed-off-by: Yunmi Ha <yunmi.ha@samsung.com>
* Update src/Tizen.System.Information/Interop/Interop.RuntimeInfo.cs

Co-authored-by: WonYoung Choi <wy80.choi@samsung.com>
* Update src/Tizen.System.Information/Usage/ProcessMemoryUsage.cs

Co-authored-by: WonYoung Choi <wy80.choi@samsung.com>
* Update src/Tizen.System.Information/Usage/ProcessMemoryUsage.cs

Co-authored-by: WonYoung Choi <wy80.choi@samsung.com>
* Update src/Tizen.System.Information/Usage/ProcessMemoryUsage.cs

Co-authored-by: WonYoung Choi <wy80.choi@samsung.com>
* Update src/Tizen.System.Information/Interop/Interop.RuntimeInfo.cs

Co-authored-by: WonYoung Choi <wy80.choi@samsung.com>
* Update src/Tizen.System.Information/Usage/ProcessMemoryUsage.cs

Co-authored-by: WonYoung Choi <wy80.choi@samsung.com>
* Update src/Tizen.System.Information/Usage/ProcessMemoryUsage.cs

Co-authored-by: WonYoung Choi <wy80.choi@samsung.com>
* Update src/Tizen.System.Information/Usage/ProcessMemoryUsage.cs

Co-authored-by: WonYoung Choi <wy80.choi@samsung.com>
* Update Interop.RuntimeInfo.cs

* Update ProcessMemoryUsage.cs

* Create ProcessMemoryUsage.cs

* Update ProcessMemoryUsage.cs

* Update ProcessMemoryUsage.cs

* Update ProcessMemoryUsage.cs

* [Tizen.System.Information][Non-ACR] Fix memory leak

Signed-off-by: Yunmi Ha <yunmi.ha@samsung.com>
Co-authored-by: WonYoung Choi <wy80.choi@samsung.com>
src/Tizen.System.Information/Interop/Interop.Libc.cs [new file with mode: 0755]
src/Tizen.System.Information/Interop/Interop.Libraries.cs [changed mode: 0644->0755]
src/Tizen.System.Information/Interop/Interop.RuntimeInfo.cs
src/Tizen.System.Information/Usage/ProcessMemoryUsage.cs

diff --git a/src/Tizen.System.Information/Interop/Interop.Libc.cs b/src/Tizen.System.Information/Interop/Interop.Libc.cs
new file mode 100755 (executable)
index 0000000..ef021f1
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+* Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+*
+* Licensed under the Apache License, Version 2.0 (the License);
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an AS IS BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+using System;
+using System.Runtime.InteropServices;
+
+internal static partial class Interop
+{
+    internal static partial class Libc
+    {
+        [DllImport(Libraries.Libc, EntryPoint = "free")]
+        public static extern void Free(IntPtr ptr);
+    }
+}
old mode 100644 (file)
new mode 100755 (executable)
index ddb1884..60ae721
@@ -20,5 +20,6 @@ internal static partial class Interop
     {
         internal const string RuntimeInfo = "libcapi-system-runtime-info.so.0";
         internal const string SystemInfo = "libcapi-system-info.so.0";
+        internal const string Libc = "libc.so.6";
     }
 }
index fb51f52..681ae93 100755 (executable)
@@ -15,6 +15,7 @@
 */
 
 using System;
+using System.ComponentModel;
 using System.Runtime.InteropServices;
 using Tizen.Internals;
 using Tizen.System;
@@ -67,6 +68,54 @@ internal static partial class Interop
             public readonly uint STime;
         }
 
+        /// <summary>
+        /// Enumeration for the process memory information key.
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public enum ProcessMemoryInfoKey
+        {
+            /// <summary>
+            /// Virtual memory size (KiB)
+            /// </summary>
+            Vsz = 100,
+            /// <summary>
+            /// Resident set size (KiB)
+            /// </summary>
+            Rss = 200,
+            /// <summary>
+            /// Proportional set size (KiB)
+            /// </summary>
+            Pss = 300,
+            /// <summary>
+            /// Not modified and mapped by other processes (KiB)
+            /// </summary>
+            SharedClean = 400,
+            /// <summary>
+            /// Modified and mapped by other processes (KiB)
+            /// </summary>
+            SharedDirty = 500,
+            /// <summary>
+            /// Not modified and available only to that process (KiB)
+            /// </summary>
+            PrivateClean = 600,
+            /// <summary>
+            /// Modified and available only to that process (KiB)
+            /// </summary>
+            PrivateDirty = 700,
+            /// <summary>
+            /// SWAP memory size (KiB)
+            /// </summary>
+            Swap = 800,
+            /// <summary>
+            /// GPU memory size (KiB)
+            /// </summary>
+            Gpu = 900,
+            /// <summary>
+            /// Resident set size in graphic execution manager (KiB)
+            /// </summary>
+            GemRss = 1000
+        }
+
         [DllImport(Libraries.RuntimeInfo, EntryPoint = "runtime_info_get_value_int")]
         public static extern InformationError GetValue(RuntimeInfoKey key, out int status);
 
@@ -105,5 +154,8 @@ internal static partial class Interop
 
         [DllImport(Libraries.RuntimeInfo, EntryPoint = "runtime_info_unset_changed_cb")]
         public static extern InformationError UnsetRuntimeInfoChangedCallback(RuntimeInfoKey runtimeInfoKey);
+
+        [DllImport(Libraries.RuntimeInfo, EntryPoint = "runtime_info_get_process_memory_value_int")]
+        public static extern InformationError GetProcessMemoryValueInt(int[] pid, int size, ProcessMemoryInfoKey memoryInfoKey, out IntPtr array);
     }
 }
index 02c03bb..9583f81 100755 (executable)
@@ -15,6 +15,7 @@
 */
 
 using System;
+using System.ComponentModel;
 using System.Collections.Generic;
 using System.IO;
 using System.Linq;
@@ -30,6 +31,9 @@ namespace Tizen.System
     {
         private int[] Pids;
         private Interop.RuntimeInfo.ProcessMemoryInfo[] Usages;
+        private int[] Swaps;
+        private int[] Gpus;
+        private int[] Gems;
 
         /// <summary>
         /// The constructor of ProcessMemoryInformation class.
@@ -50,7 +54,7 @@ namespace Tizen.System
         /// The number of usage entries.
         /// </summary>
         /// <since_tizen> 4 </since_tizen>
-        public int Count { get; internal set; }
+        public int Count => Pids.Length;
 
         /// <summary>
         /// Gets the virtual memory size of a process.
@@ -179,6 +183,108 @@ namespace Tizen.System
         }
 
         /// <summary>
+        /// Gets the GPU memory size of a process.
+        /// </summary>
+        /// <param name="pid">The process id.</param>
+        /// <returns>The GPU memory size <paramref name="pid"/> is using (KiB).</returns>
+        /// <exception cref="ArgumentException">Thrown when the <paramref name="pid"/> is invalid.</exception>
+        /// <exception cref="NotSupportedException">Thrown when the data is empty.</exception>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public int GetGPU(int pid)
+        {
+            if (Gpus == null)
+            {
+                Log.Error(InformationErrorFactory.LogTag, "No data");
+                InformationErrorFactory.ThrowException(InformationError.NoData);
+            }
+
+            for (int i = 0; i < Count; i++)
+                if (pid == Pids[i])
+                    return Gpus[i];
+
+            Log.Error(InformationErrorFactory.LogTag, "Invalid pid");
+            InformationErrorFactory.ThrowException(InformationError.InvalidParameter);
+            return 0;
+        }
+
+        /// <summary>
+        /// Gets the resident set size in graphic execution manager of a process.
+        /// </summary>
+        /// <param name="pid">The process id.</param>
+        /// <returns>The resident set size <paramref name="pid"/> is using (KiB).</returns>
+        /// <exception cref="ArgumentException">Thrown when the <paramref name="pid"/> is invalid.</exception>
+        /// <exception cref="NotSupportedException">Thrown when the data is empty.</exception>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public int GetGemRss(int pid)
+        {
+            if (Gems == null)
+            {
+                Log.Error(InformationErrorFactory.LogTag, "No data");
+                InformationErrorFactory.ThrowException(InformationError.NoData);
+            }
+
+            for (int i = 0; i < Count; i++)
+                if (pid == Pids[i])
+                    return Gems[i];
+
+            Log.Error(InformationErrorFactory.LogTag, "Invalid pid");
+            InformationErrorFactory.ThrowException(InformationError.InvalidParameter);
+            return 0;
+        }
+
+        /// <summary>
+        /// Gets the SWAP memory size of a process.
+        /// </summary>
+        /// <param name="pid">The process id.</param>
+        /// <returns>The SWAP memory size <paramref name="pid"/> is using (KiB).</returns>
+        /// <exception cref="ArgumentException">Thrown when the <paramref name="pid"/> is invalid.</exception>
+        /// <exception cref="NotSupportedException">Thrown when the data is empty.</exception>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public int GetSwap(int pid)
+        {
+            if (Swaps == null)
+            {
+                Log.Error(InformationErrorFactory.LogTag, "No data");
+                InformationErrorFactory.ThrowException(InformationError.NoData);
+            }
+
+            for (int i = 0; i < Count; i++)
+                if (pid == Pids[i])
+                    return Swaps[i];
+
+            Log.Error(InformationErrorFactory.LogTag, "Invalid pid");
+            InformationErrorFactory.ThrowException(InformationError.InvalidParameter);
+            return 0;
+        }
+
+        private int[] GetProcessMemoryValueInt(Interop.RuntimeInfo.ProcessMemoryInfoKey key, IEnumerable<int> pids)
+        {
+            var ret = Interop.RuntimeInfo.GetProcessMemoryValueInt(pids.ToArray<int>(), pids.ToArray<int>().Length, key, out IntPtr ptr);
+            if (ret != InformationError.None)
+            {
+                Log.Error(InformationErrorFactory.LogTag, "Interop failed to get process memory info: " + key.ToString());
+                if (ret == InformationError.NoData)
+                    return null;
+                InformationErrorFactory.ThrowException(ret);
+            }
+
+            try
+            {
+                var array = new int[Count];
+                unsafe
+                {
+                    for (int i = 0; i < Count; i++)
+                        array[i] = *((int*)ptr.ToPointer() + (i * sizeof(int)));
+                }
+                return array;
+            }
+            finally
+            {
+                Interop.Libc.Free(ptr);
+            }
+        }
+
+        /// <summary>
         /// Update the process memory information to the latest.
         /// </summary>
         /// <since_tizen> 4 </since_tizen>
@@ -194,21 +300,31 @@ namespace Tizen.System
 
             Pids = pid.ToArray<int>();
             IntPtr ptr = new IntPtr();
-            Count = Pids.Count<int>();
 
             ret = Interop.RuntimeInfo.GetProcessMemoryInfo(Pids, Count, ref ptr);
             if (ret != InformationError.None)
             {
-                Log.Error(InformationErrorFactory.LogTag, "Interop failed to get Process cpu usage");
+                Log.Error(InformationErrorFactory.LogTag, "Interop failed to get Process cpu usage.");
                 InformationErrorFactory.ThrowException(ret);
             }
-
-            Usages = new Interop.RuntimeInfo.ProcessMemoryInfo[Count];
-            for (int i = 0; i < Count; i++)
+            try
+            {
+                var data = ptr;
+                Usages = new Interop.RuntimeInfo.ProcessMemoryInfo[Count];
+                for (int i = 0; i < Count; i++)
+                {
+                    Usages[i] = Marshal.PtrToStructure<Interop.RuntimeInfo.ProcessMemoryInfo>(data);
+                    data += Marshal.SizeOf<Interop.RuntimeInfo.ProcessCpuUsage>();
+                }
+            }
+            finally
             {
-                Usages[i] = Marshal.PtrToStructure<Interop.RuntimeInfo.ProcessMemoryInfo>(ptr);
-                ptr += Marshal.SizeOf<Interop.RuntimeInfo.ProcessCpuUsage>();
+               Interop.Libc.Free(ptr);
             }
+
+            Gpus = GetProcessMemoryValueInt(Interop.RuntimeInfo.ProcessMemoryInfoKey.Gpu, pid);
+            Gems = GetProcessMemoryValueInt(Interop.RuntimeInfo.ProcessMemoryInfoKey.GemRss, pid);
+            Swaps = GetProcessMemoryValueInt(Interop.RuntimeInfo.ProcessMemoryInfoKey.Swap, pid);
         }
     }
 }