/*
* Copyright (c) 2012 Adam Hraska
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - 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.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* 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.
*/
/** @addtogroup kernel_generic
* @{
*/
/**
* @file
* @brief CPU mask manipulation functions.
*/
#include <assert.h>
#include <cpu/cpu_mask.h>
#include <cpu.h>
#include <config.h>
static const size_t word_size = sizeof(unsigned int);
static const size_t word_bit_cnt = 8 * sizeof(unsigned int);
/** Returns the size of cpu_mask_t for the detected number of cpus in bytes. */
size_t cpu_mask_size(void)
{
size_t word_cnt = (config.cpu_count + word_bit_cnt - 1) / word_bit_cnt;
return word_cnt * word_size;
}
/** Add first cpu_cnt cpus to the mask, ie sets the first cpu_cnt bits. */
static void cpu_mask_count(cpu_mask_t *cpus, size_t cpu_cnt)
{
assert(NULL != cpus);
assert(cpu_cnt <= config.cpu_count);
for (size_t active_word = 0;
(active_word + 1) * word_bit_cnt <= cpu_cnt;
++active_word) {
/* Set all bits in the cell/word. */
cpus->mask[active_word] = -1;
}
size_t remaining_bits = (cpu_cnt % word_bit_cnt);
if (0 < remaining_bits) {
/* Set lower remaining_bits of the last word. */
cpus->mask[cpu_cnt / word_bit_cnt] = (1 << remaining_bits) - 1;
}
}
/** Sets bits corresponding to the active cpus, ie the first
* config.cpu_active cpus.
*/
void cpu_mask_active(cpu_mask_t *cpus)
{
cpu_mask_none(cpus);
cpu_mask_count(cpus, config.cpu_active);
}
/** Sets bits for all cpus of the mask. */
void cpu_mask_all(cpu_mask_t *cpus)
{
cpu_mask_count(cpus, config.cpu_count);
}
/** Resets/removes all bits. */
void cpu_mask_none(cpu_mask_t *cpus)
{
assert(cpus);
size_t word_cnt = cpu_mask_size() / word_size;
for (size_t word = 0; word < word_cnt; ++word) {
cpus->mask[word] = 0;
}
}
/** Sets the bit corresponding to cpu_id to true. */
void cpu_mask_set(cpu_mask_t *cpus, unsigned int cpu_id)
{
size_t word = cpu_id / word_bit_cnt;
size_t word_pos = cpu_id % word_bit_cnt;
cpus->mask[word] |= (1U << word_pos);
}
/** Resets the bit corresponding to cpu_id to false. */
void cpu_mask_reset(cpu_mask_t *cpus, unsigned int cpu_id)
{
size_t word = cpu_id / word_bit_cnt;
size_t word_pos = cpu_id % word_bit_cnt;
cpus->mask[word] &= ~(1U << word_pos);
}
/** Returns true if the bit corresponding to cpu_id is set. */
bool cpu_mask_is_set(cpu_mask_t *cpus, unsigned int cpu_id)
{
size_t word = cpu_id / word_bit_cnt;
size_t word_pos = cpu_id % word_bit_cnt;
return 0 != (cpus->mask[word] & (1U << word_pos));
}
/** Returns true if no bits are set. */
bool cpu_mask_is_none(cpu_mask_t *cpus)
{
size_t word_cnt = cpu_mask_size() / word_size;
for (size_t word = 0; word < word_cnt; ++word) {
if (cpus->mask[word])
return false;
}
return true;
}
/** @}
*/