From d7f687fc9b6513875325f8aad4c9a92444984b96 Mon Sep 17 00:00:00 2001 From: Jeff Roberson Date: Sun, 2 Mar 2008 07:39:22 +0000 Subject: Add cpuset, an api for thread to cpu binding and cpu resource grouping and assignment. - Add a reference to a struct cpuset in each thread that is inherited from the thread that created it. - Release the reference when the thread is destroyed. - Add prototypes for syscalls and macros for manipulating cpusets in sys/cpuset.h - Add syscalls to create, get, and set new numbered cpusets: cpuset(), cpuset_{get,set}id() - Add syscalls for getting and setting affinity masks for cpusets or individual threads: cpuid_{get,set}affinity() - Add types for the 'level' and 'which' parameters for the cpuset. This will permit expansion of the api to cover cpu masks for other objects identifiable with an id_t integer. For example, IRQs and Jails may be coming soon. - The root set 0 contains all valid cpus. All thread initially belong to cpuset 1. This permits migrating all threads off of certain cpus to reserve them for special applications. Sponsored by: Nokia Discussed with: arch, rwatson, brooks, davidxu, deischen Reviewed by: antoine --- sys/sys/cpuset.h | 146 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 sys/sys/cpuset.h (limited to 'sys/sys/cpuset.h') diff --git a/sys/sys/cpuset.h b/sys/sys/cpuset.h new file mode 100644 index 000000000000..301f96c1680b --- /dev/null +++ b/sys/sys/cpuset.h @@ -0,0 +1,146 @@ +/*- + * Copyright (c) 2008, Jeffrey Roberson + * All rights reserved. + * + * 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 unmodified, 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * $FreeBSD$ + */ + +#ifndef _SYS_CPUSET_H_ +#define _SYS_CPUSET_H_ + +#ifdef _KERNEL +#define CPU_SETSIZE MAXCPU +#endif + +#define CPU_MAXSIZE 128 + +#ifndef CPU_SETSIZE +#define CPU_SETSIZE CPU_MAXSIZE +#endif + +#define _NCPUBITS (sizeof(long) * NBBY) /* bits per mask */ +#define _NCPUWORDS howmany(CPU_SETSIZE, _NCPUBITS) + +typedef struct _cpuset { + long __bits[howmany(CPU_SETSIZE, _NCPUBITS)]; +} cpuset_t; + +#define __cpuset_mask(n) ((long)1 << ((n) % _NCPUBITS)) +#define CPU_CLR(n, p) ((p)->__bits[(n)/_NCPUBITS] &= ~__cpuset_mask(n)) +#define CPU_COPY(f, t) (void)(*(t) = *(f)) +#define CPU_ISSET(n, p) (((p)->__bits[(n)/_NCPUBITS] & __cpuset_mask(n)) != 0) +#define CPU_SET(n, p) ((p)->__bits[(n)/_NCPUBITS] |= __cpuset_mask(n)) +#define CPU_ZERO(p) do { \ + __size_t __i; \ + for (__i = 0; __i < _NCPUWORDS; __i++) \ + (p)->__bits[__i] = 0; \ +} while (0) + +#define CPU_EMPTY(p) __extension__ ({ \ + __size_t __i; \ + for (__i = 0; __i < _NCPUWORDS; __i++) \ + if ((p)->__bits[__i]) \ + break; \ + __i == _NCPUWORDS; \ +}) + +#define CPU_OR(d, s) do { \ + __size_t __i; \ + for (__i = 0; __i < _NCPUWORDS; __i++) \ + (d)->__bits[__i] |= (s)->__bits[__i]; \ +} while (0) + +#define CPU_AND(d, s) do { \ + __size_t __i; \ + for (__i = 0; __i < _NCPUWORDS; __i++) \ + (d)->__bits[__i] &= (s)->__bits[__i]; \ +} while (0) + +#define CPU_NAND(d, s) do { \ + __size_t __i; \ + for (__i = 0; __i < _NCPUWORDS; __i++) \ + (d)->__bits[__i] &= ~(s)->__bits[__i]; \ +} while (0) + +/* + * Valid cpulevel_t values. + */ +#define CPU_LEVEL_ROOT 1 /* All system cpus. */ +#define CPU_LEVEL_CPUSET 2 /* Available cpus for which. */ +#define CPU_LEVEL_WHICH 3 /* Actual mask/id for which. */ + +/* + * Valid cpuwhich_t values. + */ +#define CPU_WHICH_TID 1 /* Specifies a thread id. */ +#define CPU_WHICH_PID 2 /* Specifies a process id. */ +#define CPU_WHICH_CPUSET 3 /* Specifies a set id. */ + +/* + * Reserved cpuset identifiers. + */ +#define CPUSET_INVALID -1 +#define CPUSET_DEFAULT 0 + +#ifdef _KERNEL +LIST_HEAD(setlist, cpuset); + +/* + * cpusets encapsulate cpu binding information for one or more threads. + * + * a - Accessed with atomics. + * s - Set at creation, never modified. Only a ref required to read. + * c - Locked internally by a cpuset lock. + * + * The bitmask is only modified while holding the cpuset lock. It may be + * read while only a reference is held but the consumer must be prepared + * to deal with inconsistent results. + */ +struct cpuset { + cpuset_t cs_mask; /* bitmask of valid cpus. */ + volatile u_int cs_ref; /* (a) Reference count. */ + int cs_flags; /* (s) Flags from below. */ + cpusetid_t cs_id; /* (s) Id or INVALID. */ + struct cpuset *cs_parent; /* (s) Pointer to our parent. */ + LIST_ENTRY(cpuset) cs_link; /* (c) All identified sets. */ + LIST_ENTRY(cpuset) cs_siblings; /* (c) Sibling set link. */ + struct setlist cs_children; /* (c) List of children. */ +}; + +#define CPU_SET_ROOT 0x0001 /* Set is a root set. */ +#define CPU_SET_RDONLY 0x0002 /* No modification allowed. */ + +struct cpuset *cpuset_thread0(void); +struct cpuset *cpuset_ref(struct cpuset *); +void cpuset_rel(struct cpuset *); +#else +__BEGIN_DECLS +int cpuset(cpusetid_t *); +int cpuset_setid(cpuwhich_t, id_t, cpusetid_t); +int cpuset_getid(cpulevel_t, cpuwhich_t, id_t, cpusetid_t *); +int cpuset_getaffinity(cpulevel_t, cpuwhich_t, id_t, int, cpuset_t *); +int cpuset_setaffinity(cpulevel_t, cpuwhich_t, id_t, int, cpuset_t *); +__END_DECLS +#endif +#endif /* !_SYS_CPUSET_H_ */ -- cgit v1.2.3