Blob Blame History Raw
#ifndef DALIST_H
#define DALIST_H

#include "dalist_api.h"

#ifdef __cplusplus
extern "C" {
#endif

/* dalist node types */
enum dalist_node_types {
	DALIST_NODE,
	DALIST_NODE_EX,
};


/* dalist caller-provided memory allocation methods */
enum dalist_memfn {
	DALIST_MEMFN_CUSTOM,
	DALIST_MEMFN_MMAP,
	DALIST_MEMFN_MALLOC,
	DALIST_MEMFN_NT_ALLOCATE_VIRTUAL_MEMORY,
};


/* dalist debug environments */
enum dalist_dbgenv {
	DALIST_DEBUG_ENV_POSIX,
	DALIST_DEBUG_ENV_NT,
};


/* dalist return values */
#define DALIST_OK			(0x0)
#define DALIST_EINTERNAL		(0xD0000000)	/* internal error */
#define DALIST_EMEMFN			(0xD0000001)	/* memory allocation error */
#define DALIST_EMEMBLOCK		(0xD0000002)	/* invalid memory block */
#define DALIST_ELIST			(0xD0000003)	/* invalid list */
#define DALIST_ENODE			(0xD0000004)	/* invalid node */
#define DALIST_EPARAMMIX		(0xD0000005)	/* invalid parameter mix */
#define DALIST_EKEYEXISTS		(0xD0000006)	/* key already exists */
#define DALIST_ELISTNOTEMPTY		(0xD0000007)	/* null insertion point with non-empty list */

/* dalist debug return values */
#define DALIST_EDEBUGSTRUCT		(0xD0001000)	/* invalid debug structure */
#define DALIST_EDEBUGENV		(0xD0001001)	/* invalid debug environment */
#define DALIST_EDEBUGSPRINTF		(0xD0001002)	/* invalid debug pointer to sprintf */
#define DALIST_EDEBUGWRITE		(0xD0001003)	/* invalid debug pointer to write (posix) */
#define DALIST_EDEBUGWRITEFILE		(0xD0001004)	/* invalid debug pointer to zw_write_file (nt) */


/* dalist node flag bits */
#define DALIST_NODE_TYPE_NONE		(0x00u)
#define DALIST_NODE_TYPE_EXISTING	(0x01u)
#define DALIST_NODE_TYPE_NEW		(0x02u)
#define DALIST_NODE_TYPE_DELETED	(0x04u)
#define DALIST_NODE_MEM_BLOCK_BASE	(0x80u)


struct dalist_node {
	struct dalist_node *	prev;
	struct dalist_node *	next;
	uintptr_t		any;
};


struct dalist {
	struct dalist_node *	head;
	struct dalist_node *	tail;
};


struct dalist_node_ex {
	struct dalist_node_ex *	prev;
	struct dalist_node_ex *	next;
	uintptr_t		key;
	uintptr_t		flags;
	uintptr_t		dblock;
};


struct dalist_debug;

struct dalist_ex {
	void *			head;		/************************************/
	void *			tail;		/* head, tail, free:                */
	void *			free;		/* dalist_node when dblock_size is  */
	uintptr_t *		bookmarks;	/* zero, dalist_node_ex otherwise.  */
	size_t			dblock_size;	/*                                  */
	size_t			lblock_size;	/* lblock_size:                     */
	void *			memfn_ptr;	/* used when memfn_method is mmap   */
	enum dalist_memfn	memfn_method;	/* or nt_allocate_virtual_memory    */
	int			memfn_status;	/* as the system call's alloc_size  */
	int			mmap_prot;	/* argument.                        */
	int			mmap_flags;	/*                                  */
	int			mmap_fildes;	/*                                  */
	intptr_t		mmap_offset;	/************************************/
	struct dalist_debug *	debug;

	struct dalist_info {
		uintptr_t	list_nodes;
		uintptr_t	free_nodes;
		uintptr_t	bookmark_from;
		uintptr_t	bookmark_to;
		uintptr_t	bookmark_key_min;
		uintptr_t	bookmark_key_max;
		uintptr_t	nodes_below_first_bookmark;
		uintptr_t	nodes_above_last_bookmark;
	} info;
};


/* signatures for caller-provided debug output functions */
typedef int	__cdecl	  dalist_sprintf(char * buffer, const char * format, ...);
typedef ssize_t	__cdecl	  dalist_write(int fildes, const void *buf, size_t nbyte);
typedef int32_t __stdcall dalist_write_file(
	void *		hfile,
	void *		hevent,
	void *		apc_routine,
	void * 		apc_context,
	void * 		io_status_block,
	void * 		buffer,
	uint32_t	bytes_sent,
	int64_t *	byte_offset,
	uint32_t *	key);


/* debug */
struct dalist_debug {
	enum dalist_dbgenv	dbgenv;
	dalist_sprintf *	sprintf;	/* required (all) */
	dalist_write *		write;		/* required (posix only) */
	dalist_write_file *	zw_write_file;	/* required (nt only) */
};


/* signatures for caller-provided memory allocation functions */
typedef void * __cdecl dalist_memfn_mmap(
	void *		addr,
	size_t		alloc_size,
	int		prot,
	int		flags,
	int		fildes,
	intptr_t	offset);


typedef void * __cdecl dalist_memfn_malloc(
	size_t		alloc_size);


typedef int32_t __stdcall dalist_memfn_nt_allocvm(
	void *		hprocess,
	void **		base_address,
	uint32_t	zero_bits,
	size_t *	alloc_size,
	uint32_t	alloc_type,
	uint32_t	protect);


/**
 *  dalist_memfn_custom:
 *  must return either DALIST_OK or DALIST_EMEMFN;
 *  may update the list's memfn_status member
**/
typedef int __cdecl dalist_memfn_custom(
	struct dalist_ex *	dlist,
	void **			addr,
	size_t *		alloc_size);

dalist_api
int dalist_init(struct dalist *	dlist);

dalist_api
int dalist_init_ex(
	struct dalist_ex *	dlist,
	size_t			dblock_size,
	size_t			lblock_size,
	void *			memfn_ptr,
	enum dalist_memfn	memfn_method);

dalist_api
int dalist_insert_before(
	struct dalist *		dlist,
	struct dalist_node *	lnode,
	struct dalist_node *	nnode);

dalist_api
int dalist_insert_after(
	struct dalist *		dlist,
	struct dalist_node *	lnode,
	struct dalist_node *	nnode);

dalist_api
int dalist_get_free_node(
	struct dalist_ex *	dlist,
	void **			fnode);

dalist_api
int dalist_deposit_free_node(
	struct dalist_ex *	dlist,
	void *			fnode);

dalist_api
int dalist_deposit_memory_block(
	struct dalist_ex *	dlist,
	void *			addr,
	size_t			alloc_size);

dalist_api
int dalist_unlink_node(
	struct dalist *		dlist,
	struct dalist_node *	node);

dalist_api
int dalist_unlink_node_ex(
	struct dalist_ex *	dlist,
	struct dalist_node_ex *	node);

dalist_api
int dalist_discard_node(
	struct dalist_ex *	dlist,
	struct dalist_node_ex *	node);

dalist_api
int dalist_get_node_by_key(
	struct dalist_ex *	dlist,
	struct dalist_node_ex **node,
	uintptr_t		key,
	uintptr_t		get_flags,
	uintptr_t *		node_flags);

dalist_api
int dalist_insert_node_by_key(
	struct dalist_ex *	dlist,
	struct dalist_node_ex *	node);

/* debug routines */
dalist_api
int dalist_debug_setup(
	struct dalist_ex *	dlist,
	struct dalist_debug *	dlist_debug,
	enum dalist_dbgenv	dbgenv,
	dalist_sprintf *	pfn_sprintf,
	dalist_write *		pfn_write,
	dalist_write_file *	pfn_write_file);

dalist_api
int dalist_debug_print(
	struct dalist_ex *	dlist,
	intptr_t		fildes_or_hfile);


#ifdef __cplusplus
}
#endif
#endif