1207753Smm/////////////////////////////////////////////////////////////////////////////// 2207753Smm// 3207753Smm/// \file hardware.c 4207753Smm/// \brief Detection of available hardware resources 5207753Smm// 6207753Smm// Author: Lasse Collin 7207753Smm// 8207753Smm// This file has been put into the public domain. 9207753Smm// You can do whatever you want with this file. 10207753Smm// 11207753Smm/////////////////////////////////////////////////////////////////////////////// 12207753Smm 13207753Smm#include "private.h" 14207753Smm 15207753Smm 16292588Sdelphij/// Maximum number of worker threads. This can be set with 17207753Smm/// the --threads=NUM command line option. 18292588Sdelphijstatic uint32_t threads_max = 1; 19207753Smm 20213700Smm/// Memory usage limit for compression 21213700Smmstatic uint64_t memlimit_compress; 22207753Smm 23213700Smm/// Memory usage limit for decompression 24213700Smmstatic uint64_t memlimit_decompress; 25213700Smm 26207753Smm/// Total amount of physical RAM 27207753Smmstatic uint64_t total_ram; 28207753Smm 29207753Smm 30207753Smmextern void 31292588Sdelphijhardware_threads_set(uint32_t n) 32207753Smm{ 33292588Sdelphij if (n == 0) { 34292588Sdelphij // Automatic number of threads was requested. 35292588Sdelphij // If threading support was enabled at build time, 36292588Sdelphij // use the number of available CPU cores. Otherwise 37292588Sdelphij // use one thread since disabling threading support 38292588Sdelphij // omits lzma_cputhreads() from liblzma. 39292588Sdelphij#ifdef MYTHREAD_ENABLED 40292588Sdelphij threads_max = lzma_cputhreads(); 41292588Sdelphij if (threads_max == 0) 42292588Sdelphij threads_max = 1; 43292588Sdelphij#else 44292588Sdelphij threads_max = 1; 45292588Sdelphij#endif 46207753Smm } else { 47292588Sdelphij threads_max = n; 48207753Smm } 49207753Smm 50207753Smm return; 51207753Smm} 52207753Smm 53207753Smm 54207753Smmextern uint32_t 55292588Sdelphijhardware_threads_get(void) 56207753Smm{ 57292588Sdelphij return threads_max; 58207753Smm} 59207753Smm 60207753Smm 61207753Smmextern void 62213700Smmhardware_memlimit_set(uint64_t new_memlimit, 63213700Smm bool set_compress, bool set_decompress, bool is_percentage) 64207753Smm{ 65213700Smm if (is_percentage) { 66213700Smm assert(new_memlimit > 0); 67213700Smm assert(new_memlimit <= 100); 68213700Smm new_memlimit = (uint32_t)new_memlimit * total_ram / 100; 69207753Smm } 70207753Smm 71213700Smm if (set_compress) 72213700Smm memlimit_compress = new_memlimit; 73213700Smm 74213700Smm if (set_decompress) 75213700Smm memlimit_decompress = new_memlimit; 76213700Smm 77207753Smm return; 78207753Smm} 79207753Smm 80207753Smm 81213700Smmextern uint64_t 82213700Smmhardware_memlimit_get(enum operation_mode mode) 83207753Smm{ 84213700Smm // Zero is a special value that indicates the default. Currently 85213700Smm // the default simply disables the limit. Once there is threading 86213700Smm // support, this might be a little more complex, because there will 87213700Smm // probably be a special case where a user asks for "optimal" number 88213700Smm // of threads instead of a specific number (this might even become 89213700Smm // the default mode). Each thread may use a significant amount of 90213700Smm // memory. When there are no memory usage limits set, we need some 91213700Smm // default soft limit for calculating the "optimal" number of 92213700Smm // threads. 93213700Smm const uint64_t memlimit = mode == MODE_COMPRESS 94213700Smm ? memlimit_compress : memlimit_decompress; 95213700Smm return memlimit != 0 ? memlimit : UINT64_MAX; 96213700Smm} 97207753Smm 98213700Smm 99213700Smm/// Helper for hardware_memlimit_show() to print one human-readable info line. 100213700Smmstatic void 101213700Smmmemlimit_show(const char *str, uint64_t value) 102213700Smm{ 103213700Smm // The memory usage limit is considered to be disabled if value 104213700Smm // is 0 or UINT64_MAX. This might get a bit more complex once there 105213700Smm // is threading support. See the comment in hardware_memlimit_get(). 106213700Smm if (value == 0 || value == UINT64_MAX) 107213700Smm printf("%s %s\n", str, _("Disabled")); 108213700Smm else 109213700Smm printf("%s %s MiB (%s B)\n", str, 110213700Smm uint64_to_str(round_up_to_mib(value), 0), 111213700Smm uint64_to_str(value, 1)); 112213700Smm 113207753Smm return; 114207753Smm} 115207753Smm 116207753Smm 117213700Smmextern void 118213700Smmhardware_memlimit_show(void) 119207753Smm{ 120213700Smm if (opt_robot) { 121213700Smm printf("%" PRIu64 "\t%" PRIu64 "\t%" PRIu64 "\n", total_ram, 122213700Smm memlimit_compress, memlimit_decompress); 123213700Smm } else { 124213700Smm // TRANSLATORS: Test with "xz --info-memory" to see if 125213700Smm // the alignment looks nice. 126213700Smm memlimit_show(_("Total amount of physical memory (RAM): "), 127213700Smm total_ram); 128213700Smm memlimit_show(_("Memory usage limit for compression: "), 129213700Smm memlimit_compress); 130213700Smm memlimit_show(_("Memory usage limit for decompression: "), 131213700Smm memlimit_decompress); 132213700Smm } 133213700Smm 134213700Smm tuklib_exit(E_SUCCESS, E_ERROR, message_verbosity_get() != V_SILENT); 135207753Smm} 136207753Smm 137207753Smm 138207753Smmextern void 139207753Smmhardware_init(void) 140207753Smm{ 141207753Smm // Get the amount of RAM. If we cannot determine it, 142207753Smm // use the assumption defined by the configure script. 143207753Smm total_ram = lzma_physmem(); 144207753Smm if (total_ram == 0) 145207753Smm total_ram = (uint64_t)(ASSUME_RAM) * 1024 * 1024; 146207753Smm 147207753Smm // Set the defaults. 148213700Smm hardware_memlimit_set(0, true, true, false); 149207753Smm return; 150207753Smm} 151