hardware.c revision 302408
190731Sjhay/////////////////////////////////////////////////////////////////////////////// 290731Sjhay// 390731Sjhay/// \file hardware.c 490731Sjhay/// \brief Detection of available hardware resources 590731Sjhay// 690731Sjhay// Author: Lasse Collin 790731Sjhay// 890731Sjhay// This file has been put into the public domain. 990731Sjhay// You can do whatever you want with this file. 1090731Sjhay// 1190731Sjhay/////////////////////////////////////////////////////////////////////////////// 1290731Sjhay 1390731Sjhay#include "private.h" 1490731Sjhay 1590731Sjhay 1690731Sjhay/// Maximum number of worker threads. This can be set with 1790731Sjhay/// the --threads=NUM command line option. 1890731Sjhaystatic uint32_t threads_max = 1; 1990731Sjhay 2090731Sjhay/// Memory usage limit for compression 2190731Sjhaystatic uint64_t memlimit_compress; 2290731Sjhay 2390731Sjhay/// Memory usage limit for decompression 2490731Sjhaystatic uint64_t memlimit_decompress; 2590731Sjhay 2690731Sjhay/// Total amount of physical RAM 2790731Sjhaystatic uint64_t total_ram; 2890731Sjhay 2990731Sjhay 3090731Sjhayextern void 3190731Sjhayhardware_threads_set(uint32_t n) 3290731Sjhay{ 3390731Sjhay if (n == 0) { 3490731Sjhay // Automatic number of threads was requested. 3590731Sjhay // If threading support was enabled at build time, 3690731Sjhay // use the number of available CPU cores. Otherwise 3790731Sjhay // use one thread since disabling threading support 3890731Sjhay // omits lzma_cputhreads() from liblzma. 3990731Sjhay#ifdef MYTHREAD_ENABLED 4090731Sjhay threads_max = lzma_cputhreads(); 4190731Sjhay if (threads_max == 0) 4290731Sjhay threads_max = 1; 4390731Sjhay#else 4490731Sjhay threads_max = 1; 4590731Sjhay#endif 4690731Sjhay } else { 4790731Sjhay threads_max = n; 4890731Sjhay } 4990731Sjhay 5090731Sjhay return; 5190731Sjhay} 5290731Sjhay 5390731Sjhay 5490731Sjhayextern uint32_t 5590731Sjhayhardware_threads_get(void) 5690731Sjhay{ 5790731Sjhay return threads_max; 5890731Sjhay} 5990731Sjhay 6090731Sjhay 6190731Sjhayextern void 6290731Sjhayhardware_memlimit_set(uint64_t new_memlimit, 6390731Sjhay bool set_compress, bool set_decompress, bool is_percentage) 6490731Sjhay{ 6590731Sjhay if (is_percentage) { 6690731Sjhay assert(new_memlimit > 0); 6790731Sjhay assert(new_memlimit <= 100); 6890731Sjhay new_memlimit = (uint32_t)new_memlimit * total_ram / 100; 6990731Sjhay } 7090731Sjhay 7190731Sjhay if (set_compress) 7290731Sjhay memlimit_compress = new_memlimit; 7390731Sjhay 7490731Sjhay if (set_decompress) 7590731Sjhay memlimit_decompress = new_memlimit; 7690731Sjhay 7790731Sjhay return; 7890731Sjhay} 7990731Sjhay 8090731Sjhay 8190731Sjhayextern uint64_t 8290731Sjhayhardware_memlimit_get(enum operation_mode mode) 8390731Sjhay{ 84102751Sjmallett // Zero is a special value that indicates the default. Currently 85102751Sjmallett // the default simply disables the limit. Once there is threading 8690731Sjhay // support, this might be a little more complex, because there will 8790731Sjhay // probably be a special case where a user asks for "optimal" number 8890731Sjhay // of threads instead of a specific number (this might even become 8990731Sjhay // the default mode). Each thread may use a significant amount of 9090731Sjhay // memory. When there are no memory usage limits set, we need some 9190731Sjhay // default soft limit for calculating the "optimal" number of 9290731Sjhay // threads. 9390731Sjhay const uint64_t memlimit = mode == MODE_COMPRESS 9490731Sjhay ? memlimit_compress : memlimit_decompress; 9590731Sjhay return memlimit != 0 ? memlimit : UINT64_MAX; 9690731Sjhay} 9790731Sjhay 9890731Sjhay 99102714Sphk/// Helper for hardware_memlimit_show() to print one human-readable info line. 100102714Sphkstatic void 10190731Sjhaymemlimit_show(const char *str, uint64_t value) 10290731Sjhay{ 10390731Sjhay // The memory usage limit is considered to be disabled if value 10490731Sjhay // is 0 or UINT64_MAX. This might get a bit more complex once there 10590731Sjhay // is threading support. See the comment in hardware_memlimit_get(). 10690731Sjhay if (value == 0 || value == UINT64_MAX) 10790731Sjhay printf("%s %s\n", str, _("Disabled")); 10890731Sjhay else 10990731Sjhay printf("%s %s MiB (%s B)\n", str, 11090731Sjhay uint64_to_str(round_up_to_mib(value), 0), 11190731Sjhay uint64_to_str(value, 1)); 11290731Sjhay 11390731Sjhay return; 11490731Sjhay} 115102893Sphk 116102893Sphk 117102734Sphkextern void 118102734Sphkhardware_memlimit_show(void) 119102734Sphk{ 120102734Sphk if (opt_robot) { 121102734Sphk printf("%" PRIu64 "\t%" PRIu64 "\t%" PRIu64 "\n", total_ram, 122102734Sphk memlimit_compress, memlimit_decompress); 123102734Sphk } else { 124102734Sphk // TRANSLATORS: Test with "xz --info-memory" to see if 125102734Sphk // the alignment looks nice. 126102734Sphk memlimit_show(_("Total amount of physical memory (RAM): "), 127102734Sphk total_ram); 128102734Sphk memlimit_show(_("Memory usage limit for compression: "), 129102734Sphk memlimit_compress); 130102734Sphk memlimit_show(_("Memory usage limit for decompression: "), 131102734Sphk memlimit_decompress); 132102734Sphk } 133112270Ssobomax 134112270Ssobomax tuklib_exit(E_SUCCESS, E_ERROR, message_verbosity_get() != V_SILENT); 135112270Ssobomax} 136112270Ssobomax 137112270Ssobomax 138112270Ssobomaxextern void 139112270Ssobomaxhardware_init(void) 140112270Ssobomax{ 141112270Ssobomax // Get the amount of RAM. If we cannot determine it, 142112270Ssobomax // use the assumption defined by the configure script. 143114344Ssobomax total_ram = lzma_physmem(); 144112270Ssobomax if (total_ram == 0) 145112270Ssobomax total_ram = (uint64_t)(ASSUME_RAM) * 1024 * 1024; 146112270Ssobomax 147112270Ssobomax // Set the defaults. 148112270Ssobomax hardware_memlimit_set(0, true, true, false); 149112270Ssobomax return; 150112270Ssobomax} 151112270Ssobomax