Initial original import from: fuse-2.4.2-2.fc4
[captive.git] / src / libcaptive / mm / pool.c
1 /* $Id$
2  * reactos memory pools emulation of libcaptive
3  * Copyright (C) 2002 Jan Kratochvil <project-captive@jankratochvil.net>
4  * 
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; exactly version 2 of June 1991 is required
8  * 
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  * 
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  */
18
19
20 #include "config.h"
21
22 #include "captive/mm.h" /* self */
23 #include "reactos/internal/mm.h"        /* self */
24 #include "reactos/ntos/types.h" /* for PVOID etc. */
25 #include <glib/gmessages.h>
26 #include <glib/gmem.h>
27 #include <glib/ghash.h>
28
29
30 /* map PVOID->GUINT_TO_POINTER(ULONG Tag) */
31 static GHashTable *memory_Tag_hash;
32
33 static void memory_Tag_hash_init(void)
34 {
35         if (memory_Tag_hash)
36                 return;
37         memory_Tag_hash=g_hash_table_new(g_direct_hash,g_direct_equal);
38 }
39
40
41 /**
42  * ExAllocatePoolWithTag:
43  * @PoolType: Type of memory to allocate. Safely ignored by libcaptive as it is
44  * too low level for it.
45  * @NumberOfBytes: Size of the requested allocation. Value 0 permitted (returns %NULL).
46  * @Tag: 4-bytes of block identification for debugging purposes and/or ExFreePoolWithTag().
47  * Bit 7 (==%0x80 ) of each byte must be cleared.
48  * %PROTECTED_POOL with @Tag bit 31 set is not yet implemented.
49  *
50  * Allocates the specified memory block. libcaptive passes the allocation to
51  * g_malloc() and @Tag is marked to this allocation.
52  *
53  * Returns: Memory block base if successfuly allocated. %NULL otherwise.
54  * The allocated memory block is not cleared.
55  */
56 PVOID ExAllocatePoolWithTag(ULONG PoolType,ULONG NumberOfBytes,ULONG Tag)
57 {
58 PVOID r;
59
60         g_return_val_if_fail((Tag&0x80808080)==0,NULL);
61
62         memory_Tag_hash_init();
63
64         if (!NumberOfBytes)
65                 return NULL;
66         /* FIXME: >=PAGE_SIZE allocations should be PAGE_SIZE aligned */
67         r=g_malloc(NumberOfBytes);
68
69         g_assert(FALSE==g_hash_table_lookup_extended(memory_Tag_hash,
70                                                 r,      /* lookup_key */
71                                                 NULL,   /* orig_key */
72                                                 NULL)); /* value */
73         g_hash_table_insert(memory_Tag_hash,
74                         (gpointer)r,    /* key */
75                         GUINT_TO_POINTER(Tag)); /* value */
76
77         return r;
78 }
79
80 /**
81  * ExAllocatePool:
82  * @PoolType: Type of memory to allocate. Safely ignored by libcaptive as it is
83  * too low level for it.
84  * @NumberOfBytes: Size of the requested allocation. Value 0 permitted (returns %NULL).
85  *
86  * Allocates the specified memory block. Calls ExAllocatePoolWithTag() with
87  * @Tag value %0x00000000. At least this value seems to be assumed by WXP <ntddk.h>
88  * although it is not officially documented for W32.
89  *
90  * Returns: Memory block base if successfuly allocated. %NULL otherwise.
91  * The allocated memory block is not cleared.
92  */
93 PVOID ExAllocatePool(POOL_TYPE PoolType,ULONG NumberOfBytes)
94 {
95         /* FIXME: It would be better to mark such block as 'unTagged' but we would have
96          * to maintain some structure for 'memory_Tag_hash' values instead of just GUINT_TO_POINTER().
97          */
98         return ExAllocatePoolWithTag(PoolType,NumberOfBytes,
99                         0x00000000); /* Tag; reactos uses TAG_NONE ('None') but it W32 uses %0x00000000 */
100 }
101
102 /**
103  * ExFreePool:
104  * @Block: Base address of the memory block. %NULL value is forbidden.
105  *
106  * Deallocate the given memory block. Block must be already successfuly
107  * allocated by a previous ExAllocatePool() or ExAllocatePoolWithTag() call.
108  * You can no longer assume anything about this base address / memory block.
109  */
110 VOID ExFreePool(IN PVOID Block)
111 {
112 gboolean errbool;
113
114         g_return_if_fail(Block!=NULL);
115
116         memory_Tag_hash_init();
117
118         errbool=g_hash_table_remove(memory_Tag_hash,Block);
119         g_assert(errbool==TRUE);
120
121         g_free(Block);
122 }
123
124
125 /**
126  * ExFreePoolWithTag:
127  * @Block: Base address of the memory block. %NULL value is forbidden.
128  * @Tag: 4-bytes of required block identification.
129  * Bit 7 (==%0x80 ) of each byte must be cleared.
130  * %PROTECTED_POOL with @Tag bit 31 set is not yet implemented.
131  * Value %0x0000000 is permitted for blocks marked with any Tag.
132  *
133  * Deallocate the given memory block. Block must be already successfuly
134  * allocated by a previous ExAllocatePoolWithTag() call.
135  * Block may be allocated by ExAllocatePool() if @Tag is passed %0x00000000.
136  * Please see more about @Tag in ExAllocatePool().
137  * It is forbidden to pass invalid @Tag for @Block.
138  *
139  * You can no longer assume anything about this base address / memory block.
140  */
141 VOID ExFreePoolWithTag(IN PVOID Block,IN ULONG Tag)
142 {
143 gpointer memory_Tag_gpointer;
144 gboolean errbool;
145
146         g_return_if_fail(Block!=NULL);
147         g_return_if_fail((Tag&0x80808080)==0);
148
149         memory_Tag_hash_init();
150
151         errbool=g_hash_table_lookup_extended(memory_Tag_hash,
152                                                 Block,  /* lookup_key */
153                                                 NULL,   /* orig_key */
154                                                 &memory_Tag_gpointer);  /* value */
155         g_return_if_fail(errbool==TRUE);
156         g_return_if_fail(!Tag || GPOINTER_TO_UINT(memory_Tag_gpointer)==Tag);
157
158         ExFreePool(Block);
159 }