| /* |
| * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>. |
| * |
| * 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 any later version. |
| * |
| * This program is distributed in the hope that it will be useful, but |
| * WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License |
| * along with this program; if not, write to the Free Software |
| * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
| */ |
| |
| FILE_LICENCE ( GPL2_OR_LATER ); |
| |
| #include <errno.h> |
| #include <gpxe/bitmap.h> |
| |
| /** @file |
| * |
| * Bitmaps for multicast downloads |
| * |
| */ |
| |
| /** |
| * Resize bitmap |
| * |
| * @v bitmap Bitmap |
| * @v new_length New length of bitmap, in bits |
| * @ret rc Return status code |
| */ |
| int bitmap_resize ( struct bitmap *bitmap, unsigned int new_length ) { |
| unsigned int old_num_blocks; |
| unsigned int new_num_blocks; |
| size_t new_size; |
| bitmap_block_t *new_blocks; |
| |
| old_num_blocks = BITMAP_INDEX ( bitmap->length + BITMAP_BLKSIZE - 1 ); |
| new_num_blocks = BITMAP_INDEX ( new_length + BITMAP_BLKSIZE - 1 ); |
| |
| if ( old_num_blocks != new_num_blocks ) { |
| new_size = ( new_num_blocks * sizeof ( bitmap->blocks[0] ) ); |
| new_blocks = realloc ( bitmap->blocks, new_size ); |
| if ( ! new_blocks ) { |
| DBGC ( bitmap, "Bitmap %p could not resize to %d " |
| "bits\n", bitmap, new_length ); |
| return -ENOMEM; |
| } |
| bitmap->blocks = new_blocks; |
| } |
| bitmap->length = new_length; |
| |
| while ( old_num_blocks < new_num_blocks ) { |
| bitmap->blocks[old_num_blocks++] = 0; |
| } |
| |
| DBGC ( bitmap, "Bitmap %p resized to %d bits\n", bitmap, new_length ); |
| return 0; |
| } |
| |
| /** |
| * Test bit in bitmap |
| * |
| * @v bitmap Bitmap |
| * @v bit Bit index |
| * @ret is_set Bit is set |
| */ |
| int bitmap_test ( struct bitmap *bitmap, unsigned int bit ) { |
| unsigned int index = BITMAP_INDEX ( bit ); |
| bitmap_block_t mask = BITMAP_MASK ( bit ); |
| |
| if ( bit >= bitmap->length ) |
| return 0; |
| return ( bitmap->blocks[index] & mask ); |
| } |
| |
| /** |
| * Set bit in bitmap |
| * |
| * @v bitmap Bitmap |
| * @v bit Bit index |
| */ |
| void bitmap_set ( struct bitmap *bitmap, unsigned int bit ) { |
| unsigned int index = BITMAP_INDEX ( bit ); |
| bitmap_block_t mask = BITMAP_MASK ( bit ); |
| |
| DBGC ( bitmap, "Bitmap %p setting bit %d\n", bitmap, bit ); |
| |
| /* Update bitmap */ |
| bitmap->blocks[index] |= mask; |
| |
| /* Update first gap counter */ |
| while ( bitmap_test ( bitmap, bitmap->first_gap ) ) { |
| bitmap->first_gap++; |
| } |
| } |