main.swift 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. //
  2. // Copyright 2026 Aarav Ravindra Kharade
  3. //
  4. // Licensed under the Apache License, Version 2.0 (the "License");
  5. // you may not use this file except in compliance with the License.
  6. // You may obtain a copy of the License at
  7. //
  8. // http://www.apache.org/licenses/LICENSE-2.0
  9. //
  10. // Unless required by applicable law or agreed to in writing, software
  11. // distributed under the License is distributed on an "AS IS" BASIS,
  12. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. // See the License for the specific language governing permissions and
  14. // limitations under the License.
  15. //
  16. import Foundation
  17. #if canImport(Glibc)
  18. import Glibc
  19. #endif
  20. // -
  21. // ArkOS Runtime Daemon (arkrt)
  22. // -
  23. // The primary system daemon, running as PID 2 (spawned by init).
  24. // Responsible for:
  25. //
  26. // 1. Mounting system and vendor partitions
  27. // 2. Configuring network interfaces
  28. // 3. Starting the IPC server for inter-process communication
  29. // 4. Discovering and starting system services (display, UI, etc.)
  30. // 5. Launching the boot splash animation
  31. // 6. Monitoring all child processes and respawning on crash
  32. //
  33. // Boot Sequence:
  34. // init (PID 1)
  35. // - arkrt (PID 2)
  36. // - IPC Server (thread)
  37. // - NetworkService (thread)
  38. // - display service (child process)
  39. // - swift_splash (child process — temporary)
  40. // - ui_test (child process — launched by ServiceManager)
  41. //
  42. // -
  43. // - Phase 1: System Initialization -
  44. LogManager.log("arkrt: ArkOS Runtime Daemon starting...")
  45. LogManager.log("arkrt: PID=\(getpid()), UID=\(getuid())")
  46. // Report system resources
  47. let cpuCores = ResourceController.getCPUCoreCount()
  48. let totalRAM = ResourceController.getTotalMemory() / 1024 / 1024
  49. let initialRSS = ResourceController.checkMemoryUsage() / 1024
  50. LogManager.log("arkrt: System: \(cpuCores) CPU cores, \(totalRAM) MB RAM, RSS=\(initialRSS) KB")
  51. // - Phase 2: Mount System Partitions -
  52. LogManager.log("arkrt: Mounting system partitions...")
  53. if let items = try? FileManager.default.contentsOfDirectory(atPath: "/dev") {
  54. LogManager.log("arkrt: /dev contents: \(items.joined(separator: ", "))")
  55. }
  56. /// Mount a block device to a mount point. Creates the directory if needed.
  57. func mountPartition(devices: [String], mountPoint: String, fsType: String) {
  58. mkdir(mountPoint, 0o755)
  59. for device in devices {
  60. // Wait up to 3 seconds for the device to appear
  61. var waited = 0
  62. if fsType != "tmpfs" {
  63. while access(device, F_OK) != 0 && waited < 30 {
  64. usleep(100_000) // 100ms
  65. waited += 1
  66. }
  67. }
  68. if fsType == "tmpfs" || access(device, F_OK) == 0 {
  69. let result = mount(device, mountPoint, fsType, 0, nil)
  70. if result == 0 {
  71. LogManager.log("arkrt: Mounted \(device) → \(mountPoint) (\(fsType))")
  72. return
  73. }
  74. }
  75. }
  76. LogManager.log("arkrt: Failed to mount any device to \(mountPoint)", level: .warn)
  77. }
  78. // Mount tmpfs for runtime state
  79. mountPartition(devices: ["tmpfs"], mountPoint: "/run", fsType: "tmpfs")
  80. mountPartition(devices: ["tmpfs"], mountPoint: "/tmp", fsType: "tmpfs")
  81. // Create essential runtime directories
  82. mkdir("/run", 0o755)
  83. mkdir("/var/log", 0o755)
  84. mkdir("/etc", 0o755)
  85. mkdir("/system", 0o755)
  86. mkdir("/vendor", 0o755)
  87. // Attempt to mount system and vendor from disk images (block devices)
  88. let systemDevices = ["/dev/vdb", "/dev/sdb", "/dev/hdb", "/dev/sda2"]
  89. let vendorDevices = ["/dev/vdc", "/dev/sdc", "/dev/hdc", "/dev/sda3"]
  90. mountPartition(devices: systemDevices, mountPoint: "/system", fsType: "ext4")
  91. mountPartition(devices: vendorDevices, mountPoint: "/vendor", fsType: "ext4")
  92. // - Phase 3: Network Configuration -
  93. LogManager.log("arkrt: Configuring network interfaces...")
  94. NetworkService.shared.configureInterfaces()
  95. NetworkService.shared.startMonitoring()
  96. // - Phase 4: IPC Server -
  97. LogManager.log("arkrt: Starting IPC server...")
  98. var server = IPCServer()
  99. server.start()
  100. LogManager.log("arkrt: Starting Input server...")
  101. InputService.start()
  102. // - Phase 5: Service Discovery -
  103. // We wait to start services until the splash completes so ui_daemon
  104. // doesn't fight over the framebuffer.
  105. // Boot splash animation has been moved into the ui_daemon service
  106. // - Phase 7: Main Monitoring Loop -
  107. LogManager.log("arkrt: Starting system services...")
  108. ServiceManager.shared.startAllServices()
  109. var lastResolution: String = ""
  110. ResourceController.executeOnCorePool {
  111. while true {
  112. // Monitor all managed services for crashes
  113. ServiceManager.shared.monitorServices()
  114. // Periodic resource health check
  115. let ram = ResourceController.checkMemoryUsage()
  116. if ram > 1_500_000_000 { // 1.5 GB
  117. LogManager.log("arkrt: HIGH MEMORY WARNING: \(ram / 1024 / 1024) MB RSS", level: .warn)
  118. }
  119. // Check for resolution changes
  120. if let fp = fopen("/sys/class/graphics/fb0/virtual_size", "r") {
  121. var buf = [CChar](repeating: 0, count: 64)
  122. if fgets(&buf, Int32(buf.count), fp) != nil {
  123. let currentRes = String(cString: buf).trimmingCharacters(in: .whitespacesAndNewlines)
  124. if lastResolution != "" && currentRes != lastResolution {
  125. LogManager.log("arkrt: Resolution changed from \(lastResolution) to \(currentRes). Restarting display service...")
  126. ServiceManager.shared.stopService(name: "display")
  127. ServiceManager.shared.startService(name: "display")
  128. }
  129. lastResolution = currentRes
  130. }
  131. fclose(fp)
  132. }
  133. // Log heartbeat every ~60 iterations (2 min)
  134. sleep(2)
  135. }
  136. }
  137. // - Keep Main Thread Alive -
  138. // The main thread must remain alive to service Foundation dispatch
  139. // queues (used by IPC, network monitor, and service manager).
  140. dispatchMain()