1 /////////////////////////////////////////////////////////////////////////////// 2 // 3 /// \file hardware.c 4 /// \brief Detection of available hardware resources 5 // 6 // Author: Lasse Collin 7 // 8 // This file has been put into the public domain. 9 // You can do whatever you want with this file. 10 // 11 /////////////////////////////////////////////////////////////////////////////// 12 13 #include "private.h" 14 15 16 /// Maximum number of worker threads. This can be set with 17 /// the --threads=NUM command line option. 18 static uint32_t threads_max = 1; 19 20 /// Memory usage limit for compression 21 static uint64_t memlimit_compress; 22 23 /// Memory usage limit for decompression 24 static uint64_t memlimit_decompress; 25 26 /// Total amount of physical RAM 27 static uint64_t total_ram; 28 29 30 extern void 31 hardware_threads_set(uint32_t n) 32 { 33 if (n == 0) { 34 // Automatic number of threads was requested. 35 // If threading support was enabled at build time, 36 // use the number of available CPU cores. Otherwise 37 // use one thread since disabling threading support 38 // omits lzma_cputhreads() from liblzma. 39 #ifdef MYTHREAD_ENABLED 40 threads_max = lzma_cputhreads(); 41 if (threads_max == 0) 42 threads_max = 1; 43 #else 44 threads_max = 1; 45 #endif 46 } else { 47 threads_max = n; 48 } 49 50 return; 51 } 52 53 54 extern uint32_t 55 hardware_threads_get(void) 56 { 57 return threads_max; 58 } 59 60 61 extern void 62 hardware_memlimit_set(uint64_t new_memlimit, 63 bool set_compress, bool set_decompress, bool is_percentage) 64 { 65 if (is_percentage) { 66 assert(new_memlimit > 0); 67 assert(new_memlimit <= 100); 68 new_memlimit = (uint32_t)new_memlimit * total_ram / 100; 69 } 70 71 if (set_compress) 72 memlimit_compress = new_memlimit; 73 74 if (set_decompress) 75 memlimit_decompress = new_memlimit; 76 77 return; 78 } 79 80 81 extern uint64_t 82 hardware_memlimit_get(enum operation_mode mode) 83 { 84 // Zero is a special value that indicates the default. Currently 85 // the default simply disables the limit. Once there is threading 86 // support, this might be a little more complex, because there will 87 // probably be a special case where a user asks for "optimal" number 88 // of threads instead of a specific number (this might even become 89 // the default mode). Each thread may use a significant amount of 90 // memory. When there are no memory usage limits set, we need some 91 // default soft limit for calculating the "optimal" number of 92 // threads. 93 const uint64_t memlimit = mode == MODE_COMPRESS 94 ? memlimit_compress : memlimit_decompress; 95 return memlimit != 0 ? memlimit : UINT64_MAX; 96 } 97 98 99 /// Helper for hardware_memlimit_show() to print one human-readable info line. 100 static void 101 memlimit_show(const char *str, uint64_t value) 102 { 103 // The memory usage limit is considered to be disabled if value 104 // is 0 or UINT64_MAX. This might get a bit more complex once there 105 // is threading support. See the comment in hardware_memlimit_get(). 106 if (value == 0 || value == UINT64_MAX) 107 printf("%s %s\n", str, _("Disabled")); 108 else 109 printf("%s %s MiB (%s B)\n", str, 110 uint64_to_str(round_up_to_mib(value), 0), 111 uint64_to_str(value, 1)); 112 113 return; 114 } 115 116 117 extern void 118 hardware_memlimit_show(void) 119 { 120 if (opt_robot) { 121 printf("%" PRIu64 "\t%" PRIu64 "\t%" PRIu64 "\n", total_ram, 122 memlimit_compress, memlimit_decompress); 123 } else { 124 // TRANSLATORS: Test with "xz --info-memory" to see if 125 // the alignment looks nice. 126 memlimit_show(_("Total amount of physical memory (RAM): "), 127 total_ram); 128 memlimit_show(_("Memory usage limit for compression: "), 129 memlimit_compress); 130 memlimit_show(_("Memory usage limit for decompression: "), 131 memlimit_decompress); 132 } 133 134 tuklib_exit(E_SUCCESS, E_ERROR, message_verbosity_get() != V_SILENT); 135 } 136 137 138 extern void 139 hardware_init(void) 140 { 141 // Get the amount of RAM. If we cannot determine it, 142 // use the assumption defined by the configure script. 143 total_ram = lzma_physmem(); 144 if (total_ram == 0) 145 total_ram = (uint64_t)(ASSUME_RAM) * 1024 * 1024; 146 147 // Set the defaults. 148 hardware_memlimit_set(0, true, true, false); 149 return; 150 } 151