Exemple #1
0
// size in words.
// Flag one means block is free.
void initialiseFreeBlock(void* freeRegion, uint32_t size, void* prevFreeRegion, 
	void* nextFreeRegion, bool flag, bool setHeader) 
{	
	totalFreeSpace += WORDS_TO_BYTES(size); // Stats

	 // Update largest free region.
	if (size > largestFreeBlock) {
		largestFreeBlock = WORDS_TO_BYTES(size);
	}

	if (setHeader) {
		struct blockHeader *header = INIT_STRUCT(blockHeader, freeRegion);
		header->attribute = size; // Set size. Size is max 2^30. Flag is 0 by default.
		if (flag)
			header->attribute |= MSB_TO_ONE; // Set flag to 1.
	}

	void* usableArea = ADDRESS_PLUS_OFFSET(freeRegion, blockHeader);
	struct freeBlockLinks *blockLinks = INIT_STRUCT(freeBlockLinks, usableArea);
	PREV_BLOCK(blockLinks) = prevFreeRegion; 
	NEXT_BLOCK(blockLinks) = nextFreeRegion;

	// Set footer free region.
	uint64_t sizeOffset = WORDS_TO_BYTES(size);
	void* footer = ADDRESS_MINUS_OFFSET(usableArea + sizeOffset, freeBlockFooter);
	struct freeBlockFooter *blockFooter = INIT_STRUCT(freeBlockFooter, footer);
	blockFooter->size = size;
}
Exemple #2
0
/* And a debugging version of the above:	*/
void * GC_debug_gcj_fast_malloc(size_t lw,
				void * ptr_to_struct_containing_descr,
				GC_EXTRA_PARAMS)
{
    GC_PTR result;
    size_t lb = WORDS_TO_BYTES(lw);

    /* We clone the code from GC_debug_gcj_malloc, so that we 	*/
    /* dont end up with extra frames on the stack, which could	*/
    /* confuse the backtrace.					*/
    LOCK();
    maybe_finalize();
    result = GC_generic_malloc_inner(lb + DEBUG_BYTES, GC_gcj_debug_kind);
    if (result == 0) {
	UNLOCK();
        GC_err_printf2("GC_debug_gcj_fast_malloc(%ld, 0x%lx) returning NIL (",
        	       (unsigned long) lw,
		       (unsigned long) ptr_to_struct_containing_descr);
        GC_err_puts(s);
        GC_err_printf1(":%ld)\n", (unsigned long)i);
        return GC_oom_fn(WORDS_TO_BYTES(lw));
    }
    *((void **)((ptr_t)result + sizeof(oh))) = ptr_to_struct_containing_descr;
    UNLOCK();
    if (!GC_debugging_started) {
    	GC_start_debugging();
    }
    ADD_CALL_CHAIN(result, ra);
    return (GC_store_debug_info(result, (word)lb, s, (word)i));
}
Exemple #3
0
// Split a large block into two sub-blocks.
// spaceLeft and size are in words
void *splitFreeBlock(void* blockToSplit, uint64_t spaceLeft,
		uint32_t size, void* currentFreeBlock, 
		struct freeBlockLinks *currentBlockLinks) 
{
	// Reinitialise header of first sub-block.
	void* block = ADDRESS_MINUS_OFFSET(blockToSplit, blockHeader);
	struct blockHeader *allocatedBlock = INIT_STRUCT(blockHeader, block);
	allocatedBlock->attribute = size;

	// Create and initialise new node.
	uint32_t sizeNewNode = spaceLeft - BYTES_TO_WORDS(sizeof(blockHeader));
 
 	uint64_t sizeOffset =  WORDS_TO_BYTES(size);
	void* endUserRequestedBlock = blockToSplit + sizeOffset;
	// initialise new block.
	void* prevBlock = PREV_BLOCK(currentBlockLinks);

	totalFreeSpace -= WORDS_TO_BYTES(spaceLeft);
	totalFreeSpace -= WORDS_TO_BYTES(size); // Stats

	initialiseFreeBlock(endUserRequestedBlock, sizeNewNode, 
		prevBlock, currentFreeBlock, false, true);
	insertFreeBlock(endUserRequestedBlock, currentBlockLinks);

	return endUserRequestedBlock;
}
Exemple #4
0
void coalesceWithNextBlock(void* newAddr, uint32_t newSize, struct freeBlockLinks *successorBlockLinks) 
{
	struct blockHeader *newBlock = newAddr;
	newBlock->attribute = newSize;

	// Update links to freenodes.
	void* blockLinks = ADDRESS_PLUS_OFFSET(newAddr, blockHeader);
	struct freeBlockLinks *newBlockLinks = INIT_STRUCT(freeBlockLinks, blockLinks);
	PREV_BLOCK(newBlockLinks) = PREV_BLOCK(successorBlockLinks);
	NEXT_BLOCK(newBlockLinks) = NEXT_BLOCK(successorBlockLinks);

	// Prev block.
	void* prevLinks = ADDRESS_PLUS_OFFSET(PREV_BLOCK(newBlockLinks), blockHeader);
	struct freeBlockLinks *prevBlockLinks = INIT_STRUCT(freeBlockLinks, prevLinks);
	NEXT_BLOCK(prevBlockLinks) = newAddr;

	// Next block.
	void* nextLinks = ADDRESS_PLUS_OFFSET(NEXT_BLOCK(newBlockLinks), blockHeader);
	struct freeBlockLinks *nextBlockLinks = INIT_STRUCT(freeBlockLinks, nextLinks);
	PREV_BLOCK(prevBlockLinks) = newAddr;

	uint64_t sizeOffset = WORDS_TO_BYTES(newSize);
	setFooterBlockOnCoalescing(newAddr, sizeOffset, newSize);
	updateNextBlockOnCoalescing(newAddr, sizeOffset);
}
Exemple #5
0
/* allocated as a small object.					*/
void * GC_gcj_fast_malloc(size_t lw, void * ptr_to_struct_containing_descr)
{
ptr_t op;
ptr_t * opp;
DCL_LOCK_STATE;

    opp = &(GC_gcjobjfreelist[lw]);
    LOCK();
    op = *opp;
    if( EXPECT(op == 0, 0) ) {
	maybe_finalize();
        op = (ptr_t)GC_clear_stack(
		GC_generic_malloc_words_small_inner(lw, GC_gcj_kind));
	if (0 == op) {
	    UNLOCK();
	    return GC_oom_fn(WORDS_TO_BYTES(lw));
	}
    } else {
        *opp = obj_link(op);
        GC_words_allocd += lw;
    }
    *(void **)op = ptr_to_struct_containing_descr;
    UNLOCK();
    return((GC_PTR) op);
}
Exemple #6
0
// lengthMmapRegion in bytes
bool coalesceMmapRegions(void* mmapsList, void* newMmapRegion, uint64_t lengthMmapRegion) 
{
	
	void* currentMmapRegion = mmapsList;
	struct headerMmapRegion *headerMmap = INIT_STRUCT(headerMmapRegion, currentMmapRegion);
	do {
		uint64_t oldLength = WORDS_TO_BYTES(headerMmap->length);
		void* endMmapRegion = currentMmapRegion + oldLength;
		if(endMmapRegion == newMmapRegion) { 
			// Coalesce mmap regions.
			uint32_t newLength = headerMmap->length + BYTES_TO_WORDS(lengthMmapRegion); // update size mmap region.
			headerMmap->length = newLength;
			// Initialize footer mmap
			setMmapFooter(currentMmapRegion, WORDS_TO_BYTES(newLength));

			// Calculate size new free region.
			void* beginningFreeRegion = ADDRESS_MINUS_OFFSET(endMmapRegion, blockHeader);
			uint64_t newFreeSpaceSize = lengthMmapRegion - sizeof(blockHeader); // size free region.
			struct blockHeader *footerPrevMmapRegion = INIT_STRUCT(blockHeader, beginningFreeRegion);
			uint32_t flag = GET_FLAG(footerPrevMmapRegion->attribute);

			// Coalesce with prev block if free.
			if (flag == MSB_TO_ONE) {
				void* previous = ADDRESS_MINUS_OFFSET(beginningFreeRegion, freeBlockFooter);
				struct freeBlockFooter *prevUsableBlockFooter = INIT_STRUCT(freeBlockFooter, previous); 
				uint64_t sizePrevBlock = WORDS_TO_BYTES(prevUsableBlockFooter->size); // Footer has no flag
				beginningFreeRegion = beginningFreeRegion - sizePrevBlock - sizeof(blockHeader);
				newFreeSpaceSize += sizeof(blockHeader) + sizePrevBlock;
				numberFreeBlocks--;

				totalFreeSpace += newFreeSpaceSize; // Stats

				uint32_t newFreeSpaceSizeInWords = BYTES_TO_WORDS(newFreeSpaceSize);
				coalesceWithPrevBlock(beginningFreeRegion, newFreeSpaceSizeInWords);
			} else {
				initialiseFreeMmapRegion(beginningFreeRegion, newFreeSpaceSize); 
			}
			return true; // coalescing.
		} else { // Check next mmap region
			currentMmapRegion = NEXT_MMAP_ADDRESS(headerMmap);
			headerMmap = currentMmapRegion;
		}
	
	} while (headerMmap != NULL && NEXT_MMAP_ADDRESS(headerMmap) != NULL);

	return false; // no coalescing.
}
Exemple #7
0
void coalesceWithPrevBlock(void* newAddr, uint32_t newSize) 
{
	struct blockHeader *newBlock = INIT_STRUCT(blockHeader, newAddr);
	newBlock->attribute = newSize;

	uint64_t sizeOffset = WORDS_TO_BYTES(newSize);
	setFooterBlockOnCoalescing(newAddr, sizeOffset, newSize);
	updateNextBlockOnCoalescing(newAddr, sizeOffset);
}
Exemple #8
0
GC_API GC_descr GC_CALL GC_make_descriptor(const GC_word * bm, size_t len)
{
    signed_word last_set_bit = len - 1;
    GC_descr result;
    DCL_LOCK_STATE;

#   if defined(AO_HAVE_load_acquire) && defined(AO_HAVE_store_release)
      if (!EXPECT(AO_load_acquire(&GC_explicit_typing_initialized), TRUE)) {
        LOCK();
        if (!GC_explicit_typing_initialized) {
          GC_init_explicit_typing();
          AO_store_release(&GC_explicit_typing_initialized, TRUE);
        }
        UNLOCK();
      }
#   else
      LOCK();
      if (!EXPECT(GC_explicit_typing_initialized, TRUE)) {
        GC_init_explicit_typing();
        GC_explicit_typing_initialized = TRUE;
      }
      UNLOCK();
#   endif

    while (last_set_bit >= 0 && !GC_get_bit(bm, last_set_bit))
      last_set_bit--;
    if (last_set_bit < 0) return(0 /* no pointers */);

#   if ALIGNMENT == CPP_WORDSZ/8
    {
      signed_word i;

      for (i = 0; i < last_set_bit; i++) {
        if (!GC_get_bit(bm, i)) {
          break;
        }
      }
      if (i == last_set_bit) {
        /* An initial section contains all pointers.  Use length descriptor. */
        return (WORDS_TO_BYTES(last_set_bit+1) | GC_DS_LENGTH);
      }
    }
#   endif
    if ((word)last_set_bit < BITMAP_BITS) {
        signed_word i;

        /* Hopefully the common case.                   */
        /* Build bitmap descriptor (with bits reversed) */
        result = SIGNB;
        for (i = last_set_bit - 1; i >= 0; i--) {
            result >>= 1;
            if (GC_get_bit(bm, i)) result |= SIGNB;
        }
        result |= GC_DS_BITMAP;
    } else {
Exemple #9
0
void coalesceWithNeighbours(void* newAddr, uint32_t newSize, struct freeBlockLinks *successorBlockLinks) 
{
	struct blockHeader *newBlock = INIT_STRUCT(blockHeader, newAddr);
	newBlock->attribute = newSize;
	uint64_t sizeOffset = WORDS_TO_BYTES(newSize);
	setFooterBlockOnCoalescing(newAddr, sizeOffset, newSize);
	updateNextBlockOnCoalescing(newAddr, sizeOffset);

	// Remove successor block
	removeAllocatedBlock(successorBlockLinks);
	numberFreeBlocks--;
}
Exemple #10
0
void freeMemory(void *ptr) 
{
	/* 
	Read flag for coalescing with previous block
	Read size to get to the next block and check if it's free (coalescing)
	*/
	void *startBlock = ADDRESS_MINUS_OFFSET(ptr, blockHeader);
	struct blockHeader *header = INIT_STRUCT(blockHeader, startBlock);
	uint32_t size = GET_SIZE(header->attribute); // in words
	if(!freeList) {
		initialiseFreeBlock(startBlock, size, 
		startBlock, startBlock, false, false);
		freeList = startBlock;
		numberFreeBlocks++;

		totalFreeSpace += WORDS_TO_BYTES(size); // Stats
	} else {
		coalescingAndFree(startBlock);
	}

	currentAllocatedMemory -= WORDS_TO_BYTES(size);
}
Exemple #11
0
// Check if the new region is big enough to store a new free block.
// if not do not split, but free list now points to next node.
void allocateBlock(uint32_t size, uint32_t spaceLeft, 
	uint32_t minFreeRegionSize, uint32_t sizeFreeRegion,  
	void* freeBlock, void* currentFreeBlock, 
	struct freeBlockLinks *currentBlockLinks) 
{
	if (spaceLeft > minFreeRegionSize) {
		if (sufficientSize(size)) {
			freeList = splitFreeBlock(freeBlock, spaceLeft, 
				size, currentFreeBlock, currentBlockLinks);
		} else {
			minFreeRegionSize -= BYTES_TO_WORDS(sizeof(freeBlockFooter));
			freeList = splitFreeBlock(freeBlock, spaceLeft, 
				minFreeRegionSize, currentFreeBlock, currentBlockLinks);
		}

		numberFreeBlocks++;
	} else { 
		// No split.
		// If successor is mmap footer, then set its flag to 0.
		totalFreeSpace -= WORDS_TO_BYTES(sizeFreeRegion);
		
		uint64_t sizeOffset = WORDS_TO_BYTES(sizeFreeRegion);
		void* next = ADDRESS_PLUS_OFFSET(currentFreeBlock + sizeOffset, blockHeader);
		struct blockHeader *nextBlockHeader = INIT_STRUCT(blockHeader, next);
		// check if last one (size = 0.)
		if (nextBlockHeader->attribute == MSB_TO_ONE) { 
			// Tell next that block is not free anymore.
			nextBlockHeader->attribute = MSB_TO_ZERO; 
		} else {
			// If next block is not last one, then just set its flag to zero and keep size.
			// Flag is automatically set to zero.
			nextBlockHeader->attribute = GET_SIZE(nextBlockHeader->attribute); 
		}

		freeList = NEXT_BLOCK(currentBlockLinks);
	}
}
Exemple #12
0
void * GC_generic_malloc(size_t lb, int k)
{
    void * result;
    DCL_LOCK_STATE;

    if (GC_have_errors) GC_print_all_errors();
    GC_INVOKE_FINALIZERS();
    if (SMALL_OBJ(lb)) {
	LOCK();
        result = GC_generic_malloc_inner((word)lb, k);
	UNLOCK();
    } else {
	size_t lw;
	size_t lb_rounded;
	word n_blocks;
	GC_bool init;
	lw = ROUNDED_UP_WORDS(lb);
	lb_rounded = WORDS_TO_BYTES(lw);
	n_blocks = OBJ_SZ_TO_BLOCKS(lb_rounded);
	init = GC_obj_kinds[k].ok_init;
	LOCK();
	result = (ptr_t)GC_alloc_large(lb_rounded, k, 0);
	if (0 != result) {
	  if (GC_debugging_started) {
	    BZERO(result, n_blocks * HBLKSIZE);
	  } else {
#           ifdef THREADS
	      /* Clear any memory that might be used for GC descriptors */
	      /* before we release the lock.			      */
	        ((word *)result)[0] = 0;
	        ((word *)result)[1] = 0;
	        ((word *)result)[lw-1] = 0;
	        ((word *)result)[lw-2] = 0;
#	    endif
	  }
	}
	GC_bytes_allocd += lb_rounded;
	UNLOCK();
    	if (init && !GC_debugging_started && 0 != result) {
	    BZERO(result, n_blocks * HBLKSIZE);
        }
    }
    if (0 == result) {
        return((*GC_oom_fn)(lb));
    } else {
        return(result);
    }
}   
Exemple #13
0
void findAndSetLargestFreeBlock() 
{
	// traverse free list.
	largestFreeBlock = 0; // Reset largest free region.
	int numberTraversedNodes = 0;
	void* currentFreeBlock = freeList;
	do {
		struct blockHeader *currentFreeRegionHeader = INIT_STRUCT(blockHeader, currentFreeBlock);
		uint32_t sizeFreeRegion = GET_SIZE(currentFreeRegionHeader->attribute); // in words.
		uint64_t sizeFreeRegionInBytes = WORDS_TO_BYTES(sizeFreeRegion);
		if(sizeFreeRegionInBytes > largestFreeBlock) {
			largestFreeBlock = sizeFreeRegionInBytes;
		}

		void* freeBlock = ADDRESS_PLUS_OFFSET(currentFreeBlock, blockHeader);
		struct freeBlockLinks *currentBlockLinks = INIT_STRUCT(freeBlockLinks, freeBlock);

		numberTraversedNodes++;
		currentFreeBlock = NEXT_BLOCK(currentBlockLinks);
	} while (numberTraversedNodes < numberFreeBlocks);
}
Exemple #14
0
STATIC void GC_init_explicit_typing(void)
{
    unsigned i;

    GC_STATIC_ASSERT(sizeof(struct LeafDescriptor) % sizeof(word) == 0);
    /* Set up object kind with simple indirect descriptor. */
      GC_eobjfreelist = (ptr_t *)GC_new_free_list_inner();
      GC_explicit_kind = GC_new_kind_inner(
                            (void **)GC_eobjfreelist,
                            (WORDS_TO_BYTES((word)-1) | GC_DS_PER_OBJECT),
                            TRUE, TRUE);
                /* Descriptors are in the last word of the object. */
      GC_typed_mark_proc_index = GC_new_proc_inner(GC_typed_mark_proc);
    /* Set up object kind with array descriptor. */
      GC_array_mark_proc_index = GC_new_proc_inner(GC_array_mark_proc);
      GC_array_kind = GC_new_kind_inner(GC_new_free_list_inner(),
                            GC_MAKE_PROC(GC_array_mark_proc_index, 0),
                            FALSE, TRUE);
      GC_bm_table[0] = GC_DS_BITMAP;
      for (i = 1; i < WORDSZ/2; i++) {
          GC_bm_table[i] = (((word)-1) << (WORDSZ - i)) | GC_DS_BITMAP;
      }
}
Exemple #15
0
// size free region in bytes
void initialiseFreeMmapRegion(void* beginningFreeRegion, uint64_t sizeFreeRegion) 
{
	uint32_t sizeFreeRegionInWords = BYTES_TO_WORDS(sizeFreeRegion); // headerMmapsize in words.
	if(!freeList) {
		freeList = beginningFreeRegion; // Initialise the free list.
		initialiseFreeBlock(beginningFreeRegion, sizeFreeRegionInWords, 
			beginningFreeRegion, beginningFreeRegion, false, true);
	} else {
		// Add to free list.
		void *currentBlock = freeList;
		void* links = ADDRESS_PLUS_OFFSET(currentBlock, blockHeader);
		struct freeBlockLinks *currentBlockLinks = INIT_STRUCT(freeBlockLinks, links);

		void* prevBlock = PREV_BLOCK(currentBlockLinks);
		initialiseFreeBlock(beginningFreeRegion, sizeFreeRegionInWords, 
			prevBlock, currentBlock, false, true); 

		// Tell next block that its previous one is NOW free. 
		uint64_t sizeOffset = WORDS_TO_BYTES(sizeFreeRegionInWords);
		updateNextBlockOnCoalescing(beginningFreeRegion, sizeFreeRegion);

		insertFreeBlock(beginningFreeRegion, currentBlockLinks);
	}
}
Exemple #16
0
/* Currently useless for multithreaded worlds.                          */
GC_API void * GC_CALL GC_is_visible(void *p)
{
    hdr *hhdr;

    if ((word)p & (ALIGNMENT - 1)) goto fail;
    if (!GC_is_initialized) GC_init();
#   ifdef THREADS
        hhdr = HDR((word)p);
        if (hhdr != 0 && GC_base(p) == 0) {
            goto fail;
        } else {
            /* May be inside thread stack.  We can't do much. */
            return(p);
        }
#   else
        /* Check stack first: */
          if (GC_on_stack(p)) return(p);
        hhdr = HDR((word)p);
        if (hhdr == 0) {
            if (GC_is_static_root(p)) return(p);
            /* Else do it again correctly:      */
#           if (defined(DYNAMIC_LOADING) || defined(MSWIN32) || \
                defined(MSWINCE) || defined(PCR))
                GC_register_dynamic_libraries();
                if (GC_is_static_root(p))
                    return(p);
#           endif
            goto fail;
        } else {
            /* p points to the heap. */
            word descr;
            ptr_t base = GC_base(p);    /* Should be manually inlined? */

            if (base == 0) goto fail;
            if (HBLKPTR(base) != HBLKPTR(p)) hhdr = HDR((word)p);
            descr = hhdr -> hb_descr;
    retry:
            switch(descr & GC_DS_TAGS) {
                case GC_DS_LENGTH:
                    if ((word)((ptr_t)p - (ptr_t)base) > (word)descr) goto fail;
                    break;
                case GC_DS_BITMAP:
                    if ((ptr_t)p - (ptr_t)base
                         >= WORDS_TO_BYTES(BITMAP_BITS)
                         || ((word)p & (sizeof(word) - 1))) goto fail;
                    if (!(((word)1 << (WORDSZ - ((ptr_t)p - (ptr_t)base) - 1))
                          & descr)) goto fail;
                    break;
                case GC_DS_PROC:
                    /* We could try to decipher this partially.         */
                    /* For now we just punt.                            */
                    break;
                case GC_DS_PER_OBJECT:
                    if ((signed_word)descr >= 0) {
                      descr = *(word *)((ptr_t)base + (descr & ~GC_DS_TAGS));
                    } else {
                      ptr_t type_descr = *(ptr_t *)base;
                      descr = *(word *)(type_descr
                              - (descr - (GC_DS_PER_OBJECT
                                          - GC_INDIR_PER_OBJ_BIAS)));
                    }
                    goto retry;
            }
            return(p);
        }
#   endif
fail:
    (*GC_is_visible_print_proc)((ptr_t)p);
    return(p);
}
Exemple #17
0
void *getFreeBlock(uint64_t requestedSize) 
{
	// Transform size in bytes to size in words.
	uint32_t size = BYTES_TO_WORDS(requestedSize);

	if (!freeList) {
	 	mmapRegion(requestedSize);
	 	return getFreeBlock(requestedSize);
	}

	int numberTraversedNodes = 0;
	bool freeBlockFound = false;
	bool updateLargestFreeBlock = false;
	void* freeBlock;
	void* currentFreeBlock = freeList;

	/*
	 Traverse free list (circular double linked list)
	 Use next-fit.
	*/
	do {
		struct blockHeader *currentFreeRegionHeader = INIT_STRUCT(blockHeader, currentFreeBlock);
		uint32_t sizeFreeRegion = GET_SIZE(currentFreeRegionHeader->attribute);

		freeBlock = ADDRESS_PLUS_OFFSET(currentFreeBlock, blockHeader);
		struct freeBlockLinks *currentBlockLinks = INIT_STRUCT(freeBlockLinks, freeBlock);
		if (sizeFreeRegion >= size) {
			freeBlockFound = true;

			int sizeFreeRegionInBytes =  WORDS_TO_BYTES(sizeFreeRegion);
			// Larger blocks than largestFreeBlock can exist if mmap is called again.
			if (sizeFreeRegionInBytes >= largestFreeBlock) {
				updateLargestFreeBlock = true;
			}

			uint32_t spaceLeft; // in words
			uint32_t minFreeRegionSize = minimumSize();
			if (sufficientSize(size)) {
				spaceLeft = sizeFreeRegion - size;
			} else {
				spaceLeft = sizeFreeRegion - minFreeRegionSize;
			}

			allocateBlock(size, spaceLeft, minFreeRegionSize, 
				sizeFreeRegion, freeBlock, currentFreeBlock, currentBlockLinks);

			// Remove allocated block.
			if (numberFreeBlocks == 1) {
				freeList = NULL;
			} else {
				removeAllocatedBlock(currentBlockLinks);
			}
			numberFreeBlocks--;

			// Look for new largestFreeBlock
			if(numberFreeBlocks && updateLargestFreeBlock) {
				findAndSetLargestFreeBlock();
			}

		}
		// Step to the next free block in the free list.
		numberTraversedNodes++;
		currentFreeBlock = NEXT_BLOCK(currentBlockLinks);
	} while (numberTraversedNodes < numberFreeBlocks && !freeBlockFound);

	if (!freeBlockFound) {
	 	mmapRegion(requestedSize);
	 	return getFreeBlock(requestedSize);
	}

	return freeBlock;
}
/*-----------------------------------------------------------------------------*
 *  NAME
 *      OtaHandleAccessWrite
 *
 *  DESCRIPTION
 *      Handle write-access requests from the Host where the characteristic
 *      handle falls within the range of the OTAU Application Service.
 *
 *  PARAMETERS
 *      p_ind [in]              Write request data
 *
 *  RETURNS
 *      Nothing
 *----------------------------------------------------------------------------*/
void OtaHandleAccessWrite(GATT_ACCESS_IND_T *p_ind)
{
    sys_status  rc = gatt_status_write_not_permitted;
                                    /* Function status */
        
    switch (p_ind->handle)
    {
        case HANDLE_CSR_OTA_CURRENT_APP:
        {
            /* Set the index of the current application */
            const uint8 app_id = p_ind->value[0];
                                            /* New application index */
#if defined(USE_STATIC_RANDOM_ADDRESS) || defined(USE_RESOLVABLE_RANDOM_ADDRESS)
            BD_ADDR_T   bd_addr;            /* Bluetooth Device address */

            GapGetRandomAddress(&bd_addr);
#endif /* USE_STATIC_RANDOM_ADDRESS || USE_RESOLVABLE_RANDOM_ADDRESS */
            
            rc = OtaWriteCurrentApp(app_id,
                                    IS_BONDED,
                                    &(CONN_HOST_ADDR),
                                    LINK_DIVERSIFIER,
#if defined(USE_STATIC_RANDOM_ADDRESS) || defined(USE_RESOLVABLE_RANDOM_ADDRESS)
                                    &bd_addr,
#else
                                    NULL,
#endif
                                    CONNECTION_IRK,
                                    GattServiceChangedIndActive());
            if (rc != sys_status_success)
            {
                /* Sanitise the result. If OtaWriteCurrentApp fails it will be
                 * because one or more of the supplied parameters was invalid.
                 */
                rc = gatt_status_invalid_param_value;
            }
        }
            break;
            
        case HANDLE_CSR_OTA_READ_CS_BLOCK:
            /* Set the offset and length of a block of CS to read */
            
            /* Validate input (expecting uint16[2]) */
            if (p_ind->size_value == WORDS_TO_BYTES(sizeof(uint16[2])))
            {
                const uint16 offset = BufReadUint16(&p_ind->value);
                
                data_transfer_data_length = (uint8)BufReadUint16(&p_ind->value);
            
                rc = readCsBlock(offset,
                                 data_transfer_data_length,
                                 data_transfer_memory);
            }
            else
            {
                rc = gatt_status_invalid_length;
            }
            break;
            
        case HANDLE_CSR_OTA_DATA_TRANSFER_CLIENT_CONFIG:
        {
            /* Modify the Data Transfer Client Characteristic Configuration
             * Descriptor
             */
            const uint16 client_config = BufReadUint16(&p_ind->value);
                                            /* Requested descriptor value */

            if((client_config == gatt_client_config_notification) ||
               (client_config == gatt_client_config_none))
            {
                data_transfer_configuration[0] = client_config;
                rc = sys_status_success;
            }
            else
            {
                /* INDICATION or RESERVED */

                /* Return error as only notifications are supported */
                rc = gatt_status_desc_improper_config;
            }
        }
            break;
            
        default:
            /* Writing to this characteristic is not permitted */
            break;
    }
 
    GattAccessRsp(p_ind->cid, p_ind->handle, rc, 0, NULL);
    
    /* Perform any follow-up actions */
    if (rc == sys_status_success)
    {
        switch (p_ind->handle)
        {
            case HANDLE_CSR_OTA_READ_CS_BLOCK:
                /* If this write action was to trigger a CS key read and
                 * notifications have been enabled send the result now.
                 */
                if (data_transfer_configuration[0] ==
                                                gatt_client_config_notification)
                {
                    GattCharValueNotification(CONNECTION_CID, 
                                              HANDLE_CSR_OTA_DATA_TRANSFER, 
                                              data_transfer_data_length,
                                              data_transfer_memory);
                }
                break;

            case HANDLE_CSR_OTA_CURRENT_APP:
                /* If a new application index has been requested disconnect from
                 * the Host and reset the device to run the new application.
                 */
                
                /* Record that the GATT database may be different after the
                 * device has reset.
                 */
                GattOnOtaSwitch();
                
                /* When the disconnect confirmation comes in, call OtaReset() */
                g_ota_reset_required = TRUE;

                /* Disconnect from the Host */
                GattDisconnectReq(CONNECTION_CID);
                break;

            default:
                /* No follow up action necessary */
                break;
        }
    }
}
Exemple #19
0
void coalescingAndFree(void* block) 
{
	struct blockHeader *header = INIT_STRUCT(blockHeader, block);
	uint32_t size = GET_SIZE(header->attribute); // in words
	uint32_t flag = GET_FLAG(header->attribute);

	NEIGHBOUR_BLOCKS state = NEIGHBOUR_BLOCKS_NOT_FREE; 

	struct freeBlockLinks *successorBlockLinks = NULL; // update only if necessary

	// Initialise addr and size for no change. 
	void* newAddr = block; 
	uint32_t newSize = size;
	uint64_t sizeOffset;
	// Is precedent block free? 
	if (flag == MSB_TO_ONE) {
		state = NEIGHBOUR_BLOCKS_PRECEDENT_FREE;
		// In this case it's just about updating the size of the prev free block 
		// and removing the successive one if free.
		void* footer = ADDRESS_MINUS_OFFSET(block, freeBlockFooter);
		struct freeBlockFooter *prevBlockFooter = INIT_STRUCT(freeBlockFooter, footer);
		sizeOffset = WORDS_TO_BYTES(prevBlockFooter->size); // Footer has no flag.
		newAddr = block - sizeOffset - sizeof(blockHeader);
		newSize = prevBlockFooter->size + BYTES_TO_WORDS(sizeof(blockHeader)) + size;
	}

	// Is successive block free? 
	sizeOffset = WORDS_TO_BYTES(size);
	void* nextBlock = ADDRESS_PLUS_OFFSET(block + sizeOffset, blockHeader);
	struct blockHeader *nextHeader = INIT_STRUCT(blockHeader, nextBlock);
	if (nextHeader->attribute != MSB_TO_ZERO) { // check if next block is mmap footer or not.
		uint32_t nextSize = GET_SIZE(nextHeader->attribute);
		sizeOffset = WORDS_TO_BYTES(nextSize);
		void* nextNextBlock =  ADDRESS_PLUS_OFFSET(nextBlock + sizeOffset, blockHeader);

		struct blockHeader *nextNextHeader = INIT_STRUCT(blockHeader, nextNextBlock);
		if (nextNextHeader->attribute != MSB_TO_ZERO) {
			flag = GET_FLAG(nextNextHeader->attribute);
			if (flag == MSB_TO_ONE) {
				if (!state) {
					state = NEIGHBOUR_BLOCKS_SUCCESSIVE_FREE;
					// Do not change address, but Increase size
					newSize = size + BYTES_TO_WORDS(sizeof(blockHeader)) + nextSize;
				} else {
					state = NEIGHBOUR_BLOCKS_BOTH_FREE;
					newSize = newSize + BYTES_TO_WORDS(sizeof(blockHeader)) + nextSize;
				}
				successorBlockLinks = nextBlock + sizeof(blockHeader);
				// IF NO PREV block is free:
				// Just update the pointers of the prev and next blocks 
				// relative to this block AND the size.
			}
		}
	} // Otherwise it's next block is the mmap footer.

	switch(state)
	{
		case NEIGHBOUR_BLOCKS_NOT_FREE: 
		{
			void *currentBlock = freeList;
			struct freeBlockLinks *currentBlockLinks = ADDRESS_PLUS_OFFSET(currentBlock, blockHeader);

			void* prevBlock = PREV_BLOCK(currentBlockLinks);
			initialiseFreeBlock(newAddr, newSize, 
				prevBlock, currentBlock, false, false);

			// Tell next block that its previous one is NOW free.
			sizeOffset = WORDS_TO_BYTES(size);
			updateNextBlockOnCoalescing(newAddr, sizeOffset);

			insertFreeBlock(newAddr, currentBlockLinks);
			numberFreeBlocks++;
			break;
		}
		case NEIGHBOUR_BLOCKS_PRECEDENT_FREE: 
		{
			coalesceWithPrevBlock(newAddr, newSize);
			break;
		}
		case NEIGHBOUR_BLOCKS_SUCCESSIVE_FREE: 
		{
			coalesceWithNextBlock(newAddr, newSize, successorBlockLinks);
			break;
		}
		case NEIGHBOUR_BLOCKS_BOTH_FREE: 
		{
			coalesceWithNeighbours(newAddr, newSize, successorBlockLinks);
			break;
		}
		default:
		{
			fprintf(stderr, "memoryManagement.coalescingAndFree - NEIGHBOUR_BLOCKS state unknown\n");
			exit(-1);
		}
	} // end switch

	// Update total free space
	// When state == 0, the totalFreeSpace is updated when the block is initialised.
	totalFreeSpace += WORDS_TO_BYTES(size); // Stats
	if (state != NEIGHBOUR_BLOCKS_NOT_FREE)
		totalFreeSpace += sizeof(blockHeader); 
	
	// Largest free region
	if (newSize > largestFreeBlock)
		largestFreeBlock = newSize;

	freeList = newAddr;
}