cubefs

Форк
0
345 строк · 8.1 Кб
1
// Copyright 2018 Tobias Klauser. All rights reserved.
2
// Use of this source code is governed by a BSD-style
3
// license that can be found in the LICENSE file.
4

5
package sysconf
6

7
import (
8
	"bufio"
9
	"io/ioutil"
10
	"os"
11
	"runtime"
12
	"strconv"
13
	"strings"
14

15
	"github.com/tklauser/numcpus"
16
	"golang.org/x/sys/unix"
17
)
18

19
const (
20
	// CLK_TCK is a constant on Linux for all architectures except alpha and ia64.
21
	// See e.g.
22
	// https://git.musl-libc.org/cgit/musl/tree/src/conf/sysconf.c#n30
23
	// https://github.com/containerd/cgroups/pull/12
24
	// https://lore.kernel.org/lkml/agtlq6$iht$1@penguin.transmeta.com/
25
	_SYSTEM_CLK_TCK = 100
26
)
27

28
func readProcFsInt64(path string, fallback int64) int64 {
29
	data, err := ioutil.ReadFile(path)
30
	if err != nil {
31
		return fallback
32
	}
33
	i, err := strconv.ParseInt(string(data[:len(data)-1]), 0, 64)
34
	if err != nil {
35
		return fallback
36
	}
37
	return i
38
}
39

40
// getMemPages computes mem*unit/os.Getpagesize(), but avoids overflowing int64.
41
func getMemPages(mem uint64, unit uint32) int64 {
42
	pageSize := os.Getpagesize()
43
	for unit > 1 && pageSize > 1 {
44
		unit >>= 1
45
		pageSize >>= 1
46
	}
47
	mem *= uint64(unit)
48
	for pageSize > 1 {
49
		pageSize >>= 1
50
		mem >>= 1
51
	}
52
	return int64(mem)
53
}
54

55
func getPhysPages() int64 {
56
	var si unix.Sysinfo_t
57
	err := unix.Sysinfo(&si)
58
	if err != nil {
59
		return int64(0)
60
	}
61
	return getMemPages(uint64(si.Totalram), si.Unit)
62
}
63

64
func getAvPhysPages() int64 {
65
	var si unix.Sysinfo_t
66
	err := unix.Sysinfo(&si)
67
	if err != nil {
68
		return int64(0)
69
	}
70
	return getMemPages(uint64(si.Freeram), si.Unit)
71
}
72

73
func getNprocsSysfs() (int64, error) {
74
	n, err := numcpus.GetOnline()
75
	return int64(n), err
76
}
77

78
func getNprocsProcStat() (int64, error) {
79
	f, err := os.Open("/proc/stat")
80
	if err != nil {
81
		return -1, err
82
	}
83
	defer f.Close()
84

85
	count := int64(0)
86
	s := bufio.NewScanner(f)
87
	for s.Scan() {
88
		if line := strings.TrimSpace(s.Text()); strings.HasPrefix(line, "cpu") {
89
			l := strings.SplitN(line, " ", 2)
90
			_, err := strconv.ParseInt(l[0][3:], 10, 64)
91
			if err == nil {
92
				count++
93
			}
94
		} else {
95
			// The current format of /proc/stat has all the
96
			// cpu* lines at the beginning. Assume this
97
			// stays this way.
98
			break
99
		}
100
	}
101
	return count, nil
102
}
103

104
func getNprocs() int64 {
105
	count, err := getNprocsSysfs()
106
	if err == nil {
107
		return count
108
	}
109

110
	count, err = getNprocsProcStat()
111
	if err == nil {
112
		return count
113
	}
114

115
	// default to the value determined at runtime startup if all else fails
116
	return int64(runtime.NumCPU())
117
}
118

119
func getNprocsConf() int64 {
120
	count, err := numcpus.GetConfigured()
121
	if err == nil {
122
		return int64(count)
123
	}
124

125
	// TODO(tk): fall back to reading /proc/cpuinfo on legacy systems
126
	// without sysfs?
127

128
	return getNprocs()
129
}
130

131
func hasClock(clockid int32) bool {
132
	var res unix.Timespec
133
	if err := unix.ClockGetres(clockid, &res); err != nil {
134
		return false
135
	}
136
	return true
137
}
138

139
func max(a, b int64) int64 {
140
	if a > b {
141
		return a
142
	}
143
	return b
144
}
145

146
func sysconf(name int) (int64, error) {
147
	switch name {
148
	case SC_AIO_LISTIO_MAX:
149
		return -1, nil
150
	case SC_AIO_MAX:
151
		return -1, nil
152
	case SC_AIO_PRIO_DELTA_MAX:
153
		return _AIO_PRIO_DELTA_MAX, nil
154
	case SC_ARG_MAX:
155
		argMax := int64(_POSIX_ARG_MAX)
156
		var rlim unix.Rlimit
157
		if err := unix.Getrlimit(unix.RLIMIT_STACK, &rlim); err == nil {
158
			argMax = max(argMax, int64(rlim.Cur/4))
159
		}
160
		return argMax, nil
161
	case SC_ATEXIT_MAX:
162
		return _INT_MAX, nil
163
	case SC_CHILD_MAX:
164
		childMax := int64(-1)
165
		var rlim unix.Rlimit
166
		if err := unix.Getrlimit(unix.RLIMIT_NPROC, &rlim); err == nil && rlim.Cur != unix.RLIM_INFINITY {
167
			childMax = int64(rlim.Cur)
168
		}
169
		return childMax, nil
170
	case SC_CLK_TCK:
171
		return _SYSTEM_CLK_TCK, nil
172
	case SC_DELAYTIMER_MAX:
173
		return _DELAYTIMER_MAX, nil
174
	case SC_GETGR_R_SIZE_MAX:
175
		return _NSS_BUFLEN_GROUP, nil
176
	case SC_GETPW_R_SIZE_MAX:
177
		return _NSS_BUFLEN_PASSWD, nil
178
	case SC_MQ_OPEN_MAX:
179
		return -1, nil
180
	case SC_MQ_PRIO_MAX:
181
		return _MQ_PRIO_MAX, nil
182
	case SC_NGROUPS_MAX:
183
		return readProcFsInt64("/proc/sys/kernel/ngroups_max", _NGROUPS_MAX), nil
184
	case SC_OPEN_MAX:
185
		openMax := int64(_OPEN_MAX)
186
		var rlim unix.Rlimit
187
		if err := unix.Getrlimit(unix.RLIMIT_NOFILE, &rlim); err == nil {
188
			openMax = int64(rlim.Cur)
189
		}
190
		return openMax, nil
191
	case SC_RTSIG_MAX:
192
		return _RTSIG_MAX, nil
193
	case SC_SEM_NSEMS_MAX:
194
		return -1, nil
195
	case SC_SEM_VALUE_MAX:
196
		return _SEM_VALUE_MAX, nil
197
	case SC_SIGQUEUE_MAX:
198
		var rlim unix.Rlimit
199
		if err := unix.Getrlimit(unix.RLIMIT_SIGPENDING, &rlim); err == nil {
200
			return int64(rlim.Cur), nil
201
		}
202
		return readProcFsInt64("/proc/sys/kernel/rtsig-max", _POSIX_SIGQUEUE_MAX), nil
203
	case SC_STREAM_MAX:
204
		return _STREAM_MAX, nil
205
	case SC_THREAD_DESTRUCTOR_ITERATIONS:
206
		return _POSIX_THREAD_DESTRUCTOR_ITERATIONS, nil
207
	case SC_THREAD_KEYS_MAX:
208
		return _PTHREAD_KEYS_MAX, nil
209
	case SC_THREAD_PRIO_INHERIT:
210
		return _POSIX_THREAD_PRIO_INHERIT, nil
211
	case SC_THREAD_PRIO_PROTECT:
212
		return _POSIX_THREAD_PRIO_PROTECT, nil
213
	case SC_THREAD_STACK_MIN:
214
		return _PTHREAD_STACK_MIN, nil
215
	case SC_THREAD_THREADS_MAX:
216
		return -1, nil
217
	case SC_TIMER_MAX:
218
		return -1, nil
219
	case SC_TTY_NAME_MAX:
220
		return _TTY_NAME_MAX, nil
221
	case SC_TZNAME_MAX:
222
		return -1, nil
223

224
	case SC_CPUTIME:
225
		if hasClock(unix.CLOCK_PROCESS_CPUTIME_ID) {
226
			return _POSIX_VERSION, nil
227
		}
228
		return -1, nil
229
	case SC_MONOTONIC_CLOCK:
230
		if hasClock(unix.CLOCK_MONOTONIC) {
231
			return _POSIX_VERSION, nil
232
		}
233
		return -1, nil
234
	case SC_SAVED_IDS:
235
		return _POSIX_SAVED_IDS, nil
236
	case SC_SPAWN:
237
		return _POSIX_SPAWN, nil
238
	case SC_SPIN_LOCKS:
239
		return _POSIX_SPIN_LOCKS, nil
240
	case SC_SPORADIC_SERVER:
241
		return _POSIX_SPORADIC_SERVER, nil
242
	case SC_SYNCHRONIZED_IO:
243
		return _POSIX_SYNCHRONIZED_IO, nil
244
	case SC_THREAD_ATTR_STACKADDR:
245
		return _POSIX_THREAD_ATTR_STACKADDR, nil
246
	case SC_THREAD_ATTR_STACKSIZE:
247
		return _POSIX_THREAD_ATTR_STACKSIZE, nil
248
	case SC_THREAD_CPUTIME:
249
		if hasClock(unix.CLOCK_THREAD_CPUTIME_ID) {
250
			return _POSIX_VERSION, nil
251
		}
252
		return -1, nil
253
	case SC_THREAD_PRIORITY_SCHEDULING:
254
		return _POSIX_THREAD_PRIORITY_SCHEDULING, nil
255
	case SC_THREAD_PROCESS_SHARED:
256
		return _POSIX_THREAD_PROCESS_SHARED, nil
257
	case SC_THREAD_SAFE_FUNCTIONS:
258
		return _POSIX_THREAD_SAFE_FUNCTIONS, nil
259
	case SC_THREAD_SPORADIC_SERVER:
260
		return _POSIX_THREAD_SPORADIC_SERVER, nil
261
	case SC_TRACE:
262
		return _POSIX_TRACE, nil
263
	case SC_TRACE_EVENT_FILTER:
264
		return _POSIX_TRACE_EVENT_FILTER, nil
265
	case SC_TRACE_EVENT_NAME_MAX:
266
		return -1, nil
267
	case SC_TRACE_INHERIT:
268
		return _POSIX_TRACE_INHERIT, nil
269
	case SC_TRACE_LOG:
270
		return _POSIX_TRACE_LOG, nil
271
	case SC_TRACE_NAME_MAX:
272
		return -1, nil
273
	case SC_TRACE_SYS_MAX:
274
		return -1, nil
275
	case SC_TRACE_USER_EVENT_MAX:
276
		return -1, nil
277
	case SC_TYPED_MEMORY_OBJECTS:
278
		return _POSIX_TYPED_MEMORY_OBJECTS, nil
279

280
	case SC_V7_ILP32_OFF32:
281
		return _POSIX_V7_ILP32_OFF32, nil
282
	case SC_V7_ILP32_OFFBIG:
283
		return _POSIX_V7_ILP32_OFFBIG, nil
284
	case SC_V7_LP64_OFF64:
285
		return _POSIX_V7_LP64_OFF64, nil
286
	case SC_V7_LPBIG_OFFBIG:
287
		return _POSIX_V7_LPBIG_OFFBIG, nil
288

289
	case SC_V6_ILP32_OFF32:
290
		return _POSIX_V6_ILP32_OFF32, nil
291
	case SC_V6_ILP32_OFFBIG:
292
		return _POSIX_V6_ILP32_OFFBIG, nil
293
	case SC_V6_LP64_OFF64:
294
		return _POSIX_V6_LP64_OFF64, nil
295
	case SC_V6_LPBIG_OFFBIG:
296
		return _POSIX_V6_LPBIG_OFFBIG, nil
297

298
	case SC_2_C_VERSION:
299
		return _POSIX2_C_VERSION, nil
300
	case SC_2_CHAR_TERM:
301
		return _POSIX2_CHAR_TERM, nil
302
	case SC_2_PBS,
303
		SC_2_PBS_ACCOUNTING,
304
		SC_2_PBS_CHECKPOINT,
305
		SC_2_PBS_LOCATE,
306
		SC_2_PBS_MESSAGE,
307
		SC_2_PBS_TRACK:
308
		return -1, nil
309
	case SC_2_UPE:
310
		return -1, nil
311

312
	case SC_XOPEN_CRYPT:
313
		// removed in glibc 2.28
314
		return -1, nil
315
	case SC_XOPEN_ENH_I18N:
316
		return _XOPEN_ENH_I18N, nil
317
	case SC_XOPEN_REALTIME:
318
		return _XOPEN_REALTIME, nil
319
	case SC_XOPEN_REALTIME_THREADS:
320
		return _XOPEN_REALTIME_THREADS, nil
321
	case SC_XOPEN_SHM:
322
		return _XOPEN_SHM, nil
323
	case SC_XOPEN_STREAMS:
324
		return -1, nil
325
	case SC_XOPEN_UNIX:
326
		return _XOPEN_UNIX, nil
327
	case SC_XOPEN_VERSION:
328
		return _XOPEN_VERSION, nil
329
	case SC_XOPEN_XCU_VERSION:
330
		return _XOPEN_XCU_VERSION, nil
331

332
	case SC_PHYS_PAGES:
333
		return getPhysPages(), nil
334
	case SC_AVPHYS_PAGES:
335
		return getAvPhysPages(), nil
336
	case SC_NPROCESSORS_CONF:
337
		return getNprocsConf(), nil
338
	case SC_NPROCESSORS_ONLN:
339
		return getNprocs(), nil
340
	case SC_UIO_MAXIOV: // same as _SC_IOV_MAX
341
		return _UIO_MAXIOV, nil
342
	}
343

344
	return sysconfGeneric(name)
345
}
346

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.