hardware.c revision 292588
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.
18static uint32_t threads_max = 1;
19
20/// Memory usage limit for compression
21static uint64_t memlimit_compress;
22
23/// Memory usage limit for decompression
24static uint64_t memlimit_decompress;
25
26/// Total amount of physical RAM
27static uint64_t total_ram;
28
29
30extern void
31hardware_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
54extern uint32_t
55hardware_threads_get(void)
56{
57	return threads_max;
58}
59
60
61extern void
62hardware_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
81extern uint64_t
82hardware_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.
100static void
101memlimit_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
117extern void
118hardware_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
138extern void
139hardware_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