Home | History | Annotate | Line # | Download | only in sys
cpuset.c revision 1.12.4.1
      1  1.12.4.1    bouyer /*	$NetBSD: cpuset.c,v 1.12.4.1 2013/10/20 14:02:51 bouyer 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.4.1    bouyer __RCSID("$NetBSD: cpuset.c,v 1.12.4.1 2013/10/20 14:02:51 bouyer 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.8  christos #define CPUSET_SIZE()	sizeof( \
     56       1.8  christos 	struct {  \
     57       1.8  christos 		uint32_t bits[cpuset_nentries]; \
     58       1.8  christos 	})
     59       1.8  christos #else
     60       1.8  christos #define CPUSET_SIZE()	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.8  christos #define KCPUSET_SIZE()	sizeof( \
     74       1.8  christos 	struct {  \
     75       1.8  christos 		unsigned int nused; \
     76       1.8  christos 		struct _kcpuset *next; \
     77       1.8  christos 		uint32_t bits[cpuset_nentries]; \
     78       1.8  christos 	})
     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.8  christos 	return cpuset_size;
     90       1.1  christos }
     91       1.1  christos 
     92       1.1  christos void
     93       1.1  christos _cpuset_zero(cpuset_t *c)
     94       1.1  christos {
     95       1.8  christos 	(void)memset(c->bits, 0, cpuset_nentries * sizeof(c->bits[0]));
     96       1.1  christos }
     97       1.1  christos 
     98       1.1  christos int
     99       1.8  christos _cpuset_isset(cpuid_t i, const cpuset_t *c)
    100       1.1  christos {
    101      1.12  dholland 	const unsigned long j = i >> CPUSET_SHIFT;
    102       1.2     rmind 
    103      1.12  dholland 	if (j >= cpuset_nentries) {
    104       1.8  christos 		errno = EINVAL;
    105       1.1  christos 		return -1;
    106       1.8  christos 	}
    107       1.1  christos 	return ((1 << (i & CPUSET_MASK)) & c->bits[j]) != 0;
    108       1.1  christos }
    109       1.1  christos 
    110       1.1  christos int
    111       1.8  christos _cpuset_set(cpuid_t i, cpuset_t *c)
    112       1.1  christos {
    113      1.12  dholland 	const unsigned long j = i >> CPUSET_SHIFT;
    114       1.2     rmind 
    115      1.12  dholland 	if (j >= cpuset_nentries) {
    116       1.8  christos 		errno = EINVAL;
    117       1.1  christos 		return -1;
    118       1.8  christos 	}
    119       1.1  christos 	c->bits[j] |= 1 << (i & CPUSET_MASK);
    120       1.1  christos 	return 0;
    121       1.1  christos }
    122       1.1  christos 
    123       1.1  christos int
    124       1.8  christos _cpuset_clr(cpuid_t i, cpuset_t *c)
    125       1.1  christos {
    126      1.12  dholland 	const unsigned long j = i >> CPUSET_SHIFT;
    127       1.2     rmind 
    128      1.12  dholland 	if (j >= cpuset_nentries) {
    129       1.8  christos 		errno = EINVAL;
    130       1.1  christos 		return -1;
    131       1.8  christos 	}
    132       1.1  christos 	c->bits[j] &= ~(1 << (i & CPUSET_MASK));
    133       1.1  christos 	return 0;
    134       1.1  christos }
    135       1.1  christos 
    136       1.1  christos cpuset_t *
    137       1.1  christos _cpuset_create(void)
    138       1.1  christos {
    139       1.8  christos 	if (cpuset_size == 0) {
    140       1.8  christos 		static int mib[2] = { CTL_HW, HW_NCPU };
    141       1.8  christos 		size_t len;
    142      1.10        he 		u_int nc;
    143       1.8  christos 
    144  1.12.4.1    bouyer 		len = sizeof(nc);
    145       1.8  christos 		if (sysctl(mib, __arraycount(mib), &nc, &len, NULL, 0) == -1)
    146       1.8  christos 			return NULL;
    147       1.8  christos 
    148      1.10        he 		cpuset_nentries = CPUSET_NENTRIES(nc);
    149       1.8  christos 		cpuset_size = CPUSET_SIZE();
    150       1.3     rmind 	}
    151       1.8  christos 	return calloc(1, cpuset_size);
    152       1.1  christos }
    153       1.1  christos 
    154       1.1  christos void
    155       1.1  christos _cpuset_destroy(cpuset_t *c)
    156       1.1  christos {
    157       1.1  christos 	free(c);
    158       1.1  christos }
    159       1.1  christos 
    160       1.8  christos #else
    161       1.8  christos 
    162       1.8  christos kcpuset_t *
    163       1.8  christos kcpuset_create(void)
    164       1.1  christos {
    165       1.8  christos 	kcpuset_t *c;
    166       1.8  christos 	if (cpuset_size == 0) {
    167       1.8  christos 		cpuset_nentries = CPUSET_NENTRIES(MAXCPUS);
    168       1.8  christos 		cpuset_size = KCPUSET_SIZE();
    169       1.8  christos 	}
    170       1.8  christos 	c = kmem_zalloc(cpuset_size, KM_SLEEP);
    171       1.8  christos 	c->next = NULL;
    172       1.8  christos 	c->nused = 1;
    173       1.8  christos 	return c;
    174       1.1  christos }
    175       1.1  christos 
    176       1.1  christos void
    177       1.8  christos kcpuset_destroy(kcpuset_t *c)
    178       1.1  christos {
    179       1.8  christos 	kcpuset_t *nc;
    180       1.8  christos 	while (c) {
    181       1.8  christos 		KASSERT(c->nused == 0);
    182       1.8  christos 		nc = c->next;
    183       1.8  christos 		kmem_free(c, cpuset_size);
    184       1.8  christos 		c = nc;
    185       1.8  christos 	}
    186       1.8  christos }
    187       1.2     rmind 
    188       1.8  christos void
    189       1.8  christos kcpuset_copy(kcpuset_t *d, const kcpuset_t *s)
    190       1.8  christos {
    191       1.1  christos 	KASSERT(d->nused == 1);
    192       1.8  christos 	(void)memcpy(d->bits, s->bits, cpuset_nentries * sizeof(s->bits[0]));
    193       1.1  christos }
    194       1.1  christos 
    195       1.1  christos void
    196       1.8  christos kcpuset_use(kcpuset_t *c)
    197       1.1  christos {
    198       1.1  christos 	atomic_inc_uint(&c->nused);
    199       1.1  christos }
    200       1.1  christos 
    201       1.1  christos void
    202       1.8  christos kcpuset_unuse(kcpuset_t *c, kcpuset_t **lst)
    203       1.1  christos {
    204       1.1  christos 	if (atomic_dec_uint_nv(&c->nused) != 0)
    205       1.1  christos 		return;
    206       1.8  christos 	KASSERT(c->nused == 0);
    207       1.1  christos 	KASSERT(c->next == NULL);
    208       1.1  christos 	if (lst == NULL) {
    209       1.8  christos 		kcpuset_destroy(c);
    210       1.1  christos 		return;
    211       1.1  christos 	}
    212       1.1  christos 	c->next = *lst;
    213       1.1  christos 	*lst = c;
    214       1.1  christos }
    215       1.8  christos 
    216       1.8  christos int
    217       1.8  christos kcpuset_copyin(const cpuset_t *u, kcpuset_t *k, size_t len)
    218       1.8  christos {
    219       1.8  christos 	KASSERT(k->nused > 0);
    220       1.8  christos 	KASSERT(k->next == NULL);
    221       1.8  christos 	if (len != CPUSET_SIZE())
    222       1.8  christos 		return EINVAL;
    223       1.8  christos 	return copyin(u->bits, k->bits, cpuset_nentries * sizeof(k->bits[0]));
    224       1.8  christos }
    225       1.8  christos 
    226       1.8  christos int
    227       1.8  christos kcpuset_copyout(const kcpuset_t *k, cpuset_t *u, size_t len)
    228       1.8  christos {
    229       1.8  christos 	KASSERT(k->nused > 0);
    230       1.8  christos 	KASSERT(k->next == NULL);
    231       1.8  christos 	if (len != CPUSET_SIZE())
    232       1.8  christos 		return EINVAL;
    233       1.8  christos 	return copyout(k->bits, u->bits, cpuset_nentries * sizeof(u->bits[0]));
    234       1.8  christos }
    235       1.8  christos 
    236       1.8  christos void
    237       1.8  christos kcpuset_zero(kcpuset_t *c)
    238       1.8  christos {
    239       1.8  christos 	KASSERT(c->nused > 0);
    240       1.8  christos 	KASSERT(c->next == NULL);
    241       1.8  christos 	(void)memset(c->bits, 0, cpuset_nentries * sizeof(c->bits[0]));
    242       1.8  christos }
    243       1.8  christos 
    244       1.8  christos int
    245       1.8  christos kcpuset_isset(cpuid_t i, const kcpuset_t *c)
    246       1.8  christos {
    247      1.12  dholland 	const unsigned long j = i >> CPUSET_SHIFT;
    248       1.8  christos 
    249      1.11     rmind 	KASSERT(c != NULL);
    250       1.8  christos 	KASSERT(c->nused > 0);
    251       1.8  christos 	KASSERT(c->next == NULL);
    252      1.11     rmind 	KASSERT(j < cpuset_nentries);
    253       1.8  christos 	return ((1 << (i & CPUSET_MASK)) & c->bits[j]) != 0;
    254       1.8  christos }
    255       1.8  christos 
    256       1.1  christos #endif
    257       1.7  christos #endif
    258