90 lines
		
	
	
	
		
			2.1 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			90 lines
		
	
	
	
		
			2.1 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
| 
								 | 
							
								/* find_next_bit.c: fallback find next bit implementation
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Copied from lib/find_next_bit.c to tools/lib/next_bit.c
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
							 | 
						||
| 
								 | 
							
								 * Written by David Howells (dhowells@redhat.com)
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * This program is free software; you can redistribute it and/or
							 | 
						||
| 
								 | 
							
								 * modify it under the terms of the GNU General Public License
							 | 
						||
| 
								 | 
							
								 * as published by the Free Software Foundation; either version
							 | 
						||
| 
								 | 
							
								 * 2 of the License, or (at your option) any later version.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <linux/bitops.h>
							 | 
						||
| 
								 | 
							
								#include <asm/types.h>
							 | 
						||
| 
								 | 
							
								#include <asm/byteorder.h>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define BITOP_WORD(nr)		((nr) / BITS_PER_LONG)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifndef find_next_bit
							 | 
						||
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								 * Find the next set bit in a memory region.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								unsigned long find_next_bit(const unsigned long *addr, unsigned long size,
							 | 
						||
| 
								 | 
							
											    unsigned long offset)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									const unsigned long *p = addr + BITOP_WORD(offset);
							 | 
						||
| 
								 | 
							
									unsigned long result = offset & ~(BITS_PER_LONG-1);
							 | 
						||
| 
								 | 
							
									unsigned long tmp;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if (offset >= size)
							 | 
						||
| 
								 | 
							
										return size;
							 | 
						||
| 
								 | 
							
									size -= result;
							 | 
						||
| 
								 | 
							
									offset %= BITS_PER_LONG;
							 | 
						||
| 
								 | 
							
									if (offset) {
							 | 
						||
| 
								 | 
							
										tmp = *(p++);
							 | 
						||
| 
								 | 
							
										tmp &= (~0UL << offset);
							 | 
						||
| 
								 | 
							
										if (size < BITS_PER_LONG)
							 | 
						||
| 
								 | 
							
											goto found_first;
							 | 
						||
| 
								 | 
							
										if (tmp)
							 | 
						||
| 
								 | 
							
											goto found_middle;
							 | 
						||
| 
								 | 
							
										size -= BITS_PER_LONG;
							 | 
						||
| 
								 | 
							
										result += BITS_PER_LONG;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									while (size & ~(BITS_PER_LONG-1)) {
							 | 
						||
| 
								 | 
							
										if ((tmp = *(p++)))
							 | 
						||
| 
								 | 
							
											goto found_middle;
							 | 
						||
| 
								 | 
							
										result += BITS_PER_LONG;
							 | 
						||
| 
								 | 
							
										size -= BITS_PER_LONG;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									if (!size)
							 | 
						||
| 
								 | 
							
										return result;
							 | 
						||
| 
								 | 
							
									tmp = *p;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								found_first:
							 | 
						||
| 
								 | 
							
									tmp &= (~0UL >> (BITS_PER_LONG - size));
							 | 
						||
| 
								 | 
							
									if (tmp == 0UL)		/* Are any bits set? */
							 | 
						||
| 
								 | 
							
										return result + size;	/* Nope. */
							 | 
						||
| 
								 | 
							
								found_middle:
							 | 
						||
| 
								 | 
							
									return result + __ffs(tmp);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifndef find_first_bit
							 | 
						||
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								 * Find the first set bit in a memory region.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								unsigned long find_first_bit(const unsigned long *addr, unsigned long size)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									const unsigned long *p = addr;
							 | 
						||
| 
								 | 
							
									unsigned long result = 0;
							 | 
						||
| 
								 | 
							
									unsigned long tmp;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									while (size & ~(BITS_PER_LONG-1)) {
							 | 
						||
| 
								 | 
							
										if ((tmp = *(p++)))
							 | 
						||
| 
								 | 
							
											goto found;
							 | 
						||
| 
								 | 
							
										result += BITS_PER_LONG;
							 | 
						||
| 
								 | 
							
										size -= BITS_PER_LONG;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									if (!size)
							 | 
						||
| 
								 | 
							
										return result;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									tmp = (*p) & (~0UL >> (BITS_PER_LONG - size));
							 | 
						||
| 
								 | 
							
									if (tmp == 0UL)		/* Are any bits set? */
							 | 
						||
| 
								 | 
							
										return result + size;	/* Nope. */
							 | 
						||
| 
								 | 
							
								found:
							 | 
						||
| 
								 | 
							
									return result + __ffs(tmp);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								#endif
							 |