Explorar o código

system: Implement thread priority setting

parazyd hai 1 ano
pai
achega
315745b8ef
Modificáronse 5 ficheiros con 146 adicións e 13 borrados
  1. 1 0
      Cargo.toml
  2. 3 0
      src/system/mod.rs
  3. 127 0
      src/system/thread_priority.rs
  4. 9 2
      src/validator/pow.rs
  5. 6 11
      src/validator/randomx_factory.rs

+ 1 - 0
Cargo.toml

@@ -175,6 +175,7 @@ validator = [
     "randomx",
     "smol",
 
+    "blockchain",
     "system",
     "wasm-runtime",
 ]

+ 3 - 0
src/system/mod.rs

@@ -37,6 +37,9 @@ pub use publisher::{Publisher, PublisherPtr, Subscription};
 pub mod timeout;
 pub use timeout::io_timeout;
 
+/// Thread priority setting
+pub mod thread_priority;
+
 pub type ExecutorPtr = Arc<Executor<'static>>;
 
 /// Sleep for any number of seconds.

+ 127 - 0
src/system/thread_priority.rs

@@ -0,0 +1,127 @@
+/* This file is part of DarkFi (https://dark.fi)
+ *
+ * Copyright (C) 2020-2025 Dyne.org foundation
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+/// Levels of thread priority
+pub enum ThreadPriority {
+    Min,
+    Low,
+    Normal,
+    High,
+    Max,
+}
+
+/// Set current thread priority to given `priority`.
+/// This usually requires root privileges.
+pub fn set_thread_priority(priority: ThreadPriority) {
+    #[cfg(windows)]
+    {
+        type HANDLE = *mut std::ffi::c_void;
+
+        const THREAD_PRIORITY_IDLE: i32 = -15;
+        const THREAD_PRIORITY_BELOW_NORMAL: i32 = -1;
+        const THREAD_PRIORITY_NORMAL: i32 = 0;
+        const THREAD_PRIORITY_ABOVE_NORMAL: i32 = 1;
+        const THREAD_PRIORITY_TIME_CRITICAL: i32 = 15;
+
+        extern "system" {
+            fn GetCurrentThread() -> HANDLE;
+            fn SetThreadPriority(hThread: HANDLE, nPriority: i32) -> i32;
+        }
+
+        let priority_value = match priority {
+            ThreadPriority::Min => THREAD_PRIORITY_IDLE,
+            ThreadPriority::Low => THREAD_PRIORITY_BELOW_NORMAL,
+            ThreadPriority::Normal => THREAD_PRIORITY_NORMAL,
+            ThreadPriority::High => THREAD_PRIORITY_ABOVE_NORMAL,
+            ThreadPriority::Max => THREAD_PRIORITY_TIME_CRITICAL,
+        };
+
+        unsafe {
+            SetThreadPriority(GetCurrentThread(), priority_value);
+        }
+    }
+
+    #[cfg(target_os = "linux")]
+    {
+        extern "C" {
+            fn setpriority(which: i32, who: u32, prio: i32) -> i32;
+        }
+
+        const PRIO_PROCESS: i32 = 0;
+
+        let nice_value = match priority {
+            ThreadPriority::Min => 19,
+            ThreadPriority::Low => 10,
+            ThreadPriority::Normal => 0,
+            ThreadPriority::High => -10,
+            ThreadPriority::Max => -20,
+        };
+
+        unsafe {
+            setpriority(PRIO_PROCESS, std::process::id(), nice_value);
+        }
+    }
+
+    #[cfg(any(target_os = "macos", target_os = "ios"))]
+    {
+        type mach_port_t = u32;
+        type thread_t = mach_port_t;
+        type thread_policy_flavor_t = i32;
+        type thread_policy_t = *mut i32;
+        type mach_msg_type_number_t = u32;
+
+        const THREAD_PRECEDENCE_POLICY: thread_policy_flavor_t = 3;
+
+        #[repr(C)]
+        struct thread_precedence_policy_data {
+            importance: i32,
+        }
+
+        extern "C" {
+            fn mach_thread_self() -> thread_t;
+            fn thread_policy_set(
+                thread: thread_t,
+                flavor: thread_policy_flavor_t,
+                policy_info: thread_policy_t,
+                count: mach_msg_type_number_t,
+            ) -> i32;
+        }
+
+        let importance = match priority {
+            ThreadPriority::Min => -30,
+            ThreadPriority::Low => -15,
+            ThreadPriority::Normal => 0,
+            ThreadPriority::High => 15,
+            ThreadPriority::Max => 30,
+        };
+
+        unsafe {
+            let thread = mach_thread_self();
+            let mut policy = thread_precedence_policy_data { importance };
+            let count =
+                std::mem::size_of::<thread_precedence_policy_data>() as mach_msg_type_number_t / 4;
+
+            thread_policy_set(
+                thread,
+                THREAD_PRECEDENCE_POLICY,
+                &mut policy as *mut _ as thread_policy_t,
+                count,
+            );
+        }
+    }
+}

+ 9 - 2
src/validator/pow.rs

@@ -36,6 +36,7 @@ use crate::{
         block_store::{BlockDifficulty, BlockInfo},
         Blockchain, BlockchainOverlayPtr,
     },
+    system::thread_priority::ThreadPriority,
     util::{ringbuffer::RingBuffer, time::Timestamp},
     validator::{randomx_factory::init_dataset_wrapper, utils::median},
     Error, Result,
@@ -380,9 +381,15 @@ pub fn mine_block(
         let dataset = if threads > 1 {
             let a = (dataset_item_count * (t as u32)) / (threads as u32);
             let b = (dataset_item_count * (t as u32 + 1)) / (threads as u32);
-            init_dataset_wrapper(flags, cache.clone(), a, b - a)?
+            init_dataset_wrapper(flags, cache.clone(), a, b - a, ThreadPriority::Normal)?
         } else {
-            init_dataset_wrapper(flags, cache.clone(), 0, dataset_item_count)?
+            init_dataset_wrapper(
+                flags,
+                cache.clone(),
+                0,
+                dataset_item_count,
+                ThreadPriority::Normal,
+            )?
         };
 
         let stop_signal = stop_signal.clone();

+ 6 - 11
src/validator/randomx_factory.rs

@@ -27,7 +27,10 @@ use std::{
 use log::{debug, warn};
 use randomx::{RandomXCache, RandomXDataset, RandomXFlags, RandomXVM};
 
-use crate::Result;
+use crate::{
+    system::thread_priority::{set_thread_priority, ThreadPriority},
+    Result,
+};
 
 /// Wrapper for creating a [`RandomXDataset`]
 pub fn init_dataset_wrapper(
@@ -35,17 +38,9 @@ pub fn init_dataset_wrapper(
     cache: RandomXCache,
     start_item: u32,
     item_count: u32,
-    /* priority: i32, */
+    priority: ThreadPriority,
 ) -> Result<RandomXDataset> {
-    /* set_thread_priority(priority); */
-
-    /*
-    if (is_x86_feature_detected!("avx2") && item_count % 5) {
-        let dataset = RandomXDataset::new(flags, cache, start_item, item_count - (item_count % 5))?;
-        let dataset = RandomXDataset::new(flags, cache, start_item + item_count - 5, 5)?;
-    }
-    */
-
+    set_thread_priority(priority);
     Ok(RandomXDataset::new(flags, cache, start_item, item_count)?)
 }