1 // 2 // Copyright (c) 2010-2023 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.Threading; 10 using Antmicro.Renode.Core; 11 using Antmicro.Renode.Exceptions; 12 using Antmicro.Renode.Logging; 13 using Antmicro.Renode.UserInterface; 14 using System.Collections.Concurrent; 15 using Antmicro.Renode.Utilities; 16 using System.IO; 17 18 namespace Antmicro.Renode 19 { 20 public static class Emulator 21 { Emulator()22 static Emulator() 23 { 24 UserDirectoryPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData, Environment.SpecialFolderOption.Create), "renode"); 25 } 26 Exit()27 public static void Exit() 28 { 29 var beforeExit = BeforeExit; 30 if(beforeExit != null) 31 { 32 try 33 { 34 beforeExit(); 35 } 36 catch (RecoverableException) 37 { 38 // Due to a complex bug, such exception is thrown on each exit if GUI was started. 39 // All OSs are affected, but only Windows logs it. As it looks like a crash and 40 // Linux/macOS seem to just silence those exceptions anyway, explicit silencing 41 // seems best for all of them until the real fix is introduced. 42 } 43 } 44 exitEvent.Set(); 45 } 46 OpenGUI()47 public static void OpenGUI() 48 { 49 if(EnableGUI == null) 50 { 51 throw new RecoverableException("This feature is available only with interactive Robot tests debug"); 52 } 53 EnableGUI(); 54 } 55 CloseGUI()56 public static void CloseGUI() 57 { 58 if(DisableGUI == null) 59 { 60 throw new RecoverableException("This feature is available only with interactive Robot tests debug"); 61 } 62 DisableGUI(); 63 } 64 WaitForExit()65 public static void WaitForExit() 66 { 67 exitEvent.Wait(); 68 } 69 DisposeAll()70 public static void DisposeAll() 71 { 72 if(!disposed) 73 { 74 disposed = true; 75 EmulationManager.Instance.Clear(); 76 TypeManager.Instance.Dispose(); 77 Logger.Dispose(); 78 } 79 } 80 81 public static IUserInterfaceProvider UserInterfaceProvider 82 { 83 get 84 { 85 if(userInterfaceProvider == null) 86 { 87 throw new RecoverableException("User interface provider not set"); 88 } 89 return userInterfaceProvider; 90 } 91 set 92 { 93 userInterfaceProvider = value; 94 } 95 } 96 97 public static string UserDirectoryPath 98 { 99 get 100 { 101 return userDirectoryPath; 102 } 103 104 set 105 { 106 userDirectoryPath = value; 107 Directory.CreateDirectory(userDirectoryPath); 108 } 109 } 110 111 // CI mode is kind-of-a-hack to allow 112 // running multiple instances of Renode 113 // at the same time by disabling writing 114 // to shared files like binaries cache, 115 // config file, etc. 116 public static bool InCIMode => (Environment.GetEnvironmentVariable("RENODE_CI_MODE") == "YES"); 117 118 private static string userDirectoryPath; 119 ExecuteOnMainThread(Action what)120 public static void ExecuteOnMainThread(Action what) 121 { 122 actionsOnMainThread.Add(what); 123 } 124 ExecuteAsMainThread()125 public static void ExecuteAsMainThread() 126 { 127 Action action; 128 while(actionsOnMainThread.TryTake(out action, -1)) 129 { 130 action(); 131 } 132 } 133 FinishExecutionAsMainThread()134 public static void FinishExecutionAsMainThread() 135 { 136 actionsOnMainThread.CompleteAdding(); 137 } 138 139 public static bool ShowAnalyzers { get; set; } 140 141 private static readonly BlockingCollection<Action> actionsOnMainThread = new BlockingCollection<Action>(); 142 143 public static event Action BeforeExit; 144 public static event Action EnableGUI; 145 public static event Action DisableGUI; 146 private static IUserInterfaceProvider userInterfaceProvider; 147 private static ManualResetEventSlim exitEvent = new ManualResetEventSlim(); 148 private static bool disposed; 149 } 150 } 151 152