lkml.org 
[lkml]   [1999]   [Feb]   [22]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
SubjectRe: Separating processes per CPU in a SMP system
From
Date
"Alexandre Hautequest" <hquest@linuxbr.com.br> writes:

> Is there some manner to i separate proccesses between processors? Like, if
> i have a machine with 4 processors, for example, and i want that httpd uses
> just processor 0, and sendmail just processor 1, and orasrv uses processors
> 2 and 3, and maybe they can be changed, with an entry at cron's or somewhat
> like this.
>
> Is this too much impossible?

Here is Tim Hockin's pset patch updated/cleaned against 2.0.36. It
allows you to lock CPU or process on specific CPU. We tested it on a
dual PII and it seems to work fine. You need the top-smp patch for
2.0.36 in order to see the CPU id when using top.

The new commands brought by the patch are:

'runon' and 'mpadmin'

Good luck

Claude

P.S.: Tim, let us know if the patch is really clean. There was a
problem with entry.S, now offsets in entry.S are in synch with
asm/unistd.h


--
Claude Gamache, CAE Electronique Ltee, 8585 Cote-de-Liesse
Saint-Laurent, Quebec, Canada H4T 1G6
Email: cgamache@cae.ca Tel.: (514) 341-2000 x3194, Fax: (514) 734-5612



diff -urN linux/arch/i386/config.in linux-pset-0.58/arch/i386/config.in
--- linux/arch/i386/config.in Sun Nov 15 13:32:46 1998
+++ linux-pset-0.58/arch/i386/config.in Mon Feb 22 13:11:32 1999
@@ -49,6 +49,12 @@
bool 'Handle buggy SMP BIOSes with bad MTRR setup' CONFIG_MTRR
fi

+if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+ bool 'SMP processor set support (experimental)' CONFIG_SMP_PSET
+ if [ "$CONFIG_SMP_PSET" = "y" ]; then
+ bool 'Verbose processor set debugging' CONFIG_SMP_PSET_VERBOSE
+ fi
+fi
endmenu

source drivers/block/Config.in
diff -urN linux/arch/i386/kernel/entry.S linux-pset-0.58/arch/i386/kernel/entry.S
--- linux/arch/i386/kernel/entry.S Sun Nov 15 13:32:46 1998
+++ linux-pset-0.58/arch/i386/kernel/entry.S Mon Feb 22 13:13:32 1999
@@ -698,7 +698,8 @@
.long SYMBOL_NAME(sys_sched_rr_get_interval)
.long SYMBOL_NAME(sys_nanosleep)
.long SYMBOL_NAME(sys_mremap)
- .long 0,0
+ .long SYMBOL_NAME(sys_sysmp)
+ .long 0
.long SYMBOL_NAME(sys_vm86) /* 166 */
.long 0 /* 167 */
.long 0 /* 168 STREAMS poll */
@@ -708,3 +709,5 @@
.long 0 /* 188 STREAMS getpmsg */
.long 0 /* 189 STREAMS putpmsg */
.space (NR_syscalls-189)*4
+
+
diff -urN linux/fs/proc/array.c linux-pset-0.58/fs/proc/array.c
--- linux/fs/proc/array.c Sun Nov 15 13:33:14 1998
+++ linux-pset-0.58/fs/proc/array.c Mon Feb 22 13:11:32 1999
@@ -30,6 +30,9 @@
* <Yves.Arrouye@marin.fdn.fr>
*
* Alan Cox : security fixes. <Alan.Cox@linux.org>
+ *
+ * Stuart Herbert : add pset for Linux/SMP
+ * <S.Herbert@sheffield.ac.uk>
*/

#include <linux/types.h>
@@ -48,6 +51,7 @@
#include <linux/mm.h>
#include <linux/pagemap.h>
#include <linux/swap.h>
+#include <linux/pset.h>

#include <asm/segment.h>
#include <asm/pgtable.h>
@@ -393,6 +397,31 @@
return result;
}

+#ifdef CONFIG_SMP_PSET
+static int get_pset(int pid, char * buffer)
+{
+ struct task_struct *p = pset_get_task(pid);
+
+ if (!p || !p->mm)
+ return 0;
+
+ if (p->pset == NULL)
+ return sprintf(buffer, "0");
+ else
+ return sprintf(buffer, "%d", p->pset->id);
+}
+#else
+static int get_pset(int pid, char * buffer)
+{
+ struct task_struct *p = pset_get_task(pid);
+
+ if (!p || !p->mm)
+ return 0;
+
+ return sprintf(buffer, "0");
+}
+#endif /* CONFIG_SMP_PSET */
+
static int get_env(int pid, char * buffer)
{
struct task_struct ** p = get_task(pid);
@@ -1017,6 +1046,10 @@
case PROC_KSYMS:
return get_ksyms_list(page, start, offset, length);
#endif
+#ifdef CONFIG_SMP_PSET
+ case PROC_PSET:
+ return pset_proc_list(page);
+#endif

case PROC_STAT:
return get_kstat(page);
@@ -1093,6 +1126,8 @@
return get_stat(pid, page);
case PROC_PID_STATM:
return get_statm(pid, page);
+ case PROC_PID_PSET:
+ return get_pset(pid, page);
}
return -EBADF;
}
diff -urN linux/fs/proc/base.c linux-pset-0.58/fs/proc/base.c
--- linux/fs/proc/base.c Wed Feb 21 04:26:09 1996
+++ linux-pset-0.58/fs/proc/base.c Mon Feb 22 13:11:32 1999
@@ -12,6 +12,7 @@
#include <linux/sched.h>
#include <linux/proc_fs.h>
#include <linux/stat.h>
+#include <linux/config.h>

static struct file_operations proc_base_operations = {
NULL, /* lseek - default */
@@ -148,4 +149,12 @@
0, &proc_arraylong_inode_operations,
NULL, proc_pid_fill_inode,
});
+#ifdef CONFIG_SMP_PSET
+ proc_register(&proc_pid, &(struct proc_dir_entry) {
+ PROC_PID_PSET, 4, "pset",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+ 0, &proc_array_inode_operations,
+ NULL, proc_pid_fill_inode,
+ });
+#endif
};
diff -urN linux/fs/proc/root.c linux-pset-0.58/fs/proc/root.c
--- linux/fs/proc/root.c Tue Apr 30 06:09:45 1996
+++ linux-pset-0.58/fs/proc/root.c Mon Feb 22 13:11:32 1999
@@ -13,6 +13,7 @@
#include <linux/proc_fs.h>
#include <linux/stat.h>
#include <linux/config.h>
+#include <linux/pset.h>
#include <asm/bitops.h>

/*
@@ -365,6 +366,12 @@

proc_register( &proc_root, &(struct proc_dir_entry)
{ PROC_MTAB, 6, "mounts", S_IFREG | S_IRUGO, 1, 0, 0, } );
+#ifdef CONFIG_SMP_PSET
+ proc_register(&proc_root, &(struct proc_dir_entry) {
+ PROC_PSET, 4, "pset",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+ });
+#endif

if (prof_shift) {
proc_register(&proc_root, &(struct proc_dir_entry) {
diff -urN linux/include/asm-i386/unistd.h linux-pset-0.58/include/asm-i386/unistd.h
--- linux/include/asm-i386/unistd.h Sun Nov 15 13:33:16 1998
+++ linux-pset-0.58/include/asm-i386/unistd.h Mon Feb 22 13:14:23 1999
@@ -169,6 +169,7 @@
#define __NR_sched_rr_get_interval 161
#define __NR_nanosleep 162
#define __NR_mremap 163
+#define __NR_sysmp 164
#define __NR_poll 168
#define __NR_getpmsg 188
#define __NR_putpmsg 189
diff -urN linux/include/linux/proc_fs.h linux-pset-0.58/include/linux/proc_fs.h
--- linux/include/linux/proc_fs.h Sun Nov 15 13:33:18 1998
+++ linux-pset-0.58/include/linux/proc_fs.h Mon Feb 22 13:11:32 1999
@@ -43,7 +43,11 @@
PROC_MTAB,
PROC_MD,
PROC_RTC,
- PROC_LOCKS
+#ifdef CONFIG_SMP_PSET
+ PROC_PSET,
+#endif
+ PROC_LOCKS,
+ PROC_PID_PSET
};

enum pid_directory_inos {
diff -urN linux/include/linux/pset.h linux-pset-0.58/include/linux/pset.h
--- linux/include/linux/pset.h Wed Dec 31 19:00:00 1969
+++ linux-pset-0.58/include/linux/pset.h Mon Feb 22 13:11:32 1999
@@ -0,0 +1,108 @@
+#ifndef __LINUX_PSET_H
+#define __LINUX_PSET_H
+
+/*
+ * Generic processor set support
+ * Tim Hockin <thockin@ais.net>
+ * based on Stuart Herbert (S.Herbert@sheffield.ac.uk)
+ */
+
+#include <linux/sched.h>
+#include <linux/smp.h>
+#include <linux/config.h>
+#include <linux/sysmp.h>
+
+#ifdef __SMP__
+#ifdef CONFIG_SMP_PSET
+
+#define CONFIG_SMP_PSET_DEBUG 0
+
+#define PSET_VERSION "0.58"
+
+/* the pset number of the master processor set (65535) */
+#define PSET_MASTER_PSET 0xFFFF
+
+/* pset flags */
+#define PSET_F_NONE 0 /* no flags */
+#define PSET_F_SYS 1 /* system CPU set - for future use */
+#define PSET_F_MASTER 2 /* master CPU set */
+#define PSET_F_USER 4 /* user-created CPU set */
+#define PSET_F_CPU 8 /* single CPU set */
+#define PSET_F_TMP 16 /* tmp CPU set */
+
+/* main structure */
+struct pset_struct
+{
+ int id; /* which processor set is this? */
+ unsigned int flags; /* list of flags set for this pset */
+ unsigned long refcount; /* how many processes in this set? */
+ unsigned long cpumask; /* which CPUs are within the set? */
+ struct pset_struct *next_pset; /* next pset in the list */
+ struct pset_struct *prev_pset; /* prev pset in the list */
+};
+
+/* external variables */
+extern struct pset_struct *pset_list;
+extern struct pset_struct *pset_master;
+extern struct pda_stat *pset_cpu_stats[NR_CPUS];
+extern unsigned long pset_cpumask_all;
+
+/* macros */
+#define pset_is_noflag_pset(pset) (pset->flags == PSET_F_NONE)
+#define pset_is_sys_pset(pset) (pset->flags & PSET_F_SYS)
+#define pset_is_master_pset(pset) (pset->flags & PSET_F_MASTER)
+#define pset_is_user_pset(pset) (pset->flags & PSET_F_USER)
+#define pset_is_cpu_pset(pset) (pset->flags & PSET_F_CPU)
+#define pset_is_ro_pset(pset) ((pset_is_cpu_pset(pset)) || \
+ (pset_is_master_pset(pset)))
+#define pset_is_active_cpumask(cpus) ((pset_master->cpumask & cpus) == cpus)
+#define pset_is_valid_cpu(int) ((long)1<<cpu_id & pset_cpumask_all)
+#define pset_clean_cpumask(set) (set & pset_master->cpumask)
+
+/* inline functions */
+inline struct pset_struct *pset_find_pset(int);
+inline int pset_not_implemented(void);
+inline struct task_struct *pset_get_task(pid_t);
+
+/* external functions from pset.c*/
+extern int pset_proc_list(char *);
+extern void pset_init(void);
+extern int pset_create_pset(int, unsigned int);
+extern int pset_del_pset(int);
+extern int pset_create_stats(int);
+extern int pset_assign_to_tmp_pset(unsigned long);
+extern int pset_add_cpumask(int, unsigned long);
+extern int pset_del_cpumask(int, unsigned long);
+extern struct pset_struct *pset_find_pset (int);
+extern void pset_print_allpsets(void);
+extern void pset_print_pset(struct pset_struct *);
+extern int pset_assign_pid_to_pset(struct task_struct *, int);
+extern int pset_remove_pid_from_pset (struct task_struct *);
+
+/* external functions from sysmp.c*/
+extern int pset_mp_pgsize(void);
+extern int pset_mp_nprocs(void);
+extern int pset_mp_naprocs(void);
+extern int pset_mp_stat(struct pda_stat *);
+extern int pset_mp_restrict(int);
+extern int pset_mp_empower(int);
+extern int pset_mp_isolate(int);
+extern int pset_mp_unisolate(int);
+extern int pset_mp_disable(int);
+extern int pset_mp_enable(int);
+extern int pset_mp_steal(int);
+extern int pset_mp_return(int);
+extern int pset_mp_mustrun(int);
+extern int pset_mp_mustrun_pid(int, pid_t);
+extern int pset_mp_runanywhere(void);
+extern int pset_mp_runanywhere_pid(pid_t);
+extern int pset_mpps_create(int, unsigned long);
+extern int pset_mpps_delete(int);
+extern int pset_mpps_add(int, unsigned long);
+extern int pset_mpps_remove(int, unsigned long);
+
+extern int sys_sysmp(int, int, unsigned int, unsigned int, unsigned long);
+
+#endif /* CONFIG_SMP_PSET */
+#endif /* __SMP__ */
+#endif /* __LINUX_PSET_H */
diff -urN linux/include/linux/sched.h linux-pset-0.58/include/linux/sched.h
--- linux/include/linux/sched.h Tue Dec 2 17:18:11 1997
+++ linux-pset-0.58/include/linux/sched.h Mon Feb 22 13:11:32 1999
@@ -17,6 +17,7 @@
#include <linux/personality.h>
#include <linux/tasks.h>
#include <linux/kernel.h>
+#include <linux/config.h>

#include <asm/system.h>
#include <asm/semaphore.h>
@@ -248,6 +249,9 @@
int processor;
int last_processor;
int lock_depth; /* Lock depth. We can context switch in and out of holding a syscall kernel lock... */
+#ifdef CONFIG_SMP_PSET
+ struct pset_struct *pset; /* processor set this task is in */
+#endif
#endif
};

diff -urN linux/include/linux/sysmp.h linux-pset-0.58/include/linux/sysmp.h
--- linux/include/linux/sysmp.h Wed Dec 31 19:00:00 1969
+++ linux-pset-0.58/include/linux/sysmp.h Mon Feb 22 13:11:32 1999
@@ -0,0 +1,68 @@
+#ifndef __LINUX_SYSMP_H
+#define __LINUX_SYSMP_H
+
+/*
+ * linux/sysmp.h
+ * Support for the sysmp(2) call.
+ * Intended to be 100% compatible with SGI interface, but probably not.
+ *
+ * Stuart Herbert (S.Herbert@sheffield.ac.uk)
+ * Tim Hockin <thockin@ais.net>
+ */
+
+#define MP_START 0
+#define MP_PGSIZE 1 /* system pagesize */
+#define MP_SCHED 2 /* schedctl()-should we support this?*/
+#define MP_NPROCS 3 /* # processors */
+#define MP_NAPROCS 4 /* # active processors */
+#define MP_STAT 5 /* return a processor status */
+#define MP_RESTRICT 6 /* restrict cpu to mustrun processes */
+#define MP_EMPOWER 7 /* allow cpu to run any process */
+#define MP_ISOLATE 8 /* restrict cpu to cpu pset */
+#define MP_UNISOLATE 9 /* allow cpu to run any process */
+#define MP_DISABLE 10 /* restrict CPU from executing */
+#define MP_ENABLE 11 /* allow CPU to continue running */
+#define MP_STEAL 12 /* Steal a CPU for ONE process */
+#define MP_RETURN 13 /* Return a stolen processor */
+#define MP_PREEMPTIVE 14 /* not yet implemented */
+#define MP_NONPREEMPTIVE 15 /* not yet implemented */
+#define MP_CLOCK 16 /* not yet implemented */
+#define MP_FASTCLOCK 17 /* not yet implemented */
+#define MP_MUSTRUN 18 /* force current pid to a pset */
+#define MP_MUSTRUN_PID 19 /* force a pid to a pset */
+#define MP_GETMUSTRUN 20 /* */
+#define MP_GETMUSTRUN_PID 21 /* */
+#define MP_RUNANYWHERE 22 /* run current pid on any cpu */
+#define MP_RUNANYWHERE_PID 23 /* run a pid on any cpu */
+#define MP_KERNADDR 24 /* not yet implemented */
+#define MP_SASZ 25 /* not yet implemented */
+#define MP_SAGET 26 /* not yet implemented */
+#define MP_SAGET1 27 /* not yet implemented */
+#define MP_PSET 28 /* pset subcommand */
+
+/* MP_PSET sub-commands */
+#define MPPS_CREATE 1 /* create a new pset */
+#define MPPS_DELETE 2 /* delete an existing pset */
+#define MPPS_ADD 3 /* add processors to a pset */
+#define MPPS_REMOVE 4 /* remove processors from a set */
+#define MPPS_MAX 4 /* Max entries <end of table>*/
+
+/* type for CPU bitmasks */
+typedef unsigned long sbv_t;
+
+/* sysmp(MP_STAT) structure */
+struct pda_stat {
+ int p_cpuid; /* processor ID */
+ int p_flags; /* various flags */
+ int p_count; /* count of sets with this cpu */
+};
+
+/* values for p_flags */
+#define PDAF_NOFLAGS 0 /* no flags - just in case */
+#define PDAF_ENABLED 1 /* processor allowed to sched procs */
+#define PDAF_RESTRICTED 2 /* processor is restricted */
+#define PDAF_ISOLATED 4 /* processor is isolated */
+#define PDAF_DISABLED 8 /* processor has been disabled */
+#define PDAF_STOLEN 16 /* processor has been stolen */
+
+#endif /* __LINUX_SYSMP_H */
diff -urN linux/init/main.c linux-pset-0.58/init/main.c
--- linux/init/main.c Sun Nov 15 13:33:19 1998
+++ linux-pset-0.58/init/main.c Mon Feb 22 13:11:32 1999
@@ -6,6 +6,7 @@
* GK 2/5/95 - Changed to support mounting root fs via NFS
* Added initrd & change_root: Werner Almesberger & Hans Lermen, Feb '96
* Moan early if gcc is old, avoiding bogus kernels - Paul Gortmaker, May '96
+ * SMP Processor set support - Stuart Herbert, June '96 & Tim Hockin '97
*/

#define __KERNEL_SYSCALLS__
@@ -208,6 +209,10 @@
#if defined(CONFIG_SYSVIPC) || defined(CONFIG_KERNELD)
extern void ipc_init(void);
#endif
+#ifdef CONFIG_SMP_PSET
+extern void pset_init(void);
+#endif
+

/*
* Boot command-line arguments
@@ -828,6 +833,11 @@
int i, j;
smp_boot_cpus();

+#ifdef CONFIG_SMP_PSET
+ /* Set up the pset stuff here, before kernel_thread is called */
+ pset_init();
+#endif
+
/*
* Create the slave init tasks as sharing pid 0.
*
diff -urN linux/kernel/Makefile linux-pset-0.58/kernel/Makefile
--- linux/kernel/Makefile Wed Jan 10 02:27:39 1996
+++ linux-pset-0.58/kernel/Makefile Mon Feb 22 13:11:32 1999
@@ -13,7 +13,7 @@
O_TARGET := kernel.o
O_OBJS = sched.o dma.o fork.o exec_domain.o panic.o printk.o sys.o \
module.o exit.o signal.o itimer.o info.o time.o softirq.o \
- resource.o sysctl.o
+ resource.o sysctl.o pset.o sysmp.o

ifeq ($(CONFIG_MODULES),y)
OX_OBJS = ksyms.o
diff -urN linux/kernel/exit.c linux-pset-0.58/kernel/exit.c
--- linux/kernel/exit.c Wed Jun 3 18:17:50 1998
+++ linux-pset-0.58/kernel/exit.c Mon Feb 22 13:11:32 1999
@@ -16,6 +16,7 @@
#include <linux/tty.h>
#include <linux/malloc.h>
#include <linux/interrupt.h>
+#include <linux/pset.h>

#include <asm/segment.h>
#include <asm/pgtable.h>
@@ -136,6 +137,9 @@
if (task[i] == p) {
nr_tasks--;
task[i] = NULL;
+#ifdef CONFIG_SMP_PSET
+ pset_remove_pid_from_pset(p);
+#endif
REMOVE_LINKS(p);
release_thread(p);
if (STACK_MAGIC != *(unsigned long *)p->kernel_stack_page)
diff -urN linux/kernel/fork.c linux-pset-0.58/kernel/fork.c
--- linux/kernel/fork.c Wed Jun 3 18:17:50 1998
+++ linux-pset-0.58/kernel/fork.c Mon Feb 22 13:11:32 1999
@@ -21,6 +21,7 @@
#include <linux/malloc.h>
#include <linux/ldt.h>
#include <linux/smp.h>
+#include <linux/pset.h>

#include <asm/segment.h>
#include <asm/system.h>
@@ -275,6 +276,12 @@
#ifdef __SMP__
p->processor = NO_PROC_ID;
p->lock_depth = 1;
+#ifdef CONFIG_SMP_PSET
+ if (p->pset == NULL)
+ pset_assign_pid_to_pset(p, PSET_MASTER_PSET);
+ else /* increment the pset refcount */
+ (p->pset->refcount)++;
+#endif
#endif
p->start_time = jiffies;
task[nr] = p;
diff -urN linux/kernel/pset.c linux-pset-0.58/kernel/pset.c
--- linux/kernel/pset.c Wed Dec 31 19:00:00 1969
+++ linux-pset-0.58/kernel/pset.c Mon Feb 22 13:11:32 1999
@@ -0,0 +1,542 @@
+/*
+ * Generic processor set support
+ * Tim Hockin <thockin@ais.net>
+ * based on work by Stuart Herbert (S.Herbert@sheffield.ac.uk)
+ */
+
+#include <linux/smp.h>
+#include <linux/config.h>
+
+#ifdef __SMP__
+#ifdef CONFIG_SMP_PSET
+
+#ifndef __KERNEL__
+#define __KERNEL__
+#endif
+
+#include <linux/pset.h>
+#include <linux/mm.h>
+#include <linux/malloc.h>
+#include <linux/tasks.h>
+
+#if CONFIG_SMP_PSET_DEBUG
+#define PRINTK0(a) printk(a)
+#define PRINTK1(a,b) printk(a,b)
+#define PRINTK2(a,b,c) printk(a,b,c)
+#define PRINTK3(a,b,c,d) printk(a,b,c,d)
+#define PRINTK4(a,b,c,d,e) printk(a,b,c,d,e)
+#define PRINTK5(a,b,c,d,e,f) printk(a,b,c,d,e,f)
+#else
+#define PRINTK0(a)
+#define PRINTK1(a,b)
+#define PRINTK2(a,b,c)
+#define PRINTK3(a,b,c,d)
+#define PRINTK4(a,b,c,d,e)
+#define PRINTK5(a,b,c,d,e,f)
+#endif
+
+/* linked list of processor sets */
+struct pset_struct *pset_list;
+struct pset_struct *pset_master;
+unsigned long pset_cpumask_all;
+
+/* array of per-cpu information */
+struct pda_stat *pset_cpu_stats[NR_CPUS];
+
+/* inline functions */
+/* ******************************************************
+ * return a task_struct * or NULL if pid does not exist
+ * *****************************************************/
+inline struct task_struct *pset_get_task(pid_t pid)
+{
+ struct task_struct *p = NULL;
+
+ for_each_task(p) {
+ if (p->pid == pid)
+ return p;
+ }
+
+ return NULL;
+}
+/* ******************************************************
+ * return a pset_struct *, or NULL if id does not exist
+ * *****************************************************/
+inline struct pset_struct *pset_find_pset(int id)
+{
+ struct pset_struct *pset = pset_list;
+
+ if (id == PSET_MASTER_PSET)
+ return pset_master;
+
+ while (pset != NULL) {
+ if (pset->id == id) {
+ return pset;
+ } else {
+ pset = pset->next_pset;
+ }
+ }
+
+ return NULL;
+}
+
+/* ******************************************************
+ * return -EINVAL
+ * *****************************************************/
+inline int pset_not_implemented(void)
+{
+ return -EINVAL;
+}
+
+
+/* ****************** normal functions **************************/
+/* ***************************************************************
+ * pset_init()
+ *
+ * Initialize the processor set support.
+ *
+ * Creates one processor set for each CPU present, and one
+ * master processor set which contains all of the CPUs.
+ * **************************************************************/
+void pset_init(void)
+{
+ int i,
+ cpu,
+ result = 0;
+
+ printk("Pset : Linux/SMP processor set support version %s\n", PSET_VERSION);
+
+ pset_list = NULL;
+
+ /* create the master processor set */
+ result = pset_create_pset(PSET_MASTER_PSET, PSET_F_MASTER);
+ if (result) panic("Unable to create master pset!");
+
+ /* the first entry is the master */
+ pset_master = pset_list;
+
+ /* add a set for each CPU - correspondingly numbered */
+ for (i = 0; i < smp_num_cpus; i++) {
+ cpu = cpu_logical_map[i];
+ result = pset_create_pset(cpu, PSET_F_CPU);
+ if (result) panic("Unable to create CPU set #%d!", cpu);
+
+ result = pset_add_cpumask(cpu, (long)(1<<cpu));
+ if (result) panic("Unable to add cpu to set %d!", cpu);
+
+ result = pset_add_cpumask(PSET_MASTER_PSET, (long)(1<<cpu));
+ if (result) panic("Unable to add CPU %d to master pset!", cpu);
+
+ pset_cpu_stats[cpu] = NULL;
+ pset_create_stats(cpu);
+ }
+
+ /* create the all set */
+ pset_cpumask_all = pset_master->cpumask;
+
+ /* So the user knows */
+ printk("Pset : Added %d processor sets.\n", i + 1);
+
+#ifdef CONFIG_SMP_PSET_VERBOSE
+ pset_print_allpsets();
+#endif
+}
+
+/* ***************************************************************
+ * pset_proc_list()
+ *
+ * return list of current psets to /proc file system
+ * This prints out a list of available processor sets in the following
+ * form :
+ *
+ * pset id bit-vector refs flags
+ *
+ * Code based on the get_module_list() from module.c ...
+ * **************************************************************/
+int pset_proc_list(char *buf)
+{
+ char *p;
+ struct pset_struct *pset;
+ char buffer[80];
+ int flag;
+
+ PRINTK0("Pset : pset_proc_list()\n");
+
+ p = buf;
+ p += sprintf(p, " Pset\t CPUs\t Refs\tFlags\n");
+
+ for (pset = pset_list; pset; pset = pset->next_pset) {
+ flag = 0;
+ if (p - buf > EXEC_PAGESIZE - 100)
+ break; /* avoid overflowing buffer */
+ sprintf(buffer, "%5d\t%8lx\t%8lu\t", pset->id, pset->cpumask,
+ pset->refcount);
+ if (pset_is_noflag_pset(pset)) {
+ sprintf(buffer, "%s(none)", buffer);
+ } else {
+ if (pset_is_sys_pset(pset)) {
+ if (flag)
+ sprintf(buffer, "%s, ", buffer);
+ flag = 1;
+ sprintf(buffer, "%ssys", buffer);
+ }
+ if (pset_is_master_pset(pset)) {
+ if (flag)
+ sprintf(buffer, "%s, ", buffer);
+ flag = 1;
+ sprintf(buffer, "%smaster", buffer);
+ }
+ if (pset_is_user_pset(pset)) {
+ if (flag)
+ sprintf(buffer, "%s, ", buffer);
+ flag = 1;
+ sprintf(buffer, "%suser", buffer);
+ }
+ if (pset_is_cpu_pset(pset)) {
+ if (flag)
+ sprintf(buffer, "%s, ", buffer);
+ flag = 1;
+ sprintf(buffer, "%scpu", buffer);
+ }
+ }
+ p += sprintf(p, "%s\n", buffer);
+ }
+ return p - buf;
+
+}
+
+/* ***************************************************************
+ * pset_create_pset ()
+ *
+ * Creates a processor set with the defined ID number.
+ * This does not add CPUs to the pset.
+ *
+ * We can assume that if we get this far, we have ok permissions, can't
+ * we?
+ *
+ * return -ENOMEM if insufficient memory to allocate data structures.
+ * return -EEXIST if a processor set with that ID already exists.
+ * return 0 on success.
+ * **************************************************************/
+int pset_create_pset(int id, unsigned int pflags)
+{
+ struct pset_struct *pset;
+
+ PRINTK2("Pset : pset_create_pset(%d, %u)\n", id, pflags);
+
+ if (pset_find_pset(id) == NULL) {
+ /* doesn't exist. Create it */
+ pset = (struct pset_struct *)kmalloc(sizeof(
+ struct pset_struct), GFP_KERNEL);
+
+ if (pset == NULL)
+ return -ENOMEM;
+
+ pset->id = id;
+ pset->flags = pflags;
+ pset->cpumask = 0L;
+ pset->prev_pset = NULL;
+ pset->refcount = 0L;
+
+ /* okay. Shove this onto the head of the list */
+ if (pset_list == NULL)
+ pset->next_pset = NULL;
+ else
+ pset->next_pset = pset_list;
+
+ pset_list = pset;
+
+ return 0;
+ } else {
+ return -EEXIST;
+ }
+}
+
+/* ***************************************************************
+ * pset_del_pset()
+ *
+ * Delete a processor set with the named ID number.
+ *
+ * return -EINVAL if the processor set does not exist.
+ * return -EBUSY if the pset has active processes
+ * return 0 on success.
+ * **************************************************************/
+int pset_del_pset(int pset_id)
+{
+ struct pset_struct *pset;
+ unsigned long mask;
+ int i = 0;
+
+ PRINTK1("Pset : pset_del_pset(%d)\n", pset_id);
+
+ /* does the processor set exist? if not, return error code */
+ if ((pset = pset_find_pset(pset_id)) == NULL)
+ return -EINVAL;
+
+ mask = pset->cpumask;
+
+ /* can't delete pset which has active processes */
+ if (pset->refcount)
+ return -EBUSY;
+
+ /* make sure it's not a CPU or MASTER pset */
+ if (pset_is_ro_pset(pset))
+ return -EBUSY;
+
+ /* unlink from the list */
+ if (pset->next_pset != NULL)
+ pset->next_pset->prev_pset = pset->prev_pset;
+
+ if (pset->prev_pset != NULL)
+ pset->prev_pset->next_pset = pset->next_pset;
+ else
+ pset_list = pset->next_pset;
+
+ kfree(pset);
+
+ /* make sure that all CPU stats get decremented */
+ while (mask != 0) {
+ if ((mask >>= i) & 1)
+ pset_cpu_stats[i]->p_count--;
+ i++;
+ }
+
+ return 0;
+}
+
+/* ***************************************************************
+ * pset_create_stats ()
+ *
+ * Creates a pda_stat structure for a CPU
+ * This should only ever be needed from pset_init()
+ *
+ * return -ENOMEM if insufficient memory to allocate data structures.
+ * return -EEXIST if a processor set with that ID already exists.
+ * return 0 on success.
+ * **************************************************************/
+int pset_create_stats(int id)
+{
+ struct pda_stat *stats;
+
+ PRINTK1("pset_create_stats(%d)\n", id);
+
+ if (pset_cpu_stats[id] != NULL)
+ return -EEXIST;
+
+ stats = (struct pda_stat *)kmalloc(sizeof(struct pda_stat), GFP_KERNEL);
+ if (stats == NULL)
+ return -ENOMEM;
+
+ stats->p_cpuid = id;
+ stats->p_flags = PDAF_ENABLED;
+ stats->p_count = 2; /* cpuset and master */
+
+ pset_cpu_stats[id] = stats;
+
+ return 0;
+}
+
+/* ***************************************************************
+ * pset_add_cpumask()
+ *
+ * add CPUs in bitmask "cpumask" to a processor set.
+ *
+ * returns -EINVAL if the processor set does not exist
+ * returns 0 on success.
+ * **************************************************************/
+int pset_add_cpumask(int pset_id, unsigned long cpumask)
+{
+ struct pset_struct *pset;
+ unsigned long mask;
+ int i = 0;
+
+ PRINTK2("Pset : pset_add_cpumask(%d, %ul)\n", pset_id, cpumask);
+
+ /* does the processor set exist? if not, return error code */
+ if ((pset = pset_find_pset(pset_id)) == NULL)
+ return -EINVAL;
+
+ pset->cpumask |= cpumask;
+
+ /* increment CPU stats */
+ mask = cpumask;
+ while (mask != 0) {
+ if ((mask >>= i) & 1)
+ pset_cpu_stats[i]->p_count++;
+ i++;
+ }
+
+ return 0;
+}
+
+/* ***************************************************************
+ * pset_del_cpumask()
+ *
+ * Remove a CPU from a processor set.
+ * return -EINVAL if processor set does not exist.
+ * return 0 on success.
+ * **************************************************************/
+int pset_del_cpumask(int pset_id, unsigned long cpumask)
+{
+ struct pset_struct *pset;
+ unsigned long mask;
+ int i = 0;
+
+ PRINTK2("Pset : pset_del_cpumask(%d, %ul)\n", pset_id, cpumask);
+
+ /* does the processor set exist? if not, return error code */
+ if ((pset = pset_find_pset(pset_id)) == NULL)
+ return -EINVAL;
+
+ /* remove only cpu's in the mask AND in this set */
+ pset->cpumask ^= (pset->cpumask & cpumask);
+
+ /* decrement CPU stats */
+ mask = cpumask;
+ while (mask != 0) {
+ if ((mask >>= i) & 1)
+ pset_cpu_stats[i]->p_count--;
+ i++;
+ }
+
+ return 0;
+}
+
+/* ***************************************************************
+ * pset_print_allpsets()
+ *
+ * Debugging support. Calls pset_print_pset to dump info about each
+ * processor set.
+ * **************************************************************/
+void pset_print_allpsets(void)
+{
+ struct pset_struct *pset = pset_list;
+
+ PRINTK0("Pset : pset_print_allpsets()\n");
+
+ /* traverse the list */
+ while (pset != NULL) {
+ pset_print_pset(pset);
+ pset = pset->next_pset;
+ }
+
+}
+
+/* ***************************************************************
+ * pset_print_pset()
+ *
+ * Debugging support. Uses printk() to display processor set info.
+ * **************************************************************/
+void pset_print_pset(struct pset_struct *pset)
+{
+ int total = 0,
+ i = 0;
+ unsigned long cpumask;
+
+ PRINTK1("Pset : pset_print_pset(%lx)\n", (unsigned long) pset);
+
+ if (pset == NULL)
+ printk("NULL pset passed to print!");
+
+ cpumask = pset->cpumask;
+ while (cpumask != 0) {
+ if ((cpumask >>= i) & 1)
+ total++;
+ i++;
+ }
+
+ printk("Pset : Processor set id %5d, CPUs %2d, bitmap %8lx, flags %4x\n",
+ pset->id, total, pset->cpumask, pset->flags);
+}
+
+/* ***************************************************************
+ * pset_assign_pid_to_pset()
+ *
+ * Change the processor set assignment for a process.
+ *
+ * return -EINVAL if the pset doesn't exist.
+ * **************************************************************/
+int pset_assign_pid_to_pset(struct task_struct *task, int pset_id)
+{
+ struct pset_struct *pset;
+
+ PRINTK2("Pset : pset_assign_pid_to_pset(%d, %d)\n", task->pid, pset_id);
+
+ /* Does the pset exists? */
+ if ((pset = pset_find_pset(pset_id)) == NULL)
+ return -EINVAL;
+
+ task->pset = pset;
+
+ (pset->refcount)++;
+
+ return 0;
+}
+
+/* ***************************************************************
+ * pset_remove_pid_from_pset()
+ *
+ * return -EINVAL if task has no pset
+ * **************************************************************/
+int pset_remove_pid_from_pset(struct task_struct *task)
+{
+ PRINTK1("Pset : pset_remove_pid_from_pset(%d)\n", task->pid);
+ if (task->pset == NULL)
+ return -EINVAL;
+
+ /*
+ * we set task->pset to NULL because we could be about to get rid of
+ * task ... if task is merely moving psets, then the caller of this
+ * routine will also call pset_assign_pid_to_pset() ...
+ */
+ if (task->pset->refcount) {
+ (task->pset->refcount)--;
+ } else {
+ printk("Pset : Tried to decrement zero refcount for pset %d,
+ pid %d\n", task->pset->id, task->pid);
+ }
+
+ task->pset = NULL;
+
+ return 0;
+}
+
+/* **********************************************************
+ * pset_assign_to_tmp_pset ()
+ *
+ * Creates a temporary pset to run a process on a disabled processor
+ * This could be trouble if a process allocates with pset_mp_steal(),
+ * but never calls pset_mp_return()
+ *
+ * We can assume that if we get this far, we have ok permissions, can't
+ * we?
+ *
+ * return -ENOMEM if insufficient memory to allocate data structures.
+ * return 0 on success.
+ * **************************************************************/
+int pset_assign_to_tmp_pset(unsigned long cpumask)
+{
+ struct pset_struct *pset;
+
+ PRINTK1("Pset : pset_assign_to_tmp_pset(%d)\n", cpumask);
+
+ /* Create it */
+ pset = (struct pset_struct *)kmalloc(sizeof(
+ struct pset_struct), GFP_KERNEL);
+ if (pset == NULL)
+ return -ENOMEM;
+
+ pset->id = -1;
+ pset->flags = PSET_F_TMP;
+ pset->cpumask |= cpumask;
+ pset->next_pset = NULL;
+ pset->prev_pset = NULL;
+
+ current->pset = pset;
+
+ (pset->refcount)++;
+
+ return 0;
+}
+
+#endif /* CONFIG_SMP_PSET */
+#endif /* __SMP__ */
diff -urN linux/kernel/sched.c linux-pset-0.58/kernel/sched.c
--- linux/kernel/sched.c Sun Nov 15 13:33:20 1998
+++ linux-pset-0.58/kernel/sched.c Mon Feb 22 13:11:32 1999
@@ -9,6 +9,8 @@
* 1997-01-28 Modified by Finn Arne Gangstad to make timers scale better.
* 1997-09-10 Updated NTP code according to technical memorandum Jan '96
* "A Kernel Model for Precision Timekeeping" by Dave Mills
+ * 1996-08-19 Modified by Stuart Herbert to add processor set support
+ * 1997-98 Continued by Tim Hockin <thockin@ais.net>
*/

/*
@@ -33,6 +35,7 @@
#include <linux/resource.h>
#include <linux/mm.h>
#include <linux/smp.h>
+#include <linux/pset.h>

#include <asm/system.h>
#include <asm/io.h>
@@ -246,9 +249,9 @@
/* We are not permitted to run a task someone else is running */
if (p->processor != NO_PROC_ID)
return -1000;
-#ifdef PAST_2_0
+#ifdef CONFIG_SMP_PSET
/* This process is locked to a processor group */
- if (p->processor_mask && !(p->processor_mask & (1<<this_cpu))
+ if ((p->pset) && !(p->pset->cpumask & (1<<this_cpu)))
return -1000;
#endif
#endif
diff -urN linux/kernel/sysmp.c linux-pset-0.58/kernel/sysmp.c
--- linux/kernel/sysmp.c Wed Dec 31 19:00:00 1969
+++ linux-pset-0.58/kernel/sysmp.c Mon Feb 22 13:11:32 1999
@@ -0,0 +1,762 @@
+/*
+ * Generic processor set support
+ * Tim Hockin <thockin@ais.net>
+ * based on work by Stuart Herbert (S.Herbert@sheffield.ac.uk)
+ */
+
+#include <linux/smp.h>
+#include <linux/config.h>
+
+#ifdef __SMP__
+#ifdef CONFIG_SMP_PSET
+
+#ifndef __KERNEL__
+#define __KERNEL__
+#endif
+
+#include <linux/pset.h>
+#include <linux/mm.h>
+#include <linux/malloc.h>
+#include <linux/tasks.h>
+#include <asm/segment.h>
+
+#if CONFIG_SMP_PSET_DEBUG
+#define PRINTK0(a) printk(a)
+#define PRINTK1(a,b) printk(a,b)
+#define PRINTK2(a,b,c) printk(a,b,c)
+#define PRINTK3(a,b,c,d) printk(a,b,c,d)
+#define PRINTK4(a,b,c,d,e) printk(a,b,c,d,e)
+#define PRINTK5(a,b,c,d,e,f) printk(a,b,c,d,e,f)
+#else
+#define PRINTK0(a)
+#define PRINTK1(a,b)
+#define PRINTK2(a,b,c)
+#define PRINTK3(a,b,c,d)
+#define PRINTK4(a,b,c,d,e)
+#define PRINTK5(a,b,c,d,e,f)
+#endif
+
+/* ***************************************************************
+ * sys_sysmp()
+ *
+ * The system call between us and the outside world
+ * **************************************************************/
+asmlinkage int sys_sysmp(int cmd, int argi1, unsigned int argi2,
+ unsigned int argi3, unsigned long argl1)
+{
+ int result = 0;
+
+ PRINTK5("Pset : sys_sysmp(%d, %d, %u, %u, %lu)\n",
+ cmd, argi1, argi2, argi3, argl1);
+
+ /* All functions are stubbed here, but not all implemented */
+ switch (cmd) {
+ case MP_PGSIZE:
+ result = pset_mp_pgsize();
+ break;
+ case MP_SCHED:
+ result = pset_not_implemented();
+ break;
+ case MP_NPROCS:
+ result = pset_mp_nprocs();
+ break;
+ case MP_NAPROCS:
+ result = pset_mp_naprocs();
+ break;
+ case MP_STAT:
+ result = pset_mp_stat((struct pda_stat *)argl1);
+ break;
+ case MP_RESTRICT:
+ result = pset_mp_restrict(argi1);
+ break;
+ case MP_EMPOWER:
+ result = pset_mp_empower(argi1);
+ break;
+ case MP_ISOLATE:
+ result = pset_mp_isolate(argi1);
+ break;
+ case MP_UNISOLATE:
+ result = pset_mp_unisolate(argi1);
+ break;
+ case MP_DISABLE:
+ result = pset_mp_disable(argi1);
+ break;
+ case MP_ENABLE:
+ result = pset_mp_enable(argi1);
+ break;
+ case MP_STEAL:
+ result = pset_mp_steal(argi1);
+ break;
+ case MP_RETURN:
+ result = pset_mp_return(argi1);
+ break;
+ case MP_PREEMPTIVE:
+ result = pset_not_implemented();
+ break;
+ case MP_NONPREEMPTIVE:
+ result = pset_not_implemented();
+ break;
+ case MP_CLOCK:
+ result = pset_not_implemented();
+ break;
+ case MP_FASTCLOCK:
+ result = pset_not_implemented();
+ break;
+ case MP_MUSTRUN:
+ result = pset_mp_mustrun(argi1);
+ break;
+ case MP_MUSTRUN_PID:
+ result = pset_mp_mustrun_pid(argi1, (pid_t)argl1);
+ break;
+ case MP_GETMUSTRUN:
+ result = pset_not_implemented();
+ break;
+ case MP_GETMUSTRUN_PID:
+ /* make sure to cast argl1 as (pid_t) */
+ result = pset_not_implemented();
+ break;
+ case MP_RUNANYWHERE:
+ result = pset_mp_runanywhere();
+ break;
+ case MP_RUNANYWHERE_PID:
+ result = pset_mp_runanywhere_pid((pid_t)argl1);
+ break;
+ case MP_KERNADDR:
+ result = pset_not_implemented();
+ break;
+ case MP_SASZ:
+ result = pset_not_implemented();
+ break;
+ case MP_SAGET:
+ /* make sure to note the order of arguments...
+ argi1 is int, argi2 is unsigned int, argl1 is (char *).
+ they should go to the handler as argi1, argl1, argi2.
+ */
+ result = pset_not_implemented();
+ break;
+ case MP_SAGET1:
+ /* make sure to note the order of arguments...
+ argi1 is int, argi2 is unsigned int, argl1 is (char*),
+ argi3 is unsigned int. they should go to the handler as
+ argi1, argl1, argi2, argi3.
+ */
+ result = pset_not_implemented();
+ break;
+ case MP_PSET:
+ switch (argi1) {
+ case MPPS_CREATE:
+ result = pset_mpps_create(argi2, argl1);
+ break;
+ case MPPS_DELETE:
+ result = pset_mpps_delete(argi2);
+ break;
+ case MPPS_ADD:
+ result = pset_mpps_add(argi2, argl1);
+ break;
+ case MPPS_REMOVE:
+ result = pset_mpps_remove(argi2, argl1);
+ break;
+ default:
+ result = -EINVAL;
+ }
+ break;
+ default:
+ result = -EINVAL;
+ }
+
+ PRINTK1("Pset : sys_sysmp() returning %d\n", result);
+
+ return result;
+}
+
+/* ***************************************************************
+ * ***************************************************************
+ * Functions called by sysmp()...
+ * ***************************************************************
+ * **************************************************************/
+
+/* ***************************************************************
+ * pset_mp_pgsize()
+ *
+ * return the system pagesize.
+ * **************************************************************/
+int pset_mp_pgsize(void)
+{
+ PRINTK0("Pset : pset_mp_pgsize()\n");
+ return EXEC_PAGESIZE;
+}
+
+/* **************************************************************
+ * pset_mp_nprocs()
+ *
+ * return the number of processors on the machine.
+ * **************************************************************/
+int pset_mp_nprocs(void)
+{
+ PRINTK0("Pset : pset_mp_nprocs()\n");
+ return smp_num_cpus;
+}
+
+/* **************************************************************
+ * pset_mp_naprocs()
+ *
+ * return the number of CPUs in the PSET_MASTER_PSET group
+ * **************************************************************/
+int pset_mp_naprocs(void)
+{
+ unsigned long cpumask;
+ int total = 0;
+ int i = 0;
+
+ PRINTK0("Pset : pset_mp_naprocs()\n");
+
+ cpumask = pset_master->cpumask;
+ while (cpumask != 0) {
+ if ((cpumask >>= i) & 1)
+ total++;
+ i++;
+ }
+
+ return total;
+}
+
+/* **************************************************************
+ * pset_mp_stat()
+ *
+ * fill an array with pda_stat information.
+ * let's hope (l)user gave us enough storage!
+ * **************************************************************/
+int pset_mp_stat(struct pda_stat *ptr)
+{
+ int i;
+ int result = 0;
+
+ PRINTK0("Pset : pset_mp_stat()\n");
+
+ for (i = 0; i < smp_num_cpus; i++) {
+ memcpy_tofs(&ptr[i], pset_cpu_stats[cpu_logical_map[i]],
+ sizeof(struct pda_stat));
+ }
+
+ return result;
+}
+
+/* **************************************************************
+ * pset_mp_restrict()
+ *
+ * Remove a CPU from the PSET_MASTER_PSET group
+ * return -EINVAL if cpu is not in master set
+ * return -EBUSY if cpu_id is the last CPU in the master set
+ * **************************************************************/
+int pset_mp_restrict(int cpu_id)
+{
+ unsigned long cpumask;
+ int result = 0;
+
+ PRINTK1("Pset : pset_mp_restrict(%d)\n", cpu_id);
+
+ /* verify permission */
+ if (!suser())
+ return -EPERM;
+
+ cpumask = (long)1<<cpu_id;
+
+ if (pset_is_active_cpumask(cpumask)) {
+ /* is this CPU the last in the master set ?*/
+ if (pset_master->cpumask == cpumask)
+ return -EBUSY;
+
+ result = pset_del_cpumask(PSET_MASTER_PSET, cpumask);
+
+ /* if processor was not available, we'd not be here */
+ if (!result)
+ pset_cpu_stats[cpu_id]->p_flags = PDAF_RESTRICTED;
+ } else {
+ return -EINVAL;
+ }
+
+ return result;
+}
+
+/* **************************************************************
+ * pset_mp_empower()
+ *
+ * Place a CPU in the PSET_MASTER_PSET group (if available)
+ * return -EINVAL if CPU does not exist.
+ * **************************************************************/
+int pset_mp_empower(int cpu_id)
+{
+ unsigned long cpumask;
+ int result = 0;
+
+ PRINTK1("Pset : pset_mp_empower(%d)\n", cpu_id);
+
+ /* verify permission */
+ if (!suser())
+ return -EPERM;
+
+ cpumask = (long)1<<cpu_id;
+
+ /* make sure the cpu_id actually exists */
+ if (pset_is_valid_cpu(cpu_id)) {
+ if (pset_cpu_stats[cpu_id]->p_flags != PDAF_RESTRICTED)
+ return -EINVAL;
+
+ result = pset_add_cpumask(PSET_MASTER_PSET, cpumask);
+ if (!result)
+ pset_cpu_stats[cpu_id]->p_flags = PDAF_ENABLED;
+ return result;
+ }
+ return -EINVAL;
+}
+
+/* **************************************************************
+ * pset_mp_isolate()
+ *
+ * Remove the CPU from ALL cpu_sets except its own
+ * return -EINVAL if cpu is not in master set
+ * return -EBUSY if cpu_id is the last CPU in the master set
+ * *************************************************************/
+int pset_mp_isolate(int cpu_id)
+{
+ unsigned long cpumask;
+ int result = 0;
+ struct pset_struct *pset = pset_list;
+
+ PRINTK1("Pset : pset_mp_isolate(%d)\n", cpu_id);
+
+ /* permissions */
+ if (!suser())
+ return -EPERM;
+
+ cpumask = (long)1<<cpu_id;
+
+ if (pset_is_active_cpumask(cpumask)) {
+ /* can't isolate the last CPU */
+ if (pset_master->cpumask == cpumask)
+ return -EBUSY;
+
+ while (pset->next_pset != NULL) {
+ /* if it is in the set, and its not it's own..*/
+ if ((pset->cpumask&cpumask) && (pset->id!=cpu_id))
+ result |= pset_del_cpumask(pset->id, cpumask);
+ pset = pset->next_pset;
+ }
+ if (!result)
+ pset_cpu_stats[cpu_id]->p_flags = PDAF_ISOLATED;
+ } else {
+ return -EINVAL;
+ }
+
+ return result;
+}
+
+/* **************************************************************
+ * pset_mp_unisolate()
+ *
+ * Whats the difference between this and empower?
+ * Place a CPU in the PSET_MASTER_PSET group (if available)
+ * return -EINVAL if CPU does not exist.
+ * *************************************************************/
+int pset_mp_unisolate(int cpu_id)
+{
+ unsigned long cpumask;
+ int result = 0;
+
+ PRINTK1("Pset : pset_mp_unisolate(%d)\n", cpu_id);
+
+ /* permissions */
+ if (!suser())
+ return -EPERM;
+
+ cpumask = (long)1<<cpu_id;
+
+ /* make sure the cpu_id is a real CPU */
+ if (pset_is_valid_cpu(cpu_id)) {
+ if (pset_cpu_stats[cpu_id]->p_flags != PDAF_ISOLATED)
+ return -EINVAL;
+
+ result = pset_add_cpumask(PSET_MASTER_PSET, cpumask);
+ if (!result)
+ pset_cpu_stats[cpu_id]->p_flags = PDAF_ENABLED;
+ return result;
+ }
+
+ return -EINVAL;
+}
+
+/* **************************************************************
+ * pset_mp_disable()
+ *
+ * Disable a CPU from running processes
+ * return -EINVAL if CPU does not exist.
+ * *************************************************************/
+int pset_mp_disable(int cpu_id)
+{
+
+ unsigned long cpumask;
+ int result = 0;
+ struct pset_struct *pset = pset_list;
+
+ PRINTK1("Pset : pset_mp_disable(%d)\n", cpu_id);
+
+ if (!suser())
+ return -EPERM;
+
+ cpumask = (long)1<<cpu_id;
+
+ if (pset_is_active_cpumask(cpumask)) {
+ /* can't disable the last CPU */
+ if (pset_master->cpumask == cpumask)
+ return -EBUSY;
+
+ while (pset->next_pset != NULL) {
+ /* if the pset has this cpu..*/
+ if (pset->cpumask & cpumask)
+ result |= pset_del_cpumask(pset->id, cpumask);
+ pset=pset->next_pset;
+ }
+ if (!result)
+ pset_cpu_stats[cpu_id]->p_flags = PDAF_DISABLED;
+ } else {
+ return -EINVAL;
+ }
+
+ return result;
+}
+
+/* **************************************************************
+ * pset_mp_enable()
+ *
+ * Enable a CPU to run processes.
+ * return -EINVAL if CPU does not exist.
+ * *************************************************************/
+int pset_mp_enable(int cpu_id)
+{
+ unsigned long cpumask;
+ int result = 0;
+
+ PRINTK1("Pset : pset_mp_enable(%d)\n", cpu_id);
+
+ /* permissions */
+ if (!suser())
+ return -EPERM;
+
+ cpumask = (long)1<<cpu_id;
+
+ /* make sure cpu_id is a real CPU */
+ if (pset_is_valid_cpu(cpu_id)) {
+ if (pset_cpu_stats[cpu_id]->p_flags != PDAF_DISABLED)
+ return -EINVAL;
+
+ result = pset_add_cpumask(PSET_MASTER_PSET, cpumask);
+ if (!result)
+ result = pset_add_cpumask(cpu_id, cpumask);
+ if (!result)
+ pset_cpu_stats[cpu_id]->p_flags = PDAF_ENABLED;
+ return result;
+ }
+ return -EINVAL;
+}
+
+/* **************************************************************
+ * pset_mp_steal()
+ *
+ * Force a process to run ONLY on one CPU, and that CPU to ONLY
+ * run one process.
+ * return -ENOMEM if no memory is available
+ * return -EINVAL if cpu does not exist
+ * return -EPERM if user is not root
+ * **************************************************************/
+int pset_mp_steal(int cpu_id)
+{
+ unsigned long cpumask;
+ int result = 0;
+
+ PRINTK1("pset_mp_steal(%d)\n", cpu_id);
+
+ /* permissions */
+ if (!suser())
+ return -EPERM;
+
+ cpumask = (long)1<<cpu_id;
+
+ if (pset_is_active_cpumask(cpumask)) {
+ /* can't steal the last CPU */
+ if (pset_master->cpumask == cpumask)
+ return -EBUSY;
+
+ result = pset_mp_disable(cpu_id);
+ if (!result)
+ result = pset_assign_to_tmp_pset(cpumask);
+ if (!result)
+ pset_cpu_stats[cpu_id]->p_flags = PDAF_STOLEN;
+ } else {
+ return -EINVAL;
+ }
+
+ return result;
+}
+
+/* **************************************************************
+ * pset_mp_return()
+ *
+ * return a stolen process and free the tmp pset
+ * return -EINVAL if cpu does not exist
+ * return -EPERM if user is not root
+ * return -EBUSY if child processes have inherited this pset
+ * **************************************************************/
+int pset_mp_return(int cpu_id)
+{
+ int result = 0;
+
+ PRINTK1("pset_mp_return(%d)\n", cpu_id);
+
+ /* permissions */
+ if (!suser())
+ return -EPERM;
+
+ /* make sure cpu_id is a real CPU */
+ if (pset_is_valid_cpu(cpu_id)) {
+ if (pset_cpu_stats[cpu_id]->p_flags != PDAF_STOLEN)
+ return -EINVAL;
+
+ result = pset_mp_enable(cpu_id);
+
+ if (result)
+ return result;
+
+ /* keep in mind current is still in refcount */
+ if ((current->pset->refcount) - 1)
+ return -EBUSY;
+ kfree(current->pset);
+ result = pset_remove_pid_from_pset(current);
+ result = pset_assign_pid_to_pset(current, PSET_MASTER_PSET);
+
+ if (!result)
+ pset_cpu_stats[cpu_id]->p_flags = PDAF_ENABLED;
+
+ return result;
+ }
+
+ return -EINVAL;
+}
+
+/* **************************************************************
+ * pset_mp_runanywhere()
+ *
+ * Force this process to run in the master pset
+ * **************************************************************/
+int pset_mp_runanywhere(void)
+{
+ int result = 0;
+
+ PRINTK0("Pset : pset_mp_runanywhere()\n");
+
+ result = pset_remove_pid_from_pset(current);
+
+ if (!result)
+ result = pset_assign_pid_to_pset(current, PSET_MASTER_PSET);
+
+ return result;
+}
+
+/* **************************************************************
+ * pset_mp_runanywhere_pid()
+ *
+ * Force a process to run in the master pset
+ * return -ESRCH if a task can not be found
+ * return -EPERM if user does not have rights over a process
+ * **************************************************************/
+int pset_mp_runanywhere_pid(pid_t pid)
+{
+ int result = 0;
+ struct task_struct *p;
+
+ PRINTK0("Pset : pset_mp_runanywhere_pid()\n");
+
+ if ((p = pset_get_task(pid)) == NULL)
+ return -ESRCH;
+
+ /* be sure we can modify this process */
+ if ((current->euid ^ p->suid) && (current->euid ^ p->uid) &&
+ (current->uid ^ p->suid) && (current->uid ^ p->uid) &&
+ !suser())
+ return -EPERM;
+
+ result = pset_remove_pid_from_pset(p);
+
+ if (!result)
+ result = pset_assign_pid_to_pset(p, PSET_MASTER_PSET);
+
+ return result;
+}
+
+/* **************************************************************
+ * pset_mp_mustrun()
+ *
+ * Force this process to run on a particular pset
+ * **************************************************************/
+int pset_mp_mustrun(int pset_id)
+{
+ int result = 0;
+
+ PRINTK1("Pset : pset_mp_mustrun(%d)\n", pset_id);
+
+ result = pset_remove_pid_from_pset(current);
+ if (!result)
+ result = pset_assign_pid_to_pset(current, pset_id);
+
+ return result;
+}
+
+/* **************************************************************
+ * pset_mp_mustrun_pid()
+ *
+ * Force a process to run on a particular pset
+ * return -EINVAL if the pset does not exist
+ * **************************************************************/
+int pset_mp_mustrun_pid(int pset_id, pid_t pid)
+{
+ int result = 0;
+ struct task_struct *p;
+
+ PRINTK2("Pset : pset_mp_mustrun_pid(%d,%d)\n", pset_id, pid);
+
+ if ((p = pset_get_task(pid)) == NULL)
+ return -ESRCH;
+
+ /* be sure we can modify this process */
+ if ((current->euid ^ p->suid) && (current->euid ^ p->uid) &&
+ (current->uid ^ p->suid) && (current->uid ^ p->uid) &&
+ !suser())
+ return -EPERM;
+
+ result = pset_remove_pid_from_pset(p);
+ if (!result)
+ result = pset_assign_pid_to_pset(p, pset_id);
+
+ return result;
+}
+
+/* **************************************************************
+ * pset_mpps_create()
+ *
+ * Create a processor set
+ * return -EPERM if user is not root
+ * **************************************************************/
+int pset_mpps_create(int pset_id, unsigned long cpumask)
+{
+ int result = 0;
+
+ PRINTK2("Pset : pset_mpps_create(%d,%ul)\n", pset_id, cpumask);
+
+ /* FIXME - should non-root users be able to create a pset ?*/
+ /* can it be destroyed when they log out? */
+ /* Owner flag in pset struct? */
+ if (!suser())
+ return -EPERM;
+
+ /* this implicitly filters out restricted CPU's */
+ cpumask = pset_clean_cpumask(cpumask);
+
+ result = pset_create_pset(pset_id, PSET_F_USER);
+ if (!result)
+ result = pset_add_cpumask(pset_id, cpumask);
+
+ return result;
+}
+
+/* **************************************************************
+ * pset_mpps_delete()
+ *
+ * Delete a processor set
+ * return -EPERM if user is not root
+ * return -EINVAL if pset does not exist
+ * return -EBUSY if this is a master or cpu pset
+ * **************************************************************/
+int pset_mpps_delete(int pset_id)
+{
+ int result = 0;
+
+ PRINTK1("Pset : pset_mpps_delete(%d)\n", pset_id);
+
+ /* FIXME - can a user delete psets if they are allowed to create? */
+ if (!suser())
+ return -EPERM;
+
+ result = pset_del_pset(pset_id);
+
+ return result;
+}
+
+/* **************************************************************
+ * pset_mpps_add()
+ *
+ * Add a bitmap of CPUs to a processor set
+ * return -EPERM if user is not root
+ * return -EINVAL if pset pset_id does not exist
+ * return -EBUSY if pset is a cpu pset or master pset
+ * **************************************************************/
+int pset_mpps_add(int pset_id, unsigned long cpumask)
+{
+ struct pset_struct *pset;
+ int result = 0;
+
+ PRINTK2("Pset : pset_mpps_add(%d, %lu)\n", pset_id, cpumask);
+
+ /* FIXME - can a user add CPUs if they own the pset? */
+ if (!suser())
+ return -EPERM;
+
+ /* this implicitly filters out restricted CPU's */
+ cpumask = pset_clean_cpumask(cpumask);
+
+ if ((pset = pset_find_pset(pset_id)) == NULL)
+ return -EINVAL;
+
+ /* to manipulate pset_master use empower */
+ if(pset_is_ro_pset(pset))
+ return -EBUSY;
+
+ result = pset_add_cpumask(pset_id, cpumask);
+
+ return result;
+}
+
+/* **************************************************************
+ * pset_mpps_remove()
+ *
+ * Remove a bitmap of CPUs from a processor set
+ * return -EPERM if not user root
+ * return -EINVAL if pset pset_id does not exist
+ * return -EBUSY if pset is a CPU pset or the master pset.
+ * **************************************************************/
+int pset_mpps_remove(int pset_id, unsigned long cpumask)
+{
+ struct pset_struct *pset;
+ int result = 0;
+
+ PRINTK2("Pset : pset_mpps_remove(%d, %lu)\n", pset_id, cpumask);
+
+ /* FIXME - Can a user remove CPU's from a PSET they create? */
+ if (!suser())
+ return -EPERM;
+
+ /* this implicitly filters out restricted CPU's */
+ cpumask = pset_clean_cpumask(cpumask);
+
+ if ((pset = pset_find_pset(pset_id)) == NULL)
+ return -EINVAL;
+
+ /* to manipulate the master set use the restrict functions */
+ if (pset_is_ro_pset(pset))
+ return -EBUSY;
+
+ result = pset_del_cpumask(pset_id, cpumask);
+
+ return result;
+}
+
+#endif /* CONFIG_SMP_PSET */
+#endif /* __SMP__ */
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/

\
 
 \ /
  Last update: 2005-03-22 13:50    [W:0.086 / U:0.268 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site