View | Details | Raw Unified | Return to bug 246940 | Differences between
and this patch

Collapse All | Expand All

(-)sys/kern/kern_clock.c (-32 / +102 lines)
Lines 94-182 Link Here
94
94
95
/* Spin-lock protecting profiling statistics. */
95
/* Spin-lock protecting profiling statistics. */
96
static struct mtx time_lock;
96
static struct mtx time_lock;
97
97
98
SDT_PROVIDER_DECLARE(sched);
98
SDT_PROVIDER_DECLARE(sched);
99
SDT_PROBE_DEFINE2(sched, , , tick, "struct thread *", "struct proc *");
99
SDT_PROBE_DEFINE2(sched, , , tick, "struct thread *", "struct proc *");
100
100
101
/* common body for read_cpu_time() and read_cpu_time_ext() */
102
static void
103
_read_cpu_time(long *cp_time, bool ext)
104
{
105
	struct pcpu *pc;
106
	size_t cpustates = (ext? CPUSTATES_EXT: CPUSTATES);
107
	int i, j;
108
109
	/* Sum up global cp_time[]. */
110
	bzero(cp_time, sizeof(long) * cpustates);
111
	CPU_FOREACH(i) {
112
		pc = pcpu_find(i);
113
		for (j = 0; j < cpustates; j++)
114
			cp_time[j] += (ext? pc->pc_cp_time_ext[j]: pc->pc_cp_time[j]);
115
	}
116
}
117
118
void
119
read_cpu_time(long *cp_time)
120
{
121
	_read_cpu_time(cp_time, false);
122
}
123
124
void
125
read_cpu_time_ext(long *cp_time)
126
{
127
	_read_cpu_time(cp_time, true);
128
}
129
130
131
/* Writes array of CPUSTATES (_EXT)
132
 * common body for sysctl_kern_cp_time() and sysctl_kern_cp_time_ext()
133
 */
101
static int
134
static int
102
sysctl_kern_cp_time(SYSCTL_HANDLER_ARGS)
135
_sysctl_kern_cp_time(SYSCTL_HANDLER_ARGS, bool ext)
103
{
136
{
104
	int error;
137
	int error;
105
	long cp_time[CPUSTATES];
138
	size_t cpustates = (ext? CPUSTATES_EXT: CPUSTATES);
139
	long cp_time[cpustates];
106
#ifdef SCTL_MASK32
140
#ifdef SCTL_MASK32
107
	int i;
141
	int i;
108
	unsigned int cp_time32[CPUSTATES];
142
	unsigned int cp_time32[cpustates];
109
#endif
143
#endif
110
144
111
	read_cpu_time(cp_time);
145
	_read_cpu_time(cp_time, ext);
112
#ifdef SCTL_MASK32
146
#ifdef SCTL_MASK32
113
	if (req->flags & SCTL_MASK32) {
147
	if (req->flags & SCTL_MASK32) {
114
		if (!req->oldptr)
148
		if (!req->oldptr)
115
			return SYSCTL_OUT(req, 0, sizeof(cp_time32));
149
			return SYSCTL_OUT(req, 0, sizeof(cp_time32));
116
		for (i = 0; i < CPUSTATES; i++)
150
		for (i = 0; i < cpustates; i++)
117
			cp_time32[i] = (unsigned int)cp_time[i];
151
			cp_time32[i] = (unsigned int)cp_time[i];
118
		error = SYSCTL_OUT(req, cp_time32, sizeof(cp_time32));
152
		error = SYSCTL_OUT(req, cp_time32, sizeof(cp_time32));
119
	} else
153
	} else
120
#endif
154
#endif
121
	{
155
	{
122
		if (!req->oldptr)
156
		if (!req->oldptr)
123
			return SYSCTL_OUT(req, 0, sizeof(cp_time));
157
			return SYSCTL_OUT(req, 0, sizeof(cp_time));
124
		error = SYSCTL_OUT(req, cp_time, sizeof(cp_time));
158
		error = SYSCTL_OUT(req, cp_time, sizeof(cp_time));
125
	}
159
	}
126
	return error;
160
	return error;
127
}
161
}
128
162
163
static int
164
sysctl_kern_cp_time(SYSCTL_HANDLER_ARGS)
165
{
166
	return _sysctl_kern_cp_time(SYSCTL_HANDLER_VARS, false);
167
}
168
169
static int
170
sysctl_kern_cp_time_ext(SYSCTL_HANDLER_ARGS)
171
{
172
	return _sysctl_kern_cp_time(SYSCTL_HANDLER_VARS, true);
173
}
174
129
SYSCTL_PROC(_kern, OID_AUTO, cp_time, CTLTYPE_LONG|CTLFLAG_RD|CTLFLAG_MPSAFE,
175
SYSCTL_PROC(_kern, OID_AUTO, cp_time, CTLTYPE_LONG|CTLFLAG_RD|CTLFLAG_MPSAFE,
130
    0,0, sysctl_kern_cp_time, "LU", "CPU time statistics");
176
    0,0, sysctl_kern_cp_time, "LU", "CPU time statistics (user/nice/sys/intr/idle [1/stathz]; cumulated)");
131
177
132
static long empty[CPUSTATES];
178
SYSCTL_PROC(_kern, OID_AUTO, cp_time_ext, CTLTYPE_LONG|CTLFLAG_RD|CTLFLAG_MPSAFE,
179
    0,0, sysctl_kern_cp_time_ext, "LU", "extra CPU time statistics (user_realtime/user_idle/nice_rt/nice_idle)\n"
180
					"\tNOTE: fractions of kern.cp_time (absolute - not a quotient)");
181
static long empty[MAX( CPUSTATES, CPUSTATES_EXT )];
133
182
183
/* common body for sysctl_kern_cp_times() and sysctl_kern_cp_times_ext() */
134
static int
184
static int
135
sysctl_kern_cp_times(SYSCTL_HANDLER_ARGS)
185
_sysctl_kern_cp_times(SYSCTL_HANDLER_ARGS, bool ext)
136
{
186
{
137
	struct pcpu *pcpu;
187
	struct pcpu *pcpu;
138
	int error;
188
	int error;
139
	int c;
189
	int c;
140
	long *cp_time;
190
	long *cp_time;
191
	size_t cpustates = (ext? CPUSTATES_EXT: CPUSTATES);
141
#ifdef SCTL_MASK32
192
#ifdef SCTL_MASK32
142
	unsigned int cp_time32[CPUSTATES];
193
	unsigned int cp_time32[cpustates];
143
	int i;
194
	int i;
144
#endif
195
#endif
145
196
146
	if (!req->oldptr) {
197
	if (!req->oldptr) {
147
#ifdef SCTL_MASK32
198
#ifdef SCTL_MASK32
148
		if (req->flags & SCTL_MASK32)
199
		if (req->flags & SCTL_MASK32)
149
			return SYSCTL_OUT(req, 0, sizeof(cp_time32) * (mp_maxid + 1));
200
			return SYSCTL_OUT(req, 0, sizeof(cp_time32) * (mp_maxid + 1));
150
		else
201
		else
151
#endif
202
#endif
152
			return SYSCTL_OUT(req, 0, sizeof(long) * CPUSTATES * (mp_maxid + 1));
203
			return SYSCTL_OUT(req, 0, sizeof(long) * cpustates * (mp_maxid + 1));
153
	}
204
	}
154
	for (error = 0, c = 0; error == 0 && c <= mp_maxid; c++) {
205
	for (error = 0, c = 0; error == 0 && c <= mp_maxid; c++) {
155
		if (!CPU_ABSENT(c)) {
206
		if (!CPU_ABSENT(c)) {
156
			pcpu = pcpu_find(c);
207
			pcpu = pcpu_find(c);
157
			cp_time = pcpu->pc_cp_time;
208
			cp_time = (ext? pcpu->pc_cp_time_ext: pcpu->pc_cp_time);
158
		} else {
209
		} else {
159
			cp_time = empty;
210
			cp_time = empty;
160
		}
211
		}
161
#ifdef SCTL_MASK32
212
#ifdef SCTL_MASK32
162
		if (req->flags & SCTL_MASK32) {
213
		if (req->flags & SCTL_MASK32) {
163
			for (i = 0; i < CPUSTATES; i++)
214
			for (i = 0; i < cpustates; i++)
164
				cp_time32[i] = (unsigned int)cp_time[i];
215
				cp_time32[i] = (unsigned int)cp_time[i];
165
			error = SYSCTL_OUT(req, cp_time32, sizeof(cp_time32));
216
			error = SYSCTL_OUT(req, cp_time32, sizeof(cp_time32));
166
		} else
217
		} else
167
#endif
218
#endif
168
			error = SYSCTL_OUT(req, cp_time, sizeof(long) * CPUSTATES);
219
			error = SYSCTL_OUT(req, cp_time, sizeof(long) * cpustates);
169
	}
220
	}
170
	return error;
221
	return error;
171
}
222
}
172
223
224
static int
225
sysctl_kern_cp_times(SYSCTL_HANDLER_ARGS)
226
{
227
	return _sysctl_kern_cp_times(SYSCTL_HANDLER_VARS, false);
228
}
229
230
static int
231
sysctl_kern_cp_times_ext(SYSCTL_HANDLER_ARGS)
232
{
233
	return _sysctl_kern_cp_times(SYSCTL_HANDLER_VARS, true);
234
}
235
173
SYSCTL_PROC(_kern, OID_AUTO, cp_times, CTLTYPE_LONG|CTLFLAG_RD|CTLFLAG_MPSAFE,
236
SYSCTL_PROC(_kern, OID_AUTO, cp_times, CTLTYPE_LONG|CTLFLAG_RD|CTLFLAG_MPSAFE,
174
    0,0, sysctl_kern_cp_times, "LU", "per-CPU time statistics");
237
    0,0, sysctl_kern_cp_times, "LU", "per-CPU time statistics (kern.cp_time[0] ...)");
175
238
239
SYSCTL_PROC(_kern, OID_AUTO, cp_times_ext, CTLTYPE_LONG|CTLFLAG_RD|CTLFLAG_MPSAFE,
240
    0,0, sysctl_kern_cp_times_ext, "LU", "extra per-CPU time statistics (kern.cp_time_ext[0] ...)");
241
176
#ifdef DEADLKRES
242
#ifdef DEADLKRES
177
static const char *blessed[] = {
243
static const char *blessed[] = {
178
	"getblk",
244
	"getblk",
179
	"so_snd_sx",
245
	"so_snd_sx",
180
	"so_rcv_sx",
246
	"so_rcv_sx",
181
	NULL
247
	NULL
182
};
248
};
Lines 312-340 Link Here
312
SYSCTL_INT(_debug_deadlkres, OID_AUTO, blktime_threshold, CTLFLAG_RW,
378
SYSCTL_INT(_debug_deadlkres, OID_AUTO, blktime_threshold, CTLFLAG_RW,
313
    &blktime_threshold, 0,
379
    &blktime_threshold, 0,
314
    "Number of seconds within is valid to block on a turnstile");
380
    "Number of seconds within is valid to block on a turnstile");
315
SYSCTL_INT(_debug_deadlkres, OID_AUTO, sleepfreq, CTLFLAG_RW, &sleepfreq, 0,
381
SYSCTL_INT(_debug_deadlkres, OID_AUTO, sleepfreq, CTLFLAG_RW, &sleepfreq, 0,
316
    "Number of seconds between any deadlock resolver thread run");
382
    "Number of seconds between any deadlock resolver thread run");
317
#endif	/* DEADLKRES */
383
#endif	/* DEADLKRES */
318
384
319
void
320
read_cpu_time(long *cp_time)
321
{
322
	struct pcpu *pc;
323
	int i, j;
324
325
	/* Sum up global cp_time[]. */
326
	bzero(cp_time, sizeof(long) * CPUSTATES);
327
	CPU_FOREACH(i) {
328
		pc = pcpu_find(i);
329
		for (j = 0; j < CPUSTATES; j++)
330
			cp_time[j] += pc->pc_cp_time[j];
331
	}
332
}
333
334
#include <sys/watchdog.h>
385
#include <sys/watchdog.h>
335
386
336
static int watchdog_ticks;
387
static int watchdog_ticks;
337
static int watchdog_enabled;
388
static int watchdog_enabled;
338
static void watchdog_fire(void);
389
static void watchdog_fire(void);
339
static void watchdog_config(void *, u_int, int *);
390
static void watchdog_config(void *, u_int, int *);
340
391
Lines 626-655 Link Here
626
statclock(int cnt, int usermode)
677
statclock(int cnt, int usermode)
627
{
678
{
628
	struct rusage *ru;
679
	struct rusage *ru;
629
	struct vmspace *vm;
680
	struct vmspace *vm;
630
	struct thread *td;
681
	struct thread *td;
631
	struct proc *p;
682
	struct proc *p;
632
	long rss;
683
	long rss;
633
	long *cp_time;
684
	long *cp_time, *cp_time_x;
634
	uint64_t runtime, new_switchtime;
685
	uint64_t runtime, new_switchtime;
635
686
636
	td = curthread;
687
	td = curthread;
637
	p = td->td_proc;
688
	p = td->td_proc;
638
689
639
	cp_time = (long *)PCPU_PTR(cp_time);
690
	cp_time = (long *)PCPU_PTR(cp_time);
691
	cp_time_x = (long *)PCPU_PTR(cp_time_ext);
640
	if (usermode) {
692
	if (usermode) {
641
		/*
693
		/*
642
		 * Charge the time as appropriate.
694
		 * Charge the time as appropriate.
643
		 */
695
		 */
644
		td->td_uticks += cnt;
696
		td->td_uticks += cnt;
645
		if (p->p_nice > NZERO)
697
		if (p->p_nice > NZERO) {
646
			cp_time[CP_NICE] += cnt;
698
			cp_time[CP_NICE] += cnt;
647
		else
699
			
700
			/* extra CPU statistics */
701
			switch (td->td_pri_class) {
702
			case PRI_REALTIME:
703
				cp_time_x[CP_NICE_RT] += cnt; break;
704
			case PRI_IDLE:
705
				cp_time_x[CP_NICE_IDLE] += cnt; break;
706
			}
707
		} else {
648
			cp_time[CP_USER] += cnt;
708
			cp_time[CP_USER] += cnt;
709
710
			/* extra CPU statistics */
711
			switch (td->td_pri_class) {
712
			case PRI_REALTIME:
713
				cp_time_x[CP_USER_RT] += cnt; break;
714
			case PRI_IDLE:
715
				cp_time_x[CP_USER_IDLE] += cnt; break;
716
			}
717
		}
718
		/* "normal" TIMESHARE_USER = cp_time[CP_USER] - (sum(cp_time_x[USER_RT,USER_IDLE])) */
649
	} else {
719
	} else {
650
		/*
720
		/*
651
		 * Came from kernel mode, so we were:
721
		 * Came from kernel mode, so we were:
652
		 * - handling an interrupt,
722
		 * - handling an interrupt,
653
		 * - doing syscall or trap work on behalf of the current
723
		 * - doing syscall or trap work on behalf of the current
654
		 *   user process, or
724
		 *   user process, or
655
		 * - spinning in the idle loop.
725
		 * - spinning in the idle loop.
(-)sys/sys/pcpu.h (-1 / +2 lines)
Lines 44-58 Link Here
44
#include <sys/_mutex.h>
44
#include <sys/_mutex.h>
45
#include <sys/_sx.h>
45
#include <sys/_sx.h>
46
#include <sys/queue.h>
46
#include <sys/queue.h>
47
#include <sys/_rmlock.h>
47
#include <sys/_rmlock.h>
48
#include <sys/resource.h>
48
#include <sys/resource.h>
49
#include <machine/pcpu.h>
49
#include <machine/pcpu.h>
50
50
51
#define	DPCPU_SETNAME		"set_pcpu"
51
#define	PCPU_SETNAME		"set_pcpu"
52
#define	DPCPU_SYMPREFIX		"pcpu_entry_"
52
#define	DPCPU_SYMPREFIX		"pcpu_entry_"
53
53
54
#ifdef _KERNEL
54
#ifdef _KERNEL
55
55
56
/*
56
/*
57
 * Define a set for pcpu data.
57
 * Define a set for pcpu data.
58
 */
58
 */
Lines 180-193 Link Here
180
	struct pcb	*pc_curpcb;		/* Current pcb */
180
	struct pcb	*pc_curpcb;		/* Current pcb */
181
	uint64_t	pc_switchtime;		/* cpu_ticks() at last csw */
181
	uint64_t	pc_switchtime;		/* cpu_ticks() at last csw */
182
	int		pc_switchticks;		/* `ticks' at last csw */
182
	int		pc_switchticks;		/* `ticks' at last csw */
183
	u_int		pc_cpuid;		/* This cpu number */
183
	u_int		pc_cpuid;		/* This cpu number */
184
	STAILQ_ENTRY(pcpu) pc_allcpu;
184
	STAILQ_ENTRY(pcpu) pc_allcpu;
185
	struct lock_list_entry *pc_spinlocks;
185
	struct lock_list_entry *pc_spinlocks;
186
	long		pc_cp_time[CPUSTATES];	/* statclock ticks */
186
	long		pc_cp_time[CPUSTATES];	/* statclock ticks */
187
	long		pc_cp_time_ext[CPUSTATES_EXT]; /* statclock ticks */
187
	struct device	*pc_device;
188
	struct device	*pc_device;
188
	void		*pc_netisr;		/* netisr SWI cookie */
189
	void		*pc_netisr;		/* netisr SWI cookie */
189
	int		pc_unused1;		/* unused field */
190
	int		pc_unused1;		/* unused field */
190
	int		pc_domain;		/* Memory domain. */
191
	int		pc_domain;		/* Memory domain. */
191
	struct rm_queue	pc_rm_queue;		/* rmlock list of trackers */
192
	struct rm_queue	pc_rm_queue;		/* rmlock list of trackers */
192
	uintptr_t	pc_dynamic;		/* Dynamic per-cpu data area */
193
	uintptr_t	pc_dynamic;		/* Dynamic per-cpu data area */
193
	uint64_t	pc_early_dummy_counter;	/* Startup time counter(9) */
194
	uint64_t	pc_early_dummy_counter;	/* Startup time counter(9) */
(-)sys/sys/resource.h (+10 lines)
Lines 168-187 Link Here
168
#define	CP_USER		0
168
#define	CP_USER		0
169
#define	CP_NICE		1
169
#define	CP_NICE		1
170
#define	CP_SYS		2
170
#define	CP_SYS		2
171
#define	CP_INTR		3
171
#define	CP_INTR		3
172
#define	CP_IDLE		4
172
#define	CP_IDLE		4
173
#define	CPUSTATES	5
173
#define	CPUSTATES	5
174
174
175
/* These are exposed via sysctls cp_time(s)_ext:
176
 * NOTE all are (absolute) fractions of CP_USER or CP_NICE, resp. (not as a quotient)
177
 */
178
#define	CP_USER_RT	0		/* (soft) realtime (rt_prio(8)) */ 
179
#define	CP_USER_IDLE	1		/* (user) idle (idprio(8)) */
180
#define	CP_NICE_RT	2		/* nice (soft) realtime */
181
#define	CP_NICE_IDLE	3		/* nice (user) idle */
182
#define	CPUSTATES_EXT	4		/* extra/refined CPU states */
183
175
#endif	/* __BSD_VISIBLE */
184
#endif	/* __BSD_VISIBLE */
176
185
177
#ifdef _KERNEL
186
#ifdef _KERNEL
178
187
179
extern struct loadavg averunnable;
188
extern struct loadavg averunnable;
180
void	read_cpu_time(long *cp_time);	/* Writes array of CPUSTATES */
189
void	read_cpu_time(long *cp_time);	/* Writes array of CPUSTATES */
190
void	read_cpu_time_ext(long *cp_time); /* Writes array of CPUSTATES_EXT */
181
191
182
#else
192
#else
183
193
184
__BEGIN_DECLS
194
__BEGIN_DECLS
185
/* XXX 2nd arg to [gs]etpriority() should be an id_t */
195
/* XXX 2nd arg to [gs]etpriority() should be an id_t */
186
int	getpriority(int, int);
196
int	getpriority(int, int);
187
int	getrlimit(int, struct rlimit *);
197
int	getrlimit(int, struct rlimit *);
(-)sys/sys/sysctl.h (+1 lines)
Lines 139-152 Link Here
139
#define	SYSCTL_CT_ASSERT_MASK CTLTYPE
139
#define	SYSCTL_CT_ASSERT_MASK CTLTYPE
140
#else
140
#else
141
#define	SYSCTL_CT_ASSERT_MASK 0
141
#define	SYSCTL_CT_ASSERT_MASK 0
142
#endif
142
#endif
143
143
144
#define	SYSCTL_HANDLER_ARGS struct sysctl_oid *oidp, void *arg1,	\
144
#define	SYSCTL_HANDLER_ARGS struct sysctl_oid *oidp, void *arg1,	\
145
	intmax_t arg2, struct sysctl_req *req
145
	intmax_t arg2, struct sysctl_req *req
146
#define	SYSCTL_HANDLER_VARS oidp, arg1, arg2, req
146
147
147
/* definitions for sysctl_req 'lock' member */
148
/* definitions for sysctl_req 'lock' member */
148
#define	REQ_UNWIRED	1
149
#define	REQ_UNWIRED	1
149
#define	REQ_WIRED	2
150
#define	REQ_WIRED	2
150
151
151
/* definitions for sysctl_req 'flags' member */
152
/* definitions for sysctl_req 'flags' member */
152
#if defined(__aarch64__) || defined(__amd64__) || defined(__powerpc64__) ||\
153
#if defined(__aarch64__) || defined(__amd64__) || defined(__powerpc64__) ||\

Return to bug 246940