2 Copyright (C) 1995-2014, The AROS Development Team. All rights reserved.
5 Desc: Create a memory pool.
9 #include <aros/kernel.h>
10 #include <aros/libcall.h>
11 #include <clib/alib_protos.h>
13 #include "exec_intern.h"
14 #include "exec_util.h"
18 /*****************************************************************************
21 #include <exec/memory.h>
22 #include <exec/memheaderext.h>
23 #include <proto/exec.h>
25 AROS_LH3(APTR
, CreatePool
,
28 AROS_LHA(ULONG
, requirements
, D0
),
29 AROS_LHA(IPTR
, puddleSize
, D1
),
30 AROS_LHA(IPTR
, threshSize
, D2
),
33 struct ExecBase
*, SysBase
, 116, Exec
)
36 Create a private pool for memory allocations.
39 requirements - The type of the memory
40 puddleSize - The number of bytes that the pool expands by
42 threshSize - Allocations beyond the threshSize are given
43 directly to the system. threshSize must be
44 smaller than or equal to the puddleSize.
47 A handle for the memory pool or NULL if the pool couldn't
51 Since exec.library v41.12, the implementation of pools has been
52 rewritten to make use of memory protection capabilities. The
53 threshSize parameter is effectively ignored and is present only
54 for backwards compatibility.
57 \* Get the handle to a private memory pool *\
58 po=CreatePool(MEMF_ANY,16384,8192);
63 mem1=AllocPooled(po,1000);
64 mem2=AllocPooled(po,2000);
65 \* Do something with the memory... *\
67 \* Free everything at once *\
74 DeletePool(), AllocPooled(), FreePooled()
78 ******************************************************************************/
82 struct TraceLocation tp
= CURRENT_LOCATION("CreatePool");
83 struct MemHeader
*firstPuddle
= NULL
;
84 IPTR align
= PrivExecBase(SysBase
)->PageSize
- 1;
89 D(bug("[exec] CreatePool(0x%08X, %u, %u)\n", requirements
, puddleSize
, threshSize
));
92 * puddleSize needs to include MEMHEADER_TOTAL, allocator context size and one pointer.
93 * This is because our puddles must be able to accommodate an allocation
94 * of own size. Allocations of larger size will always use enlarged puddles.
95 * Pointer is used for pointing back to the MemHeader from which the block
96 * was allocated, in AllocVec()-alike manner. This way we get rid of slow
97 * lookup in FreePooled().
99 puddleSize
+= MEMHEADER_TOTAL
+ mhac_GetCtxSize() + sizeof(struct MemHeader
*);
101 /* If mungwall is enabled, count also size of walls, at least for one allocation */
102 if (PrivExecBase(SysBase
)->IntFlags
& EXECF_MungWall
)
103 puddleSize
+= MUNGWALL_TOTAL_SIZE
;
105 /* Then round puddleSize up to be a multiple of page size. */
106 puddleSize
= (puddleSize
+ align
) & ~align
;
107 D(bug("[CreatePool] Aligned puddle size: %u (0x%08X)\n", puddleSize
, puddleSize
));
109 /* Allocate the first puddle. It will contain pool header. */
110 firstPuddle
= AllocMemHeader(puddleSize
, requirements
, &tp
, SysBase
);
111 D(bug("[CreatePool] Initial puddle 0x%p\n", firstPuddle
));
115 ULONG poolstruct_size
= (requirements
& MEMF_SEM_PROTECTED
) ? sizeof(struct ProtectedPool
) :
117 struct ProtectedPool
*pool
;
120 * Allocate pool header inside the puddle.
121 * It is the first allocation in this puddle, so in future we can always find
122 * header's address as poolbase + MEMHEADER_TOTAL.
124 pool
= Allocate(firstPuddle
, poolstruct_size
);
125 D(bug("[CreatePool] Pool header 0x%p (size %u)\n", pool
, poolstruct_size
));
127 /* Initialize pool header */
128 NEWLIST((struct List
*)&pool
->pool
.PuddleList
);
129 pool
->pool
.Requirements
= requirements
;
130 pool
->pool
.PuddleSize
= puddleSize
;
131 pool
->pool
.PoolMagic
= POOL_MAGIC
;
133 if (requirements
& MEMF_SEM_PROTECTED
)
135 InitSemaphore(&pool
->sem
);
139 * If the pool is in managed memory, don't bother any further setup. The
140 * pool should do the rest self.
142 if (IsManagedMem(firstPuddle
))
144 D(bug("Managed pool\n"));
146 * Just link the pool structure at the ln_Name - we will need that
149 firstPuddle
->mh_Node
.ln_Name
= (STRPTR
)&pool
->sem
;
151 /* Use mh_First to store the pool requirements */
152 firstPuddle
->mh_First
= (APTR
)(IPTR
)requirements
;
157 * Add the puddle to the list (yes, contained in itself).
158 * This is the first puddle so it's safe to use AddTail() here.
159 * Note that we use ln_Name of our MemHeader to point back to
160 * our pool (directly or indirectly).
162 mhac_PoolMemHeaderSetup(firstPuddle
, pool
);
163 AddTail((struct List
*)&pool
->pool
.PuddleList
, &firstPuddle
->mh_Node
);