blob: 8f24e934926a44e148d6a7ca1bac1e5f77c580b8 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @author Ji, Qi, 2006/10/25
*/
#ifndef _BIT_OPS_H_
#define _BIT_OPS_H_
#include "../common/gc_common.h"
inline unsigned int word_get_first_set_lsb(POINTER_SIZE_INT target_word)
{
assert(target_word != 0);
POINTER_SIZE_INT bit_offset = 0;
#if defined(_IPF_) || defined(_WIN64)
while( ! (target_word & ((POINTER_SIZE_INT)1 << bit_offset)) ){
bit_offset++;
}
#else /* !_IPF_ && !_WIN64 */
#ifdef PLATFORM_POSIX /* linux X86 32/64 */
__asm__ __volatile__(
"bsf %1,%0\n"
:"=r"(bit_offset)
:"m"(target_word)
);
#else /* !PLATFORM_POSIX */
#ifdef WIN32
__asm{
bsf eax, target_word
mov bit_offset, eax
}
#endif /* WIN32 */
#endif /* !PLATFORM_POSIX */
#endif /* !_IPF_ && !_WIN64 */
assert(bit_offset < BITS_PER_WORD);
return (unsigned int)bit_offset;
}
inline unsigned int words_get_next_set_lsb(POINTER_SIZE_INT* words, unsigned int count, unsigned int start_idx)
{
unsigned int bit_offset;
assert(start_idx < 128);
unsigned int start_word_index = start_idx >> BIT_SHIFT_TO_BITS_PER_WORD;
unsigned int start_bit_offset = start_idx & BIT_MASK_TO_BITS_PER_WORD;
bit_offset = start_idx - start_bit_offset;
for(unsigned int i = start_word_index; i < count; i ++ ){
POINTER_SIZE_INT cur_word = *(words + i);
if(start_word_index == i){
POINTER_SIZE_INT mask = ~(((POINTER_SIZE_INT)1 << start_bit_offset) - 1);
cur_word = cur_word & mask;
}
if(cur_word != 0){
bit_offset += word_get_first_set_lsb(cur_word);
return bit_offset;
}
bit_offset += BITS_PER_WORD;
}
return bit_offset;
}
inline void words_set_bit(POINTER_SIZE_INT* words, unsigned int count, unsigned int start_idx)
{
assert(start_idx < 128);
unsigned int word_index = start_idx >> BIT_SHIFT_TO_BITS_PER_WORD;
unsigned int bit_offset = start_idx & BIT_MASK_TO_BITS_PER_WORD;
if(word_index >= count) return;
volatile POINTER_SIZE_INT* p_word = words + word_index;
POINTER_SIZE_INT old_value = *p_word;
POINTER_SIZE_INT mask = (POINTER_SIZE_INT)1 << bit_offset;
POINTER_SIZE_INT new_value = old_value|mask;
while (true) {
POINTER_SIZE_INT temp = atomic_casptrsz(p_word, new_value, old_value);
if (temp == old_value) break;
old_value = *p_word;
new_value = old_value|mask;
}
return;
}
inline void words_clear_bit(POINTER_SIZE_INT* words, unsigned int count, unsigned int start_idx)
{
assert(start_idx < 128);
unsigned int word_index = start_idx >> BIT_SHIFT_TO_BITS_PER_WORD;
unsigned int bit_offset = start_idx & BIT_MASK_TO_BITS_PER_WORD;
if(word_index >= count) return;
volatile POINTER_SIZE_INT* p_word = words + word_index;
POINTER_SIZE_INT old_value = *p_word;
POINTER_SIZE_INT mask = ~((POINTER_SIZE_INT)1 << bit_offset);
POINTER_SIZE_INT new_value = old_value & mask;
while (true) {
POINTER_SIZE_INT temp = atomic_casptrsz(p_word, new_value, old_value);
if (temp == old_value) break;
old_value = *p_word;
new_value = old_value & mask;
}
return;
}
#endif