|
@@ -0,0 +1,113 @@
|
|
|
+/*
|
|
|
+ * Copyright 2012 Institute of Communication and Computer Systems (ICCS)
|
|
|
+ *
|
|
|
+ * Licensed 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.
|
|
|
+ *
|
|
|
+ */
|
|
|
+
|
|
|
+/**
|
|
|
+ * @file bibop_malloc.c
|
|
|
+ * @author Ilias Pliotas, Ioannis Koutras
|
|
|
+ * @date September, 2012
|
|
|
+ * @brief malloc() implementation for BiBoP raw blocks
|
|
|
+ */
|
|
|
+
|
|
|
+#include "bibop/bibop_malloc.h"
|
|
|
+#include "bibop/bibop_rb.h"
|
|
|
+#include "bibop/bibop_other.h"
|
|
|
+
|
|
|
+#ifdef HAVE_LOCKS
|
|
|
+#include <pthread.h>
|
|
|
+#endif /* HAVE_LOCKS */
|
|
|
+
|
|
|
+/**
|
|
|
+ * Returns a memory block from a BiBoP-organized raw block
|
|
|
+ *
|
|
|
+ * @param size_t The requested memory size.
|
|
|
+ * @retval The address to serve the request.
|
|
|
+ * @retval NULL No available memory space.
|
|
|
+ */
|
|
|
+void * bibop_malloc(raw_block_header_t *raw_block, size_t req_size) {
|
|
|
+ bibop_rb_t *rb_header;
|
|
|
+ size_t cells, stop, i;
|
|
|
+ void *ret;
|
|
|
+ unsigned int found;
|
|
|
+ BMAP_EL_TYPE mask1, mask2;
|
|
|
+ chunk_header_t *chunk_address;
|
|
|
+
|
|
|
+ rb_header = (bibop_rb_t *)((char *)raw_block + sizeof(raw_block_header_t));
|
|
|
+
|
|
|
+ ret = NULL;
|
|
|
+
|
|
|
+ req_size += sizeof(chunk_header_t);
|
|
|
+
|
|
|
+ if(req_size % rb_header->bytes_per_cell > 0) {
|
|
|
+ cells = req_size / rb_header->bytes_per_cell + 1;
|
|
|
+ } else {
|
|
|
+ cells = req_size / rb_header->bytes_per_cell;
|
|
|
+ }
|
|
|
+
|
|
|
+#ifdef HAVE_LOCKS
|
|
|
+ pthread_mutex_lock(&raw_block->mutex);
|
|
|
+#endif /* HAVE_LOCKS */
|
|
|
+
|
|
|
+ // perform bitwise shift & and operations in the BMAP_EL_TYPE arrays
|
|
|
+ stop = prev_pow2(cells);
|
|
|
+
|
|
|
+ copy_array(rb_header->bmap_array2, rb_header->bmap_array);
|
|
|
+ for(i = 1; i < stop; i <<= 1) {
|
|
|
+ copy_array(rb_header->bmap_array3, rb_header->bmap_array2);
|
|
|
+ shift_array(rb_header->bmap_array3, i);
|
|
|
+ add_arrays(rb_header->bmap_array2, rb_header->bmap_array3);
|
|
|
+ }
|
|
|
+ if(stop < cells) {
|
|
|
+ copy_array(rb_header->bmap_array3, rb_header->bmap_array2);
|
|
|
+ shift_array(rb_header->bmap_array3, cells - stop);
|
|
|
+ add_arrays(rb_header->bmap_array2, rb_header->bmap_array3);
|
|
|
+ }
|
|
|
+
|
|
|
+ found = 0 ;
|
|
|
+ ret = NULL;
|
|
|
+
|
|
|
+ for(i = 0; i < BMAP_INDEX_NUM; ++i) {
|
|
|
+ found = __builtin_ffsl(rb_header->bmap_array2[i]);
|
|
|
+ if(found) {
|
|
|
+ int ext = BMAP_EL_SIZE_BITS - found - (cells - 1);
|
|
|
+ if(ext >= 0) {
|
|
|
+ mask1 = ~make_bit_mask(found, cells);
|
|
|
+ rb_header->bmap_array[i] &= mask1;
|
|
|
+ } else {
|
|
|
+ mask1 = ~make_bit_mask(found, BMAP_EL_SIZE_BITS - found + 1);
|
|
|
+ mask2 = ~make_bit_mask(1, cells - (BMAP_EL_SIZE_BITS - found) - 1);
|
|
|
+ rb_header->bmap_array[i] &= mask1;
|
|
|
+ rb_header->bmap_array[i + 1] &= mask2;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Calculate the pointer to the chunk to be retrieved
|
|
|
+ chunk_address = (chunk_header_t *)((char *)rb_header + (i *
|
|
|
+ BMAP_EL_SIZE_BITS + found - 1) *
|
|
|
+ rb_header->bytes_per_cell);
|
|
|
+ chunk_address->num_of_cells = cells;
|
|
|
+
|
|
|
+ ret = (void *)((char *)chunk_address + sizeof(chunk_header_t));
|
|
|
+
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+#ifdef HAVE_LOCKS
|
|
|
+ pthread_mutex_unlock(&raw_block->mutex);
|
|
|
+#endif /* HAVE_LOCKS */
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|