cpuset.c revision 1.2
1/* $NetBSD: cpuset.c,v 1.2 2008/06/15 23:41:39 rmind Exp $ */ 2 3/*- 4 * Copyright (c) 2008 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Christos Zoulas. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32#include <sys/cdefs.h> 33#if defined(LIBC_SCCS) && !defined(lint) 34__RCSID("$NetBSD: cpuset.c,v 1.2 2008/06/15 23:41:39 rmind Exp $"); 35#endif /* LIBC_SCCS and not lint */ 36 37#include <sys/param.h> 38#include <sys/sched.h> 39#ifdef _KERNEL 40#include <sys/kmem.h> 41#include <lib/libkern/libkern.h> 42#include <sys/atomic.h> 43#else 44#include <string.h> 45#include <stdlib.h> 46#include <sys/sysctl.h> 47#endif 48 49#define CPUSET_SHIFT 5 50#define CPUSET_MASK 31 51#define CPUSET_SIZE(nc) ((nc) > 32 ? ((nc) >> CPUSET_SHIFT) : 1) 52 53struct _cpuset { 54 size_t size; 55 unsigned int nused; 56 struct _cpuset *next; 57 uint32_t bits[0]; 58}; 59 60size_t 61_cpuset_size(const cpuset_t *c) 62{ 63 return sizeof(struct { 64 size_t size; 65 unsigned int nused; 66 struct _cpuset *next; 67 uint32_t bits[c->size]; 68 }); 69} 70 71void 72_cpuset_zero(cpuset_t *c) 73{ 74#ifdef _KERNEL 75 KASSERT(c->nused == 1); 76#endif 77 (void)memset(c->bits, 0, c->size * sizeof(c->bits[0])); 78} 79 80int 81_cpuset_isset(const cpuset_t *c, int i) 82{ 83 const int j = i >> CPUSET_SHIFT; 84 85 if (j >= c->size || j < 0) 86 return -1; 87 return ((1 << (i & CPUSET_MASK)) & c->bits[j]) != 0; 88} 89 90int 91_cpuset_set(cpuset_t *c, int i) 92{ 93 const int j = i >> CPUSET_SHIFT; 94 95 if (j >= c->size || j < 0) 96 return -1; 97 c->bits[j] |= 1 << (i & CPUSET_MASK); 98 return 0; 99} 100 101int 102_cpuset_clr(cpuset_t *c, int i) 103{ 104 const int j = i >> CPUSET_SHIFT; 105 106 if (j >= c->size || j < 0) 107 return -1; 108 c->bits[j] &= ~(1 << (i & CPUSET_MASK)); 109 return 0; 110} 111 112cpuset_t * 113_cpuset_create(void) 114{ 115 cpuset_t s, *c; 116#ifdef _KERNEL 117 s.size = CPUSET_SIZE(MAXCPUS); 118 c = kmem_zalloc(_cpuset_size(&s), KM_SLEEP); 119#else 120 static int mib[2] = { CTL_HW, HW_NCPU }; 121 size_t len; 122 int nc; 123 if (sysctl(mib, __arraycount(mib), &nc, &len, NULL, 0) == -1) 124 return NULL; 125 s.size = CPUSET_SIZE(nc); 126 c = calloc(1, _cpuset_size(&s)); 127#endif 128 c->next = NULL; 129 c->nused = 1; 130 c->size = s.size; 131 return c; 132} 133 134void 135_cpuset_destroy(cpuset_t *c) 136{ 137#ifdef _KERNEL 138 while (c) { 139 KASSERT(c->nused == 0); 140 kmem_free(c, _cpuset_size(c)); 141 c = c->next; 142 } 143#else 144 free(c); 145#endif 146} 147 148#ifdef _KERNEL 149size_t 150_cpuset_nused(const cpuset_t *c) 151{ 152 return c->nused; 153} 154 155void 156_cpuset_copy(cpuset_t *d, const cpuset_t *s) 157{ 158 159 KASSERT(d->size == s->size); 160 KASSERT(d->nused == 1); 161 (void)memcpy(d->bits, s->bits, d->size * sizeof(d->bits[0])); 162} 163 164void 165_cpuset_use(cpuset_t *c) 166{ 167 168 atomic_inc_uint(&c->nused); 169} 170 171void 172_cpuset_unuse(cpuset_t *c, cpuset_t **lst) 173{ 174 175 if (atomic_dec_uint_nv(&c->nused) != 0) 176 return; 177 KASSERT(c->nused > 0); 178 KASSERT(c->next == NULL); 179 if (lst == NULL) { 180 _cpuset_destroy(c); 181 return; 182 } 183 c->next = *lst; 184 *lst = c; 185} 186#endif 187