Home | History | Annotate | Line # | Download | only in sys
cpuset.c revision 1.12.6.1
      1  1.12.6.1       jym /*	$NetBSD: cpuset.c,v 1.12.6.1 2009/05/13 17:23:17 jym Exp $	*/
      2       1.1  christos 
      3       1.1  christos /*-
      4       1.1  christos  * Copyright (c) 2008 The NetBSD Foundation, Inc.
      5       1.1  christos  * All rights reserved.
      6       1.1  christos  *
      7       1.1  christos  * This code is derived from software contributed to The NetBSD Foundation
      8       1.1  christos  * by Christos Zoulas.
      9       1.1  christos  *
     10       1.1  christos  * Redistribution and use in source and binary forms, with or without
     11       1.1  christos  * modification, are permitted provided that the following conditions
     12       1.1  christos  * are met:
     13       1.1  christos  * 1. Redistributions of source code must retain the above copyright
     14       1.1  christos  *    notice, this list of conditions and the following disclaimer.
     15       1.1  christos  * 2. Redistributions in binary form must reproduce the above copyright
     16       1.1  christos  *    notice, this list of conditions and the following disclaimer in the
     17       1.1  christos  *    documentation and/or other materials provided with the distribution.
     18       1.1  christos  *
     19       1.1  christos  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20       1.1  christos  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21       1.1  christos  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22       1.1  christos  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23       1.1  christos  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24       1.1  christos  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25       1.1  christos  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26       1.1  christos  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27       1.1  christos  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28       1.1  christos  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29       1.1  christos  * POSSIBILITY OF SUCH DAMAGE.
     30       1.1  christos  */
     31       1.1  christos 
     32       1.7  christos #ifndef _STANDALONE
     33       1.1  christos #include <sys/cdefs.h>
     34       1.1  christos #if defined(LIBC_SCCS) && !defined(lint)
     35  1.12.6.1       jym __RCSID("$NetBSD: cpuset.c,v 1.12.6.1 2009/05/13 17:23:17 jym Exp $");
     36       1.1  christos #endif /* LIBC_SCCS and not lint */
     37       1.1  christos 
     38       1.1  christos #include <sys/param.h>
     39       1.1  christos #include <sys/sched.h>
     40       1.1  christos #ifdef _KERNEL
     41       1.1  christos #include <sys/kmem.h>
     42       1.1  christos #include <lib/libkern/libkern.h>
     43       1.1  christos #include <sys/atomic.h>
     44       1.1  christos #else
     45       1.8  christos #include <errno.h>
     46       1.1  christos #include <string.h>
     47       1.1  christos #include <stdlib.h>
     48       1.1  christos #include <sys/sysctl.h>
     49       1.1  christos #endif
     50       1.1  christos 
     51       1.1  christos #define	CPUSET_SHIFT	5
     52       1.1  christos #define	CPUSET_MASK	31
     53       1.8  christos #define CPUSET_NENTRIES(nc)	((nc) > 32 ? ((nc) >> CPUSET_SHIFT) : 1)
     54       1.8  christos #ifndef __lint__
     55  1.12.6.1       jym #define CPUSET_SIZE(n)	(sizeof( \
     56       1.8  christos 	struct {  \
     57  1.12.6.1       jym 		uint32_t bits[0]; \
     58  1.12.6.1       jym 	}) + sizeof(uint32_t) * (n))
     59       1.8  christos #else
     60  1.12.6.1       jym #define CPUSET_SIZE(n)	0
     61       1.8  christos #endif
     62       1.1  christos 
     63       1.1  christos struct _cpuset {
     64       1.8  christos 	uint32_t	bits[0];
     65       1.8  christos };
     66       1.8  christos 
     67       1.8  christos #ifdef _KERNEL
     68       1.8  christos struct _kcpuset {
     69       1.1  christos 	unsigned int	nused;
     70       1.8  christos 	struct _kcpuset *next;
     71       1.1  christos 	uint32_t	bits[0];
     72       1.1  christos };
     73  1.12.6.1       jym #define KCPUSET_SIZE(n)	(sizeof( \
     74       1.8  christos 	struct {  \
     75       1.8  christos 		unsigned int nused; \
     76       1.8  christos 		struct _kcpuset *next; \
     77  1.12.6.1       jym 		uint32_t bits[0]; \
     78  1.12.6.1       jym 	}) + sizeof(uint32_t) * (n))
     79       1.8  christos #endif
     80       1.1  christos 
     81       1.8  christos static size_t cpuset_size = 0;
     82       1.8  christos static size_t cpuset_nentries = 0;
     83       1.8  christos 
     84       1.8  christos #ifndef _KERNEL
     85       1.1  christos size_t
     86       1.5  christos /*ARGSUSED*/
     87       1.1  christos _cpuset_size(const cpuset_t *c)
     88       1.1  christos {
     89  1.12.6.1       jym 
     90       1.8  christos 	return cpuset_size;
     91       1.1  christos }
     92       1.1  christos 
     93       1.1  christos void
     94       1.1  christos _cpuset_zero(cpuset_t *c)
     95       1.1  christos {
     96  1.12.6.1       jym 
     97  1.12.6.1       jym 	memset(c->bits, 0, cpuset_nentries * sizeof(c->bits[0]));
     98       1.1  christos }
     99       1.1  christos 
    100       1.1  christos int
    101       1.8  christos _cpuset_isset(cpuid_t i, const cpuset_t *c)
    102       1.1  christos {
    103      1.12  dholland 	const unsigned long j = i >> CPUSET_SHIFT;
    104       1.2     rmind 
    105      1.12  dholland 	if (j >= cpuset_nentries) {
    106       1.8  christos 		errno = EINVAL;
    107       1.1  christos 		return -1;
    108       1.8  christos 	}
    109       1.1  christos 	return ((1 << (i & CPUSET_MASK)) & c->bits[j]) != 0;
    110       1.1  christos }
    111       1.1  christos 
    112       1.1  christos int
    113       1.8  christos _cpuset_set(cpuid_t i, cpuset_t *c)
    114       1.1  christos {
    115      1.12  dholland 	const unsigned long j = i >> CPUSET_SHIFT;
    116       1.2     rmind 
    117      1.12  dholland 	if (j >= cpuset_nentries) {
    118       1.8  christos 		errno = EINVAL;
    119       1.1  christos 		return -1;
    120       1.8  christos 	}
    121       1.1  christos 	c->bits[j] |= 1 << (i & CPUSET_MASK);
    122       1.1  christos 	return 0;
    123       1.1  christos }
    124       1.1  christos 
    125       1.1  christos int
    126       1.8  christos _cpuset_clr(cpuid_t i, cpuset_t *c)
    127       1.1  christos {
    128      1.12  dholland 	const unsigned long j = i >> CPUSET_SHIFT;
    129       1.2     rmind 
    130      1.12  dholland 	if (j >= cpuset_nentries) {
    131       1.8  christos 		errno = EINVAL;
    132       1.1  christos 		return -1;
    133       1.8  christos 	}
    134       1.1  christos 	c->bits[j] &= ~(1 << (i & CPUSET_MASK));
    135       1.1  christos 	return 0;
    136       1.1  christos }
    137       1.1  christos 
    138       1.1  christos cpuset_t *
    139       1.1  christos _cpuset_create(void)
    140       1.1  christos {
    141  1.12.6.1       jym 
    142       1.8  christos 	if (cpuset_size == 0) {
    143       1.8  christos 		static int mib[2] = { CTL_HW, HW_NCPU };
    144       1.8  christos 		size_t len;
    145      1.10        he 		u_int nc;
    146       1.8  christos 
    147       1.8  christos 		if (sysctl(mib, __arraycount(mib), &nc, &len, NULL, 0) == -1)
    148       1.8  christos 			return NULL;
    149       1.8  christos 
    150      1.10        he 		cpuset_nentries = CPUSET_NENTRIES(nc);
    151  1.12.6.1       jym 		cpuset_size = CPUSET_SIZE(cpuset_nentries);
    152       1.3     rmind 	}
    153       1.8  christos 	return calloc(1, cpuset_size);
    154       1.1  christos }
    155       1.1  christos 
    156       1.1  christos void
    157       1.1  christos _cpuset_destroy(cpuset_t *c)
    158       1.1  christos {
    159  1.12.6.1       jym 
    160       1.1  christos 	free(c);
    161       1.1  christos }
    162       1.1  christos 
    163       1.8  christos #else
    164       1.8  christos 
    165       1.8  christos kcpuset_t *
    166       1.8  christos kcpuset_create(void)
    167       1.1  christos {
    168       1.8  christos 	kcpuset_t *c;
    169  1.12.6.1       jym 
    170       1.8  christos 	if (cpuset_size == 0) {
    171       1.8  christos 		cpuset_nentries = CPUSET_NENTRIES(MAXCPUS);
    172  1.12.6.1       jym 		cpuset_size = KCPUSET_SIZE(cpuset_nentries);
    173       1.8  christos 	}
    174       1.8  christos 	c = kmem_zalloc(cpuset_size, KM_SLEEP);
    175       1.8  christos 	c->next = NULL;
    176       1.8  christos 	c->nused = 1;
    177       1.8  christos 	return c;
    178       1.1  christos }
    179       1.1  christos 
    180       1.1  christos void
    181       1.8  christos kcpuset_destroy(kcpuset_t *c)
    182       1.1  christos {
    183       1.8  christos 	kcpuset_t *nc;
    184  1.12.6.1       jym 
    185       1.8  christos 	while (c) {
    186       1.8  christos 		KASSERT(c->nused == 0);
    187       1.8  christos 		nc = c->next;
    188       1.8  christos 		kmem_free(c, cpuset_size);
    189       1.8  christos 		c = nc;
    190       1.8  christos 	}
    191       1.8  christos }
    192       1.2     rmind 
    193       1.8  christos void
    194       1.8  christos kcpuset_copy(kcpuset_t *d, const kcpuset_t *s)
    195       1.8  christos {
    196  1.12.6.1       jym 
    197       1.1  christos 	KASSERT(d->nused == 1);
    198  1.12.6.1       jym 	memcpy(d->bits, s->bits, cpuset_nentries * sizeof(s->bits[0]));
    199       1.1  christos }
    200       1.1  christos 
    201       1.1  christos void
    202       1.8  christos kcpuset_use(kcpuset_t *c)
    203       1.1  christos {
    204  1.12.6.1       jym 
    205       1.1  christos 	atomic_inc_uint(&c->nused);
    206       1.1  christos }
    207       1.1  christos 
    208       1.1  christos void
    209       1.8  christos kcpuset_unuse(kcpuset_t *c, kcpuset_t **lst)
    210       1.1  christos {
    211  1.12.6.1       jym 
    212       1.1  christos 	if (atomic_dec_uint_nv(&c->nused) != 0)
    213       1.1  christos 		return;
    214       1.8  christos 	KASSERT(c->nused == 0);
    215       1.1  christos 	KASSERT(c->next == NULL);
    216       1.1  christos 	if (lst == NULL) {
    217       1.8  christos 		kcpuset_destroy(c);
    218       1.1  christos 		return;
    219       1.1  christos 	}
    220       1.1  christos 	c->next = *lst;
    221       1.1  christos 	*lst = c;
    222       1.1  christos }
    223       1.8  christos 
    224       1.8  christos int
    225       1.8  christos kcpuset_copyin(const cpuset_t *u, kcpuset_t *k, size_t len)
    226       1.8  christos {
    227  1.12.6.1       jym 
    228       1.8  christos 	KASSERT(k->nused > 0);
    229       1.8  christos 	KASSERT(k->next == NULL);
    230  1.12.6.1       jym 	if (len != CPUSET_SIZE(cpuset_nentries))
    231       1.8  christos 		return EINVAL;
    232       1.8  christos 	return copyin(u->bits, k->bits, cpuset_nentries * sizeof(k->bits[0]));
    233       1.8  christos }
    234       1.8  christos 
    235       1.8  christos int
    236       1.8  christos kcpuset_copyout(const kcpuset_t *k, cpuset_t *u, size_t len)
    237       1.8  christos {
    238  1.12.6.1       jym 
    239       1.8  christos 	KASSERT(k->nused > 0);
    240       1.8  christos 	KASSERT(k->next == NULL);
    241  1.12.6.1       jym 	if (len != CPUSET_SIZE(cpuset_nentries))
    242       1.8  christos 		return EINVAL;
    243       1.8  christos 	return copyout(k->bits, u->bits, cpuset_nentries * sizeof(u->bits[0]));
    244       1.8  christos }
    245       1.8  christos 
    246       1.8  christos void
    247       1.8  christos kcpuset_zero(kcpuset_t *c)
    248       1.8  christos {
    249  1.12.6.1       jym 
    250  1.12.6.1       jym 	KASSERT(c->nused > 0);
    251  1.12.6.1       jym 	KASSERT(c->next == NULL);
    252  1.12.6.1       jym 	memset(c->bits, 0, cpuset_nentries * sizeof(c->bits[0]));
    253  1.12.6.1       jym }
    254  1.12.6.1       jym 
    255  1.12.6.1       jym void
    256  1.12.6.1       jym kcpuset_fill(kcpuset_t *c)
    257  1.12.6.1       jym {
    258  1.12.6.1       jym 
    259       1.8  christos 	KASSERT(c->nused > 0);
    260       1.8  christos 	KASSERT(c->next == NULL);
    261  1.12.6.1       jym 	memset(c->bits, ~0, cpuset_nentries * sizeof(c->bits[0]));
    262  1.12.6.1       jym }
    263  1.12.6.1       jym 
    264  1.12.6.1       jym void
    265  1.12.6.1       jym kcpuset_set(cpuid_t i, kcpuset_t *c)
    266  1.12.6.1       jym {
    267  1.12.6.1       jym 	const unsigned long j = i >> CPUSET_SHIFT;
    268  1.12.6.1       jym 
    269  1.12.6.1       jym 	KASSERT(c->next == NULL);
    270  1.12.6.1       jym 	KASSERT(j < cpuset_nentries);
    271  1.12.6.1       jym 	c->bits[j] |= 1 << (i & CPUSET_MASK);
    272       1.8  christos }
    273       1.8  christos 
    274       1.8  christos int
    275       1.8  christos kcpuset_isset(cpuid_t i, const kcpuset_t *c)
    276       1.8  christos {
    277      1.12  dholland 	const unsigned long j = i >> CPUSET_SHIFT;
    278       1.8  christos 
    279      1.11     rmind 	KASSERT(c != NULL);
    280       1.8  christos 	KASSERT(c->nused > 0);
    281       1.8  christos 	KASSERT(c->next == NULL);
    282      1.11     rmind 	KASSERT(j < cpuset_nentries);
    283       1.8  christos 	return ((1 << (i & CPUSET_MASK)) & c->bits[j]) != 0;
    284       1.8  christos }
    285       1.8  christos 
    286  1.12.6.1       jym bool
    287  1.12.6.1       jym kcpuset_iszero(const kcpuset_t *c)
    288  1.12.6.1       jym {
    289  1.12.6.1       jym 	unsigned long j;
    290  1.12.6.1       jym 
    291  1.12.6.1       jym 	for (j = 0; j < cpuset_nentries; j++)
    292  1.12.6.1       jym 		if (c->bits[j] != 0)
    293  1.12.6.1       jym 			return false;
    294  1.12.6.1       jym 	return true;
    295  1.12.6.1       jym }
    296  1.12.6.1       jym 
    297  1.12.6.1       jym bool
    298  1.12.6.1       jym kcpuset_match(const kcpuset_t *c1, const kcpuset_t *c2)
    299  1.12.6.1       jym {
    300  1.12.6.1       jym 	unsigned long j;
    301  1.12.6.1       jym 
    302  1.12.6.1       jym 	for (j = 0; j < cpuset_nentries; j++)
    303  1.12.6.1       jym 		if ((c1->bits[j] & c2->bits[j]) != c2->bits[j])
    304  1.12.6.1       jym 			return false;
    305  1.12.6.1       jym 	return true;
    306  1.12.6.1       jym }
    307  1.12.6.1       jym 
    308       1.1  christos #endif
    309       1.7  christos #endif
    310