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

Collapse All | Expand All

(-)sys/kern/kern_clock.c (-26 / +104 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
/* forward decl */
102
static void _read_cpu_time(long *cp_time, bool ext)
103
104
/* Writes array of CPUSTATES (_EXT)
105
 * common body for sysctl_kern_cp_time() and sysctl_kern_cp_time_ext()
106
 */
101
static int
107
static int
102
sysctl_kern_cp_time(SYSCTL_HANDLER_ARGS)
108
_sysctl_kern_cp_time(SYSCTL_HANDLER_ARGS, bool ext)
103
{
109
{
104
	int error;
110
	int error;
105
	long cp_time[CPUSTATES];
111
	size_t cpustates = ext? CPUSTATES_EXT: CPUSTATES;
112
	long cp_time[cpustates];
106
#ifdef SCTL_MASK32
113
#ifdef SCTL_MASK32
107
	int i;
114
	int i;
108
	unsigned int cp_time32[CPUSTATES];
115
	unsigned int cp_time32[cpustates];
109
#endif
116
#endif
110
117
111
	read_cpu_time(cp_time);
118
	_read_cpu_time(cp_time, ext);
112
#ifdef SCTL_MASK32
119
#ifdef SCTL_MASK32
113
	if (req->flags & SCTL_MASK32) {
120
	if (req->flags & SCTL_MASK32) {
114
		if (!req->oldptr)
121
		if (!req->oldptr)
115
			return SYSCTL_OUT(req, 0, sizeof(cp_time32));
122
			return SYSCTL_OUT(req, 0, sizeof(cp_time32));
116
		for (i = 0; i < CPUSTATES; i++)
123
		for (i = 0; i < cpustates; i++)
117
			cp_time32[i] = (unsigned int)cp_time[i];
124
			cp_time32[i] = (unsigned int)cp_time[i];
118
		error = SYSCTL_OUT(req, cp_time32, sizeof(cp_time32));
125
		error = SYSCTL_OUT(req, cp_time32, sizeof(cp_time32));
119
	} else
126
	} else
120
#endif
127
#endif
121
	{
128
	{
122
		if (!req->oldptr)
129
		if (!req->oldptr)
123
			return SYSCTL_OUT(req, 0, sizeof(cp_time));
130
			return SYSCTL_OUT(req, 0, sizeof(cp_time));
124
		error = SYSCTL_OUT(req, cp_time, sizeof(cp_time));
131
		error = SYSCTL_OUT(req, cp_time, sizeof(cp_time));
125
	}
132
	}
126
	return error;
133
	return error;
127
}
134
}
128
135
136
static int
137
sysctl_kern_cp_time(SYSCTL_HANDLER_ARGS)
138
{
139
	return _sysctl_kern_cp_time(SYSCTL_HANDLER_VARS, false);
140
}
141
142
static int
143
sysctl_kern_cp_time_ext(SYSCTL_HANDLER_ARGS)
144
{
145
	return _sysctl_kern_cp_time(SYSCTL_HANDLER_VARS, true);
146
}
147
129
SYSCTL_PROC(_kern, OID_AUTO, cp_time, CTLTYPE_LONG|CTLFLAG_RD|CTLFLAG_MPSAFE,
148
SYSCTL_PROC(_kern, OID_AUTO, cp_time, CTLTYPE_LONG|CTLFLAG_RD|CTLFLAG_MPSAFE,
130
    0,0, sysctl_kern_cp_time, "LU", "CPU time statistics");
149
    0,0, sysctl_kern_cp_time, "LU", "CPU time statistics (user/nice/sys/intr/idle [1/stathz]; cumulated)");
131
150
151
SYSCTL_PROC(_kern, OID_AUTO, cp_time_ext, CTLTYPE_LONG|CTLFLAG_RD|CTLFLAG_MPSAFE,
152
    0,0, sysctl_kern_cp_time_ext, "LU", "extra CPU time statistics (fifo/realtime/user_idle/nice_fifo/nice_rt/nice_idle)\n"
153
					"\tNOTE: fractions of kern.cp_time[user/nice] (absolute -- not a quotient)");
154
132
static long empty[CPUSTATES];
155
static long empty[CPUSTATES];
156
static long empty_x[CPUSTATES_EXT];
133
157
158
/* common body for sysctl_kern_cp_times() and sysctl_kern_cp_times_ext() */
134
static int
159
static int
135
sysctl_kern_cp_times(SYSCTL_HANDLER_ARGS)
160
_sysctl_kern_cp_times(SYSCTL_HANDLER_ARGS, bool ext)
136
{
161
{
137
	struct pcpu *pcpu;
162
	struct pcpu *pcpu;
138
	int error;
163
	int error;
139
	int c;
164
	int c;
140
	long *cp_time;
165
	long *cp_time;
166
	size_t cpustates = ext? CPUSTATES_EXT: CPUSTATES;
141
#ifdef SCTL_MASK32
167
#ifdef SCTL_MASK32
142
	unsigned int cp_time32[CPUSTATES];
168
	unsigned int cp_time32[cpustates];
143
	int i;
169
	int i;
144
#endif
170
#endif
145
171
146
	if (!req->oldptr) {
172
	if (!req->oldptr) {
147
#ifdef SCTL_MASK32
173
#ifdef SCTL_MASK32
148
		if (req->flags & SCTL_MASK32)
174
		if (req->flags & SCTL_MASK32)
149
			return SYSCTL_OUT(req, 0, sizeof(cp_time32) * (mp_maxid + 1));
175
			return SYSCTL_OUT(req, 0, sizeof(cp_time32) * (mp_maxid + 1));
150
		else
176
		else
151
#endif
177
#endif
152
			return SYSCTL_OUT(req, 0, sizeof(long) * CPUSTATES * (mp_maxid + 1));
178
			return SYSCTL_OUT(req, 0, sizeof(long) * cpustates * (mp_maxid + 1));
153
	}
179
	}
154
	for (error = 0, c = 0; error == 0 && c <= mp_maxid; c++) {
180
	for (error = 0, c = 0; error == 0 && c <= mp_maxid; c++) {
155
		if (!CPU_ABSENT(c)) {
181
		if (!CPU_ABSENT(c)) {
156
			pcpu = pcpu_find(c);
182
			pcpu = pcpu_find(c);
157
			cp_time = pcpu->pc_cp_time;
183
			cp_time = ext? pcpu->pc_cp_time_ext: pcpu->pc_cp_time;
158
		} else {
184
		} else {
159
			cp_time = empty;
185
			cp_time = ext? empty_x: empty;
160
		}
186
		}
161
#ifdef SCTL_MASK32
187
#ifdef SCTL_MASK32
162
		if (req->flags & SCTL_MASK32) {
188
		if (req->flags & SCTL_MASK32) {
163
			for (i = 0; i < CPUSTATES; i++)
189
			for (i = 0; i < cpustates; i++)
164
				cp_time32[i] = (unsigned int)cp_time[i];
190
				cp_time32[i] = (unsigned int)cp_time[i];
165
			error = SYSCTL_OUT(req, cp_time32, sizeof(cp_time32));
191
			error = SYSCTL_OUT(req, cp_time32, sizeof(cp_time32));
166
		} else
192
		} else
167
#endif
193
#endif
168
			error = SYSCTL_OUT(req, cp_time, sizeof(long) * CPUSTATES);
194
			error = SYSCTL_OUT(req, cp_time, sizeof(long) * cpustates);
169
	}
195
	}
170
	return error;
196
	return error;
171
}
197
}
172
198
199
static int
200
sysctl_kern_cp_times(SYSCTL_HANDLER_ARGS)
201
{
202
	return _sysctl_kern_cp_times(SYSCTL_HANDLER_VARS, false);
203
}
204
205
static int
206
sysctl_kern_cp_times_ext(SYSCTL_HANDLER_ARGS)
207
{
208
	return _sysctl_kern_cp_times(SYSCTL_HANDLER_VARS, true);
209
}
210
173
SYSCTL_PROC(_kern, OID_AUTO, cp_times, CTLTYPE_LONG|CTLFLAG_RD|CTLFLAG_MPSAFE,
211
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");
212
    0,0, sysctl_kern_cp_times, "LU", "per-CPU time statistics (kern.cp_time[0] ...)");
175
213
214
SYSCTL_PROC(_kern, OID_AUTO, cp_times_ext, CTLTYPE_LONG|CTLFLAG_RD|CTLFLAG_MPSAFE,
215
    0,0, sysctl_kern_cp_times_ext, "LU", "extra per-CPU time statistics (kern.cp_time_ext[0] ...)");
216
176
#ifdef DEADLKRES
217
#ifdef DEADLKRES
177
static const char *blessed[] = {
218
static const char *blessed[] = {
178
	"getblk",
219
	"getblk",
179
	"so_snd_sx",
220
	"so_snd_sx",
180
	"so_rcv_sx",
221
	"so_rcv_sx",
181
	NULL
222
	NULL
182
};
223
};
Lines 312-338 Link Here
312
SYSCTL_INT(_debug_deadlkres, OID_AUTO, blktime_threshold, CTLFLAG_RW,
353
SYSCTL_INT(_debug_deadlkres, OID_AUTO, blktime_threshold, CTLFLAG_RW,
313
    &blktime_threshold, 0,
354
    &blktime_threshold, 0,
314
    "Number of seconds within is valid to block on a turnstile");
355
    "Number of seconds within is valid to block on a turnstile");
315
SYSCTL_INT(_debug_deadlkres, OID_AUTO, sleepfreq, CTLFLAG_RW, &sleepfreq, 0,
356
SYSCTL_INT(_debug_deadlkres, OID_AUTO, sleepfreq, CTLFLAG_RW, &sleepfreq, 0,
316
    "Number of seconds between any deadlock resolver thread run");
357
    "Number of seconds between any deadlock resolver thread run");
317
#endif	/* DEADLKRES */
358
#endif	/* DEADLKRES */
318
359
360
/* common body for read_cpu_time() and read_cpu_time_ext() */
361
static void
362
_read_cpu_time(long *cp_time, bool ext)
363
{
364
    struct pcpu *pc;
365
    size_t cpustates = (ext? CPUSTATES_EXT: CPUSTATES);
366
    int i, j;
367
    
368
    /* Sum up global cp_time[]. */
369
    bzero(cp_time, sizeof(long) * cpustates);
370
    CPU_FOREACH(i) {
371
	pc = pcpu_find(i);
372
	for (j = 0; j < cpustates; j++)
373
	    cp_time[j] += (ext? pc->pc_cp_time_ext[j]: pc->pc_cp_time[j]);
374
    }
375
}
376
319
void
377
void
320
read_cpu_time(long *cp_time)
378
read_cpu_time(long *cp_time)
321
{
379
{
322
	struct pcpu *pc;
380
    _read_cpu_time(cp_time, false);
323
	int i, j;
381
}
324
382
325
	/* Sum up global cp_time[]. */
383
void
326
	bzero(cp_time, sizeof(long) * CPUSTATES);
384
read_cpu_time_ext(long *cp_time)
327
	CPU_FOREACH(i) {
385
{
328
		pc = pcpu_find(i);
386
    _read_cpu_time(cp_time, true);
329
		for (j = 0; j < CPUSTATES; j++)
330
			cp_time[j] += pc->pc_cp_time[j];
331
	}
332
}
387
}
333
388
334
#include <sys/watchdog.h>
389
#include <sys/watchdog.h>
335
390
336
static int watchdog_ticks;
391
static int watchdog_ticks;
337
static int watchdog_enabled;
392
static int watchdog_enabled;
338
static void watchdog_fire(void);
393
static void watchdog_fire(void);
Lines 626-655 Link Here
626
statclock(int cnt, int usermode)
681
statclock(int cnt, int usermode)
627
{
682
{
628
	struct rusage *ru;
683
	struct rusage *ru;
629
	struct vmspace *vm;
684
	struct vmspace *vm;
630
	struct thread *td;
685
	struct thread *td;
631
	struct proc *p;
686
	struct proc *p;
632
	long rss;
687
	long rss;
633
	long *cp_time;
688
	long *cp_time, *cp_time_x;
634
	uint64_t runtime, new_switchtime;
689
	uint64_t runtime, new_switchtime;
635
690
636
	td = curthread;
691
	td = curthread;
637
	p = td->td_proc;
692
	p = td->td_proc;
638
693
639
	cp_time = (long *)PCPU_PTR(cp_time);
694
	cp_time = (long *)PCPU_PTR(cp_time);
695
	cp_time_x = (long *)PCPU_PTR(cp_time_ext);
640
	if (usermode) {
696
	if (usermode) {
641
		/*
697
		/*
642
		 * Charge the time as appropriate.
698
		 * Charge the time as appropriate.
643
		 */
699
		 */
644
		td->td_uticks += cnt;
700
		td->td_uticks += cnt;
645
		if (p->p_nice > NZERO)
701
		if (p->p_nice > NZERO) {
646
			cp_time[CP_NICE] += cnt;
702
			cp_time[CP_NICE] += cnt;
647
		else
703
			
704
			/* extra CPU statistics */
705
			switch (td->td_pri_class) {
706
			case PRI_FIFO:
707
				cp_time_x[CPX_NICE_FIFO] += cnt; break;
708
			case PRI_REALTIME:
709
				cp_time_x[CPX_NICE_RT] += cnt; break;
710
			case PRI_IDLE:
711
				cp_time_x[CPX_NICE_IDLE] += cnt; break;
712
			}
713
		} else {
648
			cp_time[CP_USER] += cnt;
714
			cp_time[CP_USER] += cnt;
715
716
			/* extra CPU statistics */
717
			switch (td->td_pri_class) {
718
			case PRI_FIFO:
719
				cp_time_x[CPX_USER_FIFO] += cnt; break;
720
			case PRI_REALTIME:
721
				cp_time_x[CPX_USER_RT] += cnt; break;
722
			case PRI_IDLE:
723
				cp_time_x[CPX_USER_IDLE] += cnt; break;
724
			}
725
		}
726
		/* "normal" USER_TIMESHARE = cp_time[CP_USER] - (sum(cp_time_x[USER_FIFO,USER_RT,USER_IDLE])) */
649
	} else {
727
	} else {
650
		/*
728
		/*
651
		 * Came from kernel mode, so we were:
729
		 * Came from kernel mode, so we were:
652
		 * - handling an interrupt,
730
		 * - handling an interrupt,
653
		 * - doing syscall or trap work on behalf of the current
731
		 * - doing syscall or trap work on behalf of the current
654
		 *   user process, or
732
		 *   user process, or
655
		 * - spinning in the idle loop.
733
		 * - spinning in the idle loop.
(-)sys/sys/pcpu.h (+1 lines)
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 (+12 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	CPX_USER_FIFO	0		/* fifo+realtime (libthr(3), rt_prio(8)) */ 
179
#define	CPX_USER_RT	1		/* (soft) realtime (rt_prio(8)) */ 
180
#define	CPX_USER_IDLE	2		/* (user) idle (idprio(8)) */
181
#define	CPX_NICE_FIFO	3		/* nice fifo+realtime */
182
#define	CPX_NICE_RT	4		/* nice (soft) realtime */
183
#define	CPX_NICE_IDLE	5		/* nice (user) idle */
184
#define	CPUSTATES_EXT	6		/* extra/refined CPU states */
185
175
#endif	/* __BSD_VISIBLE */
186
#endif	/* __BSD_VISIBLE */
176
187
177
#ifdef _KERNEL
188
#ifdef _KERNEL
178
189
179
extern struct loadavg averunnable;
190
extern struct loadavg averunnable;
180
void	read_cpu_time(long *cp_time);	/* Writes array of CPUSTATES */
191
void	read_cpu_time(long *cp_time);	/* Writes array of CPUSTATES */
192
void	read_cpu_time_ext(long *cp_time); /* Writes array of CPUSTATES_EXT */
181
193
182
#else
194
#else
183
195
184
__BEGIN_DECLS
196
__BEGIN_DECLS
185
/* XXX 2nd arg to [gs]etpriority() should be an id_t */
197
/* XXX 2nd arg to [gs]etpriority() should be an id_t */
186
int	getpriority(int, int);
198
int	getpriority(int, int);
187
int	getrlimit(int, struct rlimit *);
199
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