Add cpuctl(8). For now this is not much more than a toy for debugging and

benchmarking that allows taking CPUs online/offline.
This commit is contained in:
ad 2007-08-04 11:02:56 +00:00
parent e4f6da7b0c
commit 18af8ee9bd
19 changed files with 616 additions and 31 deletions

View File

@ -1,4 +1,4 @@
# $NetBSD: mi,v 1.717 2007/07/15 18:23:36 jmmv Exp $
# $NetBSD: mi,v 1.718 2007/08/04 11:02:56 ad Exp $
. base-sys-root
./altroot base-sys-root
./bin base-sys-root
@ -1036,6 +1036,7 @@
./usr/sbin/chroot base-sysutil-bin
./usr/sbin/chrtbl base-sysutil-bin
./usr/sbin/cnwctl base-netutil-bin
./usr/sbin/cpuctl base-sysutil-bin
./usr/sbin/cron base-cron-bin
./usr/sbin/daicctl base-isdn-bin
./usr/sbin/dbsym base-sysutil-bin bfd

View File

@ -1,4 +1,4 @@
# $NetBSD: mi,v 1.1056 2007/07/30 06:58:18 taca Exp $
# $NetBSD: mi,v 1.1057 2007/08/04 11:02:58 ad Exp $
./etc/mtree/set.comp comp-sys-root
./usr/bin/addr2line comp-debug-bin bfd
./usr/bin/ar comp-util-bin bfd
@ -1769,6 +1769,7 @@
./usr/include/sys/conf.h comp-c-include
./usr/include/sys/core.h comp-c-include
./usr/include/sys/cpu_data.h comp-obsolete obsolete
./usr/include/sys/cpuio.h comp-c-include
./usr/include/sys/device.h comp-c-include
./usr/include/sys/dir.h comp-c-include
./usr/include/sys/dirent.h comp-c-include

View File

@ -1,4 +1,4 @@
# $NetBSD: mi,v 1.1017 2007/07/28 15:01:25 kiyohara Exp $
# $NetBSD: mi,v 1.1018 2007/08/04 11:02:57 ad Exp $
./etc/mtree/set.man man-sys-root
./usr/share/info/am-utils.info man-amd-info info
./usr/share/info/as.info man-computil-info bfd,info
@ -1888,6 +1888,7 @@
./usr/share/man/cat8/compat_win32.0 man-sys-catman .cat
./usr/share/man/cat8/compat_xenix.0 man-sys-catman .cat
./usr/share/man/cat8/comsat.0 man-man-catman .cat
./usr/share/man/cat8/cpuctl.0 man-sysutil-catman .cat
./usr/share/man/cat8/cron.0 man-cron-catman .cat
./usr/share/man/cat8/dbsym.0 man-sysutil-catman bfd,.cat
./usr/share/man/cat8/defer.0 man-postfix-catman postfix,.cat
@ -4366,6 +4367,7 @@
./usr/share/man/man8/compat_win32.8 man-sys-man .man
./usr/share/man/man8/compat_xenix.8 man-sys-man .man
./usr/share/man/man8/comsat.8 man-man-man .man
./usr/share/man/man8/cpuctl.8 man-sysutil-man .man
./usr/share/man/man8/cron.8 man-cron-man .man
./usr/share/man/man8/dbsym.8 man-sysutil-man bfd,.man
./usr/share/man/man8/defer.8 man-postfix-man postfix,.man

View File

@ -1,5 +1,5 @@
#!/bin/sh -
# $NetBSD: MAKEDEV.tmpl,v 1.86 2007/05/16 13:06:03 martti Exp $
# $NetBSD: MAKEDEV.tmpl,v 1.87 2007/08/04 11:03:04 ad Exp $
#
# Copyright (c) 2003,2007 The NetBSD Foundation, Inc.
# All rights reserved.
@ -234,6 +234,7 @@
# ch* SCSI media changer
# cir* Consumer IR
# clockctl clock control for non root users
# cpuctl CPU control
# crypto hardware crypto access driver
# dmoverio hardware-assisted data movers
# dpt* DPT/Adaptec EATA RAID management interface
@ -521,7 +522,7 @@ all)
makedev bpf
makedev tun0 tun1 tun2 tun3
makedev ipl pf crypto random systrace
makedev lkm lockstat clockctl
makedev lkm lockstat clockctl cpuctl
makedev atabus0 atabus1 atabus2 atabus3
makedev tap tap0 tap1 tap2 tap3
makedev gpio gpio0 gpio1 gpio2 gpio3 gpio4 gpio5 gpio6 gpio7
@ -1058,6 +1059,10 @@ lockstat)
mkdev lockstat c %lockstat_chr% 0
;;
cpuctl)
mkdev cpuctl c %cpuctl_chr% 0 666
;;
audio*)
unit=${i#audio}
audio=audio$unit

View File

@ -1,4 +1,4 @@
# $NetBSD: files,v 1.856 2007/07/29 14:44:09 pooka Exp $
# $NetBSD: files,v 1.857 2007/08/04 11:02:59 ad Exp $
# @(#)files.newconf 7.5 (Berkeley) 5/10/93
@ -1217,6 +1217,9 @@ defpseudo fwiso: ieee1394
defpseudo drvctl
file kern/kern_drvctl.c drvctl
# cpu control
defpseudo cpuctl
#
# File systems
#

View File

@ -1,4 +1,4 @@
# $NetBSD: majors,v 1.34 2007/05/01 17:18:55 bouyer Exp $
# $NetBSD: majors,v 1.35 2007/08/04 11:03:00 ad Exp $
#
# Device majors for Machine-Independent drivers.
#
@ -32,3 +32,4 @@ device-major srt char 179 srt
device-major drm char 180 drmbase
device-major bio char 181 bio
device-major twa char 187 twa
device-major cpuctl char 188

View File

@ -1,4 +1,4 @@
# $NetBSD: std,v 1.8 2007/05/17 14:51:37 yamt Exp $
# $NetBSD: std,v 1.9 2007/08/04 11:03:00 ad Exp $
#
# standard MI 'options'
#
@ -23,3 +23,5 @@ options secmodel_bsd44 # Traditional 4.4BSD security model
# Scheduling algorithm
#
options SCHED_4BSD
pseudo-device cpuctl

View File

@ -1,4 +1,4 @@
/* $NetBSD: init_main.c,v 1.311 2007/07/30 08:45:26 pooka Exp $ */
/* $NetBSD: init_main.c,v 1.312 2007/08/04 11:03:00 ad Exp $ */
/*
* Copyright (c) 1982, 1986, 1989, 1991, 1992, 1993
@ -71,7 +71,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: init_main.c,v 1.311 2007/07/30 08:45:26 pooka Exp $");
__KERNEL_RCSID(0, "$NetBSD: init_main.c,v 1.312 2007/08/04 11:03:00 ad Exp $");
#include "opt_ipsec.h"
#include "opt_multiprocessor.h"
@ -256,6 +256,8 @@ main(void)
#ifdef NVNODE_IMPLICIT
int usevnodes;
#endif
CPU_INFO_ITERATOR cii;
struct cpu_info *ci;
/*
* Initialize the current LWP pointer (curlwp) before
@ -340,6 +342,7 @@ main(void)
(void)chgproccnt(0, 1);
/* Initialize the run queues, turnstiles and sleep queues. */
mutex_init(&cpu_lock, MUTEX_DEFAULT, IPL_NONE);
sched_rqinit();
turnstile_init();
sleeptab_init(&sleeptab);
@ -611,6 +614,10 @@ main(void)
}
mutex_exit(&proclist_lock);
for (CPU_INFO_FOREACH(cii, ci)) {
ci->ci_schedstate.spc_lastmod = time_second;
}
/* Create the pageout daemon kernel thread. */
uvm_swap_init();
if (kthread_create(PVM, 0, NULL, uvm_pageout,

View File

@ -1,4 +1,40 @@
/* $NetBSD: kern_cpu.c,v 1.2 2007/05/17 14:51:38 yamt Exp $ */
/* $NetBSD: kern_cpu.c,v 1.3 2007/08/04 11:03:01 ad Exp $ */
/*-
* Copyright (c) 2007 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Andrew Doran.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*-
* Copyright (c)2007 YAMAMOTO Takashi,
@ -28,14 +64,30 @@
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: kern_cpu.c,v 1.2 2007/05/17 14:51:38 yamt Exp $");
__KERNEL_RCSID(0, "$NetBSD: kern_cpu.c,v 1.3 2007/08/04 11:03:01 ad Exp $");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/idle.h>
#include <sys/sched.h>
#include <sys/conf.h>
#include <sys/cpu.h>
#include <sys/cpuio.h>
#include <sys/proc.h>
#include <sys/kernel.h>
#include <sys/kauth.h>
#include <machine/cpu.h>
void cpuctlattach(int);
dev_type_ioctl(cpuctl_ioctl);
const struct cdevsw cpuctl_cdevsw = {
nullopen, nullclose, nullread, nullwrite, cpuctl_ioctl,
nullstop, notty, nopoll, nommap, nokqfilter,
D_OTHER | D_MPSAFE
};
kmutex_t cpu_lock;
int
mi_cpu_attach(struct cpu_info *ci)
@ -56,3 +108,138 @@ mi_cpu_attach(struct cpu_info *ci)
return 0;
}
void
cpuctlattach(int dummy)
{
}
int
cpuctl_ioctl(dev_t dev, u_long cmd, void *data, int flag, lwp_t *l)
{
CPU_INFO_ITERATOR cii;
cpustate_t *cs;
struct cpu_info *ci;
int error, i;
u_int id;
error = 0;
mutex_enter(&cpu_lock);
switch (cmd) {
case IOC_CPU_SETSTATE:
error = kauth_authorize_generic(l->l_cred,
KAUTH_GENERIC_ISSUSER, NULL);
if (error != 0)
break;
cs = data;
if ((ci = cpu_lookup(cs->cs_id)) == NULL) {
error = ESRCH;
break;
}
if (!cs->cs_intr) {
error = EOPNOTSUPP;
break;
}
error = cpu_setonline(ci, cs->cs_online);
break;
case IOC_CPU_GETSTATE:
cs = data;
id = cs->cs_id;
memset(cs, sizeof(*cs), 0);
cs->cs_id = id;
if ((ci = cpu_lookup(id)) == NULL) {
error = ESRCH;
break;
}
if ((ci->ci_schedstate.spc_flags & SPCF_OFFLINE) != 0)
cs->cs_online = false;
else
cs->cs_online = true;
cs->cs_intr = true;
cs->cs_lastmod = ci->ci_schedstate.spc_lastmod;
break;
case IOC_CPU_MAPID:
i = 0;
for (CPU_INFO_FOREACH(cii, ci)) {
if (i++ == *(int *)data)
break;
}
if (ci == NULL)
error = ESRCH;
else
*(int *)data = ci->ci_cpuid;
break;
case IOC_CPU_GETCOUNT:
*(int *)data = ncpu;
break;
default:
error = ENOTTY;
break;
}
mutex_exit(&cpu_lock);
return error;
}
struct cpu_info *
cpu_lookup(cpuid_t id)
{
CPU_INFO_ITERATOR cii;
struct cpu_info *ci;
for (CPU_INFO_FOREACH(cii, ci)) {
if (ci->ci_cpuid == id)
return ci;
}
return NULL;
}
int
cpu_setonline(struct cpu_info *ci, bool online)
{
struct schedstate_percpu *spc;
CPU_INFO_ITERATOR cii;
struct cpu_info *ci2;
int nonline;
spc = &ci->ci_schedstate;
KASSERT(mutex_owned(&cpu_lock));
if (online) {
if ((spc->spc_flags & SPCF_OFFLINE) == 0)
return 0;
spc_lock(ci);
spc->spc_flags &= ~SPCF_OFFLINE;
cpu_need_resched(ci, true);
spc_unlock(ci);
spc->spc_lastmod = time_second;
} else {
if ((spc->spc_flags & SPCF_OFFLINE) != 0)
return 0;
nonline = 0;
for (CPU_INFO_FOREACH(cii, ci2)) {
nonline += ((ci2->ci_schedstate.spc_flags &
SPCF_OFFLINE) == 0);
}
if (nonline == 1)
return EBUSY;
spc_lock(ci);
spc->spc_flags |= SPCF_OFFLINE;
cpu_need_resched(ci, true);
spc_unlock(ci);
do {
kpause("cpu", false, 1, NULL);
} while (ci->ci_curlwp != ci->ci_data.cpu_idlelwp);
spc->spc_lastmod = time_second;
}
return 0;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: kern_synch.c,v 1.192 2007/08/02 01:48:44 rmind Exp $ */
/* $NetBSD: kern_synch.c,v 1.193 2007/08/04 11:03:01 ad Exp $ */
/*-
* Copyright (c) 1999, 2000, 2004, 2006, 2007 The NetBSD Foundation, Inc.
@ -75,7 +75,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: kern_synch.c,v 1.192 2007/08/02 01:48:44 rmind Exp $");
__KERNEL_RCSID(0, "$NetBSD: kern_synch.c,v 1.193 2007/08/04 11:03:01 ad Exp $");
#include "opt_kstack.h"
#include "opt_lockdebug.h"
@ -394,13 +394,13 @@ mi_switch(struct lwp *l)
pmc_save_context(l->l_proc);
}
#endif
spc->spc_flags &= ~SPCF_SWITCHCLEAR;
updatertime(l, spc);
/*
* If on the CPU and we have gotten this far, then we must yield.
*/
mutex_spin_enter(spc->spc_mutex);
spc->spc_flags &= ~SPCF_SWITCHCLEAR;
KASSERT(l->l_stat != LSRUN);
if (l->l_stat == LSONPROC) {
KASSERT(lwp_locked(l, &spc->spc_lwplock));

View File

@ -1,4 +1,4 @@
/* $NetBSD: sched_4bsd.c,v 1.3 2007/07/09 21:10:55 ad Exp $ */
/* $NetBSD: sched_4bsd.c,v 1.4 2007/08/04 11:03:02 ad Exp $ */
/*-
* Copyright (c) 1999, 2000, 2004, 2006, 2007 The NetBSD Foundation, Inc.
@ -75,7 +75,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: sched_4bsd.c,v 1.3 2007/07/09 21:10:55 ad Exp $");
__KERNEL_RCSID(0, "$NetBSD: sched_4bsd.c,v 1.4 2007/08/04 11:03:02 ad Exp $");
#include "opt_ddb.h"
#include "opt_lockdebug.h"
@ -145,6 +145,7 @@ sched_tick(struct cpu_info *ci)
spc->spc_ticks = rrticks;
spc_lock(ci);
if (!CURCPU_IDLE_P()) {
if (spc->spc_flags & SPCF_SEENRR) {
/*
@ -157,6 +158,7 @@ sched_tick(struct cpu_info *ci)
spc->spc_flags |= SPCF_SEENRR;
}
cpu_need_resched(curcpu(), 0);
spc_unlock(ci);
}
#define NICE_WEIGHT 2 /* priorities per nice level */
@ -514,9 +516,15 @@ sched_setrunnable(struct lwp *l)
bool
sched_curcpu_runnable_p(void)
{
runqueue_t *rq = curcpu()->ci_schedstate.spc_sched_info;
struct schedstate_percpu *spc;
runqueue_t *rq;
return (global_queue.rq_bitmap | rq->rq_bitmap) != 0;
spc = &curcpu()->ci_schedstate;
rq = spc->spc_sched_info;
if (__predict_true((spc->spc_flags & SPCF_OFFLINE) == 0))
return (global_queue.rq_bitmap | rq->rq_bitmap) != 0;
return rq->rq_bitmap != 0;
}
void
@ -664,10 +672,15 @@ sched_dequeue(struct lwp *l)
struct lwp *
sched_nextlwp(void)
{
struct schedstate_percpu *spc;
lwp_t *l1, *l2;
spc = &curcpu()->ci_schedstate;
/* For now, just pick the highest priority LWP. */
l1 = runqueue_nextlwp(curcpu()->ci_schedstate.spc_sched_info);
l1 = runqueue_nextlwp(spc->spc_sched_info);
if (__predict_false((spc->spc_flags & SPCF_OFFLINE) != 0))
return l1;
l2 = runqueue_nextlwp(&global_queue);
if (l1 == NULL)

View File

@ -1,4 +1,4 @@
# $NetBSD: Makefile,v 1.94 2007/04/30 14:44:31 rmind Exp $
# $NetBSD: Makefile,v 1.95 2007/08/04 11:03:03 ad Exp $
INCSDIR= /usr/include/sys
@ -6,7 +6,7 @@ INCS= acct.h agpio.h aio.h ansi.h ataio.h audioio.h \
bootblock.h bswap.h buf.h \
callout.h cdefs.h cdefs_aout.h \
cdefs_elf.h cdio.h chio.h clockctl.h condvar.h conf.h core.h \
device.h dir.h dirent.h disk.h disklabel.h disklabel_acorn.h \
cpuio.h device.h dir.h dirent.h disk.h disklabel.h disklabel_acorn.h \
disklabel_gpt.h \
dkbad.h dkio.h dkstat.h domain.h drvctlio.h dvdio.h \
endian.h envsys.h errno.h evcnt.h event.h exec.h exec_aout.h \

View File

@ -1,4 +1,4 @@
/* $NetBSD: cpu.h,v 1.8 2007/05/17 14:51:42 yamt Exp $ */
/* $NetBSD: cpu.h,v 1.9 2007/08/04 11:03:02 ad Exp $ */
/*-
* Copyright (c) 2007 YAMAMOTO Takashi,
@ -43,6 +43,9 @@ void cpu_idle(void);
void cpu_need_resched(struct cpu_info *, int);
#endif
/* flags for cpu_need_resched */
#define RESCHED_IMMED 1
#ifndef cpu_did_resched
#define cpu_did_resched() \
do { \
@ -50,9 +53,16 @@ do { \
} while (0)
#endif
/* flags for cpu_need_resched */
#define RESCHED_IMMED 1
#ifndef CPU_INFO_ITERATOR
#define CPU_INFO_ITERATOR int
#define CPU_INFO_FOREACH(cii, ci) \
(void)cii, ci = curcpu(); ci != NULL; ci = NULL
#endif
lwp_t *cpu_switchto(lwp_t *, lwp_t *);
lwp_t *cpu_switchto(lwp_t *, lwp_t *);
struct cpu_info *cpu_lookup(cpuid_t);
int cpu_setonline(struct cpu_info *, bool);
extern kmutex_t cpu_lock;
#endif /* !_SYS_CPU_H_ */

69
sys/sys/cpuio.h Normal file
View File

@ -0,0 +1,69 @@
/* $NetBSD: cpuio.h,v 1.1 2007/08/04 11:03:03 ad Exp $ */
/*-
* Copyright (c) 2007 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Andrew Doran.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#if !defined(_SYS_CPUIO_H_)
#define _SYS_CPUIO_H_
#include <sys/types.h>
#include <sys/time.h>
#include <sys/ioccom.h>
#ifndef _KERNEL
#include <stdbool.h>
#endif
/*
* This is not a great place to describe CPU properties, those
* are better returned via autoconf.
*/
typedef struct cpustate {
u_int cs_id; /* matching ci_cpuid */
bool cs_online; /* running unbound LWPs */
bool cs_intr; /* fielding interrupts */
bool cs_unused[2]; /* reserved */
time_t cs_lastmod; /* time of last state change */
char cs_name[16]; /* reserved */
uint32_t cs_reserved[4]; /* reserved */
} cpustate_t;
#define IOC_CPU_SETSTATE _IOW('c', 0, cpustate_t)
#define IOC_CPU_GETSTATE _IOWR('c', 1, cpustate_t)
#define IOC_CPU_GETCOUNT _IOR('c', 2, int)
#define IOC_CPU_MAPID _IOWR('c', 3, int)
#endif /* !_SYS_CPUIO_H_ */

View File

@ -1,4 +1,4 @@
/* $NetBSD: sched.h,v 1.35 2007/07/09 21:11:33 ad Exp $ */
/* $NetBSD: sched.h,v 1.36 2007/08/04 11:03:02 ad Exp $ */
/*-
* Copyright (c) 1999, 2000, 2001, 2002, 2007 The NetBSD Foundation, Inc.
@ -122,24 +122,27 @@ struct sched_param {
* s: splsched, may only be safely accessed by the CPU itself
* m: spc_mutex
* (: unlocked, stable
* c: cpu_lock
*/
struct schedstate_percpu {
void *spc_sched_info;/* (: scheduler-specific structure */
kmutex_t *spc_mutex; /* (: lock on below, runnable LWPs */
kmutex_t spc_lwplock; /* (: general purpose lock for LWPs */
struct timeval spc_runtime; /* s: time curlwp started running */
volatile int spc_flags; /* s: flags; see below */
volatile int spc_flags; /* m: flags; see below */
u_int spc_schedticks; /* s: ticks for schedclock() */
uint64_t spc_cp_time[CPUSTATES];/* s: CPU state statistics */
pri_t spc_curpriority;/* m: usrpri of curlwp */
int spc_ticks; /* s: ticks until sched_tick() */
int spc_pscnt; /* s: prof/stat counter */
int spc_psdiv; /* s: prof/stat divisor */
time_t spc_lastmod; /* c: time of last cpu state change */
};
/* spc_flags */
#define SPCF_SEENRR 0x0001 /* process has seen roundrobin() */
#define SPCF_SHOULDYIELD 0x0002 /* process should yield the CPU */
#define SPCF_OFFLINE 0x0004 /* CPU marked offline */
#define SPCF_SWITCHCLEAR (SPCF_SEENRR|SPCF_SHOULDYIELD)

View File

@ -1,11 +1,11 @@
# $NetBSD: Makefile,v 1.228 2007/06/25 23:34:52 christos Exp $
# $NetBSD: Makefile,v 1.229 2007/08/04 11:03:03 ad Exp $
# from: @(#)Makefile 5.20 (Berkeley) 6/12/93
.include <bsd.own.mk>
SUBDIR= ac accton acpitools altq amd apm apmd arp bad144 bind bootp \
btconfig btdevctl bthcid btuartd catman \
chown chroot chrtbl cnwctl cron dev_mkdb \
chown chroot chrtbl cnwctl cpuctl cron dev_mkdb \
dhcp diskpart dumpfs dumplfs edquota eeprom \
envstat eshconfig etcupdate extattrctl fssconfig fwctl gpioctl \
grfconfig grfinfo gspa hilinfo ifwatchd inetd installboot \

6
usr.sbin/cpuctl/Makefile Normal file
View File

@ -0,0 +1,6 @@
# $NetBSD: Makefile,v 1.1 2007/08/04 11:03:04 ad Exp $
PROG= cpuctl
MAN= cpuctl.8
.include <bsd.prog.mk>

87
usr.sbin/cpuctl/cpuctl.8 Normal file
View File

@ -0,0 +1,87 @@
.\" $NetBSD: cpuctl.8,v 1.1 2007/08/04 11:03:05 ad Exp $
.\"
.\" Copyright (c) 2007 The NetBSD Foundation, Inc.
.\" All rights reserved.
.\"
.\" This code is derived from software contributed to The NetBSD Foundation
.\" by Andrew Doran.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 3. All advertising materials mentioning features or use of this software
.\" must display the following acknowledgement:
.\" This product includes software developed by the NetBSD
.\" Foundation, Inc. and its contributors.
.\" 4. Neither the name of The NetBSD Foundation nor the names of its
.\" contributors may be used to endorse or promote products derived
.\" from this software without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd August 3, 2007
.Dt CPUCTL 8
.Os
.Sh NAME
.Nm cpuctl
.Nd a program to control CPUs
.Sh SYNOPSIS
.Nm cpuctl
.Ar command
.Op Ar arguments
.Sh DESCRIPTION
The
.Nm
command can be used to control and inspect the state of CPUs in the system.
.Pp
The first argument,
.Ar command ,
specifies the action to take.
Valid commands are:
.Bl -tag -width xx
.It list
.Pp
For each CPU in the system, display the current state and time of the last
state change.
.It offline Ar cpuid
.Pp
Set the specified CPU off line.
.Pp
Unbound LWPs (lightweight processes) will not be executed on the CPU
while it is off line.
Bound LWPs will continue to be executed on the CPU, and device interrupts
routed to the CPU will continue to be handled.
A future release of the system may allow device interrupts to be re-routed
away from individual CPUs.
.Pp
At least one CPU in the system must remain on line.
.It online Ar cpuid
.Pp
Set the specified CPU on line, making it available to run unbound LWPs.
.El
.Pp
.Sh FILES
.Bl -tag -width /dev/cpuctl -compact
.It Pa /dev/cpuctl
control device
.El
.Sh HISTORY
The
.Nm
command first appeared in
.Nx 5.0 .

188
usr.sbin/cpuctl/cpuctl.c Normal file
View File

@ -0,0 +1,188 @@
/* $NetBSD: cpuctl.c,v 1.1 2007/08/04 11:03:05 ad Exp $ */
/*-
* Copyright (c) 2007 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Andrew Doran.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef lint
#include <sys/cdefs.h>
__RCSID("$NetBSD: cpuctl.c,v 1.1 2007/08/04 11:03:05 ad Exp $");
#endif /* not lint */
#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/uio.h>
#include <sys/cpuio.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
#include <util.h>
#include <time.h>
u_int getcpuid(char **);
int main(int, char **);
void usage(void);
void cpu_list(char **);
void cpu_offline(char **);
void cpu_online(char **);
struct cmdtab {
const char *label;
int takesargs;
void (*func)(char **);
} const cpu_cmdtab[] = {
{ "list", 0, cpu_list },
{ "offline", 1, cpu_offline },
{ "online", 1, cpu_online },
{ NULL, 0, NULL },
};
int fd;
int
main(int argc, char **argv)
{
const struct cmdtab *ct;
if (argc < 2)
usage();
if ((fd = open("/dev/cpuctl", O_RDWR)) < 0)
err(EXIT_FAILURE, "/dev/cpuctl");
for (ct = cpu_cmdtab; ct->label != NULL; ct++) {
if (strcmp(argv[1], ct->label) == 0) {
if ((ct->takesargs == 0) ^ (argv[2] == NULL))
usage();
(*ct->func)(argv + 2);
break;
}
}
if (ct->label == NULL)
errx(EXIT_FAILURE, "unknown command ``%s''", argv[optind]);
close(fd);
exit(EXIT_SUCCESS);
/* NOTREACHED */
}
void
usage(void)
{
(void)fprintf(stderr, "usage: %s <command> [arguments]\n",
getprogname());
exit(EXIT_FAILURE);
/* NOTREACHED */
}
void
cpu_online(char **argv)
{
cpustate_t cs;
cs.cs_id = getcpuid(argv);
if (ioctl(fd, IOC_CPU_GETSTATE, &cs) < 0)
err(EXIT_FAILURE, "IOC_CPU_GETSTATE");
cs.cs_online = true;
if (ioctl(fd, IOC_CPU_SETSTATE, &cs) < 0)
err(EXIT_FAILURE, "IOC_CPU_SETSTATE");
}
void
cpu_offline(char **argv)
{
cpustate_t cs;
cs.cs_id = getcpuid(argv);
if (ioctl(fd, IOC_CPU_GETSTATE, &cs) < 0)
err(EXIT_FAILURE, "IOC_CPU_GETSTATE");
cs.cs_online = false;
if (ioctl(fd, IOC_CPU_SETSTATE, &cs) < 0)
err(EXIT_FAILURE, "IOC_CPU_SETSTATE");
}
u_int
getcpuid(char **argv)
{
char *argp;
u_int id;
id = (int)strtoul(argv[0], &argp, 0);
if (*argp != '\0')
usage();
return id;
}
void
cpu_list(char **argv)
{
const char *state, *intr;
cpustate_t cs;
u_int cnt, i;
if (ioctl(fd, IOC_CPU_GETCOUNT, &cnt) < 0)
err(EXIT_FAILURE, "IOC_CPU_GETCOUNT");
printf("ID Unbound LWPs Interrupts Last change\n");
printf("---- ------------ -------------- ----------------------------\n");
for (i = 0; i < cnt; i++) {
cs.cs_id = i;
if (ioctl(fd, IOC_CPU_MAPID, &cs.cs_id) < 0)
err(EXIT_FAILURE, "IOC_CPU_MAPID");
if (ioctl(fd, IOC_CPU_GETSTATE, &cs) < 0)
err(EXIT_FAILURE, "IOC_CPU_GETINFO");
if (cs.cs_online)
state = "online";
else
state = "offline";
if (cs.cs_intr)
intr = "intr";
else
intr = "nointr";
printf("%-4d %-12s %-12s %s", cs.cs_id, state,
intr, asctime(localtime(&cs.cs_lastmod)));
}
}