]> icculus.org git repositories - icculus/xz.git/blob - src/lzma/hardware.c
Oh well, big messy commit again. Some highlights:
[icculus/xz.git] / src / lzma / hardware.c
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 /// \file       hardware.c
4 /// \brief      Detection of available hardware resources
5 //
6 //  Copyright (C) 2007 Lasse Collin
7 //
8 //  This program is free software; you can redistribute it and/or
9 //  modify it under the terms of the GNU Lesser General Public
10 //  License as published by the Free Software Foundation; either
11 //  version 2.1 of the License, or (at your option) any later version.
12 //
13 //  This program is distributed in the hope that it will be useful,
14 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
15 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 //  Lesser General Public License for more details.
17 //
18 ///////////////////////////////////////////////////////////////////////////////
19
20 #include "private.h"
21 #include "physmem.h"
22
23
24 /// Maximum number of free *coder* threads. This can be set with
25 /// the --threads=NUM command line option.
26 size_t opt_threads = 1;
27
28
29 /// Memory usage limit for encoding
30 static uint64_t memlimit_encoder;
31
32 /// Memory usage limit for decoding
33 static uint64_t memlimit_decoder;
34
35 /// Memory usage limit given on the command line or environment variable.
36 /// Zero indicates the default (memlimit_encoder or memlimit_decoder).
37 static uint64_t memlimit_custom = 0;
38
39
40 /// Get the number of CPU cores, and set opt_threads to default to that value.
41 /// User can then override this with --threads command line option.
42 static void
43 hardware_cores(void)
44 {
45 #if defined(HAVE_NUM_PROCESSORS_SYSCONF)
46         const long cpus = sysconf(_SC_NPROCESSORS_ONLN);
47         if (cpus > 0)
48                 opt_threads = (size_t)(cpus);
49
50 #elif defined(HAVE_NUM_PROCESSORS_SYSCTL)
51         int name[2] = { CTL_HW, HW_NCPU };
52         int cpus;
53         size_t cpus_size = sizeof(cpus);
54         if (!sysctl(name, &cpus, &cpus_size, NULL, NULL)
55                         && cpus_size == sizeof(cpus) && cpus > 0)
56                 opt_threads = (size_t)(cpus);
57 #endif
58
59         // Limit opt_threads so that maximum number of threads doesn't exceed.
60
61 #if defined(_SC_THREAD_THREADS_MAX)
62         const long threads_max = sysconf(_SC_THREAD_THREADS_MAX);
63         if (threads_max > 0 && (size_t)(threads_max) < opt_threads)
64                 opt_threads = (size_t)(threads_max);
65
66 #elif defined(PTHREAD_THREADS_MAX)
67         if (opt_threads > PTHREAD_THREADS_MAX)
68                 opt_threads = PTHREAD_THREADS_MAX;
69 #endif
70
71         return;
72 }
73
74
75 static void
76 hardware_memlimit_init(void)
77 {
78         uint64_t mem = physmem();
79
80         // If we cannot determine the amount of RAM, assume 32 MiB. Maybe
81         // even that is too much on some systems. But on most systems it's
82         // far too little, and can be annoying.
83         if (mem == 0)
84                 mem = UINT64_C(16) * 1024 * 1024;
85
86         // Use at maximum of 90 % of RAM when encoding and 33 % when decoding.
87         memlimit_encoder = mem - mem / 10;
88         memlimit_decoder = mem / 3;
89
90         return;
91 }
92
93
94 extern void
95 hardware_memlimit_set(uint64_t memlimit)
96 {
97         memlimit_custom = memlimit;
98         return;
99 }
100
101
102 extern uint64_t
103 hardware_memlimit_encoder(void)
104 {
105         return memlimit_custom != 0 ? memlimit_custom : memlimit_encoder;
106 }
107
108
109 extern uint64_t
110 hardware_memlimit_decoder(void)
111 {
112         return memlimit_custom != 0 ? memlimit_custom : memlimit_decoder;
113 }
114
115
116 extern void
117 hardware_init(void)
118 {
119         hardware_memlimit_init();
120         hardware_cores();
121         return;
122 }