/*
 *   Copyright 2011 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 	linked_lists.h
 * \author 	Ioannis Koutras (joko@microlab.ntua.gr)
 * \date 	September, 2011
 *  
 * \brief Linked list node header structure and functions.
 */

#ifndef LINKED_LISTS_H
#define LINKED_LISTS_H

#include "dmm_config.h"
#ifndef LEON3
#include <stdint.h>
#else
#include <sys/types.h>
#endif /* LEON3 */
#include <dmmlib/heap.h>

/** The type of the pointer to a list node */
#ifndef LEON3
typedef uintptr_t list_node_ptr;
#else
typedef void* list_node_ptr;
#endif /* LEON3 */

/** The header structure of a linked list node */
typedef struct list_node_header_s {
    list_node_ptr next; /**< The pointer to the next node in the list */
#ifdef BLOCKS_IN_DLL
    list_node_ptr previous; /**< The pointer to the previous node in the list */
#endif /* BLOCKS_IN_DLL */
} list_node_header_t;

/**
 * Set the next memory block of a block in a linked list.
 *
 * \param block 	The pointer to the data part of the current memory
 * block.
 * \param next_block 	The pointer to the data part of the next memory block.
 */
void set_next(void *block, void *next_block);

/**
 * Get the next memory block in a linked list.
 *
 * \param ptr The pointer to the data part of the current memory block.
 *
 * \return The pointer of the data part of the next (in list) memory block.
 * \retval NULL There is no next memory block in the list.
 */
void * get_next(void *ptr);

#ifdef BLOCKS_IN_DLL

/**
 * Set the previous memory block of a block in a linked list.
 *
 * \param block             The pointer to the data part of the current memory
 * block.
 * \param previous_block    The pointer to the data part of the previous memory
 * block.
 */
void set_previous(void *previous, void *previous_block);

/**
 * Get the previous memory block in a linked list.
 *
 * \param ptr The pointer to the data part of the current memory block.
 *
 * \return The pointer of the data part of the previous (in list) memory block.
 * \retval NULL There is no previous memory block in the list.
 */
void * get_previous(void *ptr);

#endif /* BLOCKS_IN_DLL */

/**
 * Push a memory block to the head of a linked list.
 * 
 * \param **block A pointer to the block to be put.
 * \param **starting_node A pointer to the starting memory block of the list.
 */
void push_block(void **block, void **starting_node);

/**
 * Removes a memory block from a linked list of memory blocks.
 *
 * \param **block A pointer to the block to be removed.
 * \param **starting_node A pointer to the starting memory block of the list.
 */
void remove_block(void **block, void **starting_node);

/**
 * Removes a memory block from any of the linked lists of free memory blocks.
 *
 * \param **block A pointer to the block to be removed.
 * \param *heap A pointer to the heap which manages the block.
 */
void remove_block_from_lists(void **block, heap_t *heap);

#endif /* LINKED_LISTS_H */